diff --git a/artifacts/config_files/Perks.ini b/artifacts/config_files/Perks.ini index 71b50ae0..63a892c8 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/Modules/AI.cpp b/sfall/Modules/AI.cpp index 349095d8..dee6be9f 100644 --- a/sfall/Modules/AI.cpp +++ b/sfall/Modules/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/Modules/Perks.cpp b/sfall/Modules/Perks.cpp index 3a273b0b..86516745 100644 --- a/sfall/Modules/Perks.cpp +++ b/sfall/Modules/Perks.cpp @@ -23,6 +23,8 @@ #include "LoadGameHook.h" #include "PartyControl.h" +#include "SubModules\EnginePerks.h" + #include "Perks.h" namespace sfall @@ -820,6 +822,8 @@ void __stdcall ApplyHeaveHoFix() { // not really a fix } static void PerkEngineInit() { + perk::EnginePerkBonusInit(); + // Character screen (list_perks_) HookCall(0x434256, PlayerHasTraitHook); // jz func MakeJump(0x43436B, PlayerHasPerkHack); @@ -1519,26 +1523,7 @@ 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)); - } + perk::ReadPerksBonuses(perksFile); } } diff --git a/sfall/Modules/SubModules/EnginePerks.cpp b/sfall/Modules/SubModules/EnginePerks.cpp new file mode 100644 index 00000000..9b0b483a --- /dev/null +++ b/sfall/Modules/SubModules/EnginePerks.cpp @@ -0,0 +1,204 @@ +/* + * sfall + * Copyright (C) 2008-2021 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "..\..\main.h" +#include "..\..\FalloutEngine\Fallout2.h" + +#include "EnginePerks.h" + +namespace sfall +{ +namespace perk +{ + +static class EnginePerkBonus { +public: + long WeaponScopeRangePenalty = 8; + long WeaponScopeRangeBonus = 5; + long WeaponLongRangeBonus = 4; + long WeaponAccurateBonus = 20; + long WeaponHandlingBonus = 3; + + float MasterTraderBonus = 25; + long SalesmanBonus = 20; + + 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); + } + + 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)); + } + +} perks; + +static void __declspec(naked) perk_adjust_skill_hack_salesman() { + __asm { + imul eax, [perks.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, [perks.DemolitionExpertBonus]; + add ecx, eax; // maxBaseDmg + (perkLevel * DemolitionExpertBonus) + add ebx, eax // minBaseDmg + (perkLevel * DemolitionExpertBonus) + retn; + } +} + +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 = iniGetInt("PerksTweak", "WeaponScopeRangePenalty", 8, perksFile); + if (wScopeRangeMod != 8) perks.setWeaponScopeRangePenalty(wScopeRangeMod); + wScopeRangeMod = iniGetInt("PerksTweak", "WeaponScopeRangeBonus", 5, perksFile); + if (wScopeRangeMod != 5) perks.setWeaponScopeRangeBonus(wScopeRangeMod); + + int enginePerkMod = iniGetInt("PerksTweak", "WeaponLongRangeBonus", 4, perksFile); + if (enginePerkMod != 4) perks.setWeaponLongRangeBonus(enginePerkMod); + + enginePerkMod = iniGetInt("PerksTweak", "WeaponAccurateBonus", 20, perksFile); + if (enginePerkMod != 20) perks.setWeaponAccurateBonus(enginePerkMod); + + enginePerkMod = iniGetInt("PerksTweak", "WeaponHandlingBonus", 3, perksFile); + if (enginePerkMod != 3) perks.setWeaponHandlingBonus(enginePerkMod); + + int masterTraderBonus = iniGetInt("PerksTweak", "MasterTraderBonus", 25, perksFile); + if (masterTraderBonus != 25) perks.setMasterTraderBonus(masterTraderBonus); + + int salesmanBonus = iniGetInt("PerksTweak", "SalesmanBonus", 20, perksFile); + if (salesmanBonus != 20) perks.setSalesmanBonus(salesmanBonus); + + int livingAnatomyBonus = iniGetInt("PerksTweak", "LivingAnatomyBonus", 5, perksFile); + if (livingAnatomyBonus != 5) perks.setLivingAnatomyBonus(livingAnatomyBonus); + + int pyromaniacBonus = iniGetInt("PerksTweak", "PyromaniacBonus", 5, perksFile); + if (pyromaniacBonus != 5) perks.setPyromaniacBonus(pyromaniacBonus); + + int stonewallPercent = iniGetInt("PerksTweak", "StonewallPercent", 50, perksFile); + if (stonewallPercent != 50) perks.setStonewallPercent(stonewallPercent); + + int demolitionExpertBonus = iniGetInt("PerksTweak", "DemolitionExpertBonus", 10, perksFile); + if (demolitionExpertBonus != 10) perks.setDemolitionExpertBonus(demolitionExpertBonus); + + int vaultCityInoculationsBonus = iniGetInt("PerksTweak", "VaultCityInoculationsPoisonBonus", 10, perksFile); + if (vaultCityInoculationsBonus != 10) perks.setVaultCityInoculationsPoisonBonus(vaultCityInoculationsBonus); + vaultCityInoculationsBonus = iniGetInt("PerksTweak", "VaultCityInoculationsRadBonus", 10, perksFile); + if (vaultCityInoculationsBonus != 10) perks.setVaultCityInoculationsRadBonus(vaultCityInoculationsBonus); +} + +} +} diff --git a/sfall/Modules/SubModules/EnginePerks.h b/sfall/Modules/SubModules/EnginePerks.h new file mode 100644 index 00000000..8e67b687 --- /dev/null +++ b/sfall/Modules/SubModules/EnginePerks.h @@ -0,0 +1,30 @@ +/* + * sfall + * Copyright (C) 2008-2021 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +namespace sfall +{ +namespace perk +{ + +void EnginePerkBonusInit(); +void ReadPerksBonuses(const char* perksFile); + +} +} diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index 3c301a23..64f625dd 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -318,6 +318,7 @@ + @@ -415,6 +416,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 7f60f541..ace745fc 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -307,6 +307,9 @@ Modules + + Modules\SubModules + @@ -568,6 +571,9 @@ Modules + + Modules\SubModules +