From 23d50410e208192b48d7f7b4eebb8edc6fbca7c8 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Fri, 29 Jan 2021 10:46:14 +0800 Subject: [PATCH] Added SmallFrameFix option Code style edit: use !boolean instead of (boolean == false) for some checks. --- artifacts/ddraw.ini | 3 +++ sfall/FalloutEngine/FunctionOffsets.h | 18 +++++++++--------- sfall/Game/skills.cpp | 16 +++++++--------- sfall/Game/stats.cpp | 22 +++++++++++++++++----- sfall/Modules/HookScripts.cpp | 4 ++-- sfall/Modules/HookScripts/ObjectHs.cpp | 2 +- sfall/Modules/Interface.cpp | 4 ++-- sfall/Modules/PartyControl.cpp | 2 +- sfall/Modules/Perks.cpp | 4 ++++ sfall/Modules/Perks.h | 2 ++ sfall/Modules/ScriptExtender.cpp | 4 ++-- 11 files changed, 50 insertions(+), 31 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 3ef40800..41bb06ed 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -547,6 +547,9 @@ RemoveCriticalTimelimits=0 ;3 - Fallout 1 original behavior: -1 AP cost for all weapons; aimed attacks are disabled FastShotFix=1 +;Set to 1 to fix the carry weight penalty of the Small Frame trait not being applied to bonus Strength points +SmallFrameFix=0 + ;Set to 1 to boost the maximum number of script names from 1450 to 10000 BoostScriptDialogLimit=0 diff --git a/sfall/FalloutEngine/FunctionOffsets.h b/sfall/FalloutEngine/FunctionOffsets.h index 5db69a19..942180d0 100644 --- a/sfall/FalloutEngine/FunctionOffsets.h +++ b/sfall/FalloutEngine/FunctionOffsets.h @@ -19,15 +19,15 @@ #pragma once /* -* HOW TO USE ENGINE FUNCTIONS: -* -* in ASM code, call offsets directly, don't call wrappers as they might not be __stdcall -* in C++ code, use wrappers (add new ones if the don't exist yet, see Wrappers_def.h) -* -* Note: USE C++! -* 1) Place thin __declspec(naked) hooks, only use minimum ASM to pass values to/from C++ -* 2) Call __stdcall functions from (1), write those entirely in C++ (with little ASM blocks only to call engine functions, when you are too lazy to add wrapper) -*/ + * HOW TO USE ENGINE FUNCTIONS: + * + * in ASM code, call offsets directly, don't call wrappers as they might not be __stdcall + * in C++ code, use wrappers (add new ones if the don't exist yet, see Functions_def.h) + * + * Note: USE C++! + * 1) Place thin __declspec(naked) hooks, only use minimum ASM to pass values to/from C++ + * 2) Call __stdcall functions from (1), write those entirely in C++ (with little ASM blocks only to call engine functions, when you are too lazy to add wrapper) + */ namespace fo { diff --git a/sfall/Game/skills.cpp b/sfall/Game/skills.cpp index 72e7e59a..9cd6dbfa 100644 --- a/sfall/Game/skills.cpp +++ b/sfall/Game/skills.cpp @@ -18,21 +18,19 @@ namespace sf = sfall; // TODO: skill_level_, perk_adjust_skill_ -static bool CheckTrait(DWORD traitID) { +static __forceinline bool CheckTrait(DWORD traitID) { return (!sf::Perks::IsTraitDisabled(traitID) && (fo::var::pc_trait[0] == traitID || fo::var::pc_trait[1] == traitID)); } int __stdcall Skills::trait_adjust_skill(DWORD skillID) { int result = 0; - if (fo::var::pc_trait[0] != -1) { - result += sf::Perks::GetTraitSkillBonus(skillID, 0); - } - if (fo::var::pc_trait[1] != -1) { - result += sf::Perks::GetTraitSkillBonus(skillID, 1); - } - if (CheckTrait(fo::TRAIT_gifted)) { - result -= 10; + if (sf::Perks::TraitsModEnable()) { + if (fo::var::pc_trait[0] != -1) result += sf::Perks::GetTraitSkillBonus(skillID, 0); + if (fo::var::pc_trait[1] != -1) result += sf::Perks::GetTraitSkillBonus(skillID, 1); } + + if (CheckTrait(fo::TRAIT_gifted)) result -= 10; + if (CheckTrait(fo::TRAIT_good_natured)) { if (skillID <= fo::SKILL_THROWING) { result -= 10; diff --git a/sfall/Game/stats.cpp b/sfall/Game/stats.cpp index e2663301..46ddbb5e 100644 --- a/sfall/Game/stats.cpp +++ b/sfall/Game/stats.cpp @@ -16,11 +16,13 @@ namespace game namespace sf = sfall; +static bool smallFrameTraitFix = false; + static int DudeGetBaseStat(DWORD statID) { return fo::func::stat_get_base_direct(fo::var::obj_dude, statID); } -static bool CheckTrait(DWORD traitID) { +static __forceinline bool CheckTrait(DWORD traitID) { return (!sf::Perks::IsTraitDisabled(traitID) && (fo::var::pc_trait[0] == traitID || fo::var::pc_trait[1] == traitID)); } @@ -28,8 +30,10 @@ int __stdcall Stats::trait_adjust_stat(DWORD statID) { if (statID > fo::STAT_max_derived) return 0; int result = 0; - if (fo::var::pc_trait[0] != -1) result += sf::Perks::GetTraitStatBonus(statID, 0); - if (fo::var::pc_trait[1] != -1) result += sf::Perks::GetTraitStatBonus(statID, 1); + if (sf::Perks::TraitsModEnable()) { + if (fo::var::pc_trait[0] != -1) result += sf::Perks::GetTraitStatBonus(statID, 0); + if (fo::var::pc_trait[1] != -1) result += sf::Perks::GetTraitStatBonus(statID, 1); + } switch (statID) { case fo::STAT_st: @@ -66,8 +70,13 @@ int __stdcall Stats::trait_adjust_stat(DWORD statID) { break; case fo::STAT_carry_amt: if (CheckTrait(fo::TRAIT_small_frame)) { - int str = DudeGetBaseStat(fo::STAT_st); - result -= str * 10; + int st; + if (smallFrameTraitFix) { + st = fo::func::stat_level(fo::var::obj_dude, fo::STAT_st); + } else { + st = DudeGetBaseStat(fo::STAT_st); + } + result -= st * 10; } break; case fo::STAT_sequence: @@ -107,6 +116,9 @@ static void __declspec(naked) trait_adjust_stat_hack() { void Stats::init() { // Replace functions sf::MakeJump(fo::funcoffs::trait_adjust_stat_, trait_adjust_stat_hack); // 0x4B3C7C + + // Fix the carry weight penalty of the Small Frame trait not being applied to bonus Strength points + smallFrameTraitFix = (sf::GetConfigInt("Misc", "SmallFrameFix", 0) != 0); } } diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index 7ec62742..cfd39322 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -111,7 +111,7 @@ static HooksInjectInfo injectHooks[] = { }; void HookScripts::InjectingHook(int hookId) { - if (IsInjectHook(hookId) == false && injectHooks[hookId].id == hookId) { + if (!IsInjectHook(hookId) && injectHooks[hookId].id == hookId) { injectHooks[hookId].injectState = 2; injectHooks[hookId].inject(); devlog_f("Inject hook ID: %d\n", DL_INIT, hookId); @@ -123,7 +123,7 @@ bool HookScripts::IsInjectHook(int hookId) { } bool HookScripts::HookHasScript(int hookId) { - return (hooks[hookId].empty() == false); + return (!hooks[hookId].empty()); } void HookScripts::RegisterHook(fo::Program* script, int id, int procNum, bool specReg) { diff --git a/sfall/Modules/HookScripts/ObjectHs.cpp b/sfall/Modules/HookScripts/ObjectHs.cpp index 79b9e68a..9494a527 100644 --- a/sfall/Modules/HookScripts/ObjectHs.cpp +++ b/sfall/Modules/HookScripts/ObjectHs.cpp @@ -332,7 +332,7 @@ static void __declspec(naked) critter_adjust_poison_hack() { } static DWORD __fastcall AdjustRads_Script(DWORD critter, long amount) { - if (HookScripts::HookHasScript(HOOK_ADJUSTRADS) == false) return amount; + if (!HookScripts::HookHasScript(HOOK_ADJUSTRADS)) return amount; BeginHook(); argCount = 2; diff --git a/sfall/Modules/Interface.cpp b/sfall/Modules/Interface.cpp index 2c12ce29..d5033dbc 100644 --- a/sfall/Modules/Interface.cpp +++ b/sfall/Modules/Interface.cpp @@ -981,8 +981,8 @@ void Interface::init() { } // Corrects the height of the black background for death screen subtitles - if (hrpIsEnabled == false) SafeWrite32(0x48134D, 38 - (640 * 3)); // main_death_scene_ (shift y-offset 2px up, w/o HRP) - if (hrpIsEnabled == false || hrpVersionValid) SafeWrite8(0x481345, 4); // main_death_scene_ + if (!hrpIsEnabled) SafeWrite32(0x48134D, 38 - (640 * 3)); // main_death_scene_ (shift y-offset 2px up, w/o HRP) + if (!hrpIsEnabled || hrpVersionValid) SafeWrite8(0x481345, 4); // main_death_scene_ if (hrpVersionValid) SafeWrite8(HRPAddress(0x10011738), 10); // Cosmetic fix for the background image of the character portrait on the player's inventory screen diff --git a/sfall/Modules/PartyControl.cpp b/sfall/Modules/PartyControl.cpp index 3786593d..15cef0c0 100644 --- a/sfall/Modules/PartyControl.cpp +++ b/sfall/Modules/PartyControl.cpp @@ -555,7 +555,7 @@ void PartyControl::SwitchToCritter(fo::GameObject* critter) { if (critter == nullptr || critter == realDude.obj_dude) RestoreRealDudeState(); // return control to dude } if (critter != nullptr && critter != PartyControl::RealDudeObject()) { - if (!isControllingNPC && realDude.isSaved == false) { + if (!isControllingNPC && !realDude.isSaved) { SaveRealDudeState(); } SetCurrentDude(critter); diff --git a/sfall/Modules/Perks.cpp b/sfall/Modules/Perks.cpp index d47db8c9..64862070 100644 --- a/sfall/Modules/Perks.cpp +++ b/sfall/Modules/Perks.cpp @@ -981,6 +981,10 @@ static void PerkSetup() { /////////////////////////// TRAIT FUNCTIONS /////////////////////////////////// +int Perks::TraitsModEnable() { + return traitsEnable; +} + bool Perks::IsTraitDisabled(int traitID) { return disableTraits[traitID]; } diff --git a/sfall/Modules/Perks.h b/sfall/Modules/Perks.h index e2ecbd82..1c555e5d 100644 --- a/sfall/Modules/Perks.h +++ b/sfall/Modules/Perks.h @@ -28,6 +28,8 @@ public: const char* name() { return "Perks"; } void init(); + // Enable the modifications for traits by using the perks ini file + static int TraitsModEnable(); static bool IsTraitDisabled(int traitID); static DWORD GetTraitStatBonus(int statID, int traitIndex); static DWORD GetTraitSkillBonus(int skillID, int traitIndex); diff --git a/sfall/Modules/ScriptExtender.cpp b/sfall/Modules/ScriptExtender.cpp index a9203c70..42865a12 100644 --- a/sfall/Modules/ScriptExtender.cpp +++ b/sfall/Modules/ScriptExtender.cpp @@ -675,7 +675,7 @@ static DWORD HandleTimedEventScripts() { bool eventWasRunning = false; for (auto timerIt = timerEventScripts.cbegin(); timerIt != timerEventScripts.cend(); ++timerIt) { - if (timerIt->isActive == false) continue; + if (!timerIt->isActive) continue; if (currentTime >= timerIt->time) { if (timedEvent) executeTimedEvents.push(timedEvent); // store a pointer to the currently running event @@ -702,7 +702,7 @@ static DWORD HandleTimedEventScripts() { timedEvent = nullptr; // delete all previously executed events for (auto it = timerEventScripts.cbegin(); it != timerEventScripts.cend();) { - if (it->isActive == false) { + if (!it->isActive) { fo::func::dev_printf("\n[TimedEventScripts] Remove event: %d", it->time); it = timerEventScripts.erase(it); } else {