diff --git a/EEex/copy/EEex_scripts/EEex_Mix_Patch.lua b/EEex/copy/EEex_scripts/EEex_Mix_Patch.lua index 715689d..02b9d5d 100644 --- a/EEex/copy/EEex_scripts/EEex_Mix_Patch.lua +++ b/EEex/copy/EEex_scripts/EEex_Mix_Patch.lua @@ -12,12 +12,36 @@ -- [Lua] EEex_Opcode_Hook_OnAfterSwingCheckedOp248() -- ------------------------------------------------------- + -- r15 holds the resolved melee target at this point. Let op418 replace it before + -- base weapon damage, weapon on-hit effects, and the existing Lua hooks observe it. EEex_HookAfterCallWithLabels(EEex_Label("Hook-CGameSprite::Swing()-CImmunitiesWeapon::OnList()-Melee"), { - {"hook_integrity_watchdog_ignore_registers", {EEex_HookIntegrityWatchdogRegister.RAX}}}, + {"hook_integrity_watchdog_ignore_registers", {EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.R15}}}, EEex_FlattenTable({ {[[ - #MAKE_SHADOW_SPACE(72) + #MAKE_SHADOW_SPACE(112) + ; Preserve volatile registers across the C++ resolver; this hook runs + ; immediately before the existing Lua calls that still need swing state. mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)], rax + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)], rcx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)], rdx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-32)], r8 + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-40)], r9 + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-48)], r10 + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-56)], r11 + + ; The resolver returns either the original target or the captive that + ; should receive this weapon hit. + mov rcx, r15 + mov rdx, r15 + call #L(EEex::Opcode_Hook_Constrict_ResolveRedirectTarget) + mov r15, rax + + mov r11, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-56)] + mov r10, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-48)] + mov r9, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-40)] + mov r8, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-32)] + mov rdx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)] + mov rcx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)] ]]}, EEex_GenLuaCall("EEex_Sprite_Hook_CheckBlockWeaponHit", { ["labelSuffix"] = "_1", @@ -71,12 +95,36 @@ -- [Lua] EEex_Opcode_Hook_OnAfterSwingCheckedOp249() -- ------------------------------------------------------- + -- r15 is also the live target for the ranged path; redirect it before any later + -- damage/on-hit consumers read the target register. EEex_HookAfterCallWithLabels(EEex_Label("Hook-CGameSprite::Swing()-CImmunitiesWeapon::OnList()-Ranged"), { - {"hook_integrity_watchdog_ignore_registers", {EEex_HookIntegrityWatchdogRegister.RAX}}}, + {"hook_integrity_watchdog_ignore_registers", {EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.R15}}}, EEex_FlattenTable({ {[[ - #MAKE_SHADOW_SPACE(72) + #MAKE_SHADOW_SPACE(112) + ; Preserve volatile registers across the C++ resolver; this hook runs + ; immediately before the existing Lua calls that still need swing state. mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)], rax + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)], rcx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)], rdx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-32)], r8 + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-40)], r9 + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-48)], r10 + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-56)], r11 + + ; The resolver returns either the original target or the captive that + ; should receive this weapon hit. + mov rcx, r15 + mov rdx, r15 + call #L(EEex::Opcode_Hook_Constrict_ResolveRedirectTarget) + mov r15, rax + + mov r11, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-56)] + mov r10, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-48)] + mov r9, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-40)] + mov r8, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-32)] + mov rdx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)] + mov rcx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)] ]]}, EEex_GenLuaCall("EEex_Sprite_Hook_CheckBlockWeaponHit", { ["labelSuffix"] = "_1", diff --git a/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua b/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua index 871cb2f..0c6cee9 100644 --- a/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua +++ b/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua @@ -127,6 +127,33 @@ ]]} ) + --[[ + +--------------------------------------------------------------------------------+ + | Opcode #162 | + +--------------------------------------------------------------------------------+ + | After vanilla Remove Hold clears op109/op175, also release active op418 | + | constricts on the target. | + +--------------------------------------------------------------------------------+ + | [EEex.dll] EEex::Opcode_Hook_RemoveHold_ApplyEffect(pEffect: CGameEffect*, | + | pSprite: CGameSprite*) | + +--------------------------------------------------------------------------------+ + --]] + + EEex_HookAfterRestoreWithLabels(EEex_Label("Hook-CGameEffectRemoveHold::ApplyEffect()-OnDone"), 0, 5, 5, { + {"hook_integrity_watchdog_ignore_registers", { + EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.RCX, EEex_HookIntegrityWatchdogRegister.RDX, + EEex_HookIntegrityWatchdogRegister.R8, EEex_HookIntegrityWatchdogRegister.R9, EEex_HookIntegrityWatchdogRegister.R10, + EEex_HookIntegrityWatchdogRegister.R11 + }}}, + {[[ + #MAKE_SHADOW_SPACE + mov rcx, r14 ; pEffect + mov rdx, rbp ; pSprite + call #L(EEex::Opcode_Hook_RemoveHold_ApplyEffect) + #DESTROY_SHADOW_SPACE + ]]} + ) + --[[ +--------------------------------------------------------------------------------------------------+ | Opcode #214 | @@ -1111,6 +1138,41 @@ ]]}, }) + --[[ + +-------------------------------------------------------------------------------------------------------------+ + | New Opcode #418 (Constrict) | + +-------------------------------------------------------------------------------------------------------------+ + | Hold one victim per source. Victim escape checks start one round after application and repeat each round. | + | Weapon hits against the source can redirect to the held victim based on param2's clamped 0..100 chance. | + +-------------------------------------------------------------------------------------------------------------+ + | [EEex.dll] EEex::Opcode_Hook_Constrict_ApplyEffect(pEffect: CGameEffect*, pSprite: CGameSprite*) -> int | + | return: | + | -> 0 - Halt effect list processing | + | -> !0 - Continue effect list processing | + +-------------------------------------------------------------------------------------------------------------+ + | [EEex.dll] EEex::Opcode_Hook_Constrict_OnRemove(pEffect: CGameEffect*, pSprite: CGameSprite*) | + +-------------------------------------------------------------------------------------------------------------+ + --]] + + local EEex_Constrict = genOpcodeDecode({ + + ["ApplyEffect"] = {[[ + #STACK_MOD(8) ; This was called, the ret ptr broke alignment + #MAKE_SHADOW_SPACE + call #L(EEex::Opcode_Hook_Constrict_ApplyEffect) + #DESTROY_SHADOW_SPACE + ret + ]]}, + + ["OnRemove"] = {[[ + #STACK_MOD(8) ; This was called, the ret ptr broke alignment + #MAKE_SHADOW_SPACE + call #L(EEex::Opcode_Hook_Constrict_OnRemove) + #DESTROY_SHADOW_SPACE + ret + ]]}, + }) + --[[ +-------------------------------------+ | [JIT] Decode switch for new opcodes | @@ -1154,8 +1216,13 @@ _409: cmp eax, 409 - jne #L(jmp_success) + jne _418 ]], EEex_EnableActionListener, [[ + + _418: + cmp eax, 418 + jne #L(jmp_success) + ]], EEex_Constrict, [[ ]]}) ) EEex_HookIntegrityWatchdog_IgnoreStackSizes(EEex_Label("Hook-CGameEffect::DecodeEffect()-DefaultJmp"), {{0x60, 8}}) diff --git a/EEex/loader/InfinityLoader.db b/EEex/loader/InfinityLoader.db index 0b182a9..5d78db1 100644 --- a/EEex/loader/InfinityLoader.db +++ b/EEex/loader/InfinityLoader.db @@ -2251,6 +2251,10 @@ Operations=ADD -43 Pattern=488D8FC81C0000 Operations=ADD 20 +[Hook-CGameEffectRemoveHold::ApplyEffect()-OnDone] +Pattern=33F6488BD841BE01000000 +Operations=ADD -8 + [Hook-CGameEffectSaveVsDeath::ApplyEffect()-ImmediateSaveWriteOffset] Pattern=0F852E0100000FB687AC050000 Operations=ADD -8