259 lines
8.1 KiB
ArmAsm
259 lines
8.1 KiB
ArmAsm
.meta name="DMC"
|
|
.meta description="Mitigates effects\nof enemy health\ndesync"
|
|
.meta client_flag="0x0000001000000000"
|
|
|
|
entry_ptr:
|
|
reloc0:
|
|
.offsetof start
|
|
|
|
write_call_to_code_multi:
|
|
.include WriteCallToCodeMulti-59NL
|
|
write_address_of_code:
|
|
.include WriteAddressOfCode-59NL
|
|
|
|
start:
|
|
|
|
# Replace 6x09 with 6xE4 in subcommand handler table
|
|
mov dword [0x00A0FC30], 0x000600E4 # subcommand=0xE4, flags=6
|
|
push 0x00A0FC34
|
|
call +4
|
|
.deltaof handle_6xE4_start, handle_6xE4_end
|
|
pop eax
|
|
push dword [eax]
|
|
call handle_6xE4_end
|
|
|
|
handle_6xE4_start: # (G_6xE4* cmd @ [esp + 4]) -> void
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
test byte [0x00AAB27C], 0x80
|
|
jz handle_6xE4_return
|
|
mov ebx, [esp + 0x10] # cmd
|
|
movzx eax, word [ebx + 2]
|
|
cmp eax, 0x1000
|
|
jl handle_6xE4_return
|
|
cmp eax, 0x1B50
|
|
jge handle_6xE4_return
|
|
|
|
movzx eax, word [ebx + 2]
|
|
.include GetEnemyEntity-59NL # auto* ene = get_enemy_entity(cmd->header.entity_id);
|
|
push eax
|
|
|
|
movzx eax, word [ebx + 2]
|
|
and eax, 0x0FFF
|
|
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
|
|
push ecx
|
|
fild st0, dword [esp] # 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], st0
|
|
mov ecx, dword [esp] # adjusted_hit_amount = static_cast<int16_t>(current_hp * cmd->factor)
|
|
add esp, 4
|
|
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
|
|
add edx, esi # st.total_damage + cmd->hit_amount
|
|
cmp edx, edi
|
|
jl handle_6xE4_damage_less_than_max_hp
|
|
mov [eax + 0x06], di # st.total_damage = cmd->max_hp;
|
|
mov edx, [eax]
|
|
test edx, 0x800
|
|
jnz handle_6xE4_return_pop_ene
|
|
or edx, 0x800
|
|
mov [eax], edx
|
|
cmp dword [esp], 0
|
|
je handle_6xE4_return_pop_ene
|
|
push edx # out_cmd.flags
|
|
sub esp, 8
|
|
mov word [esp], 0x030A # out_cmd.header.{subcommand,size}
|
|
mov si, [ebx + 2]
|
|
mov [esp + 2], si # out_cmd.header.entity_id
|
|
and si, 0x0FFF
|
|
mov [esp + 4], si # out_cmd.entity_index
|
|
mov [esp + 6], di # out_cmd.total_damage
|
|
mov ecx, esp
|
|
mov edx, 0x008003E0
|
|
call edx # send_and_handle_60(&out_cmd);
|
|
add esp, 0x10
|
|
jmp handle_6xE4_return
|
|
|
|
handle_6xE4_damage_less_than_max_hp:
|
|
xor edi, edi
|
|
cmp edx, edx
|
|
cmovl edx, edi
|
|
mov [eax + 0x06], dx # st.total_damage = std::max<int16_t>(st.total_damage + cmd->hit_amount, 0);
|
|
|
|
mov edx, eax # edx = ene_st
|
|
mov eax, [esp] # eax = ene
|
|
test eax, eax
|
|
jz handle_6xE4_return_pop_ene
|
|
mov ecx, eax
|
|
push edx
|
|
mov edx, [ecx]
|
|
call [edx + 0x148] # ene->vtable[0x52](ene, &st);
|
|
|
|
handle_6xE4_return_pop_ene:
|
|
add esp, 4
|
|
handle_6xE4_return:
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
|
|
handle_6xE4_end:
|
|
call write_address_of_code
|
|
|
|
|
|
|
|
# Write TObjectV00b441c0::incr_hp_with_sync
|
|
push 5
|
|
push 0x00774448 # TObjectV00b441c0::v18_accept_hit (presumably Resta) - this is add_hp, not subtract_hp!
|
|
push 5
|
|
push 0x00777287 # TObjectV00b441c0::subtract_hp_if_not_in_state_2
|
|
push 5
|
|
push 0x00776CD6 # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00776D4F # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00776E20 # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00776E99 # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00775F51 # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00775BE6 # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00775A60 # TObjectV00b441c0::v19_handle_hit_special_effects
|
|
push 5
|
|
push 0x00775726 # TObjectV00b441c0::v19_handle_hit_special_effects (Devil's/Demon's)
|
|
push 5
|
|
push 0x00774D7B # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x00774C47 # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x00774A14 # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x0077482A # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x007746E0 # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x00774061 # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x00773EFA # TObjectV00b441c0::v18_accept_hit
|
|
push 5
|
|
push 0x00773937 # TObjectV00b441c0::v17
|
|
push 18
|
|
call +4
|
|
.deltaof on_add_or_subtract_hp_start, on_add_or_subtract_hp_end
|
|
pop eax
|
|
push dword [eax]
|
|
call on_add_or_subtract_hp_end
|
|
|
|
on_add_or_subtract_hp_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
|
|
test byte [0x00AAB27C], 0x80
|
|
jz on_add_or_subtract_hp_skip_send
|
|
movzx eax, word [ecx + 0x1C] # ene->entity_id
|
|
cmp eax, 0x1000
|
|
jl on_add_or_subtract_hp_skip_send
|
|
cmp eax, 0x1B50
|
|
jge on_add_or_subtract_hp_skip_send
|
|
|
|
and eax, 0x0FFF
|
|
imul eax, eax, 0x0C
|
|
add eax, [0x00AB02B8] # eax = state_for_enemy(cmd->header.entity_id)
|
|
|
|
sub esp, 0x10
|
|
mov word [esp], 0x04E4
|
|
mov dx, [ecx + 0x1C]
|
|
mov [esp + 0x02], dx # cmd.entity_id
|
|
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:
|
|
mov [esp + 0x04], dx # cmd.hit_amount
|
|
mov dx, [eax + 6]
|
|
mov [esp + 0x06], dx # cmd.total_damage_before_hit
|
|
mov dx, [ecx + 0x0334]
|
|
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)
|
|
push edx
|
|
fild st0, dword [esp] # current_hp_factor = static_cast<float>(100 - special_amount)
|
|
fmul st0, dword [esp + 0x54] # *= weapon_reduction_factor
|
|
mov dword [esp], 0x42C80000 # 100.0f
|
|
fdiv st0, dword [esp]
|
|
add 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 0x10
|
|
push edx
|
|
mov ecx, [0x00AAB284]
|
|
mov edx, 0x007D3F38
|
|
call edx # send_60(root_protocol, &cmd, sizeof(cmd));
|
|
pop ecx
|
|
add esp, 0x10
|
|
|
|
on_add_or_subtract_hp_skip_send:
|
|
mov eax, 0x00777414 # subtract_hp
|
|
mov edx, 0x007773D4 # add_hp
|
|
cmp dword [esp], 0x0077444D # Check if callsite is add_hp
|
|
cmove eax, edx
|
|
jmp eax
|
|
|
|
on_add_or_subtract_hp_end:
|
|
call write_call_to_code_multi
|
|
|
|
|
|
|
|
push 5
|
|
push 0x0078781F
|
|
push 1
|
|
call +4
|
|
.deltaof on_6x0A_patch_start, on_6x0A_patch_end
|
|
pop eax
|
|
push dword [eax]
|
|
call on_6x0A_patch_end
|
|
|
|
on_6x0A_patch_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
|
|
test byte [0x00AAB27C], 0x80
|
|
jz on_6x0A_patch_skip_write
|
|
mov [esp + 0x0A], cx
|
|
on_6x0A_patch_skip_write:
|
|
ret
|
|
|
|
on_6x0A_patch_end:
|
|
call write_call_to_code_multi
|
|
|
|
|
|
|
|
ret
|