From 1687e5072958ccad599112c82ab75bd031a6acb5 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Thu, 21 Feb 2019 10:53:55 +0800 Subject: [PATCH] Fixed the negative skill points of a skill not being taken into account when calculating the skill level (from Mr.Stalin, #202) Fixed the return value of has_skill function for incorrect skill numbers. --- artifacts/ddraw.ini | 4 +-- sfall/Modules/BugFixes.cpp | 67 ++++++++++++++++++++------------------ sfall/Modules/Skills.cpp | 24 ++++++++++++-- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 3d0bb23c..3970d171 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -92,7 +92,7 @@ FadeMultiplier=100 ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [Input] -;Set to 1 to enable the mouse scroll wheel to scroll through inventory, barter, and loot screens +;Set to 1 to enable the mouse scroll wheel to scroll through the inventory, barter, and loot screens UseScrollWheel=1 ;The mouse Z position is divided by this modifier to calculate the number of inventory @@ -645,7 +645,7 @@ WorldMapFontPatch=0 ;Set to 1 to keep the selected attack mode when moving the weapon between active item slots KeepWeaponSelectMode=1 -;Set to 1 to display full item description for weapon/ammo in barter screen +;Set to 1 to display full item description for weapon/ammo in the barter screen FullItemDescInBarter=0 ;Set to 1 to display experience points with the bonus from Swift Learner perk when gained from non-scripted situations diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index dda891de..509ed3b9 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -293,7 +293,7 @@ static void __declspec(naked) queue_clear_type_mem_free_hook() { } } -static void __declspec(naked) partyMemberCopyLevelInfo_stat_level_hook() { +static void __declspec(naked) partyMemberCopyLevelInfo_hook_stat_level() { __asm { nextArmor: mov eax, esi @@ -308,7 +308,7 @@ noArmor: } } -static void __declspec(naked) correctFidForRemovedItem_adjust_ac_hook() { +static void __declspec(naked) correctFidForRemovedItem_hook_adjust_ac() { __asm { call fo::funcoffs::adjust_ac_ nextArmor: @@ -323,40 +323,40 @@ end: } } -static void __declspec(naked) partyMemberCopyLevelInfo_hook() { +static void __declspec(naked) partyMemberIncLevels_hook() { __asm { - push eax - call fo::funcoffs::partyMemberCopyLevelInfo_ - pop ebx - cmp eax, -1 - je end - pushad - mov dword ptr ds:[FO_VAR_critterClearObj], ebx - mov edx, fo::funcoffs::critterClearObjDrugs_ - call fo::funcoffs::queue_clear_type_ - mov ecx, 8 - mov edi, FO_VAR_drugInfoList - mov esi, ebx + mov ebx, eax; // party member pointer + call fo::funcoffs::partyMemberCopyLevelInfo_; + cmp eax, -1; + je end; + xor edx, edx; // queue type (0) + mov eax, ebx; // source + call fo::funcoffs::queue_remove_this_; + push ecx; + push edi; + mov ecx, 8; + mov edi, FO_VAR_drugInfoList; loopAddict: - mov eax, dword ptr [edi] // eax = drug pid - call fo::funcoffs::item_d_check_addict_ - test eax, eax // Has addiction? - jz noAddict // No - cmp dword ptr [eax], 0 // queue_addict.init - jne noAddict // Addiction is not active yet - mov edx, dword ptr [eax+0x8] // queue_addict.perk - mov eax, ebx - call fo::funcoffs::perk_add_effect_ + mov eax, dword ptr [edi]; // eax = drug pid + call fo::funcoffs::item_d_check_addict_; + test eax, eax; // Has addiction? + jz noAddict; // No + cmp dword ptr [eax], 0; // queue_addict.init + jne noAddict; // Addiction is not active yet + mov edx, dword ptr [eax + 0x8]; // queue_addict.perk + mov eax, ebx; + call fo::funcoffs::perk_add_effect_; noAddict: - add edi, 12 - loop loopAddict - popad + lea edi, [edi + 12]; + dec ecx; + jnz loopAddict; + pop edi; + pop ecx; end: - retn + retn; } } - static void __declspec(naked) gdProcessUpdate_hack() { __asm { add eax, esi @@ -1894,14 +1894,14 @@ void BugFixes::init() // The same happens if you just order NPC to remove the armor through dialogue. //if (GetConfigInt("Misc", "ArmorCorruptsNPCStatsFix", 1)) { dlog("Applying fix for armor reducing NPC original stats when removed.", DL_INIT); - HookCall(0x495F3B, partyMemberCopyLevelInfo_stat_level_hook); - HookCall(0x45419B, correctFidForRemovedItem_adjust_ac_hook); + HookCall(0x495F3B, partyMemberCopyLevelInfo_hook_stat_level); + HookCall(0x45419B, correctFidForRemovedItem_hook_adjust_ac); dlogr(" Done", DL_INIT); //} // Fix of invalid stats when party member gains a level while being on drugs dlog("Applying fix for addicted party member level up bug.", DL_INIT); - HookCall(0x495D5C, partyMemberCopyLevelInfo_hook); + HookCall(0x495D5C, partyMemberIncLevels_hook); dlogr(" Done", DL_INIT); // Allow 9 options (lines of text) to be displayed correctly in a dialog window @@ -2320,6 +2320,9 @@ void BugFixes::init() // Fix for the reserved item FRM being displayed in the top-left corner when in the loot/barter screens HookCalls(JesseContainerFid, {0x473AC9, 0x475895}); + + // Fix the return value of has_skill function for incorrect skill numbers + SafeWrite32(0x4AA56B, 0); } } diff --git a/sfall/Modules/Skills.cpp b/sfall/Modules/Skills.cpp index d6a30d4d..e9b0bddc 100644 --- a/sfall/Modules/Skills.cpp +++ b/sfall/Modules/Skills.cpp @@ -39,8 +39,8 @@ struct SkillModifier { SkillModifier() : id(0), maximum(300)/*, mod(0)*/ {} - SkillModifier(long _id, int max) { - id = _id; + SkillModifier(long id, int max) { + this->id = id; maximum = max; //mod = _mod; } @@ -61,6 +61,8 @@ static double* multipliers = nullptr; static std::vector pickpocketMods; static ChanceModifier basePickpocket; +static int skillNegPoints; + static int __fastcall PickpocketMod(int base, fo::GameObject* critter) { for (DWORD i = 0; i < pickpocketMods.size(); i++) { if (critter->id == pickpocketMods[i].id) { @@ -84,6 +86,8 @@ static void __declspec(naked) skill_check_stealing_hack() { } static int __fastcall CheckSkillMax(fo::GameObject* critter, int base) { + base += skillNegPoints; // add the negative skill points after calculating the skill level + for (DWORD i = 0; i < skillMaxMods.size(); i++) { if (critter->id == skillMaxMods[i].id) { return min(base, skillMaxMods[i].maximum); @@ -101,6 +105,19 @@ static void __declspec(naked) skill_level_hack() { } } +static void __declspec(naked) skill_level_hook() { + __asm { + mov skillNegPoints, 0; // reset value + call fo::funcoffs::skill_points_; + test eax, eax; + jge skip; // skip if eax >= 0 + mov skillNegPoints, eax; // save the negative skill points + xor eax, eax; +skip: + retn; + } +} + static void __declspec(naked) skill_inc_point_force_hack() { __asm { push ecx; @@ -236,7 +253,7 @@ void _stdcall SetPickpocketMax(fo::GameObject* critter, DWORD maximum, DWORD mod pickpocketMods.push_back(ChanceModifier(id, maximum, mod)); } -void Skills_OnGameLoad() { +static void Skills_OnGameLoad() { pickpocketMods.clear(); basePickpocket.SetDefault(); @@ -245,6 +262,7 @@ void Skills_OnGameLoad() { } void Skills::init() { + HookCall(0x4AA574, skill_level_hook); // fix for negative skill points MakeJump(0x4AA63C, skill_level_hack, 1); MakeCall(0x4AA847, skill_inc_point_force_hack); MakeCall(0x4AA725, skill_inc_point_hack);