From cd5c80338630a56c29a32e91e45a779946ff130e Mon Sep 17 00:00:00 2001 From: phobos2077 Date: Sun, 30 Jul 2023 19:58:34 +0200 Subject: [PATCH] EnginePerks: rewritten and expanded - Got rid of unused and repeated code - Added all perk skill bonuses --- artifacts/config_files/Perks.ini | 63 ++++++- sfall/Modules/SubModules/EnginePerks.cpp | 219 ++++++++--------------- sfall/Utils.h | 7 + 3 files changed, 143 insertions(+), 146 deletions(-) diff --git a/artifacts/config_files/Perks.ini b/artifacts/config_files/Perks.ini index 0ff4861b..1176265c 100644 --- a/artifacts/config_files/Perks.ini +++ b/artifacts/config_files/Perks.ini @@ -34,9 +34,10 @@ VaultCityInoculationsRadBonus=10 ;999 - maximum bonus, 10 - default bonus DemolitionExpertBonus=10 -;Changes the damage bonus for 'Living Anatomy' perk (ID 97) -;125 - maximum bonus, 5 - default bonus +;Changes the damage bonus and Doctor Skill for 'Living Anatomy' perk (ID 97) +;125 - maximum bonus, 5 - default bonus, 10 - default skill bonus LivingAnatomyBonus=5 +LivingAnatomyDoctorBonus=10 ;Changes the damage bonus for 'Pyromaniac' perk (ID 101) ;125 - maximum bonus, 5 - default bonus @@ -54,6 +55,64 @@ StonewallPercent=50 ;0 - no bonus, 10 - maximum bonus, 3 - default bonus WeaponHandlingBonus=3 +;Changes the Skill bonuses for 'Medic' perk (ID 32) +;125 - maximum bonus, 10 - default bonus +MedicFirstAidBonus=10 +MedicDoctorBonus=10 + +;Changes the Skill bonuses for 'Vault City Training' perk (ID 107) +;125 - maximum bonus, 5 - default bonus +VaultCityTrainingFirstAidBonus=5 +VaultCityTrainingDoctorBonus=5 + +;Changes the Sneak skill bonus for 'Ghost' perk (ID 38) +;125 - maximum bonus, 20 - default bonus +GhostSneakBonus=20 + +;Changes the Lockpick, Steal and Traps skill bonus for 'Thief' perk (ID 105) +;125 - maximum bonus, 10 - default bonus +ThiefSkillsBonus=10 + +;Changes the Lockpick and Steal skill bonus for 'Master Thief' perk (ID 3) +;125 - maximum bonus, 15 - default bonus +MasterThiefSkillsBonus=15 + +;Changes the Steal skill bonus for 'Harmless' perk (ID 91) +;125 - maximum bonus, 20 - default bonus +HarmlessStealBonus=20 + +;Changes the Speech skill bonus for 'Speaker' perk (ID 34) +;125 - maximum bonus, 20 - default bonus +SpeakerSpeechBonus=20 + +;Changes the Speech skill bonus for 'Expert Excrement Expeditor' perk (ID 116) +;125 - maximum bonus, 5 - default bonus +ExpertExcrementExpeditorSpeechBonus=5 + +;Changes the Speech and Barter skill bonus for 'Negotiator' perk (ID 99) +;125 - maximum bonus, 10 - default bonus +NegotiatorSkillsBonus=10 + +;Changes the Barter skill bonus for 'Salesman' perk (ID 103) +;125 - maximum bonus, 20 - default bonus +SalesmanBarterBonus=20 + +;Changes the Gambling skill bonus for 'Gambler' perk (ID 83) +;125 - maximum bonus, 20 - default bonus +GamblerGamblingBonus=20 + +;Changes the Outdoorsman skill bonus for 'Ranger' perk (ID 47) +;125 - maximum bonus, 15 - default bonus +RangerOutdoorsmanBonus=15 + +;Changes the Outdoorsman skill bonus for 'Survivalist' perk (ID 16) +;125 - maximum bonus, 25 - default bonus +SurvivalistOutdoorsmanBonus=25 + +;Changes the Science and Repair skill bonus for 'Mr.Fixit' perk (ID 31) +;125 - maximum bonus, 10 - default bonus +MrFixitSkillsBonus=10 + ;############################################################################## [Perks] ;Set to 1 to enable the modifications for perks diff --git a/sfall/Modules/SubModules/EnginePerks.cpp b/sfall/Modules/SubModules/EnginePerks.cpp index e90f29e0..a90f8976 100644 --- a/sfall/Modules/SubModules/EnginePerks.cpp +++ b/sfall/Modules/SubModules/EnginePerks.cpp @@ -17,6 +17,7 @@ */ #include "..\..\main.h" +#include "..\..\Utils.h" #include "..\..\FalloutEngine\Fallout2.h" #include "EnginePerks.h" @@ -26,120 +27,39 @@ namespace sfall namespace perk { -static class EnginePerkBonus { -public: - long WeaponScopeRangePenalty = 8; - long WeaponScopeRangeBonus = 5; - long WeaponLongRangeBonus = 4; - long WeaponAccurateBonus = 20; - long WeaponHandlingBonus = 3; +static long SalesmanBonus; +static long DemolitionExpertBonus; - float MasterTraderBonus = 25; - long SalesmanBonus = 20; +static bool TryGetModifiedInt(const char* key, int defaultValue, int& outValue, const char* perksFile) { + outValue = IniReader::GetInt("PerksTweak", key, defaultValue, perksFile); + return outValue != defaultValue; +} - long LivingAnatomyBonus = 5; - long PyromaniacBonus = 5; - - long StonewallPercent = 50; - - long DemolitionExpertBonus = 10; - - long VaultCityInoculationsPoisonBonus = 10; - long VaultCityInoculationsRadBonus = 10; - - /////////////////////////////////////////// - - void setWeaponScopeRangePenalty(long value) { - if (value < 0) return; - WeaponScopeRangePenalty = value; - SafeWrite32(0x42448E, value); +static void TryPatchValue8(const char* key, int defaultValue, int minValue, int maxValue, DWORD addr, const char* perksFile) { + int value; + if (TryGetModifiedInt(key, defaultValue, value, perksFile) && value >= minValue) { + SafeWrite8(addr, static_cast(min(value, maxValue))); } +} - void setWeaponScopeRangeBonus(long value) { - if (value < 2) return; - WeaponScopeRangeBonus = value; - SafeWrite32(0x424489, value); +static void TryPatchValue32(const char* key, int defaultValue, int minValue, int maxValue, DWORD addr, const char* perksFile) { + int value; + if (TryGetModifiedInt(key, defaultValue, value, perksFile) && value >= minValue) { + SafeWrite32(addr, min(value, maxValue)); } +} - void setWeaponLongRangeBonus(long value) { - if (value < 2) return; - WeaponLongRangeBonus = value; - SafeWrite32(0x424474, value); - } +static void TryPatchSkillBonus8(const char* key, int defaultValue, DWORD addr, const char* perksFile) { + TryPatchValue8(key, defaultValue, 0, 125, addr, perksFile); +} - 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 > 999) SalesmanBonus = 999; - } - - 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; - if (DemolitionExpertBonus > 999) DemolitionExpertBonus = 999; - } - - 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)); - } - -} perks; +static void TryPatchSkillBonus32(const char* key, int defaultValue, DWORD addr, const char* perksFile) { + TryPatchValue32(key, defaultValue, 0, 125, addr, perksFile); +} static void __declspec(naked) perk_adjust_skill_hack_salesman() { __asm { - imul eax, [perks.SalesmanBonus]; + imul eax, [SalesmanBonus]; add ecx, eax; // barter_skill + (perkLevel * SalesmanBonus) mov eax, ecx retn; @@ -148,7 +68,7 @@ static void __declspec(naked) perk_adjust_skill_hack_salesman() { static void __declspec(naked) queue_explode_exit_hack_demolition_expert() { __asm { - imul eax, [perks.DemolitionExpertBonus]; + imul eax, [DemolitionExpertBonus]; add ecx, eax; // maxBaseDmg + (perkLevel * DemolitionExpertBonus) add ebx, eax // minBaseDmg + (perkLevel * DemolitionExpertBonus) retn; @@ -156,48 +76,59 @@ static void __declspec(naked) queue_explode_exit_hack_demolition_expert() { } 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); + } - void ReadPerksBonuses(const char* perksFile) { - int wScopeRangeMod = IniReader::GetInt("PerksTweak", "WeaponScopeRangePenalty", 8, perksFile); - if (wScopeRangeMod != 8) perks.setWeaponScopeRangePenalty(wScopeRangeMod); - wScopeRangeMod = IniReader::GetInt("PerksTweak", "WeaponScopeRangeBonus", 5, perksFile); - if (wScopeRangeMod != 5) perks.setWeaponScopeRangeBonus(wScopeRangeMod); + int value; + TryPatchValue32("WeaponScopeRangePenalty", 8, 0, 100, 0x42448E, perksFile); + TryPatchValue32("WeaponScopeRangeBonus", 5, 2, 100, 0x424489, perksFile); + TryPatchValue32("WeaponLongRangeBonus", 4, 2, 100, 0x424474, perksFile); + TryPatchSkillBonus8("WeaponAccurateBonus", 20, 0x42465D, perksFile); + if (TryGetModifiedInt("WeaponHandlingBonus", 3, value, perksFile) && value >= 0) { + if (value > 10) value = 10; + SafeWrite8(0x424636, static_cast(value)); + SafeWrite8(0x4251CE, static_cast(-value)); + } + if (TryGetModifiedInt("MasterTraderBonus", 25, value, perksFile) && value >= 0) { + float floatValue = static_cast(value); + SafeWrite32(0x474BB3, *(DWORD*)&floatValue); // write float data + } + if (TryGetModifiedInt("SalesmanBonus", 20, value, perksFile) && value >= 0) { + SalesmanBonus = min(value, 999); + // Allows the current perk level to affect the calculation of its bonus value + MakeCall(0x496F5E, perk_adjust_skill_hack_salesman); + } + TryPatchSkillBonus8("LivingAnatomyBonus", 5, 0x424A91, perksFile); + TryPatchSkillBonus8("LivingAnatomyDoctorBonus", 10, 0x496E66, perksFile); + TryPatchSkillBonus8("PyromaniacBonus", 5, 0x424AB6, perksFile); + TryPatchValue8("StonewallPercent", 50, 0, 100, 0x424B50, perksFile); + if (TryGetModifiedInt("DemolitionExpertBonus", 10, value, perksFile) && value >= 0) { + DemolitionExpertBonus = min(value, 999); + MakeCall(0x4A289C, queue_explode_exit_hack_demolition_expert, 1); + } + if (TryGetModifiedInt("VaultCityInoculationsPoisonBonus", 10, value, perksFile)) { + SafeWrite8(0x4AF26A, static_cast(clamp(value, -100, 100))); + } + if (TryGetModifiedInt("VaultCityInoculationsRadBonus", 10, value, perksFile)) { + SafeWrite8(0x4AF287, static_cast(clamp(value, -100, 100))); + } + TryPatchSkillBonus8("VaultCityTrainingFirstAidBonus", 5, 0x496E35, perksFile); + TryPatchSkillBonus8("VaultCityTrainingDoctorBonus", 5, 0x496E7F, perksFile); + TryPatchSkillBonus32("MedicFirstAidBonus", 10, 0x496E19, perksFile); + TryPatchSkillBonus32("MedicDoctorBonus", 10, 0x496E4E, perksFile); - int wLongRangeBonus = IniReader::GetInt("PerksTweak", "WeaponLongRangeBonus", 4, perksFile); - if (wLongRangeBonus != 4) perks.setWeaponLongRangeBonus(wLongRangeBonus); - - int wAccurateBonus = IniReader::GetInt("PerksTweak", "WeaponAccurateBonus", 20, perksFile); - if (wAccurateBonus != 20) perks.setWeaponAccurateBonus(wAccurateBonus); - - int wHandlingBonus = IniReader::GetInt("PerksTweak", "WeaponHandlingBonus", 3, perksFile); - if (wHandlingBonus != 3) perks.setWeaponHandlingBonus(wHandlingBonus); - - int masterTraderBonus = IniReader::GetInt("PerksTweak", "MasterTraderBonus", 25, perksFile); - if (masterTraderBonus != 25) perks.setMasterTraderBonus(masterTraderBonus); - - int salesmanBonus = IniReader::GetInt("PerksTweak", "SalesmanBonus", 20, perksFile); - if (salesmanBonus != 20) perks.setSalesmanBonus(salesmanBonus); - - int livingAnatomyBonus = IniReader::GetInt("PerksTweak", "LivingAnatomyBonus", 5, perksFile); - if (livingAnatomyBonus != 5) perks.setLivingAnatomyBonus(livingAnatomyBonus); - - int pyromaniacBonus = IniReader::GetInt("PerksTweak", "PyromaniacBonus", 5, perksFile); - if (pyromaniacBonus != 5) perks.setPyromaniacBonus(pyromaniacBonus); - - int stonewallPercent = IniReader::GetInt("PerksTweak", "StonewallPercent", 50, perksFile); - if (stonewallPercent != 50) perks.setStonewallPercent(stonewallPercent); - - int demolitionExpertBonus = IniReader::GetInt("PerksTweak", "DemolitionExpertBonus", 10, perksFile); - if (demolitionExpertBonus != 10) perks.setDemolitionExpertBonus(demolitionExpertBonus); - - int vaultCityInoculationsBonus = IniReader::GetInt("PerksTweak", "VaultCityInoculationsPoisonBonus", 10, perksFile); - if (vaultCityInoculationsBonus != 10) perks.setVaultCityInoculationsPoisonBonus(vaultCityInoculationsBonus); - vaultCityInoculationsBonus = IniReader::GetInt("PerksTweak", "VaultCityInoculationsRadBonus", 10, perksFile); - if (vaultCityInoculationsBonus != 10) perks.setVaultCityInoculationsRadBonus(vaultCityInoculationsBonus); + TryPatchSkillBonus32("GhostSneakBonus", 20, 0x496EA9, perksFile); + TryPatchSkillBonus8("ThiefSkillsBonus", 10, 0x496EC1, perksFile); + TryPatchSkillBonus8("MasterThiefSkillsBonus", 15, 0x496EE0, perksFile); + TryPatchSkillBonus8("HarmlessStealBonus", 20, 0x496F02, perksFile); + TryPatchSkillBonus32("SpeakerSpeechBonus", 20, 0x496F1B, perksFile); + TryPatchSkillBonus8("ExpertExcrementExpeditorSpeechBonus", 5, 0x496F33, perksFile); + TryPatchSkillBonus8("NegotiatorSkillsBonus", 10, 0x496F48, perksFile); + TryPatchSkillBonus8("SalesmanBarterBonus", 20, 0x496F60, perksFile); + TryPatchSkillBonus32("GamblerGamblingBonus", 20, 0x496F79, perksFile); + TryPatchSkillBonus32("RangerOutdoorsmanBonus", 15, 0x496F95, perksFile); + TryPatchSkillBonus8("SurvivalistOutdoorsmanBonus", 25, 0x496FAB, perksFile); + TryPatchSkillBonus8("MrFixitSkillsBonus", 10, 0x496E00, perksFile); } } diff --git a/sfall/Utils.h b/sfall/Utils.h index a0666dd1..a376a0c5 100644 --- a/sfall/Utils.h +++ b/sfall/Utils.h @@ -21,6 +21,13 @@ void split(const std::string &s, char delim, T result, size_t limit = -1) { } } +template +T clamp(T value, T min, T max) { + if (value < min) return min; + if (value > max) return max; + return value; +} + WORD ByteSwapW(WORD w); DWORD ByteSwapD(DWORD dw);