Decouple gameplay from presentation and preserve signed movement fractions. Separate cinematic camera ownership with safe body handoff and transactional current-room restarts. Resample input latches on focus regain, discard modal timing debt, and attach cinematic lighting to the view to match editor preview. Verify editor 137/137 and ASM 288/288, cinematic traces, RGB bake and IPC framebuffer parity without changing project assets.
222 lines
4.5 KiB
PHP
222 lines
4.5 KiB
PHP
; Fixed-tick player simulation. Wire coordinates remain raw world units.
|
|
.code
|
|
StartCutscene PROTO
|
|
StopCutscene PROTO
|
|
UpdateCutscene PROTO
|
|
|
|
IsGameplayBlocked PROC
|
|
mov eax, gameplayTickBlocked
|
|
or eax, isPlayerDead
|
|
or eax, isCutsceneActive
|
|
or eax, cutscenePending
|
|
or eax, fadeState
|
|
or eax, isGamePaused
|
|
or eax, gameDialogActive
|
|
ret
|
|
IsGameplayBlocked ENDP
|
|
|
|
ResetMovementFractions PROC
|
|
mov playerFractionX, 0
|
|
mov playerFractionY, 0
|
|
ret
|
|
ResetMovementFractions ENDP
|
|
|
|
; Test every overlapped cell, not only the leading edge's center. Portal cells
|
|
; block rays but deliberately remain walkable for players/camera handoff.
|
|
CanOccupyPlayer PROC uses ebx ecx edx esi edi, x:DWORD, y:DWORD
|
|
LOCAL minX:DWORD, maxX:DWORD, maxY:DWORD, row:DWORD
|
|
mov eax, x
|
|
sub eax, playerRadius
|
|
sar eax, CELL_SHIFT
|
|
mov minX, eax
|
|
mov eax, x
|
|
add eax, playerRadius
|
|
sar eax, CELL_SHIFT
|
|
mov maxX, eax
|
|
mov eax, y
|
|
sub eax, playerRadius
|
|
sar eax, CELL_SHIFT
|
|
mov row, eax
|
|
mov eax, y
|
|
add eax, playerRadius
|
|
sar eax, CELL_SHIFT
|
|
mov maxY, eax
|
|
body_row:
|
|
mov ebx, minX
|
|
body_cell:
|
|
invoke GetMapCell, ebx, row
|
|
cmp eax, CELL_PORTAL
|
|
je body_next
|
|
invoke IsSolidCell, eax
|
|
test eax, eax
|
|
jnz body_blocked
|
|
body_next:
|
|
inc ebx
|
|
cmp ebx, maxX
|
|
jle body_cell
|
|
inc row
|
|
mov eax, row
|
|
cmp eax, maxY
|
|
jle body_row
|
|
mov eax, 1
|
|
ret
|
|
body_blocked:
|
|
xor eax, eax
|
|
ret
|
|
CanOccupyPlayer ENDP
|
|
|
|
UpdatePlayer PROC uses ebx ecx edx esi edi
|
|
LOCAL forward:SDWORD, strafe:SDWORD, speed:DWORD
|
|
LOCAL moveX:SDWORD, moveY:SDWORD, steps:DWORD
|
|
mov gameplayTickBlocked, 1
|
|
cmp isGamePaused, 0
|
|
jne player_done
|
|
cmp gameDialogActive, 0
|
|
jne player_done
|
|
cmp isPlayerDead, 0
|
|
jne player_done
|
|
cmp fadeState, 0
|
|
jne player_done
|
|
cmp cutscenePending, 0
|
|
je @F
|
|
call StartCutscene
|
|
@@:
|
|
cmp keyCutscene, 0
|
|
je @F
|
|
cmp isCutsceneActive, 0
|
|
jne @F
|
|
call StartCutscene
|
|
@@:
|
|
cmp isCutsceneActive, 0
|
|
je player_active
|
|
cmp keySkipScene, 0
|
|
je player_scene
|
|
call StopCutscene
|
|
ret
|
|
player_scene:
|
|
call UpdateCutscene
|
|
ret
|
|
player_active:
|
|
mov gameplayTickBlocked, 0
|
|
movzx eax, keyTurnRight
|
|
movzx ebx, keyTurnLeft
|
|
sub eax, ebx
|
|
imul eax, playerTurnSpeed
|
|
add eax, playerAngle
|
|
and eax, ANGLE_MASK
|
|
mov playerAngle, eax
|
|
cmp keyAction, 0
|
|
je @F
|
|
call InteractDoor
|
|
call IsGameplayBlocked
|
|
test eax, eax
|
|
jnz player_done
|
|
@@:
|
|
movzx eax, keyForward
|
|
movzx ebx, keyBackward
|
|
sub eax, ebx
|
|
mov forward, eax
|
|
movzx eax, keyStrafeRight
|
|
movzx ebx, keyStrafeLeft
|
|
sub eax, ebx
|
|
mov strafe, eax
|
|
or eax, forward
|
|
jz player_done
|
|
mov eax, playerMoveSpeed
|
|
cmp keyRun, 0
|
|
je @F
|
|
mov eax, playerRunSpeed
|
|
@@:
|
|
shl eax, 16
|
|
cmp forward, 0
|
|
je speed_ready
|
|
cmp strafe, 0
|
|
je speed_ready
|
|
; 1/sqrt(2), 16.16. Product may exceed 32 bits.
|
|
mov ebx, 46341
|
|
imul ebx
|
|
shrd eax, edx, 16
|
|
speed_ready:
|
|
mov speed, eax
|
|
mov ecx, playerAngle
|
|
mov eax, [tableCos+ecx*4]
|
|
imul eax, forward
|
|
mov ebx, [tableSin+ecx*4]
|
|
imul ebx, strafe
|
|
sub eax, ebx
|
|
imul speed
|
|
mov ebx, FIXED_ONE
|
|
idiv ebx
|
|
add eax, playerFractionX
|
|
cdq
|
|
mov ebx, FIXED_ONE
|
|
idiv ebx
|
|
mov moveX, eax
|
|
mov playerFractionX, edx
|
|
mov eax, [tableSin+ecx*4]
|
|
imul eax, forward
|
|
mov ebx, [tableCos+ecx*4]
|
|
imul ebx, strafe
|
|
add eax, ebx
|
|
imul speed
|
|
mov ebx, FIXED_ONE
|
|
idiv ebx
|
|
add eax, playerFractionY
|
|
cdq
|
|
mov ebx, FIXED_ONE
|
|
idiv ebx
|
|
mov moveY, eax
|
|
mov playerFractionY, edx
|
|
; Unit substeps prevent tunneling even when scripts increase speed.
|
|
mov steps, 0
|
|
player_step:
|
|
mov eax, moveX
|
|
or eax, moveY
|
|
jz player_done
|
|
inc steps
|
|
cmp steps, 64
|
|
ja player_done
|
|
cmp moveX, 0
|
|
je step_y
|
|
mov esi, 1
|
|
jg @F
|
|
mov esi, -1
|
|
@@:
|
|
mov ebx, playerX
|
|
add ebx, esi
|
|
invoke CanOccupyPlayer, ebx, playerY
|
|
test eax, eax
|
|
jz blocked_x
|
|
mov playerX, ebx
|
|
sub moveX, esi
|
|
jmp step_y
|
|
blocked_x:
|
|
mov moveX, 0
|
|
mov playerFractionX, 0
|
|
step_y:
|
|
cmp moveY, 0
|
|
je player_step
|
|
mov esi, 1
|
|
jg @F
|
|
mov esi, -1
|
|
@@:
|
|
mov ebx, playerY
|
|
add ebx, esi
|
|
invoke CanOccupyPlayer, playerX, ebx
|
|
test eax, eax
|
|
jz blocked_y
|
|
mov playerY, ebx
|
|
sub moveY, esi
|
|
jmp player_step
|
|
blocked_y:
|
|
mov moveY, 0
|
|
mov playerFractionY, 0
|
|
jmp player_step
|
|
player_done:
|
|
call IsGameplayBlocked
|
|
test eax, eax
|
|
jnz @F
|
|
call CheckPortalTriggers
|
|
@@:
|
|
ret
|
|
UpdatePlayer ENDP
|