Fixed the mode 2 of get_tile_fid

Minor code/comment/format edits.
This commit is contained in:
NovaRain
2023-06-13 10:15:02 +08:00
parent f5e7235a80
commit 492e31410c
8 changed files with 52 additions and 57 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ ScriptValue HookCommon::GetHSArgAt(DWORD id) {
return args[id];
}
void __stdcall HookCommon::SetHSReturn(const ScriptValue& value) {
void HookCommon::SetHSReturn(const ScriptValue& value) {
// For backward compatibility - ignore non-int return values
if (!allowNonIntReturn && !value.isInt()) return;
+1 -1
View File
@@ -15,7 +15,7 @@ public:
static script::ScriptValue GetHSArg();
static script::ScriptValue GetHSArgAt(DWORD id);
static void SetHSArg(DWORD id, const script::ScriptValue& value);
static void __stdcall SetHSReturn(const script::ScriptValue& value);
static void SetHSReturn(const script::ScriptValue& value);
static void GameModeChangeHook(DWORD exit);
static void __stdcall KeyPressHook(DWORD* dxKey, bool pressed, DWORD vKey);
+2 -2
View File
@@ -167,8 +167,8 @@ static DWORD __fastcall DescriptionObjHook_Script(DWORD object) {
RunHookScript(HOOK_DESCRIPTIONOBJ);
DWORD textPtr = cRet > 0 && (retTypes[0] == DataType::INT || retTypes[0] == DataType::STR)
? rets[0]
: 0;
? rets[0]
: 0;
EndHook();
return textPtr;
+23 -24
View File
@@ -556,6 +556,28 @@ skip:
}
}
// Allow passing non-weapon/armor items to invenWieldFunc_ engine function without error
// It used to treat all non-armor items as "weapon" and try to check if critter had weapon animation,
// which isn't valid for other item subtypes.
static void __declspec(naked) invenWieldFunc_hack() {
static const DWORD invenWieldFunc_hack_back = 0x47285D;
static const DWORD invenWieldFunc_hack_skip = 0x4728A7;
using namespace fo;
using namespace Fields;
__asm {
mov eax, edi; // weapon
call fo::funcoffs::item_get_type_;
cmp eax, item_type_weapon;
je isWeapon;
jmp invenWieldFunc_hack_skip;
isWeapon: // overwritten engine code
mov eax, [esi + rotation]; // cur_rot
inc eax;
push eax;
jmp invenWieldFunc_hack_back;
}
}
static void __declspec(naked) do_move_timer_hook() {
static const DWORD DoMoveTimer_Ret = 0x476920;
__asm {
@@ -626,29 +648,6 @@ void InventoryReset() {
invenApCost = invenApCostDef;
}
// Allows to pass items of non-armor and non-weapon type to invenWieldFunc without error
// It used to treat all non-armor items as "weapon" and try to check if critter had weapon animation,
// which isn't valid for other item subtypes.
static void __declspec(naked) invenWieldFunc_hack() {
static const DWORD invenWieldFunc_hack_back = 0x47285D;
static const DWORD invenWieldFunc_hack_skip = 0x4728A7;
using namespace fo;
using namespace Fields;
__asm {
mov eax, edi; // weapon
call fo::funcoffs::item_get_type_;
cmp eax, item_type_weapon;
je isWeapon;
jmp invenWieldFunc_hack_skip;
isWeapon: // overwritten engine code
mov eax, [esi + rotation]; // cur_rot
inc eax;
push eax;
jmp invenWieldFunc_hack_back;
}
}
void Inventory::init() {
OnKeyPressed() += InventoryKeyPressedHook;
LoadGameHook::OnGameReset() += InventoryReset;
@@ -766,7 +765,7 @@ void Inventory::init() {
HookCall(0x45B0CE, op_inven_unwield_hook); // with fix to update interface slot after unwielding
HookCall(0x45693C, op_wield_obj_critter_hook);
// Fix for invenWieldFunc (used by wield_obj_critter) to be able to put non-armor & non-weapon types into active slot.
// Fix for invenWieldFunc_ (used by wield_obj_critter) to be able to put non-weapon/armor items into active slot
MakeJump(0x472858, invenWieldFunc_hack);
}
+17 -22
View File
@@ -18,7 +18,6 @@
#include <algorithm>
#include <fstream>
#include <filesystem>
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
@@ -266,8 +265,8 @@ static void __fastcall game_init_databases_hook1() {
*/
static bool NormalizePath(std::string &path) {
const char* whiteSpaces = " \t";
// Remove comments
std::size_t pos = path.find_first_of(";#");
// Remove comments.
size_t pos = path.find_first_of(";#");
if (pos != std::string::npos) {
path.erase(pos);
}
@@ -279,7 +278,7 @@ static bool NormalizePath(std::string &path) {
// Disallow paths going outside of root folder.
if (path.find(".\\") != std::string::npos || path.find("..\\") != std::string::npos) return false;
// Trim whitespaces.
path.erase(0, path.find_first_not_of(whiteSpaces)); // trim left
path.erase(path.find_last_not_of(whiteSpaces) + 1); // trim right
@@ -295,14 +294,12 @@ static bool FileOrFolderExists(const std::string& path) {
static bool FileExists(const std::string& path) {
DWORD dwAttrib = GetFileAttributesA(path.c_str());
return dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
static bool FolderExists(const std::string& path) {
DWORD dwAttrib = GetFileAttributesA(path.c_str());
return dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
// Patches placed at the back of the vector will have priority in the chain over the front(previous) patches
@@ -316,18 +313,18 @@ static void GetExtraPatches() {
}
const std::string modsPath = ".\\mods\\";
const std::string loadOrderFilePath = modsPath + "mods_order.txt";
dlogr("Loading custom patches:", DL_MAIN);
// Check if mods folder exists, if not, create it.
// If the mods folder does not exist, create it.
if (!FolderExists(modsPath)) {
CreateDirectoryA(modsPath.c_str(), 0);
}
// Check if load order file does not exist yet and initialize automatically with mods already in the mods folder.
// If load order file does not exist, initialize it automatically with mods already in the mods folder.
if (!FileExists(loadOrderFilePath)) {
std::ofstream loadOrderFile(loadOrderFilePath, std::ios::out | std::ios::trunc);
if (loadOrderFile.is_open()) {
// Search all .dat files and folders in mods folder.
// Search all .dat files and folders in the mods folder.
std::vector<std::string> autoLoadedPatchFiles;
std::string pathMask(modsPath + "*.dat");
WIN32_FIND_DATA findData;
@@ -337,22 +334,21 @@ static void GetExtraPatches() {
std::string name(findData.cFileName);
if ((name.length() - name.find_last_of('.')) > 4) continue;
autoLoadedPatchFiles.push_back(name.c_str());
autoLoadedPatchFiles.push_back(name);
} while (FindNextFile(hFind, &findData));
FindClose(hFind);
}
// Sort the search result.
std::sort(autoLoadedPatchFiles.begin(), autoLoadedPatchFiles.end());
// Write found files into load_order files.
// Write found files into load order file.
for (auto& filePath : autoLoadedPatchFiles) {
loadOrderFile << filePath << '\n';
}
}
else {
dlog_f("Error creating load order file %s.", DL_MAIN, loadOrderFilePath.c_str());
} else {
dlog_f("Error creating load order file %s.\n", DL_MAIN, loadOrderFilePath.c_str() + 2);
}
}
// Add mods from load_order file.
// Add mods from load order file.
std::ifstream loadOrderFile(loadOrderFilePath, std::ios::in);
if (loadOrderFile.is_open()) {
std::string patch;
@@ -361,12 +357,11 @@ static void GetExtraPatches() {
patch = modsPath + patch;
if (!FileOrFolderExists(patch)) continue;
dlog_f("> %s\n", DL_MAIN, patch.c_str());
dlog_f("> %s\n", DL_MAIN, patch.c_str() + 2);
patchFiles.push_back(patch);
}
}
else {
dlog_f("Error opening %s for read: %x", DL_MAIN, loadOrderFilePath.c_str(), GetLastError());
} else {
dlog_f("Error opening %s for read: %d\n", DL_MAIN, loadOrderFilePath.c_str() + 2, GetLastError());
}
// Remove first duplicates
+2 -2
View File
@@ -88,12 +88,12 @@ static void __declspec(naked) register_object_take_out_hack() {
}
static void __declspec(naked) gdAddOptionStr_hack() {
static const DWORD gdAddOptionStr_hack_Ret = 0x4458FA;
__asm {
mov ecx, ds:[FO_VAR_gdNumOptions];
add ecx, '1';
push ecx;
mov ecx, 0x4458FA;
jmp ecx;
jmp gdAddOptionStr_hack_Ret;
}
}
+5 -4
View File
@@ -333,10 +333,10 @@ end:
void op_get_tile_fid(OpcodeContext& ctx) {
long tileX, tileY, squareNum, squareData, result,
tileAndElev = ctx.arg(0).rawValue(),
tileNum = tileAndElev & 0xFFFFFF,
elevation = (tileAndElev >> 24) & 0x0F,
mode = tileAndElev >> 28;
tileAndElev = ctx.arg(0).rawValue(),
tileNum = tileAndElev & 0xFFFFFF,
elevation = (tileAndElev >> 24) & 0x0F,
mode = tileAndElev >> 28;
fo::func::tile_coord(tileNum, &tileX, &tileY);
squareNum = fo::func::square_num(tileX, tileY, elevation);
@@ -347,6 +347,7 @@ void op_get_tile_fid(OpcodeContext& ctx) {
break;
case 2:
result = squareData; // raw data
break;
default:
// Vanilla uses 12 bits for Tile FID, which means 4096 possible values, the mask was 0x0FFF
// BUT sfall's FRM Limit patch extended it to 14 bits, so we need to use mask 0x3FFF
+1 -1
View File
@@ -179,7 +179,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = {
{0x239, "scan_array", op_scan_array, 2, true, -1, {ARG_OBJECT, ARG_ANY}},
{0x23a, "get_tile_fid", op_get_tile_fid, 1, true, 0, {ARG_INT}},
{0x23c, "get_sfall_args", op_get_sfall_args, 0, true},
{0x23d, "set_sfall_arg", op_set_sfall_arg, 2, false, 0, {ARG_INT, ARG_ANY}}, // hookscript system will validate type
{0x23d, "set_sfall_arg", op_set_sfall_arg, 2, false, 0, {ARG_INT, ARG_ANY}}, // hook script system will validate type
{0x241, "get_npc_level", op_get_npc_level, 1, true, -1, {ARG_INTSTR}},
{0x242, "set_critter_skill_points", op_set_critter_skill_points, 3, false, 0, {ARG_OBJECT, ARG_INT, ARG_INT}},
{0x243, "get_critter_skill_points", op_get_critter_skill_points, 2, true, 0, {ARG_OBJECT, ARG_INT}},