Skip to content

Clamp path velocity only when it exceeds the maximum - #258

Open
ResurrectedTrader wants to merge 1 commit into
ThePhrozenKeep:masterfrom
ResurrectedTrader:fix/path-acceleration-clamp
Open

ResurrectedTrader wants to merge 1 commit into
ThePhrozenKeep:masterfrom
ResurrectedTrader:fix/path-acceleration-clamp

Conversation

@ResurrectedTrader

Copy link
Copy Markdown
Contributor

sub_6FD5CEB0 clamped dwVelocity and cleared dwAcceleration as soon as the velocity reached dwMaxVelocity. The game does that only when the velocity exceeds it; at exactly the maximum the acceleration is kept.

1.10f

Inlined in D2Common_10226 (D2Common.0x6FDAC9A0), Hex-Rays (v2 = pDynamicPath; +124 dwVelocity, +132 dwMaxVelocity, +136 dwAcceleration, +140 dwAccelerationsCounter):

v15 = a2;
if ( a2 <= 0 )
  v15 = 1024;
v16 = *(_DWORD *)(v2 + 136);
if ( v16 != 0 )
{
  v17 = *(_DWORD *)(v2 + 140) + 1;
  *(_DWORD *)(v2 + 140) = v17;
  if ( v17 >= 5 )
  {
    v18 = v16 + *(_DWORD *)(v2 + 124);
    v19 = *(_DWORD *)(v2 + 132);
    *(_DWORD *)(v2 + 124) = v18;
    if ( v18 <= v19 )                      // <== at the maximum: keep accelerating
    {
      if ( v18 < 0 )
        *(_DWORD *)(v2 + 124) = 0;
    }
    else                                   // <== only above it: clamp
    {
      *(_DWORD *)(v2 + 124) = v19;
      *(_DWORD *)(v2 + 136) = 0;
    }
    *(_DWORD *)(v2 + 140) = 0;
  }
}
v20 = (v15 * *(_DWORD *)(v2 + 124)) >> 6;
6FDACB60  mov     eax, [esi+88h]                    ; dwAcceleration
6FDACB66  cmp     eax, ebx
6FDACB68  jz      short loc_6FDACBAA
6FDACB6A  mov     edi, [esi+8Ch]                    ; dwAccelerationsCounter
6FDACB70  inc     edi
6FDACB71  mov     ecx, edi
6FDACB73  mov     [esi+8Ch], edi
6FDACB79  cmp     ecx, 5
6FDACB7C  jl      short loc_6FDACBAA
6FDACB7E  mov     ebp, [esi+7Ch]                    ; dwVelocity
6FDACB81  add     ebp, eax
6FDACB83  mov     eax, [esi+84h]                    ; dwMaxVelocity
6FDACB89  mov     ecx, ebp
6FDACB8B  mov     [esi+7Ch], ebp
6FDACB8E  cmp     ecx, eax
6FDACB90  jle     short loc_6FDACB9D                ; <== <= max: no clamp
6FDACB92  mov     [esi+7Ch], eax
6FDACB95  mov     [esi+88h], ebx                    ; dwAcceleration = 0
6FDACB9B  jmp     short loc_6FDACBA4
6FDACB9D  cmp     ecx, ebx
6FDACB9F  jge     short loc_6FDACBA4
6FDACBA1  mov     [esi+7Ch], ebx
6FDACBA4  mov     [esi+8Ch], ebx

1.14d

PATH_UpdateVelocityWithAcceleration (Game.exe 0x006502D0), Hex-Rays:

v3 = result[34];
if ( v3 != 0 && (int)++result[35] >= 5 )
{
  result[31] += v3;
  v4 = result[31];
  v5 = result[33];
  if ( v4 <= v5 )                          // <== at the maximum: keep accelerating
  {
    if ( v4 < 0 )
      result[31] = 0;
  }
  else
  {
    result[31] = v5;
    result[34] = 0;
  }
  result[35] = 0;
}
006502F6  add     [eax+7Ch], ecx
006502F9  mov     edx, [eax+7Ch]
006502FC  mov     ecx, [eax+84h]
00650302  cmp     edx, ecx
00650304  jle     short loc_650315                  ; <== <= max: no clamp
00650306  mov     [eax+7Ch], ecx
00650309  mov     dword ptr [eax+88h], 0

Change

if (pDynamicPath->dwVelocity > nOldVelocity). Not version-gated, since 1.10f and 1.14d agree; I have not checked 1.13c, whose address the function is annotated with. Also adds the 1.14d address.

🤖 Generated with Claude Code

sub_6FD5CEB0 clamped dwVelocity and cleared dwAcceleration when the
velocity reached dwMaxVelocity. The game does that only when the
velocity exceeds it; at exactly the maximum the acceleration is kept.

1.10f inlines this in D2Common_10226 (0x6FDAC9A0), Hex-Rays (v2 =
pDynamicPath; +124 dwVelocity, +132 dwMaxVelocity, +136 dwAcceleration,
+140 dwAccelerationsCounter):

    v16 = *(_DWORD *)(v2 + 136);
    if ( v16 != 0 )
    {
        v17 = *(_DWORD *)(v2 + 140) + 1;
        *(_DWORD *)(v2 + 140) = v17;
        if ( v17 >= 5 )
        {
            v18 = v16 + *(_DWORD *)(v2 + 124);
            v19 = *(_DWORD *)(v2 + 132);
            *(_DWORD *)(v2 + 124) = v18;
            if ( v18 <= v19 )
            {
                if ( v18 < 0 )
                    *(_DWORD *)(v2 + 124) = 0;
            }
            else
            {
                *(_DWORD *)(v2 + 124) = v19;
                *(_DWORD *)(v2 + 136) = 0;
            }
            *(_DWORD *)(v2 + 140) = 0;
        }
    }

Disassembly:

    6FDACB7E  mov  ebp, [esi+7Ch]      ; dwVelocity
    6FDACB81  add  ebp, eax            ; + dwAcceleration
    6FDACB83  mov  eax, [esi+84h]      ; dwMaxVelocity
    6FDACB89  mov  ecx, ebp
    6FDACB8B  mov  [esi+7Ch], ebp
    6FDACB8E  cmp  ecx, eax
    6FDACB90  jle  6FDACB9D            ; <= max: keep acceleration
    6FDACB92  mov  [esi+7Ch], eax
    6FDACB95  mov  [esi+88h], ebx      ; dwAcceleration = 0

1.14d (Game.exe 0x006502D0) is the same: if ( v4 <= v5 ) ... else
{ clamp; result[34] = 0; }, 0x00650302 cmp edx, ecx / jle. 1.13c was
not checked.

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