.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-59NJ write_address_of_code: .include WriteAddressOfCode-59NJ start: # Replace 6x09 with 6xE4 in subcommand handler table mov dword [0x00A0DC30], 0x000600E4 # subcommand=0xE4, flags=6 push 0x00A0DC34 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 [0x00AA8DFC], 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-59NJ # 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, [0x00AADE38] # 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(max(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(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(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, 0x00801150 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(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 TObjectV00b421c0::incr_hp_with_sync push 5 push 0x00775224 # TObjectV00b421c0::v18_accept_hit (presumably Resta) - this is add_hp, not subtract_hp! push 5 push 0x00778063 # TObjectV00b421c0::subtract_hp_if_not_in_state_2 push 5 push 0x00777AB2 # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x00777B2B # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x00777BFC # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x00777C75 # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x00776D2D # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x007769C2 # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x0077683C # TObjectV00b421c0::v19_handle_hit_special_effects push 5 push 0x00776502 # TObjectV00b421c0::v19_handle_hit_special_effects (Devil's/Demon's) push 5 push 0x00775B57 # TObjectV00b421c0::v18_accept_hit push 5 push 0x00775A23 # TObjectV00b421c0::v18_accept_hit push 5 push 0x007757F0 # TObjectV00b421c0::v18_accept_hit push 5 push 0x00775606 # TObjectV00b421c0::v18_accept_hit push 5 push 0x007754BC # TObjectV00b421c0::v18_accept_hit push 5 push 0x00774E3D # TObjectV00b421c0::v18_accept_hit push 5 push 0x00774CD6 # TObjectV00b421c0::v18_accept_hit push 5 push 0x00774713 # TObjectV00b421c0::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: # (TObjectV00b421c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax test byte [0x00AA8DFC], 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, [0x00AADE38] # 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], 0x00775229 # 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], 0x00776507 # 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(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, [0x00AA8E04] mov edx, 0x007D4CBC call edx # send_60(root_protocol, &cmd, sizeof(cmd)); pop ecx add esp, 0x10 on_add_or_subtract_hp_skip_send: mov eax, 0x007781F0 # subtract_hp mov edx, 0x007781B0 # add_hp cmp dword [esp], 0x00775229 # 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 0x0078864B 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: # (TObjectV00b421c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax test byte [0x00AA8DFC], 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