Moved item_count function fix to Game\items.cpp

Finished the code of item_weapon_mp_cost replacement.
This commit is contained in:
NovaRain
2021-05-08 12:42:53 +08:00
parent 6d88f21028
commit 183b74a8fa
5 changed files with 50 additions and 39 deletions
+1 -2
View File
@@ -68,8 +68,7 @@ DWORD __stdcall Inventory::adjust_fid() {
indexNum = critterPro->fid & 0xFFF; indexNum = critterPro->fid & 0xFFF;
} }
if (fo::var::i_worn != nullptr) { if (fo::var::i_worn != nullptr) {
fo::Proto* armorPro; fo::Proto* armorPro = fo::GetProto(fo::var::i_worn->protoId);
fo::GetProto(fo::var::i_worn->protoId, &armorPro);
DWORD armorFid = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE DWORD armorFid = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE
? armorPro->item.armor.femaleFID ? armorPro->item.armor.femaleFID
: armorPro->item.armor.maleFID; : armorPro->item.armor.maleFID;
+44 -6
View File
@@ -45,6 +45,13 @@ long Items::item_weapon_range(fo::GameObject* source, fo::GameObject* weapon, lo
return range; 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 // 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 __fastcall Items::item_weapon_mp_cost(fo::GameObject* source, fo::GameObject* weapon, long hitMode, long isCalled) {
long cost = 0; 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); long type = fo::func::item_w_subtype(weapon, hitMode);
if (source->id == fo::PLAYER_ID && sf::Perks::DudeHasTrait(fo::Trait::TRAIT_fast_shot)) { if (source->protoId == fo::ProtoID::PID_Player && sf::Perks::DudeHasTrait(fo::Trait::TRAIT_fast_shot)) {
// Fallout 1 behavior and Alternative behavior (allowed for all weapons) if (fastShotTweak || // Fallout 1 behavior and Alternative behavior (allowed for all weapons)
bool allow = false; // TODO: add FastShotFix variable (fo::func::item_w_range(source, hitMode) >= 2 && type > fo::AttackSubType::MELEE)) // Fallout 2 behavior (with fix) and Haenlomal's tweak
{
// Fallout 2 behavior (with fix) and Haenlomal's fix cost--;
if (allow || (fo::func::item_w_range(source, hitMode) >= 2 && type > fo::AttackSubType::MELEE)) cost--; }
} }
if ((type == fo::AttackSubType::MELEE || type == fo::AttackSubType::UNARMED) && Stats::perk_level(source, fo::Perk::PERK_bonus_hth_attacks)) { if ((type == fo::AttackSubType::MELEE || type == fo::AttackSubType::UNARMED) && Stats::perk_level(source, fo::Perk::PERK_bonus_hth_attacks)) {
cost--; 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() { void Items::init() {
// Replace the item_w_primary_mp_cost_ function with the sfall implementation // Replace the item_w_primary_mp_cost_ function with the sfall implementation
sf::HookCall(0x429A08, ai_search_inven_weap_hook); 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);
} }
} }
+4
View File
@@ -15,6 +15,8 @@ public:
static long item_weapon_range(fo::GameObject* source, fo::GameObject* weapon, long hitMode); 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 // 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 // Note: Use only for weapons
static long __fastcall item_weapon_mp_cost(fo::GameObject* source, fo::GameObject* weapon, long hitMode, long isCalled); 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 // 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 // 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 item_w_mp_cost(fo::GameObject* source, long hitMode, long isCalled);
static long __fastcall item_count(fo::GameObject* who, fo::GameObject* item);
}; };
} }
+1 -2
View File
@@ -175,8 +175,7 @@ long __fastcall Tilemap::tile_num_beyond(long sourceTile, long targetTile, long
} }
static void __declspec(naked) tile_num_beyond_hack() { static void __declspec(naked) tile_num_beyond_hack() {
__asm { __asm { //push ecx;
//push ecx;
push ebx; push ebx;
mov ecx, eax; mov ecx, eax;
call Tilemap::tile_num_beyond; call Tilemap::tile_num_beyond;
-29
View File
@@ -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() { static void __declspec(naked) Save_as_ASCII_hack() {
__asm { __asm {
mov edx, STAT_sequence; 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 // 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); 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 // Fix for Sequence stat value not being printed correctly when using "print to file" option
MakeCall(0x4396F5, Save_as_ASCII_hack, 2); MakeCall(0x4396F5, Save_as_ASCII_hack, 2);