Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
!/EEex/language/schinese/*.*
!/EEex/language/spanish
!/EEex/language/spanish/*.*
!/EEex/language/italian
!/EEex/language/italian/*.*
!/EEex/lib
!/EEex/lib/*.*
!/EEex/loader
Expand Down
35 changes: 34 additions & 1 deletion EEex/EEex.tp2
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ BEGIN @1 LABEL ~B3-EEex-Main~ DESIGNATED 1
REQUIRE_PREDICATE (GAME_IS ~bgee bg2ee eet iwdee~ AND FILE_EXISTS ~data/PATCH26.BIF~) @1000 // Game not supported.
REQUIRE_PREDICATE MOD_IS_INSTALLED ~EEex.tp2~ 0 @1001 // This component requires the core component to be installed.

ACTION_FOR_EACH file IN ACTION OBJECT TRIGGER BEGIN
ACTION_FOR_EACH file IN ACTION OBJECT TRIGGER STATS DMGTYPE DAMAGES BEGIN
COPY ~EEex/patch/%file%.IDS~ ~EEex/patch~
COUNT_2DA_ROWS 2 rows
FOR (i = 0; i <= rows; ++i) BEGIN
Expand Down Expand Up @@ -103,11 +103,44 @@ REQUIRE_PREDICATE MOD_IS_INSTALLED ~EEex.tp2~ 0 @1001 // This component requires
APPEND ~%data%.IDS~ ~%data_1% %data_2%~ UNLESS ~^[ %TAB%]*%data_1_escaped%[ %TAB%]+%data_2_escaped%[ %TAB%]*%MNL%*$~
END

WITH_SCOPE BEGIN
WITH_TRA "EEex\language\english\new_damage_types.tra" "EEex\language\%LANGUAGE%\new_damage_types.tra" BEGIN
OUTER_SET "sonic" = RESOLVE_STR_REF (@0)
OUTER_SET "positive" = RESOLVE_STR_REF (@1)
OUTER_SET "negative" = RESOLVE_STR_REF (@2)
OUTER_SET "divine" = RESOLVE_STR_REF (@3)
//
APPEND ~DMGTYPES.2DA~ ~B3_SONIC * * * %sonic%~ UNLESS ~^[ %TAB%]*B3_SONIC[ %TAB%]~
APPEND ~DMGTYPES.2DA~ ~B3_POSITIVEENERGY * * * %positive%~ UNLESS ~^[ %TAB%]*B3_POSITIVEENERGY[ %TAB%]~
APPEND ~DMGTYPES.2DA~ ~B3_NEGATIVEENERGY * * * %negative%~ UNLESS ~^[ %TAB%]*B3_NEGATIVEENERGY[ %TAB%]~
APPEND ~DMGTYPES.2DA~ ~B3_DIVINE * * * %divine%~ UNLESS ~^[ %TAB%]*B3_DIVINE[ %TAB%]~
// formatting
COPY_EXISTING ~DMGTYPES.2DA~ ~override~
PRETTY_PRINT_2DA
BUT_ONLY_IF_IT_CHANGES
END
END

COPY ~EEex/loader~ ~.~
COPY ~EEex/loader/Lua52~ ~.~
COPY ~EEex/copy/EEex_scripts~ ~EEex_scripts~
COPY ~EEex/copy/override~ ~override~

WITH_SCOPE BEGIN
APPEND ~X-STATS.2DA~ ~B3_RESISTSONIC -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_RESISTSONIC[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_RESISTPOSITIVEENERGY -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_RESISTPOSITIVEENERGY[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_RESISTNEGATIVEENERGY -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_RESISTNEGATIVEENERGY[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_RESISTDIVINE -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_RESISTDIVINE[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_SPECIFICDAMAGEBONUSSONIC -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_SPECIFICDAMAGEBONUSSONIC[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_SPECIFICDAMAGEBONUSPOSITIVEENERGY -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_SPECIFICDAMAGEBONUSPOSITIVEENERGY[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_SPECIFICDAMAGEBONUSNEGATIVEENERGY -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_SPECIFICDAMAGEBONUSNEGATIVEENERGY[ %TAB%]~
APPEND ~X-STATS.2DA~ ~B3_SPECIFICDAMAGEBONUSDIVINE -32768 32767 0~ UNLESS ~^[ %TAB%]*B3_SPECIFICDAMAGEBONUSDIVINE[ %TAB%]~
// formatting
COPY_EXISTING "X-STATS.2DA" ~override~
PRETTY_PRINT_2DA
BUT_ONLY_IF_IT_CHANGES
END

//////////////////////////////////////////////////////////////////////////////////
// Enable effect menu module: LShift-on-hover to view spells affecting creature //
//////////////////////////////////////////////////////////////////////////////////
Expand Down
256 changes: 255 additions & 1 deletion EEex/copy/EEex_scripts/EEex_Opcode_Patch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,155 @@
-- Opcode Changes --
--------------------------------------

--[[
+------------------------------------------------------------------------------------------------------------+
| Opcode #12 |
+------------------------------------------------------------------------------------------------------------+
| Extend damage resistance, source-specific damage bonus, and combat-log feedback for B3 damage types. |
| |
| Uses the B3 high-word masks from DMGTYPE.IDS: |
| B3_SONIC -> 0x10000000 |
| B3_POSITIVEENERGY -> 0x20000000 |
| B3_NEGATIVEENERGY -> 0x40000000 |
| B3_DIVINE -> 0x80000000 |
+------------------------------------------------------------------------------------------------------------+
| [EEex.dll] EEex::Damage_Hook_ApplyB3DamageType( |
| pEffect: CGameEffect*, pTarget: CGameSprite*, pSource: CGameSprite*, damage: int) -> uint64 |
| return: |
| -> 0 - Continue through vanilla damage resistance handling |
| -> !0 - High dword marks B3 handled; low dword is replacement damage |
| |
| [EEex.dll] EEex::Damage_Hook_GetB3DamageFeedback(pEffect: CGameEffect*) -> uint64 |
| return: |
| -> 0 - Keep vanilla damage feedback |
| -> !0 - High dword is text color; low dword is damage-name strref |
+------------------------------------------------------------------------------------------------------------+
--]]

------------------------------------------------------
-- [EEex.dll] EEex::Damage_Hook_ApplyB3DamageType() --
------------------------------------------------------

local applyB3DamageTypeHookAddress = EEex_Label("Hook-CGameEffectDamage::ApplyEffect()-BeforeDamageResistance")
local applyB3DamageTypeVanillaResistanceAddress = applyB3DamageTypeHookAddress + 8
local applyB3DamageTypeAfterVanillaResistanceAddress = applyB3DamageTypeHookAddress + 0x26

-- The hook site starts with "test edi, edi; je ...; mov r8d, [r14+1Ch]".
-- EEex_HookBeforeRestoreWithLabels() cannot be used here because it would copy
-- the short conditional branch into relocated JIT code, making the branch target
-- relative to the JIT allocation instead of the original function.
--
-- This trampoline re-emits the overwritten vanilla branch explicitly:
-- * no B3 type: run the same "test/je/mov" sequence and continue in vanilla
-- resistance code.
-- * B3 type: write the C++-computed damage and jump past vanilla resistance.
--
-- The stack frame is manual rather than #MAKE_SHADOW_SPACE because nested
-- #SHADOW_SPACE_BOTTOM() expansion in EEex_JITNear() previously evaluated before
-- the macro state had an active shadow-space entry during startup.
local applyB3DamageTypeHook = EEex_JITNear({
[[
lea rsp, qword ptr ss:[rsp-60h]
mov qword ptr ss:[rsp+58h], rax
mov qword ptr ss:[rsp+50h], rcx
mov qword ptr ss:[rsp+48h], rdx
mov qword ptr ss:[rsp+40h], r8
mov qword ptr ss:[rsp+38h], r9
mov qword ptr ss:[rsp+30h], r10
mov qword ptr ss:[rsp+28h], r11

mov rcx, r14
mov rdx, rbx
mov r8, qword ptr ss:[rbp-41h]
mov r9d, dword ptr ds:[r14+1Ch]
call #L(EEex::Damage_Hook_ApplyB3DamageType)

mov qword ptr ss:[rsp+20h], rax
mov r11, rax
shr r11, 20h
test r11d, r11d
jnz b3_damage_type_handled

mov r11, qword ptr ss:[rsp+28h]
mov r10, qword ptr ss:[rsp+30h]
mov r9, qword ptr ss:[rsp+38h]
mov r8, qword ptr ss:[rsp+40h]
mov rdx, qword ptr ss:[rsp+48h]
mov rcx, qword ptr ss:[rsp+50h]
mov rax, qword ptr ss:[rsp+58h]
lea rsp, qword ptr ss:[rsp+60h]
test edi, edi
je #$(1)
mov r8d, dword ptr ds:[r14+1Ch]
jmp #$(2)

b3_damage_type_handled:
mov eax, dword ptr ss:[rsp+20h]
mov dword ptr ds:[r14+1Ch], eax
mov r11, qword ptr ss:[rsp+28h]
mov r10, qword ptr ss:[rsp+30h]
mov r9, qword ptr ss:[rsp+38h]
mov r8, qword ptr ss:[rsp+40h]
mov rdx, qword ptr ss:[rsp+48h]
mov rcx, qword ptr ss:[rsp+50h]
mov rax, qword ptr ss:[rsp+58h]
lea rsp, qword ptr ss:[rsp+60h]
jmp #$(1)
]],
{applyB3DamageTypeAfterVanillaResistanceAddress, applyB3DamageTypeVanillaResistanceAddress},
})

EEex_JITAt(applyB3DamageTypeHookAddress, {[[
jmp short ]], applyB3DamageTypeHook, [[ #ENDL
#REPEAT(3,nop #ENDL)
]]})

--------------------------------------------------------
-- [EEex.dll] EEex::Damage_Hook_GetB3DamageFeedback() --
--------------------------------------------------------

-- This label points at a real "call rel32" instruction. Do not use
-- EEex_HookBeforeRestoreWithLabels(): copying those call bytes into JIT keeps the
-- original rel32 displacement, which redirects execution into invalid memory.
-- EEex_HookBeforeCallWithLabels() decodes the original call target and emits a
-- fresh call from the JIT block.
EEex_HookBeforeCallWithLabels(EEex_Label("Hook-CGameEffectDamage::DisplayDamageAmount()-AfterDamageStrRefLoad"), {
{"hook_integrity_watchdog_ignore_registers", {
EEex_HookIntegrityWatchdogRegister.RAX, EEex_HookIntegrityWatchdogRegister.RCX, EEex_HookIntegrityWatchdogRegister.RDX,
EEex_HookIntegrityWatchdogRegister.RDI, EEex_HookIntegrityWatchdogRegister.R8, EEex_HookIntegrityWatchdogRegister.R9,
EEex_HookIntegrityWatchdogRegister.R10, EEex_HookIntegrityWatchdogRegister.R11
}}},
EEex_FlattenTable({
{[[
#MAKE_SHADOW_SPACE(32)
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)], r8
mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-32)], r9

mov rcx, rsi
call #L(EEex::Damage_Hook_GetB3DamageFeedback)

mov rcx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)]
mov r8, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-24)]
mov r9, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-32)]
test rax, rax
jz no_b3_damage_feedback

mov edx, eax
shr rax, 20h
mov edi, eax
jmp b3_damage_feedback_done

no_b3_damage_feedback:
mov rdx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)]

b3_damage_feedback_done:
#DESTROY_SHADOW_SPACE
]]},
})
)

--[[
+------------------------------------------------------------------------------------+
| Opcode #146 |
Expand Down Expand Up @@ -538,6 +687,60 @@
EEex_HookIntegrityWatchdogRegister.R10, EEex_HookIntegrityWatchdogRegister.R11
})

--[[
+------------------------------------------------------------------------------------------------------------+
| Opcode #332 |
+------------------------------------------------------------------------------------------------------------+
| Extend the vanilla specific-damage modifier table to B3 damage types. |
| |
| param2 -> 11 - B3_SPECIFICDAMAGEBONUSSONIC |
| param2 -> 12 - B3_SPECIFICDAMAGEBONUSPOSITIVEENERGY |
| param2 -> 13 - B3_SPECIFICDAMAGEBONUSNEGATIVEENERGY |
| param2 -> 14 - B3_SPECIFICDAMAGEBONUSDIVINE |
+------------------------------------------------------------------------------------------------------------+
| [EEex.dll] EEex::Opcode_Hook_Op332_TryApplyB3SpecificDamageMod( |
| pEffect: CGameEffect*, pSprite: CGameSprite*) -> int |
| return: |
| -> 0 - Continue through vanilla op332 handling |
| -> !0 - B3 param2 handled |
+------------------------------------------------------------------------------------------------------------+
--]]

----------------------------------------------------------------------
-- [EEex.dll] EEex::Opcode_Hook_Op332_TryApplyB3SpecificDamageMod() --
----------------------------------------------------------------------

-- The first six bytes are ordinary non-relative instructions, so a restore hook is
-- safe here. The C++ hook returns nonzero only for the new B3 param2 values.
EEex_HookBeforeRestoreWithLabels(EEex_Label("Hook-CGameEffectSpecificDamageMod::ApplyEffect()-FirstInstruction"), 0, 6, 6, {
{"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
}}},
EEex_FlattenTable({
{[[
#MAKE_SHADOW_SPACE(16)
mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)], rcx
mov qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)], rdx

call #L(EEex::Opcode_Hook_Op332_TryApplyB3SpecificDamageMod)

mov rcx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-8)]
mov rdx, qword ptr ss:[rsp+#SHADOW_SPACE_BOTTOM(-16)]
test eax, eax
#DESTROY_SHADOW_SPACE
jz no_b3_specific_damage_mod

mov eax, 1
#MANUAL_HOOK_EXIT(0)
ret

no_b3_specific_damage_mod:
]]},
})
)

--[[
+-----------------------------------------------------------------+
| Opcode #333 |
Expand Down Expand Up @@ -1111,6 +1314,37 @@
]]},
})

--[[
+-----------------------------------------------------------------------------------------------------------------------+
| New Opcodes #413-416 (B3 Damage Resistance Modifier) |
+-----------------------------------------------------------------------------------------------------------------------+
| Modify B3 extended resistance stats using op401-style arithmetic. |
| |
| 413 -> B3_RESISTSONIC |
| 414 -> B3_RESISTPOSITIVEENERGY |
| 415 -> B3_RESISTNEGATIVEENERGY |
| 416 -> B3_RESISTDIVINE |
| |
| param1 -> Modification amount |
| param2 -> Modification type: 0 (Sum), 1 (Set), 2 (Percent) |
+-----------------------------------------------------------------------------------------------------------------------+
| [EEex.dll] EEex::Opcode_Hook_B3DamageResistanceMod_ApplyEffect(pEffect: CGameEffect*, pSprite: CGameSprite*) -> int |
| return: |
| -> 0 - Halt effect list processing |
| -> !0 - Continue effect list processing |
+-----------------------------------------------------------------------------------------------------------------------+
--]]

local EEex_B3DamageResistanceMod = genOpcodeDecode({
["ApplyEffect"] = {[[
#STACK_MOD(8) ; This was called, the ret ptr broke alignment
#MAKE_SHADOW_SPACE
call #L(EEex::Opcode_Hook_B3DamageResistanceMod_ApplyEffect)
#DESTROY_SHADOW_SPACE
ret
]]},
})

--[[
+-------------------------------------+
| [JIT] Decode switch for new opcodes |
Expand Down Expand Up @@ -1154,8 +1388,28 @@

_409:
cmp eax, 409
jne #L(jmp_success)
jne _413
]], EEex_EnableActionListener, [[

_413:
cmp eax, 413
jne _414
]], EEex_B3DamageResistanceMod, [[

_414:
cmp eax, 414
jne _415
]], EEex_B3DamageResistanceMod, [[

_415:
cmp eax, 415
jne _416
]], EEex_B3DamageResistanceMod, [[

_416:
cmp eax, 416
jne #L(jmp_success)
]], EEex_B3DamageResistanceMod, [[
]]})
)
EEex_HookIntegrityWatchdog_IgnoreStackSizes(EEex_Label("Hook-CGameEffect::DecodeEffect()-DefaultJmp"), {{0x60, 8}})
Expand Down
5 changes: 5 additions & 0 deletions EEex/language/english/new_damage_types.tra
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Damage type names
@0 = ~sonic~
@1 = ~positive energy~
@2 = ~negative energy~
@3 = ~divine~
5 changes: 5 additions & 0 deletions EEex/language/italian/new_damage_types.tra
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Damage type names
@0 = ~sonoro/i~
@1 = ~da energia positiva~
@2 = ~da energia negativa~
@3 = ~divino/i~
16 changes: 16 additions & 0 deletions EEex/loader/InfinityLoader.db
Original file line number Diff line number Diff line change
Expand Up @@ -2211,10 +2211,18 @@ Operations=ADD 64
Pattern=448964242041FF92E8000000
Operations=ADD 23

[Hook-CGameEffectDamage::ApplyEffect()-BeforeDamageResistance]
Pattern=40FEC703F0
Operations=ADD 503

[Hook-CGameEffectDamage::ApplyEffect()-StartingCalculations]
Pattern=3881F81000007407
Operations=ADD 56

[Hook-CGameEffectDamage::DisplayDamageAmount()-AfterDamageStrRefLoad]
Pattern=4C8D45F74533C9
Operations=ADD 24

[Hook-CGameEffectForceSurge::ApplyEffect()-FirstInstruction]
Pattern=898248130000
Operations=ADD -3
Expand All @@ -2235,6 +2243,14 @@ Operations=ADD -10
Pattern=F6472004
Operations=ADD 25

[Hook-CGameEffectSpecificDamageMod::ApplyEffect()-FirstInstruction]
; FindPattern/find_pattern.py cannot generate this leaf-function entry reliably:
; CGameEffectSpecificDamageMod::ApplyEffect() has no x64 runtime-function record,
; and the nearest generated cross-binary pattern targets an earlier function
; (BGEE/BG2EE 0x1401C6B20, IWDEE 0x1401C6BB0) instead of this leaf
; (BGEE/BG2EE 0x1401C7720, IWDEE 0x1401C77B0).
Pattern=8B412083F80B730F488D14420FB7411C660182662C0000B801000000C3

[Hook-CGameEffectOverrideAnimation::ApplyEffect()-LastParam2Jmp]
Pattern=4889742420574883EC30488BF1488BFA
Operations=ADD 40
Expand Down
4 changes: 4 additions & 0 deletions EEex/patch/DAMAGES.IDS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
0x1000 B3_SONIC
0x2000 B3_POSITIVEENERGY
0x4000 B3_NEGATIVEENERGY
0x8000 B3_DIVINE
Loading