handle devil's/demon's in EnemyDamageSync

This commit is contained in:
Martin Michelsen
2025-09-12 22:41:32 -07:00
parent 526bfb64e5
commit 22d7825ba3
7 changed files with 343 additions and 175 deletions
@@ -92,10 +92,20 @@ start:
.data 4
.address <VERS 0x80012C58 0x80012C88 0x80012F50 0x80012C38 0x80012C70 0x80012C70 0x80012C38 0x80012CB0>
bl on_TObjectV8047c128_subtract_hp_with_sync
.data <VERS 0x80012FE0 0x80013010 0x800132D8 0x80012FC0 0x80012FF8 0x80012FF8 0x80012FC0 0x80013038>
.data 8
fmuls f3, f0, f2
fmuls f31, f30, f3
.data <VERS 0x80012FFC 0x8001302C 0x800132F4 0x80012FDC 0x80013014 0x80013014 0x80012FDC 0x80013054>
.data 4
fctiwz f3, f31
.data <VERS 0x80013004 0x80013034 0x800132FC 0x80012FE4 0x8001301C 0x8001301C 0x80012FE4 0x8001305C>
.data 4
stfd [r1 + 0x40], f3
.data <VERS 0x8001300C 0x8001303C 0x80013304 0x80012FEC 0x80013024 0x80013024 0x80012FEC 0x80013064>
.data 4
.address <VERS 0x8001300C 0x8001303C 0x80013304 0x80012FEC 0x80013024 0x80013024 0x80012FEC 0x80013064>
bl on_TObjectV8047c128_subtract_hp_with_sync
bl on_TObjectV8047c128_subtract_hp_with_sync_demons_devils
# subtract_hp callsites in TObjectV8047c128_v17_accept_hit
.data <VERS 0x80013454 0x80013484 0x800137F4 0x80013434 0x8001346C 0x8001346C 0x80013434 0x800134AC>
.data 4
@@ -163,6 +173,41 @@ handle_6xE4: # [std] (G_IncrementEnemyDamage_Extension_6xE4* cmd @ r3) -> void
lhbrx r3, [r31 + r3]
bl state_for_enemy # EnemyState* st = state_for_enemy(cmd->header.entity_id);
li r4, 0x0C
lwbrx r5, [r31 + r4] # cmd->factor
andis. r0, r5, 0x8000
bne handle_6xE4_not_proportional
stwx [r31 + r4], r5
li r8, 0x0A
lhbrx r8, [r31 + r8]
lhz r4, [r3 + 6]
sub r8, r8, r4 # current_hp = cmd->max_hp - st->total_damage
cmpwi r8, 0
blt handle_6xE4_not_proportional
lis r4, 0x4B00
or r5, r4, r8
stw [r1 - 4], r5
lfs f1, [r1 - 4]
stw [r1 - 4], r4
lfs f2, [r1 - 4]
fsubs f1, f1, f2 # f1 = static_cast<float>(current_hp)
lfs f2, [r31 + 0x0C]
fmuls f1, f1, f2
fctiwz f1, f1
stfd [r1 - 8], f1
lwz r8, [r1 - 4]
li r4, 1
cmp r8, r4
bge handle_6xE4_proportional_positive
mr r8, r4
handle_6xE4_proportional_positive:
li r5, 0x04
sthbrx [r31 + r5], r8
handle_6xE4_not_proportional:
# r3 still has the return value of state_for_enemy
lhz r4, [r3 + 6] # st->total_damage
li r5, 0x04
lhbrx r5, [r31 + r5] # cmd->hit_amount
@@ -236,13 +281,23 @@ state_for_enemy: # [/r4] (uint16_t entity_id @ r3) -> EnemyState* @ r3
on_TObjectV8047c128_add_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4) -> void
# AdjustmentType:
# 0 = SUBTRACT
# 1 = SUBTRACT_PROPORTION
# 2 = ADD
on_TObjectV8047c128_subtract_hp_with_sync_demons_devils:
li r5, 1
b on_add_or_subtract_hp
on_TObjectV8047c128_add_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4) -> void
li r5, 2
b on_add_or_subtract_hp
on_TObjectV8047c128_subtract_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4) -> void
li r5, 0
on_add_or_subtract_hp: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4, bool is_add @ r5) -> void
on_add_or_subtract_hp: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4, AdjustmentType type @ r5) -> void
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
andi. r12, r12, 0x0080
beq on_add_or_subtract_hp_skip_send
@@ -259,10 +314,10 @@ on_add_or_subtract_hp: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4
mflr r0
stw [r1 + 4], r0
stwu [r1 - 0x20], r1
stw [r1 + 0x14], r29
stw [r1 + 0x18], r30
stw [r1 + 0x1C], r31
stwu [r1 - 0x40], r1
stw [r1 + 0x34], r29
stw [r1 + 0x38], r30
stw [r1 + 0x3C], r31
mr r29, r3
mr r30, r4
mr r31, r5
@@ -271,14 +326,14 @@ on_add_or_subtract_hp: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4
bl state_for_enemy # EnemyState* st = state_for_enemy(ene->entity_id);
mr r5, r30
cmplwi r31, 0
beq on_add_or_subtract_hp_skip_negate_amount
cmplwi r31, 2
bne on_add_or_subtract_hp_skip_negate_amount
neg r5, r5
on_add_or_subtract_hp_skip_negate_amount:
li r4, 0x1C
lhbrx r4, [r29 + r4]
oris r4, r4, 0xE403
oris r4, r4, 0xE404
stw [r1 + 0x08], r4
li r4, 0x0C
sthbrx [r1 + r4], r5
@@ -291,25 +346,37 @@ on_add_or_subtract_hp_skip_negate_amount:
li r4, 0x2B8
lhbrx r4, [r29 + r4]
sth [r1 + 0x12], r4
li r5, 0x14
cmplwi r31, 1
bne on_add_or_subtract_hp_not_proportional
fmuls f0, f30, f0
stfsx [r1 + r5], f0 # current_hp_factor (== (1.0 - special_amount * 0.01)) * weapon_reduction_factor
lwzx r4, [r1 + r5]
b on_add_or_subtract_hp_proportional_check_end
on_add_or_subtract_hp_not_proportional:
lis r4, 0xBF80
on_add_or_subtract_hp_proportional_check_end:
stwbrx [r1 + r5], r4
mr r3, r11
addi r4, r1, 0x08
li r5, 0x0C
li r5, 0x10
bl send_60
on_add_or_subtract_hp_tail_call:
mr r3, r29
mr r4, r30
mr r5, r31
lwz r31, [r1 + 0x1C]
lwz r30, [r1 + 0x18]
lwz r29, [r1 + 0x14]
addi r1, r1, 0x20
lwz r31, [r1 + 0x3C]
lwz r30, [r1 + 0x38]
lwz r29, [r1 + 0x34]
addi r1, r1, 0x40
lwz r0, [r1 + 4]
mtlr r0
on_add_or_subtract_hp_skip_send:
cmplwi r5, 0
beq on_add_or_subtract_hp_tail_call_subtract_hp
cmplwi r5, 2
bne on_add_or_subtract_hp_tail_call_subtract_hp
b TObjectV8047c128_add_hp
on_add_or_subtract_hp_tail_call_subtract_hp:
b TObjectV8047c128_subtract_hp
@@ -103,11 +103,11 @@ on_add_or_subtract_hp_start: # (TObjectV004434c8* this @ eax, int16_t amount @
imul edx, edx, 0x0C
add edx, [<VERS 0x00633068 0x006336C8 0x0063B210 0x006386F8 0x00637F90 0x006386F8 0x00638A90>] # eax = state_for_enemy(cmd->header.entity_id)
sub esp, 0x0C
mov word [esp], 0x03E4
sub esp, 0x10
mov word [esp], 0x04E4
mov bx, [eax + 0x1C]
mov [esp + 0x02], bx # cmd.entity_id
cmp dword [esp + 0x18], <VERS 0x002A6900 0x002A73E0 0x002A88B0 0x002A8340 0x002A8520 0x002A8360 0x002A85E0> # Check if callsite is add_hp
cmp dword [esp + 0x1C], <VERS 0x002A6900 0x002A73E0 0x002A88B0 0x002A8340 0x002A8520 0x002A8360 0x002A85E0> # Check if callsite is add_hp
jne on_add_or_subtract_hp_skip_negate_amount
neg cx
on_add_or_subtract_hp_skip_negate_amount:
@@ -118,16 +118,31 @@ on_add_or_subtract_hp_skip_negate_amount:
mov [esp + 0x08], bx # cmd.current_hp
mov bx, [eax + 0x02BC]
mov [esp + 0x0A], bx # cmd.max_hp
mov dword [esp + 0x0C], 0xBF800000 # cmd.factor
cmp dword [esp + 0x1C], <VERS 0x002A7CE0 0x002A87C4 0x002A9C94 0x002A9724 0x002A9904 0x002A9744 0x002A99C4> # Check if callsite is Devil's/Demon's
jne on_add_or_subtract_hp_not_proportional
# esp is 0x20 down from where it is in caller's context
mov cx, 100
sub cx, [esp + 0x34] # cx = (100 - special_amount)
movsx ecx, cx
mov [esp - 4], ecx
fild st0, dword [esp - 4] # current_hp_factor = static_cast<float>(100 - special_amount)
fmul st0, dword [esp + 0x38] # *= weapon_reduction_factor
mov dword [esp - 4], 0x42C80000 # 100.0f
fdiv st0, dword [esp - 4]
fstp dword [esp + 0x0C], st0 # cmd.factor = ((100 - special_amount) * weapon_reduction_factor) / 100
on_add_or_subtract_hp_not_proportional:
mov ecx, esp
mov ebx, [<VERS 0x0071EEFC 0x0071F55C 0x007270A0 0x0072459C 0x00723E20 0x0072459C 0x00724920>] # root_protocol
test ebx, ebx
jz on_add_or_subtract_hp_skip_send
mov eax, 0x0C
mov eax, 0x10
# Can't just `call <addr>` here because this code is relocated at apply time
mov edx, <VERS 0x002DA120 0x002DACF0 0x002DC5B0 0x002DC080 0x002DC580 0x002DC0B0 0x002DC600>
call edx # send_60(root_protocol, &out_cmd, sizeof(out_cmd))
add esp, 0x0C
add esp, 0x10
on_add_or_subtract_hp_skip_send:
mov edx, <VERS 0x002A80C0 0x002A8BA0 0x002AA070 0x002A9B00 0x002A9CE0 0x002A9B20 0x002A9DA0> # subtract_hp
@@ -188,6 +203,27 @@ handle_6xE4: # [std] (G_6xE4* cmd @ [esp + 4]) -> void
imul eax, eax, 0x0C
add eax, [<VERS 0x00633068 0x006336C8 0x0063B210 0x006386F8 0x00637F90 0x006386F8 0x00638A90>] # eax = state_for_enemy(cmd->header.entity_id)
cmp dword [ebx + 0x0C], 0
jl handle_6xE4_not_proportional
mov cx, [ebx + 0x0A] # cmd->max_hp
sub cx, [eax + 0x06] # st.total_damage
movzx ecx, cx
xor edx, edx
cmp ecx, edx
cmovl ecx, edx
mov [esp - 4], ecx
fild st0, dword [esp - 4] # current_hp = static_cast<float>(max<int32_t>(cmd->max_hp - st.total_damage, 0))
fld st0, dword [ebx + 0x0C]
fmulp st1, st0
fistp dword [esp - 4], st0
mov ecx, dword [esp - 4] # adjusted_hit_amount = static_cast<int16_t>(current_hp * cmd->factor)
xor edx, edx
inc edx
cmp ecx, edx
cmovl ecx, edx
mov [ebx + 0x04], cx # cmd->hit_amount = min<int32_t>(1, adjusted_hit_amount)
handle_6xE4_not_proportional:
movzx edx, word [eax + 0x06] # st.total_damage
movsx esi, word [ebx + 0x04] # cmd->hit_amount
movzx edi, word [ebx + 0x0A] # cmd->max_hp
@@ -46,6 +46,27 @@ handle_6xE4_start: # (G_6xE4* cmd @ [esp + 4]) -> void
imul eax, eax, 0x0C
add eax, [0x00AB02B8] # eax = state_for_enemy(cmd->header.entity_id)
cmp dword [ebx + 0x0C], 0
jl handle_6xE4_not_proportional
mov cx, [ebx + 0x0A] # cmd->max_hp
sub cx, [eax + 0x06] # st.total_damage
movzx ecx, cx
xor edx, edx
cmp ecx, edx
cmovl ecx, edx
mov [esp - 4], ecx
fild st0, dword [esp - 4] # current_hp = static_cast<float>(max<int32_t>(cmd->max_hp - st.total_damage, 0))
fld st0, dword [ebx + 0x0C]
fmulp st1, st0
fistp dword [esp - 4], st0
mov ecx, dword [esp - 4] # adjusted_hit_amount = static_cast<int16_t>(current_hp * cmd->factor)
xor edx, edx
inc edx
cmp ecx, edx
cmovl ecx, edx
mov [ebx + 0x04], cx # cmd->hit_amount = min<int32_t>(1, adjusted_hit_amount)
handle_6xE4_not_proportional:
movzx edx, word [eax + 0x06] # st.total_damage
movsx esi, word [ebx + 0x04] # cmd->hit_amount
movzx edi, word [ebx + 0x0A] # cmd->max_hp
@@ -122,7 +143,7 @@ handle_6xE4_end:
push 5
push 0x00775A60 # TObjectV00b441c0::v19_handle_hit_special_effects
push 5
push 0x00775726 # TObjectV00b441c0::v19_handle_hit_special_effects
push 0x00775726 # TObjectV00b441c0::v19_handle_hit_special_effects (Devil's/Demon's)
push 5
push 0x00774D7B # TObjectV00b441c0::v18_accept_hit
push 5
@@ -159,12 +180,12 @@ on_add_or_subtract_hp_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @
imul eax, eax, 0x0C
add eax, [0x00AB02B8] # eax = state_for_enemy(cmd->header.entity_id)
sub esp, 0x0C
mov word [esp], 0x03E4
sub esp, 0x10
mov word [esp], 0x04E4
mov dx, [ecx + 0x1C]
mov [esp + 0x02], dx # cmd.entity_id
mov dx, [esp + 0x10]
cmp dword [esp + 0x0C], 0x0077444D # Check if callsite is add_hp
mov dx, [esp + 0x14]
cmp dword [esp + 0x10], 0x0077444D # Check if callsite is add_hp
jne on_add_or_subtract_hp_skip_negate_amount
neg dx
on_add_or_subtract_hp_skip_negate_amount:
@@ -175,15 +196,30 @@ on_add_or_subtract_hp_skip_negate_amount:
mov [esp + 0x08], dx # cmd.current_hp
mov dx, [ecx + 0x02BC]
mov [esp + 0x0A], dx # cmd.max_hp
mov dword [esp + 0x0C], 0xBF800000 # cmd.factor
cmp dword [esp + 0x10], 0x0077572B # Check if callsite is Devil's/Demon's
jne on_add_or_subtract_hp_not_proportional
# esp is 0x18 down from where it is in caller's context
mov edx, 100
sub edx, [esp + 0x24] # edx = (100 - special_amount)
mov [esp - 4], edx
fild st0, dword [esp - 4] # current_hp_factor = static_cast<float>(100 - special_amount)
fmul st0, dword [esp + 0x50] # *= weapon_reduction_factor
mov dword [esp - 4], 0x42C80000 # 100.0f
fdiv st0, dword [esp - 4]
fstp dword [esp + 0x0C], st0 # cmd.factor = ((100 - special_amount) * weapon_reduction_factor) / 100
on_add_or_subtract_hp_not_proportional:
mov edx, esp
push ecx
push 0x0C
push 0x10
push edx
mov ecx, [0x00AAB284]
mov edx, 0x007D3F38
call edx # send_60(root_protocol, &cmd, sizeof(cmd));
pop ecx
add esp, 0x0C
add esp, 0x10
on_add_or_subtract_hp_skip_send:
mov eax, 0x00777414 # subtract_hp