.meta visibility="all" .meta key="EnemyDamageSync" .meta name="DMC" .meta description="Mitigates effects\nof enemy health\ndesync" .meta client_flag="0x0000001000000000" .versions 3OJ2 3OJ3 3OJ4 3OJ5 3OE0 3OE1 3OE2 3OP0 entry_ptr: reloc0: .offsetof start start: .include WriteCodeBlocks .label TObjectV8047c128_add_hp, .label TObjectV8047c128_subtract_hp, .label get_enemy_entity, .label send_60, .label send_and_handle_60, .data .data 8 cmpwi r0, 0 beq +0x0C # Don't allow 6x0A to set total_damage; we'll do it with 6xE4 instead .data .data 4 .address bl set_enemy_total_damage_hook # Replace 6x09 with 6xE4 in subcommand handler table .data .data 8 .data 0x00E40006 # subcommand=0xE4, flags=6 .data 0x800041C0 # handle_6xE4 # add_hp callsite in TObjectV8047c128_v17_accept_hit .data .data 4 .address bl on_TObjectV8047c128_add_hp_with_sync # subtract_hp callsites in TObjectV8047c128_subtract_hp_if_not_in_state_2 .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync # subtract_hp callsites in TObjectV8047c128_v18_handle_hit_special_effects .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 8 fmuls f3, f0, f2 fmuls f31, f30, f3 .data .data 4 fctiwz f3, f31 .data .data 4 stfd [r1 + 0x40], f3 .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync_demons_devils # subtract_hp callsites in TObjectV8047c128_v17_accept_hit .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync # subtract_hp callsites in TObjectV8047c128_v16 .data .data 4 .address bl on_TObjectV8047c128_subtract_hp_with_sync .data 0x800041C0 .deltaof code_start, code_end .address 0x800041C0 code_start: handle_6xE4: # [std] (G_IncrementEnemyDamage_Extension_6xE4* cmd @ r3) -> void lwz r12, [r13 - ] andi. r12, r12, 0x0080 beqlr mflr r0 stw [r1 + 4], r0 stwu [r1 - 0x20], r1 stw [r1 + 0x08], r31 stw [r1 + 0x0C], r30 mr r31, r3 li r3, 2 lhbrx r3, [r31 + r3] cmplwi r3, 0x1000 blt handle_6xE4_return cmplwi r3, 0x1B50 bge handle_6xE4_return bl get_enemy_entity stw [r1 + 0x18], r3 # TObjEnemy* ene @ var18 = get_enemy_entity(cmd->header.entity_id); li r3, 2 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 + 0x10], r5 lfs f1, [r1 + 0x10] stw [r1 + 0x10], r4 lfs f2, [r1 + 0x10] fsubs f1, f1, f2 # f1 = static_cast(current_hp) lfs f2, [r31 + 0x0C] fmuls f1, f1, f2 fctiwz f1, f1 stfd [r1 + 0x10], f1 lwz r8, [r1 + 0x14] 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 add r4, r4, r5 # st->total_damage + cmd->hit_amount li r5, 0x0A lhbrx r5, [r31 + r5] # cmd->max_hp cmp r4, r5 blt handle_6xE4_damage_less_than_max_hp sth [r3 + 6], r5 # st->total_damage = cmd->max_hp; lwz r4, [r3] andi. r0, r4, 0x800 bne handle_6xE4_return ori r4, r4, 0x800 stw [r3], r4 # st->game_flags |= 0x800; # Send 6x0A with dead flag, but only if the entity is constructed lwz r6, [r1 + 0x18] cmplwi r6, 0 beq handle_6xE4_return stw [r1 + 0x14], r4 li r6, 0x12 sthbrx [r1 + r6], r5 lhz r6, [r31 + 2] oris r6, r6, 0x0A03 stw [r1 + 0x0C], r6 andi. r6, r6, 0xFF0F sth [r1 + 0x10], r6 addi r3, r1, 0x0C bl send_and_handle_60 b handle_6xE4_return handle_6xE4_damage_less_than_max_hp: cmpwi r4, 0 bge handle_6xE4_damage_nonnegative li r4, 0 handle_6xE4_damage_nonnegative: sth [r3 + 6], r4 # st->total_damage = std::max(st->total_damage + cmd->hit_amount, 0); mr r30, r3 lwz r3, [r1 + 0x18] # if (ene) ene->v50_on_state_updated(&st); cmplwi r3, 0 beq handle_6xE4_return mr r4, r30 lwz r12, [r3 + 0x18] lwz r12, [r12 + 0x140] mtctr r12 bctrl handle_6xE4_return: lwz r30, [r1 + 0x0C] lwz r31, [r1 + 0x08] addi r1, r1, 0x20 lwz r0, [r1 + 4] mtlr r0 blr state_for_enemy: # [/r4] (uint16_t entity_id @ r3) -> EnemyState* @ r3 # return &enemy_states[entity_id & 0x0FFF]; lwz r4, [r13 - ] andi. r3, r3, 0x0FFF mulli r3, r3, 0x0C add r3, r3, r4 blr # 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, AdjustmentType type @ r5) -> void lwz r12, [r13 - ] andi. r12, r12, 0x0080 beq on_add_or_subtract_hp_skip_send lhz r0, [r3 + 0x1C] cmplwi r0, 0x1000 blt on_add_or_subtract_hp_skip_send cmplwi r0, 0x1B50 bge on_add_or_subtract_hp_skip_send lwz r11, [r13 - ] cmplwi r11, 0 beq on_add_or_subtract_hp_skip_send mflr r0 stw [r1 + 4], r0 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 lhz r3, [r29 + 0x1C] bl state_for_enemy # EnemyState* st = state_for_enemy(ene->entity_id); mr r5, r30 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, 0xE404 stw [r1 + 0x08], r4 li r4, 0x0C sthbrx [r1 + r4], r5 li r4, 6 lhbrx r4, [r3 + r4] sth [r1 + 0x0E], r4 li r4, 0x32C lhbrx r4, [r29 + r4] sth [r1 + 0x10], r4 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, 0x10 bl send_60 mr r3, r29 mr r4, r30 mr r5, r31 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, 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 set_enemy_total_damage_hook: lwz r12, [r13 - ] andi. r12, r12, 0x0080 bnelr sth [r1 + 0x0E], r3 blr code_end: .data 0x00000000 .data 0x00000000