From 087b259b04863efd59ac225d0761539547bb345b Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 5 Jan 2021 14:15:33 +0800 Subject: [PATCH] Added more options for tweaking some engine perks to the perks ini file Added tweaks to include the perk level in the calculation of the bonus value for "Salesman" and "Demolition Expert" perks. --- artifacts/config_files/Perks.ini | 47 +++++-- sfall/AI.cpp | 1 + sfall/Perks.cpp | 222 ++++++++++++++++++++++++++++--- 3 files changed, 241 insertions(+), 29 deletions(-) diff --git a/artifacts/config_files/Perks.ini b/artifacts/config_files/Perks.ini index e89ce435..eab36c3b 100644 --- a/artifacts/config_files/Perks.ini +++ b/artifacts/config_files/Perks.ini @@ -7,22 +7,51 @@ ; be used to remove their hardcoded effects, and add new stat/skill effects [PerksTweak] -;Change the penalty distance and distance bonus for 'Weapon Scope Range' weapon perk +;Changes the bonus for 'Master Trader' perk (ID 17) +;25 - default bonus +MasterTraderBonus=25 + +;Changes the distance bonus for 'Weapon Long Range' weapon perk (ID 58) +;2 - no bonus, 4 - default bonus +WeaponLongRangeBonus=4 + +;Changes the hit chance bonus for 'Weapon Accurate' weapon perk (ID 59) +;0 - no bonus, 125 - maximum bonus, 20 - default bonus +WeaponAccurateBonus=20 + +;Change the penalty distance and distance bonus for 'Weapon Scope Range' weapon perk (ID 64) ;0 - no penalty, 8 - default penalty WeaponScopeRangePenalty=8 ;2 - no bonus, 5 - default bonus WeaponScopeRangeBonus=5 -;Changes the distance bonus for 'Weapon Long Range' weapon perk -;2 - no bonus, 4 - default bonus -WeaponLongRangeBonus=4 +;Changes the resistance bonuses for 'Vault City Inoculations' perk (ID 78) +;valid range: -100..100, 10 - default bonus +VaultCityInoculationsPoisonBonus=10 +VaultCityInoculationsRadBonus=10 -;Changes the hit chance bonus for 'Weapon Accurate' weapon perk -;0 - no bonus, 200 - maximum bonus, 20 - default bonus -WeaponAccurateBonus=20 +;Changes the damage bonus per level for 'Demolition Expert' perk (ID 82) +;10 - default bonus +DemolitionExpertBonus=10 -;Changes the strength bonus for 'Weapon Handling' perk -;0 - no bonus, 10 - maximum bonus, 3 - default bonus +;Changes the damage bonus for 'Living Anatomy' perk (ID 97) +;125 - maximum bonus, 5 - default bonus +LivingAnatomyBonus=5 + +;Changes the damage bonus for 'Pyromaniac' perk (ID 101) +;125 - maximum bonus, 5 - default bonus +PyromaniacBonus=5 + +;Changes the skill bonus per level for 'Salesman' perk (ID 103) +;125 - maximum bonus, 20 - default bonus +SalesmanBonus=20 + +;Changes the percent chance for 'Stonewall' perk (ID 104) +;valid range: 0..100, 50 - default percent +StonewallPercent=50 + +;Changes the strength bonus for 'Weapon Handling' perk (ID 106) +;0 - no bonus, 10 - maximum bonus, 3 - default bonus WeaponHandlingBonus=3 ;############################################################################## diff --git a/sfall/AI.cpp b/sfall/AI.cpp index a79bcc30..d447e948 100644 --- a/sfall/AI.cpp +++ b/sfall/AI.cpp @@ -473,6 +473,7 @@ void AI_Init() { HookCall(0x421666, combat_safety_invalidate_weapon_func_hook_check); // Fix AI weapon switching when not having enough action points + // AI will try to change attack mode before deciding to switch weapon HookCall(0x42AB57, ai_try_attack_hook_switch_fix); // Fix for duplicate critters being added to the list of potential targets for AI diff --git a/sfall/Perks.cpp b/sfall/Perks.cpp index d4d47449..dcc74808 100644 --- a/sfall/Perks.cpp +++ b/sfall/Perks.cpp @@ -623,7 +623,208 @@ void __stdcall ApplyHeaveHoFix() { // not really a fix perkHeaveHoModFix = true; } +//////////////////////////////// ENGINE PERKS ///////////////////////////////// + +static class EnginePerkBonus { +public: + long WeaponScopeRangePenalty; + long WeaponScopeRangeBonus; + long WeaponLongRangeBonus; + long WeaponAccurateBonus; + long WeaponHandlingBonus; + + float MasterTraderBonus; + long SalesmanBonus; + + long LivingAnatomyBonus; + long PyromaniacBonus; + + long StonewallPercent; + + long DemolitionExpertBonus; + + long VaultCityInoculationsPoisonBonus; + long VaultCityInoculationsRadBonus; + + EnginePerkBonus() { + WeaponScopeRangePenalty = 8; + WeaponScopeRangeBonus = 5; + WeaponLongRangeBonus = 4; + WeaponAccurateBonus = 20; + WeaponHandlingBonus = 3; + + MasterTraderBonus = 25; + SalesmanBonus = 20; + + LivingAnatomyBonus = 5; + PyromaniacBonus = 5; + + StonewallPercent = 50; + + DemolitionExpertBonus = 10; + + VaultCityInoculationsPoisonBonus = 10; + VaultCityInoculationsRadBonus = 10; + } + + /////////////////////////////////////////// + + void setWeaponScopeRangePenalty(long value) { + if (value < 0) return; + WeaponScopeRangePenalty = value; + SafeWrite32(0x42448E, value); + } + + void setWeaponScopeRangeBonus(long value) { + if (value < 2) return; + WeaponScopeRangeBonus = value; + SafeWrite32(0x424489, value); + } + + void setWeaponLongRangeBonus(long value) { + if (value < 2) return; + WeaponLongRangeBonus = value; + SafeWrite32(0x424474, value); + } + + void setWeaponAccurateBonus(long value) { + if (value < 0) return; + WeaponAccurateBonus = value; + if (WeaponAccurateBonus > 125) WeaponAccurateBonus = 125; + SafeWrite8(0x42465D, static_cast(WeaponAccurateBonus)); + } + + void setWeaponHandlingBonus(long value) { + if (value < 0) return; + WeaponHandlingBonus = value; + if (WeaponHandlingBonus > 10) WeaponHandlingBonus = 10; + SafeWrite8(0x424636, static_cast(WeaponHandlingBonus)); + SafeWrite8(0x4251CE, static_cast(-WeaponHandlingBonus)); + } + + void setMasterTraderBonus(long value) { + if (value < 0) return; + MasterTraderBonus = static_cast(value); + SafeWrite32(0x474BB3, *(DWORD*)&MasterTraderBonus); // write float data + } + + void setSalesmanBonus(long value) { + if (value < 0) return; + SalesmanBonus = value; + if (SalesmanBonus > 125) SalesmanBonus = 125; + SafeWrite8(0x496F60, static_cast(SalesmanBonus)); + } + + void setLivingAnatomyBonus(long value) { + if (value < 0) return; + LivingAnatomyBonus = value; + if (LivingAnatomyBonus > 125) LivingAnatomyBonus = 125; + SafeWrite8(0x424A91, static_cast(LivingAnatomyBonus)); + } + + void setPyromaniacBonus(long value) { + if (value < 0) return; + PyromaniacBonus = value; + if (PyromaniacBonus > 125) PyromaniacBonus = 125; + SafeWrite8(0x424AB6, static_cast(PyromaniacBonus)); + } + + void setStonewallPercent(long value) { + if (value < 0) return; + StonewallPercent = value; + if (StonewallPercent > 100) StonewallPercent = 100; + SafeWrite8(0x424B50, static_cast(StonewallPercent)); + } + + void setDemolitionExpertBonus(long value) { + if (value < 0) return; + DemolitionExpertBonus = value; + } + + void setVaultCityInoculationsPoisonBonus(long value) { + if (value < -100) value = -100; + if (value > 100) value = 100; + VaultCityInoculationsPoisonBonus = value; + SafeWrite8(0x4AF26A, static_cast(VaultCityInoculationsPoisonBonus)); + } + + void setVaultCityInoculationsRadBonus(long value) { + if (value < -100) value = -100; + if (value > 100) value = 100; + VaultCityInoculationsRadBonus = value; + SafeWrite8(0x4AF287, static_cast(VaultCityInoculationsRadBonus)); + } + +} enginePerks; + +static void __declspec(naked) perk_adjust_skill_hack_salesman() { + __asm { + imul eax, [enginePerks.SalesmanBonus]; + add ecx, eax; // barter_skill + (perkLevel * SalesmanBonus) + mov eax, ecx + retn; + } +} + +static void __declspec(naked) queue_explode_exit_hack_demolition_expert() { + __asm { + imul eax, [enginePerks.DemolitionExpertBonus]; + add ecx, eax; // maxBaseDmg + (perkLevel * DemolitionExpertBonus) + add ebx, eax // minBaseDmg + (perkLevel * DemolitionExpertBonus) + retn; + } +} + +static void EnginePerkBonusInit() { + // Allows the current perk level to affect the calculation of its bonus value + MakeCall(0x496F5E, perk_adjust_skill_hack_salesman); + MakeCall(0x4A289C, queue_explode_exit_hack_demolition_expert, 1); +} + +static void ReadPerksBonuses(const char* perksFile) { + int wScopeRangeMod = iniGetInt("PerksTweak", "WeaponScopeRangePenalty", 8, perksFile); + if (wScopeRangeMod != 8) enginePerks.setWeaponScopeRangePenalty(wScopeRangeMod); + wScopeRangeMod = iniGetInt("PerksTweak", "WeaponScopeRangeBonus", 5, perksFile); + if (wScopeRangeMod != 5) enginePerks.setWeaponScopeRangeBonus(wScopeRangeMod); + + int enginePerkMod = iniGetInt("PerksTweak", "WeaponLongRangeBonus", 4, perksFile); + if (enginePerkMod != 4) enginePerks.setWeaponLongRangeBonus(enginePerkMod); + + enginePerkMod = iniGetInt("PerksTweak", "WeaponAccurateBonus", 20, perksFile); + if (enginePerkMod != 20) enginePerks.setWeaponAccurateBonus(enginePerkMod); + + enginePerkMod = iniGetInt("PerksTweak", "WeaponHandlingBonus", 3, perksFile); + if (enginePerkMod != 3) enginePerks.setWeaponHandlingBonus(enginePerkMod); + + int masterTraderBonus = iniGetInt("PerksTweak", "MasterTraderBonus", 25, perksFile); + if (masterTraderBonus != 25) enginePerks.setMasterTraderBonus(masterTraderBonus); + + int salesmanBonus = iniGetInt("PerksTweak", "SalesmanBonus", 20, perksFile); + if (salesmanBonus != 20) enginePerks.setSalesmanBonus(salesmanBonus); + + int livingAnatomyBonus = iniGetInt("PerksTweak", "LivingAnatomyBonus", 5, perksFile); + if (livingAnatomyBonus != 5) enginePerks.setLivingAnatomyBonus(livingAnatomyBonus); + + int pyromaniacBonus = iniGetInt("PerksTweak", "PyromaniacBonus", 5, perksFile); + if (pyromaniacBonus != 5) enginePerks.setPyromaniacBonus(pyromaniacBonus); + + int stonewallPercent = iniGetInt("PerksTweak", "StonewallPercent", 50, perksFile); + if (stonewallPercent != 50) enginePerks.setStonewallPercent(stonewallPercent); + + int demolitionExpertBonus = iniGetInt("PerksTweak", "DemolitionExpertBonus", 10, perksFile); + if (demolitionExpertBonus != 10) enginePerks.setDemolitionExpertBonus(demolitionExpertBonus); + + int vaultCityInoculationsBonus = iniGetInt("PerksTweak", "VaultCityInoculationsPoisonBonus", 10, perksFile); + if (vaultCityInoculationsBonus != 10) enginePerks.setVaultCityInoculationsPoisonBonus(vaultCityInoculationsBonus); + vaultCityInoculationsBonus = iniGetInt("PerksTweak", "VaultCityInoculationsRadBonus", 10, perksFile); + if (vaultCityInoculationsBonus != 10) enginePerks.setVaultCityInoculationsRadBonus(vaultCityInoculationsBonus); +} + +/////////////////////////////////////////////////////////////////////////////// + static void PerkEngineInit() { + EnginePerkBonusInit(); + // Character screen (list_perks_) HookCall(0x434256, PlayerHasTraitHook); // jz func MakeJump(0x43436B, PlayerHasPerkHack); @@ -1240,25 +1441,6 @@ void Perks_Init() { } // Engine perks settings - long enginePerkMod = iniGetInt("PerksTweak", "WeaponScopeRangePenalty", -1, perksFile); - if (enginePerkMod >= 0 && enginePerkMod != 8) SafeWrite32(0x42448E, enginePerkMod); - enginePerkMod = iniGetInt("PerksTweak", "WeaponScopeRangeBonus", -1, perksFile); - if (enginePerkMod >= 2 && enginePerkMod != 5) SafeWrite32(0x424489, enginePerkMod); - - enginePerkMod = iniGetInt("PerksTweak", "WeaponLongRangeBonus", -1, perksFile); - if (enginePerkMod >= 2 && enginePerkMod != 4) SafeWrite32(0x424474, enginePerkMod); - - enginePerkMod = iniGetInt("PerksTweak", "WeaponAccurateBonus", -1, perksFile); - if (enginePerkMod >= 0 && enginePerkMod != 20) { - if (enginePerkMod > 200) enginePerkMod = 200; - SafeWrite8(0x42465D, static_cast(enginePerkMod)); - } - - enginePerkMod = iniGetInt("PerksTweak", "WeaponHandlingBonus", -1, perksFile); - if (enginePerkMod >= 0 && enginePerkMod != 3) { - if (enginePerkMod > 10) enginePerkMod = 10; - SafeWrite8(0x424636, static_cast(enginePerkMod)); - SafeWrite8(0x4251CE, static_cast(-enginePerkMod)); - } + ReadPerksBonuses(perksFile); } }