From 183b74a8faf4881d5fd8707e1819b61cd550350a Mon Sep 17 00:00:00 2001 From: NovaRain Date: Sat, 8 May 2021 12:42:53 +0800 Subject: [PATCH] Moved item_count function fix to Game\items.cpp Finished the code of item_weapon_mp_cost replacement. --- sfall/Game/inventory.cpp | 3 +-- sfall/Game/items.cpp | 50 +++++++++++++++++++++++++++++++++----- sfall/Game/items.h | 4 +++ sfall/Game/tilemap.cpp | 3 +-- sfall/Modules/BugFixes.cpp | 29 ---------------------- 5 files changed, 50 insertions(+), 39 deletions(-) diff --git a/sfall/Game/inventory.cpp b/sfall/Game/inventory.cpp index a7a748db..148a36e7 100644 --- a/sfall/Game/inventory.cpp +++ b/sfall/Game/inventory.cpp @@ -68,8 +68,7 @@ DWORD __stdcall Inventory::adjust_fid() { indexNum = critterPro->fid & 0xFFF; } if (fo::var::i_worn != nullptr) { - fo::Proto* armorPro; - fo::GetProto(fo::var::i_worn->protoId, &armorPro); + fo::Proto* armorPro = fo::GetProto(fo::var::i_worn->protoId); DWORD armorFid = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE ? armorPro->item.armor.femaleFID : armorPro->item.armor.maleFID; diff --git a/sfall/Game/items.cpp b/sfall/Game/items.cpp index 78d98447..9d7488ce 100644 --- a/sfall/Game/items.cpp +++ b/sfall/Game/items.cpp @@ -45,6 +45,13 @@ long Items::item_weapon_range(fo::GameObject* source, fo::GameObject* weapon, lo return range; } +// TODO +//long Items::item_w_range(fo::GameObject* source, long hitMode) { +// return item_weapon_range(source, fo::func::item_hit_with(source, hitMode), hitMode); +//} + +static bool fastShotTweak = false; + // Implementation of item_w_primary_mp_cost_ and item_w_secondary_mp_cost_ engine functions in a single function with the HOOK_CALCAPCOST hook long __fastcall Items::item_weapon_mp_cost(fo::GameObject* source, fo::GameObject* weapon, long hitMode, long isCalled) { long cost = 0; @@ -73,12 +80,12 @@ long __fastcall Items::item_weapon_mp_cost(fo::GameObject* source, fo::GameObjec long type = fo::func::item_w_subtype(weapon, hitMode); - if (source->id == fo::PLAYER_ID && sf::Perks::DudeHasTrait(fo::Trait::TRAIT_fast_shot)) { - // Fallout 1 behavior and Alternative behavior (allowed for all weapons) - bool allow = false; // TODO: add FastShotFix variable - - // Fallout 2 behavior (with fix) and Haenlomal's fix - if (allow || (fo::func::item_w_range(source, hitMode) >= 2 && type > fo::AttackSubType::MELEE)) cost--; + if (source->protoId == fo::ProtoID::PID_Player && sf::Perks::DudeHasTrait(fo::Trait::TRAIT_fast_shot)) { + if (fastShotTweak || // Fallout 1 behavior and Alternative behavior (allowed for all weapons) + (fo::func::item_w_range(source, hitMode) >= 2 && type > fo::AttackSubType::MELEE)) // Fallout 2 behavior (with fix) and Haenlomal's tweak + { + cost--; + } } if ((type == fo::AttackSubType::MELEE || type == fo::AttackSubType::UNARMED) && Stats::perk_level(source, fo::Perk::PERK_bonus_hth_attacks)) { cost--; @@ -109,9 +116,40 @@ static void __declspec(naked) ai_search_inven_weap_hook() { } } +long __fastcall Items::item_count(fo::GameObject* who, fo::GameObject* item) { + int count = 0; + for (int i = 0; i < who->invenSize; i++) { + auto tableItem = &who->invenTable[i]; + if (tableItem->object == item) { + count += tableItem->count; + } else if (fo::func::item_get_type(tableItem->object) == fo::item_type_container) { + count += item_count(tableItem->object, item); + } + } + return count; +} + +static void __declspec(naked) item_count_hack() { + __asm { + push ecx; // save state + //push edx; ??? + mov ecx, eax; // container-object + call Items::item_count; // edx - item + //pop edx; + pop ecx; // restore + retn; + } +} + void Items::init() { // Replace the item_w_primary_mp_cost_ function with the sfall implementation sf::HookCall(0x429A08, ai_search_inven_weap_hook); + + // Replace the item_count_ function (fix vanilla function returning incorrect value when there is a container-item inside) + sf::MakeJump(0x47808C, item_count_hack); + + int fastShotFix = sf::IniReader::GetConfigInt("Misc", "FastShotFix", 0); + fastShotTweak = (fastShotFix > 0 && fastShotFix <= 3); } } diff --git a/sfall/Game/items.h b/sfall/Game/items.h index dd2352b5..1fcd285d 100644 --- a/sfall/Game/items.h +++ b/sfall/Game/items.h @@ -15,6 +15,8 @@ public: static long item_weapon_range(fo::GameObject* source, fo::GameObject* weapon, long hitMode); + //static long item_w_range(fo::GameObject* source, long hitMode); + // Implementation of item_w_primary_mp_cost_ and item_w_secondary_mp_cost_ engine functions in a single function with the HOOK_CALCAPCOST hook // Note: Use only for weapons static long __fastcall item_weapon_mp_cost(fo::GameObject* source, fo::GameObject* weapon, long hitMode, long isCalled); @@ -22,6 +24,8 @@ public: // Implementation of item_w_mp_cost_ engine function with the HOOK_CALCAPCOST hook // Note: Use the generic item_mp_cost function which has a hook call static long item_w_mp_cost(fo::GameObject* source, long hitMode, long isCalled); + + static long __fastcall item_count(fo::GameObject* who, fo::GameObject* item); }; } \ No newline at end of file diff --git a/sfall/Game/tilemap.cpp b/sfall/Game/tilemap.cpp index 03dcad46..ba1db0f8 100644 --- a/sfall/Game/tilemap.cpp +++ b/sfall/Game/tilemap.cpp @@ -175,8 +175,7 @@ long __fastcall Tilemap::tile_num_beyond(long sourceTile, long targetTile, long } static void __declspec(naked) tile_num_beyond_hack() { - __asm { - //push ecx; + __asm { //push ecx; push ebx; mov ecx, eax; call Tilemap::tile_num_beyond; diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index bc14ca5a..c94c0582 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -1475,32 +1475,6 @@ end: } } -static int __stdcall ItemCountFix(fo::GameObject* who, fo::GameObject* item) { - int count = 0; - for (int i = 0; i < who->invenSize; i++) { - auto tableItem = &who->invenTable[i]; - if (tableItem->object == item) { - count += tableItem->count; - } else if (fo::func::item_get_type(tableItem->object) == fo::item_type_container) { - count += ItemCountFix(tableItem->object, item); - } - } - return count; -} - -static void __declspec(naked) item_count_hack() { - __asm { - push ecx; - push edx; // save state - push edx; // item - push eax; // container-object - call ItemCountFix; - pop edx; - pop ecx; // restore - retn; - } -} - static void __declspec(naked) Save_as_ASCII_hack() { __asm { mov edx, STAT_sequence; @@ -3390,9 +3364,6 @@ void BugFixes::init() // Fix crash when clicking on empty space in the inventory list opened by "Use Inventory Item On" (backpack) action icon MakeCall(0x471A94, use_inventory_on_hack); - // Fix item_count function returning incorrect value when there is a container-item inside - MakeJump(0x47808C, item_count_hack); // replacing item_count_ function - // Fix for Sequence stat value not being printed correctly when using "print to file" option MakeCall(0x4396F5, Save_as_ASCII_hack, 2);