diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 727ddc33..3b432e33 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -386,9 +386,9 @@ TownMapHotkeysFix=1 ;Set to 1 to disable the Horrigan encounter DisableHorrigan=0 -;Set to 1 to disable the random element in NPC levelling -;This will cause all NPC party members to automatically level up as soon as the player reaches the requirements -NPCAutoLevel=0 +;Set to 1 to disable the random element in party member leveling +;This will prevent party members from randomly leveling up 'earlier' and instead level them up at defined regular intervals +PartyMemberNoEarlyLevelUp=0 ;Change the initial starting location and world map viewport ;Leave at -1 for default diff --git a/sfall/Modules/PartyControl.cpp b/sfall/Modules/PartyControl.cpp index 86dd1852..406f967a 100644 --- a/sfall/Modules/PartyControl.cpp +++ b/sfall/Modules/PartyControl.cpp @@ -28,7 +28,6 @@ namespace sfall { -bool npcAutoLevelEnabled; bool npcEngineLevelUp = true; static bool isControllingNPC = false; @@ -692,11 +691,11 @@ void PartyControl::OrderAttackPatch() { orderAttackPatch = true; } -static void NpcAutoLevelPatch() { - npcAutoLevelEnabled = IniReader::GetConfigInt("Misc", "NPCAutoLevel", 0) != 0; - if (npcAutoLevelEnabled) { - dlogr("Applying NPC autolevel patch.", DL_INIT); - SafeWrite8(0x495CFB, CodeType::JumpShort); // jmps 0x495D28 (skip random check) +static void PartyMemberNoEarlyLevelUpPatch() { + if (IniReader::GetConfigInt("Misc", "PartyMemberNoEarlyLevelUp", 0)) { + dlogr("Applying no early level-up patch for party members.", DL_INIT); + __int64 data = 0x014FE9; // jmp 0x495E51 + SafeWriteBytes(0x495CFD, (BYTE*)&data, 5); } } @@ -725,7 +724,7 @@ void PartyControl::init() { const DWORD switchHandAddr[] = {0x4712E3, 0x47136D}; // left slot, right slot HookCalls(inven_pickup_hook, switchHandAddr); // will be overwritten if HOOK_INVENTORYMOVE is injected - NpcAutoLevelPatch(); + PartyMemberNoEarlyLevelUpPatch(); // Display party member's current level & AC & addict flag if (IniReader::GetConfigInt("Misc", "PartyMemberExtraInfo", 0)) { diff --git a/sfall/Modules/PartyControl.h b/sfall/Modules/PartyControl.h index 64ee0831..bf2b56fc 100644 --- a/sfall/Modules/PartyControl.h +++ b/sfall/Modules/PartyControl.h @@ -44,7 +44,6 @@ public: static void OrderAttackPatch(); }; -extern bool npcAutoLevelEnabled; extern bool npcEngineLevelUp; } diff --git a/sfall/Modules/Scripting/Handlers/Objects.cpp b/sfall/Modules/Scripting/Handlers/Objects.cpp index a4479f72..0f941e7e 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.cpp +++ b/sfall/Modules/Scripting/Handlers/Objects.cpp @@ -54,10 +54,9 @@ static void __cdecl IncNPCLevel(const char* fmt, const char* name) { SafeMemSet(0x495C77, CodeType::Nop, 6); // Check that the player is high enough for the npc to consider this level //SafeMemSet(0x495C8C, CodeType::Nop, 6); // Check that the npc isn't already at its maximum level - SafeMemSet(0x495CEC, CodeType::Nop, 6); // Check that the npc hasn't already levelled up recently - if (!npcAutoLevelEnabled) { - SafeWrite8(0x495CFB, CodeType::JumpShort); // Disable random element - } + SafeMemSet(0x495CE3, CodeType::Nop, 5); // Check if npc had "early" level up before the next scheduled one, resets the "early" flag + SafeMemSet(0x495CEC, CodeType::Nop, 6); // Related to above + SafeWrite8(0x495CFB, CodeType::JumpShort); // Skip random roll for early level up __asm mov dword ptr [ebp + 0x150 - 0x28 + 16], 255; // set counter for exit loop } else { if (!onceNpcLoop) { @@ -78,16 +77,17 @@ void op_inc_npc_level(OpcodeContext& ctx) { onceNpcLoop = false; // restore code + SafeWrite32(0x495BF1 + 1, 0x031352); // restore debug_printf call SafeWrite32(0x495C50, 0x01FB840F); __int64 data = 0x01D48C0F; SafeWriteBytes(0x495C77, (BYTE*)&data, 6); //SafeWrite16(0x495C8C, 0x8D0F); //SafeWrite32(0x495C8E, 0x000001BF); - data = 0x0130850F; + data = 0x0169E9; + SafeWriteBytes(0x495CE3, (BYTE*)&data, 5); + data = 0x015F850F; SafeWriteBytes(0x495CEC, (BYTE*)&data, 6); - if (!npcAutoLevelEnabled) { - SafeWrite8(0x495CFB, CodeType::JumpZ); - } + SafeWrite8(0x495CFB, CodeType::JumpZ); } void op_get_npc_level(OpcodeContext& ctx) {