- Secret Fortune Teller Room: arcade lantern toggle, sliding timber panel, dedicated staircase and compact cellar chamber - Lived-in den pass v3: cloth hangings, draped workbench, props/clutter, centered entrance, and custom light sources - Bar camera stabilization: remove alcohol horizon sway while retaining drink animations - Synchronize binaries and update launcher hash to EADBA9C8C9BD5B7E3CC4CE486ED647C1CE9383D1DCB6EBC94FE755EA1F4BF927
359 lines
8.1 KiB
PHP
359 lines
8.1 KiB
PHP
; Hysteresis and a hold timer keep the shared doorway safe on both sides.
|
|
UpdateBasementDoor3D PROC uses ebx
|
|
local nearDoor:DWORD,rangeX:DWORD,rangeY:DWORD
|
|
mov nearDoor,0
|
|
mov rangeX,FP_1*12/5
|
|
mov rangeY,FP_1*7/5
|
|
mov eax,basementDoorTarget3D
|
|
or eax,basementDoorOpen3D
|
|
or eax,basementWheelTime3D
|
|
jz @F
|
|
mov rangeX,3*FP_1
|
|
mov rangeY,FP_1*9/5
|
|
@@:
|
|
cmp engineMode,MODE_WALK
|
|
jne steel_approach_stairs
|
|
cmp hallLevel3D,0
|
|
jne steel_door_clock
|
|
mov eax,playerX
|
|
sub eax,FP_1*289/10
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,rangeX
|
|
ja steel_door_clock
|
|
mov eax,playerY
|
|
sub eax,FP_1*105/10
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,rangeY
|
|
ja steel_door_clock
|
|
jmp steel_request_open
|
|
steel_approach_stairs:
|
|
cmp engineMode,MODE_STAIRS
|
|
jne steel_door_clock
|
|
cmp stairRoute3D,1
|
|
jne steel_door_clock
|
|
mov eax,5*FP_1
|
|
cmp rangeX,3*FP_1
|
|
jne @F
|
|
mov eax,FP_1*13/2
|
|
@@:
|
|
cmp playerX,eax
|
|
ja steel_door_clock
|
|
cmp playerY,FP_1*195/10
|
|
jb steel_door_clock
|
|
cmp playerY,FP_1*235/10
|
|
ja steel_door_clock
|
|
steel_request_open:
|
|
mov nearDoor,1
|
|
mov basementDoorTarget3D,FP_1
|
|
mov basementDoorHold3D,1200
|
|
steel_door_clock:
|
|
mov eax,animationClock3D
|
|
cmp eax,interiorDoorClock3D
|
|
je steel_update_done
|
|
mov interiorDoorClock3D,eax
|
|
mov ebx,deltaTime3D
|
|
cmp ebx,100
|
|
jbe @F
|
|
mov ebx,100
|
|
@@:
|
|
cmp nearDoor,1
|
|
je steel_animate
|
|
; A manual E request outside the automatic opening radius still gets time.
|
|
cmp basementDoorTarget3D,FP_1
|
|
jne steel_far_hold
|
|
cmp basementDoorHold3D,0
|
|
jne steel_far_hold
|
|
mov eax,basementDoorOpen3D
|
|
or eax,basementWheelTime3D
|
|
jnz steel_far_hold
|
|
mov basementDoorHold3D,2000
|
|
steel_far_hold:
|
|
cmp basementDoorHold3D,0
|
|
je steel_request_close
|
|
mov eax,basementDoorHold3D
|
|
sub eax,ebx
|
|
jae @F
|
|
xor eax,eax
|
|
@@:
|
|
mov basementDoorHold3D,eax
|
|
jmp steel_animate
|
|
steel_request_close:
|
|
mov basementDoorTarget3D,0
|
|
steel_animate:
|
|
cmp basementDoorTarget3D,0
|
|
je steel_close_leaf
|
|
cmp basementWheelTime3D,700
|
|
jae steel_swing
|
|
mov eax,700
|
|
sub eax,basementWheelTime3D
|
|
cmp ebx,eax
|
|
jb steel_wheel_partial
|
|
sub ebx,eax
|
|
mov basementWheelTime3D,700
|
|
jmp steel_swing
|
|
steel_wheel_partial:
|
|
add basementWheelTime3D,ebx
|
|
jmp steel_update_done
|
|
steel_swing:
|
|
; Opening: unlock first, then swing around the fixed hinge over 1000ms.
|
|
imul eax,ebx,FP_1
|
|
xor edx,edx
|
|
mov ecx,1000
|
|
div ecx
|
|
add eax,basementDoorOpen3D
|
|
cmp eax,FP_1
|
|
jbe @F
|
|
mov eax,FP_1
|
|
@@:
|
|
mov basementDoorOpen3D,eax
|
|
jmp steel_update_done
|
|
steel_close_leaf:
|
|
cmp basementDoorOpen3D,0
|
|
je steel_lock_wheel
|
|
; Carry unused milliseconds into locking only after the leaf is fully shut.
|
|
imul eax,basementDoorOpen3D,1000
|
|
add eax,FP_1-1
|
|
shr eax,16
|
|
cmp ebx,eax
|
|
jb steel_close_partial
|
|
sub ebx,eax
|
|
mov basementDoorOpen3D,0
|
|
jmp steel_lock_wheel
|
|
steel_close_partial:
|
|
imul eax,ebx,FP_1
|
|
xor edx,edx
|
|
mov ecx,1000
|
|
div ecx
|
|
sub basementDoorOpen3D,eax
|
|
jmp steel_update_done
|
|
steel_lock_wheel:
|
|
mov eax,basementWheelTime3D
|
|
sub eax,ebx
|
|
jae @F
|
|
xor eax,eax
|
|
@@:
|
|
mov basementWheelTime3D,eax
|
|
steel_update_done:
|
|
ret
|
|
UpdateBasementDoor3D ENDP
|
|
|
|
; The shared doorway occupies the overlapping landing in both local maps.
|
|
StairDoorCanWalk3D PROC px:DWORD,py:DWORD
|
|
cmp stairRoute3D,1
|
|
jne stair_steel_clear
|
|
cmp px,FP_1*35/10
|
|
jb stair_steel_clear
|
|
cmp px,FP_1*42/10
|
|
ja stair_steel_clear
|
|
cmp py,FP_1*2025/100
|
|
jb stair_steel_blocked
|
|
cmp py,FP_1*2175/100
|
|
jae stair_steel_blocked
|
|
mov eax,px
|
|
add eax,25*FP_1
|
|
mov edx,py
|
|
sub edx,FP_1*21/2
|
|
invoke InteriorDoorCanWalk3D,eax,edx
|
|
ret
|
|
stair_steel_blocked:
|
|
xor eax,eax
|
|
ret
|
|
stair_steel_clear:
|
|
mov eax,1
|
|
ret
|
|
StairDoorCanWalk3D ENDP
|
|
|
|
RenderStairDoor3D PROC
|
|
local oldX:DWORD,oldY:DWORD,oldEye:DWORD
|
|
cmp stairRoute3D,1
|
|
jne stair_steel_done
|
|
; Fill the wider landing around the actual narrow doorway on the stair side.
|
|
invoke DrawCityBoxSides3D,FP_1*375/100,4*FP_1,20*FP_1,FP_1*2025/100,FP_1*3/2,FP_1*37/10,92
|
|
invoke DrawCityBoxSides3D,FP_1*375/100,4*FP_1,FP_1*2175/100,23*FP_1,FP_1*3/2,FP_1*37/10,92
|
|
mov eax,playerX
|
|
mov oldX,eax
|
|
add playerX,25*FP_1
|
|
mov eax,playerY
|
|
mov oldY,eax
|
|
sub playerY,FP_1*21/2
|
|
mov eax,viewEye3D
|
|
mov oldEye,eax
|
|
sub viewEye3D,FP_1*3/2
|
|
invoke DrawCityVertical3D,0,FP_1*2838/100,9*FP_1,12*FP_1,-FP_1/10,FP_1*21/10,131
|
|
call DrawBasementLeaf3D
|
|
mov eax,oldX
|
|
mov playerX,eax
|
|
mov eax,oldY
|
|
mov playerY,eax
|
|
mov eax,oldEye
|
|
mov viewEye3D,eax
|
|
stair_steel_done:
|
|
ret
|
|
RenderStairDoor3D ENDP
|
|
|
|
; Perspective-correct vertical plane with a rotating horizontal basis. The wheel
|
|
; is baked into offline texture phases, not rotated in screen space at runtime.
|
|
DrawBasementLeaf3D PROC uses ebx esi edi
|
|
local ux:DWORD,uy:DWORD,nx:DWORD,ny:DWORD,numerator:DWORD
|
|
local depth:DWORD,texture:DWORD,sourceX:DWORD,top:DWORD,bottom:DWORD
|
|
local stepY:DWORD,sourceY:DWORD,row:DWORD,column:DWORD,destination:DWORD
|
|
invoke ResolveUpperMaterial3D,128
|
|
test eax,eax
|
|
jz steel_leaf_done
|
|
mov texture,eax
|
|
mov eax,basementDoorOpen3D
|
|
imul eax,128
|
|
shr eax,16
|
|
and eax,511
|
|
mov ecx,tableSin[eax*4]
|
|
mov ux,ecx
|
|
neg ecx
|
|
mov ny,ecx
|
|
mov ecx,tableCos[eax*4]
|
|
mov uy,ecx
|
|
mov nx,ecx
|
|
mov eax,FP_1*289/10
|
|
sub eax,playerX
|
|
imul nx
|
|
shrd eax,edx,16
|
|
mov ebx,eax
|
|
mov eax,FP_1*975/100
|
|
sub eax,playerY
|
|
imul ny
|
|
shrd eax,edx,16
|
|
add eax,ebx
|
|
mov numerator,eax
|
|
mov column,0
|
|
steel_leaf_column:
|
|
mov ebx,column
|
|
mov eax,cityRayX3D[ebx*4]
|
|
imul nx
|
|
shrd eax,edx,16
|
|
mov esi,eax
|
|
mov eax,cityRayY3D[ebx*4]
|
|
imul ny
|
|
shrd eax,edx,16
|
|
add eax,esi
|
|
mov ecx,eax
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,256
|
|
jb steel_leaf_next_column
|
|
mov eax,numerator
|
|
cdq
|
|
shld edx,eax,16
|
|
shl eax,16
|
|
idiv ecx
|
|
cmp eax,4096
|
|
jle steel_leaf_next_column
|
|
cmp eax,zBuffer[ebx*4]
|
|
jae steel_leaf_next_column
|
|
cmp portalRendering3D,0
|
|
je @F
|
|
cmp eax,portalClipDepth3D[ebx*4]
|
|
jb steel_leaf_next_column
|
|
@@:
|
|
mov depth,eax
|
|
imul cityRayX3D[ebx*4]
|
|
shrd eax,edx,16
|
|
add eax,playerX
|
|
sub eax,FP_1*289/10
|
|
imul ux
|
|
shrd eax,edx,16
|
|
mov esi,eax
|
|
mov eax,depth
|
|
imul cityRayY3D[ebx*4]
|
|
shrd eax,edx,16
|
|
add eax,playerY
|
|
sub eax,FP_1*975/100
|
|
imul uy
|
|
shrd eax,edx,16
|
|
add eax,esi
|
|
test eax,eax
|
|
js steel_leaf_next_column
|
|
cmp eax,FP_1*3/2
|
|
jae steel_leaf_next_column
|
|
imul eax,256
|
|
xor edx,edx
|
|
mov ecx,FP_1*3/2
|
|
div ecx
|
|
mov sourceX,eax
|
|
mov eax,viewEye3D
|
|
sub eax,FP_1*19/10
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv depth
|
|
add eax,viewHorizon3D
|
|
mov top,eax
|
|
mov eax,viewEye3D
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv depth
|
|
add eax,viewHorizon3D
|
|
mov bottom,eax
|
|
sub eax,top
|
|
jle steel_leaf_next_column
|
|
mov ecx,eax
|
|
mov eax,512*FP_1
|
|
xor edx,edx
|
|
div ecx
|
|
mov stepY,eax
|
|
mov eax,top
|
|
test eax,eax
|
|
jns @F
|
|
xor eax,eax
|
|
@@:
|
|
mov row,eax
|
|
sub eax,top
|
|
imul eax,stepY
|
|
mov sourceY,eax
|
|
cmp bottom,SCREEN_H
|
|
jle @F
|
|
mov bottom,SCREEN_H
|
|
@@:
|
|
mov eax,row
|
|
cmp eax,bottom
|
|
jge steel_leaf_next_column
|
|
imul eax,SCREEN_W
|
|
add eax,column
|
|
shl eax,2
|
|
mov destination,eax
|
|
steel_leaf_pixel:
|
|
mov edi,destination
|
|
mov eax,depth
|
|
cmp eax,cityDepthBuffer3D[edi]
|
|
ja steel_leaf_next_pixel
|
|
mov eax,sourceY
|
|
shr eax,16
|
|
cmp eax,512
|
|
jae steel_leaf_next_pixel
|
|
shl eax,8
|
|
add eax,sourceX
|
|
mov esi,texture
|
|
mov eax,[esi+eax*4]
|
|
cmp eax,80000000h
|
|
jb steel_leaf_next_pixel
|
|
and eax,00FFFFFFh
|
|
mov screenBuffer[edi],eax
|
|
mov eax,depth
|
|
mov cityDepthBuffer3D[edi],eax
|
|
steel_leaf_next_pixel:
|
|
mov eax,stepY
|
|
add sourceY,eax
|
|
add destination,SCREEN_W*4
|
|
inc row
|
|
mov eax,row
|
|
cmp eax,bottom
|
|
jb steel_leaf_pixel
|
|
steel_leaf_next_column:
|
|
inc column
|
|
cmp column,SCREEN_W
|
|
jb steel_leaf_column
|
|
steel_leaf_done:
|
|
ret
|
|
DrawBasementLeaf3D ENDP
|