Fix NPCAutoLevel and set_npc_level opcode

- Now properly doesn't shift first level up too early and doesn't set "early" flag
- Fixed using set_npc_level without disabling engine leveling logic
- Renamed to PartyMemberNoEarlyLevelUpPatch to match behavior
This commit is contained in:
phobos2077
2024-05-31 17:28:16 +02:00
parent a8ac1f8402
commit 002dfa61cb
4 changed files with 18 additions and 19 deletions
+3 -3
View File
@@ -383,9 +383,9 @@ TownMapHotkeysFix=1
;Set to 1 to disable the Horrigan encounter ;Set to 1 to disable the Horrigan encounter
DisableHorrigan=0 DisableHorrigan=0
;Set to 1 to disable the random element in NPC levelling ;Set to 1 to disable the random element in party member levelling
;This will cause all NPC party members to automatically level up as soon as the player reaches the requirements ;This will prevent party members from randomly leveling up "earlier" and instead level up in defined regular intervals
NPCAutoLevel=0 PartyMemberNoEarlyLevelUp=0
;Change the initial starting location and world map viewport ;Change the initial starting location and world map viewport
;Leave at -1 for default ;Leave at -1 for default
+7 -7
View File
@@ -34,7 +34,6 @@
namespace sfall namespace sfall
{ {
bool npcAutoLevelEnabled;
bool npcEngineLevelUp = true; bool npcEngineLevelUp = true;
static bool isControllingNPC = false; static bool isControllingNPC = false;
@@ -837,11 +836,12 @@ void PartyControl::OrderAttackPatch() {
orderAttackPatch = true; orderAttackPatch = true;
} }
static void NpcAutoLevelPatch() { static void PartyMemberNoEarlyLevelUpPatch() {
npcAutoLevelEnabled = IniReader::GetConfigInt("Misc", "NPCAutoLevel", 0) != 0; if (IniReader::GetConfigInt("Misc", "PartyMemberNoEarlyLevelUp", 0) != 0) {
if (npcAutoLevelEnabled) { dlogr("Applying PartyMemberNoEarlyLevelUp patch.", DL_INIT);
dlogr("Applying NPC autolevel patch.", DL_INIT); // if (numLevels % level_up_every) != 0, skip random "early level up" roll and continue to the next party member instead
SafeWrite8(0x495CFB, CodeType::JumpShort); // jmps 0x495D28 (skip random check) SafeWrite8(0x495CFD, CodeType::Jump); // JMP
SafeWrite32(0x495CFE, 0x14F); // jumps to 0x495E51
} }
} }
@@ -864,7 +864,7 @@ void PartyControl::init() {
0x47136D // right slot 0x47136D // right slot
}); });
NpcAutoLevelPatch(); PartyMemberNoEarlyLevelUpPatch();
// Display party member's current level & AC & addict flag // Display party member's current level & AC & addict flag
if (IniReader::GetConfigInt("Misc", "PartyMemberExtraInfo", 0)) { if (IniReader::GetConfigInt("Misc", "PartyMemberExtraInfo", 0)) {
-1
View File
@@ -42,7 +42,6 @@ public:
static void OrderAttackPatch(); static void OrderAttackPatch();
}; };
extern bool npcAutoLevelEnabled;
extern bool npcEngineLevelUp; extern bool npcEngineLevelUp;
} }
+8 -8
View File
@@ -56,10 +56,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(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(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 SafeMemSet(0x495CE3, CodeType::Nop, 5); // Check if npc had "early" level up before the next scheduled one, resets the "early" flag
if (!npcAutoLevelEnabled) { SafeMemSet(0x495CEC, CodeType::Nop, 6); // Related to above
SafeWrite8(0x495CFB, CodeType::JumpShort); // Disable random element 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 __asm mov dword ptr [ebp + 0x150 - 0x28 + 16], 255; // set counter for exit loop
} else { } else {
if (!onceNpcLoop) { if (!onceNpcLoop) {
@@ -80,16 +79,17 @@ void op_inc_npc_level(OpcodeContext& ctx) {
onceNpcLoop = false; onceNpcLoop = false;
// restore code // restore code
SafeWrite32(0x495BF1 + 1, 0x031352); // restore debug_printf call
SafeWrite32(0x495C50, 0x01FB840F); SafeWrite32(0x495C50, 0x01FB840F);
__int64 data = 0x01D48C0F; __int64 data = 0x01D48C0F;
SafeWriteBytes(0x495C77, (BYTE*)&data, 6); SafeWriteBytes(0x495C77, (BYTE*)&data, 6);
//SafeWrite16(0x495C8C, 0x8D0F); //SafeWrite16(0x495C8C, 0x8D0F);
//SafeWrite32(0x495C8E, 0x000001BF); //SafeWrite32(0x495C8E, 0x000001BF);
data = 0x0130850F; data = 0x0169E9;
SafeWriteBytes(0x495CE3, (BYTE*)&data, 5);
data = 0x015F850F;
SafeWriteBytes(0x495CEC, (BYTE*)&data, 6); SafeWriteBytes(0x495CEC, (BYTE*)&data, 6);
if (!npcAutoLevelEnabled) { SafeWrite8(0x495CFB, CodeType::JumpZ);
SafeWrite8(0x495CFB, CodeType::JumpZ);
}
} }
void op_get_npc_level(OpcodeContext& ctx) { void op_get_npc_level(OpcodeContext& ctx) {