From 485816f7300929d8675e1c4ba700f8b830983dba Mon Sep 17 00:00:00 2001 From: 4Luke4 Date: Wed, 6 May 2026 15:03:51 +0200 Subject: [PATCH] Op135 --- EEex/copy/EEex_scripts/EEex_Fix_Patch.lua | 29 +++++++++++++++++++++++ EEex/loader/InfinityLoader.db | 7 ++++++ 2 files changed, 36 insertions(+) diff --git a/EEex/copy/EEex_scripts/EEex_Fix_Patch.lua b/EEex/copy/EEex_scripts/EEex_Fix_Patch.lua index aa42746..be3e28b 100644 --- a/EEex/copy/EEex_scripts/EEex_Fix_Patch.lua +++ b/EEex/copy/EEex_scripts/EEex_Fix_Patch.lua @@ -561,6 +561,35 @@ EEex_JITAt(EEex_Label("Hook-bsearchrange()-FirstInstruction"), {"jmp #L(EEex::Override_bsearchrange)"}) + --[[ + +------------------------------------------------------------------------------------+ + | Fix op135 (CGameEffectPolymorph) form-to-form transition | + | Issue: uses UnequipAll(animationOnly=0) when already polymorphed | + | causing passive equipment bonuses (rings, amulets, etc.) | + | to be stripped instead of preserved. | + | Particularly bad for undroppable items like Edwin's Amulet or Nalia's Ring. | + +------------------------------------------------------------------------------------+ + | Root cause: a JNE at the "is already polymorphed?" check incorrectly | + | skips setting edx=1 (animation-only), so the second | + | polymorph always calls UnequipAll with animationOnly=0. | + | Fix: NOP out the 2-byte JNE (75 02) so animationOnly=1 is always used. | + +------------------------------------------------------------------------------------+ + --]] + + EEex_Utility_NewScope(function() + local jneAddr = EEex_Label("Hook-CGameEffectPolymorph::ApplyEffect()-FormToFormUnequipAllBugJne") + local byte0 = EEex_ReadU8(jneAddr) + if byte0 == 0x90 then return end -- already patched + if byte0 ~= 0x75 then -- sanity: expect JNE short opcode + EEex_Error(string.format( + "[op135 form-to-form bug fix] Unexpected opcode 0x%02X at hook label, cannot patch", + byte0)) + return + end + EEex_WriteU8(jneAddr, 0x90) -- NOP (was 0x75 = JNE short) + EEex_WriteU8(jneAddr + 1, 0x90) -- NOP (was 0x02 = rel8 offset) + end) + EEex_EnableCodeProtection() end)() diff --git a/EEex/loader/InfinityLoader.db b/EEex/loader/InfinityLoader.db index 4dc5798..4a2d021 100644 --- a/EEex/loader/InfinityLoader.db +++ b/EEex/loader/InfinityLoader.db @@ -2207,6 +2207,13 @@ Operations=ADD 25 Pattern=4889742420574883EC30488BF1488BFA Operations=ADD 40 +; op135 (CGameEffectPolymorph) hooks +; Bug fix: form-to-form transition incorrectly calls UnequipAll(animationOnly=0); +; the JNE at this address should be NOP'd so animationOnly=1 is always used. +[Hook-CGameEffectPolymorph::ApplyEffect()-FormToFormUnequipAllBugJne] +Pattern=4C89AC24D00000004533FF +Operations=ADD 64 + [Hook-CGameEffectProtectionCircle::ApplyEffect()-AddTail] Pattern=488D8E001D0000 Operations=ADD 17