From 56a5db9c41e595d64268f7921c9eecc2573ae03d Mon Sep 17 00:00:00 2001 From: 4Luke4 Date: Mon, 8 Jun 2026 12:37:06 +0200 Subject: [PATCH 1/2] Weapon Style utils --- EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua | 64 ++++++++++++++- EEex/copy/EEex_scripts/EEex_Sprite.lua | 23 ++++++ EEex/copy/EEex_scripts/EEex_Sprite_Patch.lua | 85 ++++++++++++++++++++ EEex/loader/InfinityLoader.db | 32 ++++++++ 4 files changed, 200 insertions(+), 4 deletions(-) diff --git a/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua b/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua index 871cb2f..85a6344 100644 --- a/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua +++ b/EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua @@ -85,6 +85,56 @@ -- Opcode Changes -- -------------------------------------- + --[[ + +-----------------------------------------------------------------------------------------------------------+ + | Opcode #73 | + +-----------------------------------------------------------------------------------------------------------+ + | special bit0 -> Apply to main-hand damage bonus only | + | special bit1 -> Apply to off-hand damage bonus only | + | special 0 or both bits -> Vanilla opcode #73 behavior | + +-----------------------------------------------------------------------------------------------------------+ + | [EEex.dll] EEex::Opcode_Hook_DamageMod_ApplyEffect(pEffect: CGameEffect*, pSprite: CGameSprite*) -> int | + | return: | + | -> 0 - Don't alter engine behavior | + | -> !0 - Effect was handled | + +-----------------------------------------------------------------------------------------------------------+ + --]] + + EEex_HookBeforeRestoreWithLabels(EEex_Label("Hook-CGameEffectDamageMod::ApplyEffect()-FirstInstruction"), 0, 7, 7, { + {"stack_mod", 8}, + {"hook_integrity_watchdog_ignore_registers", { + EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.R8, EEex_HookIntegrityWatchdogRegister.R9, + EEex_HookIntegrityWatchdogRegister.R10, EEex_HookIntegrityWatchdogRegister.R11 + }}}, + {[[ + #MAKE_SHADOW_SPACE(16) + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)], rcx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)], rdx + + ; rcx already pEffect + ; rdx already pSprite + call #L(EEex::Opcode_Hook_DamageMod_ApplyEffect) + + mov rdx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)] + mov rcx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)] + #DESTROY_SHADOW_SPACE + + test eax, eax + jz #L(return) + + mov eax, 1 + #MANUAL_HOOK_EXIT(1) + ret + ]]} + ) + + -- Manually define the ignored registers for the unusual `ret` above + EEex_HookIntegrityWatchdog_IgnoreRegistersForInstance(EEex_Label("Hook-CGameEffectDamageMod::ApplyEffect()-FirstInstruction"), 1, { + EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.RCX, EEex_HookIntegrityWatchdogRegister.RDX, + EEex_HookIntegrityWatchdogRegister.R8, EEex_HookIntegrityWatchdogRegister.R9, EEex_HookIntegrityWatchdogRegister.R10, + EEex_HookIntegrityWatchdogRegister.R11 + }) + --[[ +------------------------------------------------------------------------------------+ | Opcode #146 | @@ -580,11 +630,17 @@ | param2 == 5 -> Override `combat_round_` in animation INI to `resource`: | | param1 -> Combat round slot | | resource -> Resref of RNDBASE*-like .BMP | + | special bit0 -> Tag repeated offhand frame type 11 attacks for THAC0 adjustment | + | param3 -> Direct THAC0 delta for tagged repeated offhand attacks | +------------------------------------------------------------------------------------------------------+ | [EEex.dll] EEex::Opcode_Hook_Op342_OnUnhandledParam2(pEffect: CGameEffect*, pSprite: CGameSprite*) | | | | [EEex.dll] EEex::Sprite_Hook_OnGetAttackFrameType(pSprite: CGameSprite*, numAttacks: byte) -> byte | | return: Palette index of fetched pixel in RNDBASE*-like .BMP | + | [EEex.dll] EEex::Sprite_Hook_OnSwingGetAttackFrameType( | + | pSprite: CGameSprite*, numAttacks: byte | + | ) -> byte | + | return: Palette index of fetched pixel in RNDBASE*-like .BMP | +------------------------------------------------------------------------------------------------------+ --]] @@ -601,7 +657,7 @@ ]]} ) - local patchGetAttackFrameType = function(label, spriteRegister) + local patchGetAttackFrameType = function(label, spriteRegister, hookLabel) EEex_HookNOPsWithLabels(EEex_Label(label), 1, { {"hook_integrity_watchdog_ignore_registers", { EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.RCX, EEex_HookIntegrityWatchdogRegister.RDX, @@ -611,13 +667,13 @@ {[[ mov rcx, #$(1) ]], {spriteRegister}, [[ #ENDL ; pSprite ; dl already numAttacks - call #L(EEex::Sprite_Hook_OnGetAttackFrameType) + call #L(]] .. hookLabel .. [[) ]]} ) end - patchGetAttackFrameType("Hook-CGameSprite::OneSwing()-GetAttackFrameType()", "rdi") - patchGetAttackFrameType("Hook-CGameSprite::Swing()-GetAttackFrameType()", "rbx") + patchGetAttackFrameType("Hook-CGameSprite::OneSwing()-GetAttackFrameType()", "rdi", "EEex::Sprite_Hook_OnGetAttackFrameType") + patchGetAttackFrameType("Hook-CGameSprite::Swing()-GetAttackFrameType()", "rbx", "EEex::Sprite_Hook_OnSwingGetAttackFrameType") --[[ +------------------------------------------------------------------------------------------------+ diff --git a/EEex/copy/EEex_scripts/EEex_Sprite.lua b/EEex/copy/EEex_scripts/EEex_Sprite.lua index b2d8d93..651e100 100644 --- a/EEex/copy/EEex_scripts/EEex_Sprite.lua +++ b/EEex/copy/EEex_scripts/EEex_Sprite.lua @@ -548,6 +548,29 @@ function EEex_Sprite_GetActiveStats(sprite) end CGameSprite.getActiveStats = EEex_Sprite_GetActiveStats +-- @bubb_doc { EEex_Sprite_GetWeaponStyle / instance_name=getWeaponStyle } +-- +-- @summary: +-- +-- Returns the given ``sprite``'s currently active weapon style, the active rank for that style, and the original +-- rank recorded on the creature before active stat and effect modification. +-- +-- ``style`` is the engine stat id for the active weapon style. For example, the two-weapon style is +-- ``PROFICIENCY2WEAPON``. +-- +-- If ``sprite`` is invalid, returns ``-1``, ``0``, and ``0`` respectively. +-- +-- @self { sprite / type=CGameSprite }: The sprite whose weapon style is being fetched. +-- +-- @return { type=number }: First return value; the active weapon style stat id. +-- @return { type=number }: Second return value; the active rank for ``style`` after derived-stat effects are applied. +-- @return { type=number }: Third return value; the original rank for ``style`` from the creature's weapon proficiency list. + +function EEex_Sprite_GetWeaponStyle(sprite) + return EEex.GetWeaponStyle(sprite) +end +CGameSprite.getWeaponStyle = EEex_Sprite_GetWeaponStyle + -- @bubb_doc { EEex_Sprite_GetExtendedStat / instance_name=getExtendedStat } -- @deprecated: Use ``EEex_Sprite_GetStat()`` instead. -- @summary: Returns the value of the extended stat on the given ``sprite``. diff --git a/EEex/copy/EEex_scripts/EEex_Sprite_Patch.lua b/EEex/copy/EEex_scripts/EEex_Sprite_Patch.lua index 8a9fd16..f6fa04b 100644 --- a/EEex/copy/EEex_scripts/EEex_Sprite_Patch.lua +++ b/EEex/copy/EEex_scripts/EEex_Sprite_Patch.lua @@ -641,6 +641,50 @@ EEex_HookIntegrityWatchdogRegister.R11 }) + local adjustDisplayedDamage = function(label) + EEex_HookBeforeRestoreWithLabels(EEex_Label(label), 0, 7, 7, { + {"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 + }}}, + {[[ + mov r9d, dword ptr ss:[rsp+0xF8] ; saved hand argument + #MAKE_SHADOW_SPACE + mov rcx, rdi ; pSprite + mov rdx, r13 ; pItem + mov r8d, eax ; displayed damage + call #L(EEex::Sprite_Hook_AdjustDisplayedDamage) + #DESTROY_SHADOW_SPACE + ]]} + ) + end + + adjustDisplayedDamage("Hook-CGameSprite::GetMaxDamage()-AdjustDisplayedDamage") + adjustDisplayedDamage("Hook-CGameSprite::GetMinDamage()-AdjustDisplayedDamage") + + EEex_HookBeforeCallWithLabels(EEex_Label("Hook-CGameSprite::Damage()-AdjustRollHandBonus"), { + {"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(24) + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)], rcx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)], rdx + mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)], r9 + mov edx, r8d ; handBonus + mov rcx, rdi ; pSprite + call #L(EEex::Sprite_Hook_AdjustDamageRollHandBonus) + mov r8d, eax + mov r9, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)] + mov rdx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)] + mov rcx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)] + #DESTROY_SHADOW_SPACE + ]]} + ) + --[[ +---------------------------------------------------------------------------------------------------------------------------------+ | Implement X-CLSERG.2DA - Ignore the -8 thac0 penalty characters incur when meleeing with a ranged weapon for specific | @@ -763,6 +807,47 @@ +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ --]] + --[[ + +-------------------------------------------------------------------------------------------------------------+ + | Implement opcode #342 special BIT0 repeated-offhand THAC0 tagging | + +-------------------------------------------------------------------------------------------------------------+ + | [EEex.dll] EEex::Sprite_Hook_ApplyOp342OffhandFrame(pSprite: CGameSprite*) | + | Promotes the tagged repeated offhand frame into a real offhand damage frame. | + | [EEex.dll] EEex::Sprite_Hook_GetOp342OffhandTHAC0(pSprite: CGameSprite*, thac0: int) -> int | + | Applies the queued opcode #342 THAC0 delta only to the tagged repeated offhand attack roll. | + +-------------------------------------------------------------------------------------------------------------+ + --]] + + EEex_HookBeforeRestoreWithLabels(EEex_Label("Hook-CGameSprite::Swing()-Op342OffhandFrame"), 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, rbx ; pSprite + call #L(EEex::Sprite_Hook_ApplyOp342OffhandFrame) + #DESTROY_SHADOW_SPACE + ]]} + ) + + EEex_HookBeforeRestoreWithLabels(EEex_Label("Hook-CGameSprite::Hit()-FinalTHAC0Compare"), 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, rbx ; pSprite + movsx edx, r15w ; final THAC0 accumulator + call #L(EEex::Sprite_Hook_GetOp342OffhandTHAC0) + mov r15w, ax + #DESTROY_SHADOW_SPACE + ]]} + ) + --[[ +-------------------------------------------------------------------------------------------------------------+ | Implement EEex_Sprite_AddAlterBaseWeaponDamageListener() - Lua listeners that can alter base weapon damage | diff --git a/EEex/loader/InfinityLoader.db b/EEex/loader/InfinityLoader.db index 0b182a9..33ef494 100644 --- a/EEex/loader/InfinityLoader.db +++ b/EEex/loader/InfinityLoader.db @@ -309,6 +309,10 @@ Pattern=48895C24105556574154415541564157488D6C24F9 Pattern=488D81C81D0000C3 Operations=ADD -16 +[CGameSprite::GetActiveWeaponStyleAndLevel] +Pattern=4883EC300FB681F8100000 +Operations=ADD -22 + [CGameSprite::GetCasterLevel] Pattern=48895C2418555741564883EC30 @@ -370,6 +374,10 @@ Operations=ADD -6 Pattern=41554157488D6C24D0 Operations=ADD -4 +[CGameSprite::Swing] +Pattern=664183FC027507 +Operations=ADD -7 + [CGameSprite::UpdateTarget] Pattern=488BD94885D2740F Operations=ADD -13 @@ -2215,6 +2223,10 @@ Operations=ADD 23 Pattern=3881F81000007407 Operations=ADD 56 +[Hook-CGameEffectDamageMod::ApplyEffect()-FirstInstruction] +Pattern=40534883EC208B4120 +Operations=ADD -112 + [Hook-CGameEffectForceSurge::ApplyEffect()-FirstInstruction] Pattern=898248130000 Operations=ADD -3 @@ -2340,6 +2352,18 @@ Operations=ADD -8 Pattern=03457F894577 Operations=ADD -8 +[Hook-CGameSprite::GetMaxDamage()-AdjustDisplayedDamage] +Pattern=4C8BC88B5010 +Operations=ADD 81 + +[Hook-CGameSprite::GetMinDamage()-AdjustDisplayedDamage] +Pattern=83EA0C7416 +Operations=ADD 51 + +[Hook-CGameSprite::Damage()-AdjustRollHandBonus] +Pattern=488D542448488D4DBF +Operations=ADD -12 + [Hook-CGameSprite::GetRatingWithItem()-CGameSprite::Copy()] Pattern=410FB69D283A0000 Operations=ADD 38 @@ -2360,6 +2384,10 @@ Operations=ADD 18 Pattern=2BF90FAFC0 Operations=ADD 9 +[Hook-CGameSprite::Hit()-FinalTHAC0Compare] +Pattern=66443B7D48 +Operations=ADD 0 + [Hook-CGameSprite::IsOver()-B3Invis] Pattern=3843387627 Operations=ADD 3 @@ -2464,6 +2492,10 @@ Operations=ADD 36 Pattern=488983D84A00004439B3A44E0000 Operations=ADD 75 +[Hook-CGameSprite::Swing()-Op342OffhandFrame] +Pattern=0FBF073BC8 +Operations=ADD 53 + [Hook-CGameSprite::Swing()-NoCImmunitiesWeaponElseContinue] Pattern=418B47484D8D6F0C Operations=ADD 41 From 3e94840126e3ae9dcd9f7dee3ebc7ffd076747a5 Mon Sep 17 00:00:00 2001 From: 4Luke4 Date: Tue, 16 Jun 2026 20:19:58 +0200 Subject: [PATCH 2/2] Document inactive proficiency, add loader pattern --- EEex/copy/EEex_scripts/EEex_Sprite.lua | 2 +- EEex/loader/InfinityLoader.db | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/EEex/copy/EEex_scripts/EEex_Sprite.lua b/EEex/copy/EEex_scripts/EEex_Sprite.lua index 651e100..67afb57 100644 --- a/EEex/copy/EEex_scripts/EEex_Sprite.lua +++ b/EEex/copy/EEex_scripts/EEex_Sprite.lua @@ -564,7 +564,7 @@ CGameSprite.getActiveStats = EEex_Sprite_GetActiveStats -- -- @return { type=number }: First return value; the active weapon style stat id. -- @return { type=number }: Second return value; the active rank for ``style`` after derived-stat effects are applied. --- @return { type=number }: Third return value; the original rank for ``style`` from the creature's weapon proficiency list. +-- @return { type=number }: Third return value; the original rank for ``style`` from the engine's inactive proficiency value. function EEex_Sprite_GetWeaponStyle(sprite) return EEex.GetWeaponStyle(sprite) diff --git a/EEex/loader/InfinityLoader.db b/EEex/loader/InfinityLoader.db index 33ef494..e53b19a 100644 --- a/EEex/loader/InfinityLoader.db +++ b/EEex/loader/InfinityLoader.db @@ -313,6 +313,10 @@ Operations=ADD -16 Pattern=4883EC300FB681F8100000 Operations=ADD -22 +[CGameSprite::GetInactiveProficiency] +Pattern=83F82D7728 +Operations=ADD -10 + [CGameSprite::GetCasterLevel] Pattern=48895C2418555741564883EC30