Skip to content

Fix UNITS_IsAnimModeGetHit testing the block modes - #241

Open
ResurrectedTrader wants to merge 1 commit into
ThePhrozenKeep:masterfrom
ResurrectedTrader:fix/units-gethit-anim-mode
Open

ResurrectedTrader wants to merge 1 commit into
ThePhrozenKeep:masterfrom
ResurrectedTrader:fix/units-gethit-anim-mode

Conversation

@ResurrectedTrader

Copy link
Copy Markdown
Contributor

UNITS_IsAnimModeGetHit compares against PLRMODE_BLOCK / MONMODE_BLOCK, which makes it a copy of UNITS_IsAnimModeBlocking. Because the block test runs first in UNITS_UpdateAnimRateAndVelocity, the get-hit branch can never be reached, and a get-hit plays at the default rate instead of (faster hit recovery + 50)%.

1.10f

Both checks are inlined in UNITS_UpdateAnimRateAndVelocity (D2Common.0x6FDBF050, #10376). The block test (player 9 / monster 6) goes to STAT_ITEM_FASTERBLOCKRATE (0x66). The get-hit test after it uses player 4 / monster 3 and goes to STAT_ITEM_FASTERGETHITRATE (0x63) + 50:

6FDBF1F5  mov     edx, ecx                          ; unit type
6FDBF1F7  sub     edx, 0
6FDBF1FA  jz      short loc_6FDBF21C
6FDBF1FC  dec     edx
6FDBF1FD  jnz     short loc_6FDBF204
6FDBF1FF  cmp     eax, 6                            ; monster: MONMODE_BLOCK (6)
6FDBF202  jz      short loc_6FDBF221                ; -> block rate
6FDBF204  mov     edx, ecx
6FDBF206  sub     edx, 0
6FDBF209  jz      short loc_6FDBF285
6FDBF20B  dec     edx
6FDBF20C  jnz     loc_6FDBF2BE
6FDBF212  cmp     eax, 3                            ; <== monster: MONMODE_GETHIT (3)
6FDBF215  jz      short loc_6FDBF28A                ; <== -> get-hit rate
6FDBF217  jmp     loc_6FDBF2BE
6FDBF21C  cmp     eax, 9                            ; player: PLRMODE_BLOCK (9)
6FDBF21F  jnz     short loc_6FDBF204
6FDBF221  push    0
6FDBF223  push    66h                               ; STAT_ITEM_FASTERBLOCKRATE
6FDBF225  push    ebp
6FDBF226  call    D2Common_10520
6FDBF22B  mov     esi, eax
6FDBF22D  test    esi, esi
6FDBF22F  jz      short loc_6FDBF242
6FDBF231  lea     eax, [esi+esi*2]
6FDBF234  add     esi, 78h
6FDBF237  lea     eax, [eax+eax*4]
6FDBF23A  shl     eax, 3
6FDBF23D  cdq
6FDBF23E  idiv    esi
6FDBF240  mov     esi, eax
6FDBF242  push    65h
6FDBF244  push    ebp
6FDBF245  mov     edi, 32h
6FDBF24A  call    D2Common_10487
6FDBF24F  test    eax, eax
6FDBF251  jz      short loc_6FDBF258
6FDBF253  mov     edi, 64h
6FDBF258  add     esi, edi
6FDBF25A  mov     eax, 51EB851Fh
6FDBF25F  imul    esi, [ebx+0Ch]
6FDBF263  mul     esi
6FDBF265  shr     edx, 5
6FDBF268  cmp     edx, 1
6FDBF26B  jge     short loc_6FDBF27C
6FDBF26D  mov     eax, 1
6FDBF272  cmp     eax, 7FFFh
6FDBF277  jmp     loc_6FDBF8B9
6FDBF27C  mov     eax, edx
6FDBF27E  test    edx, edx
6FDBF280  jmp     loc_6FDBF865
6FDBF285  cmp     eax, 4                            ; <== player: PLRMODE_GETHIT (4)
6FDBF288  jnz     short loc_6FDBF2BE
6FDBF28A  push    0
6FDBF28C  push    63h                               ; STAT_ITEM_FASTERGETHITRATE
6FDBF28E  push    ebp
6FDBF28F  call    D2Common_10520
6FDBF294  mov     ecx, eax
6FDBF296  test    ecx, ecx
6FDBF298  jz      short loc_6FDBF2AB
6FDBF29A  lea     eax, [ecx+ecx*2]
6FDBF29D  add     ecx, 78h
6FDBF2A0  lea     eax, [eax+eax*4]
6FDBF2A3  shl     eax, 3
6FDBF2A6  cdq
6FDBF2A7  idiv    ecx
6FDBF2A9  mov     ecx, eax
6FDBF2AB  add     ecx, 32h                          ; + 50
6FDBF2AE  mov     eax, 51EB851Fh
6FDBF2B3  imul    ecx, [ebx+0Ch]                    ; * pAnimData->dwAnimSpeed
6FDBF2B7  mul     ecx
6FDBF2B9  jmp     loc_6FDBF8AA

1.14d

The same in Game.exe 0x623F50:

00624089  mov     ecx, ebx
0062408B  sub     ecx, 0
0062408E  jz      short loc_62409A
00624090  sub     ecx, 1
00624093  jnz     short loc_6240B6
00624095  cmp     eax, 3                            ; <== monster: MONMODE_GETHIT (3)
00624098  jmp     short loc_62409D
0062409A  cmp     eax, 4                            ; <== player: PLRMODE_GETHIT (4)
0062409D  jnz     short loc_6240B6
0062409F  mov     eax, 1
006240A4  mov     ecx, edi
006240A6  call    GetDiminishedStat                 ; faster hit recovery
006240AB  mov     ecx, [esi+0Ch]
006240AE  add     eax, 32h                          ; + 50
006240B1  jmp     loc_62435C

A 1.14d replay shows the effect: a monster's get-hit wAnimSpeed was 152 with MOO and 76 on the real client, with the same dwFrameCountPrecise, so MOO's get-hit finished twice as fast.

Change

Compare against PLRMODE_GETHIT / MONMODE_GETHIT.

🤖 Generated with Claude Code

UNITS_IsAnimModeGetHit compared against PLRMODE_BLOCK / MONMODE_BLOCK,
which makes it a copy of UNITS_IsAnimModeBlocking. Since the block test
runs first in UNITS_UpdateAnimRateAndVelocity, the get-hit branch was
unreachable and a get-hit animation ran at the default rate instead of
(faster hit recovery + 50)%.

In 1.10f the check is inlined in UNITS_UpdateAnimRateAndVelocity
(D2Common.0x6FDBF050): after the block test (player 9 / monster 6) it
compares player mode 4 (0x6FDBF285) and monster mode 3 (0x6FDBF212),
then reads STAT_ITEM_FASTERGETHITRATE and adds 50. 1.14d does the same
(Game.exe.0x624095 / 0x62409A).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant