997 lines
26 KiB
PHP
997 lines
26 KiB
PHP
; Connected stairwells use the normal player movement and body collision routines.
|
|
; Only room-local coordinates are translated at a landing, never by a timer.
|
|
ResolveUpperMaterial3D PROC material:DWORD
|
|
cmp material,131
|
|
jne @F
|
|
mov eax,basementDoorArt3D.pixels
|
|
test eax,eax
|
|
jz upper_material_missing
|
|
add eax,17*256*512*4
|
|
mov ecx,256
|
|
mov edx,512
|
|
ret
|
|
@@:
|
|
cmp material,129
|
|
jne @F
|
|
mov eax,upperPortal3D.frame
|
|
imul eax,256*512*4
|
|
cmp upperPortalArt3D.pixels,0
|
|
je upper_material_missing
|
|
add eax,upperPortalArt3D.pixels
|
|
mov ecx,256
|
|
mov edx,512
|
|
ret
|
|
@@:
|
|
cmp material,130
|
|
jne @F
|
|
mov eax,OFFSET upperGlowPixels3D
|
|
mov ecx,32
|
|
mov edx,32
|
|
ret
|
|
@@:
|
|
cmp material,128
|
|
jne upper_material_not_door
|
|
cmp basementDoorArt3D.pixels,0
|
|
je upper_material_missing
|
|
imul eax,basementWheelTime3D,16
|
|
xor edx,edx
|
|
mov ecx,700
|
|
div ecx
|
|
cmp eax,16
|
|
jbe @F
|
|
mov eax,16
|
|
@@:
|
|
imul eax,256*512*4
|
|
add eax,basementDoorArt3D.pixels
|
|
mov ecx,256
|
|
mov edx,512
|
|
ret
|
|
upper_material_not_door:
|
|
cmp material,126
|
|
jne @F
|
|
mov eax,OFFSET upperFeltPixels3D
|
|
mov ecx,32
|
|
mov edx,32
|
|
ret
|
|
@@:
|
|
cmp material,127
|
|
jne @F
|
|
mov eax,OFFSET upperKeyPixels3D
|
|
mov ecx,32
|
|
mov edx,32
|
|
ret
|
|
@@:
|
|
mov eax,upperMaterialArt3D.pixels
|
|
test eax,eax
|
|
jz upper_material_missing
|
|
mov ecx,material
|
|
sub ecx,122
|
|
cmp ecx,3
|
|
ja upper_material_missing
|
|
shl ecx,18
|
|
add eax,ecx
|
|
mov ecx,256
|
|
mov edx,256
|
|
ret
|
|
upper_material_missing:
|
|
xor eax,eax
|
|
ret
|
|
ResolveUpperMaterial3D ENDP
|
|
|
|
InitUpperSurfaces3D PROC uses esi
|
|
xor esi,esi
|
|
upper_surface_pixel:
|
|
; Small native material swatches, not a replacement external renderer.
|
|
mov eax,esi
|
|
imul eax,1103515245
|
|
xor eax,5A63h
|
|
and eax,7
|
|
add eax,0FF1B5039h
|
|
mov upperFeltPixels3D[esi*4],eax
|
|
and eax,7
|
|
add eax,0FF311114h
|
|
mov upperGlowPixels3D[esi*4],eax
|
|
mov eax,esi
|
|
and eax,31
|
|
and eax,3
|
|
cmp eax,3
|
|
je upper_key_dark
|
|
cmp esi,16*32
|
|
jae upper_key_white
|
|
test eax,eax
|
|
jz upper_key_dark
|
|
upper_key_white:
|
|
mov eax,0FFECE3C8h
|
|
jmp upper_key_store
|
|
upper_key_dark:
|
|
mov eax,0FF16191Bh
|
|
upper_key_store:
|
|
mov upperKeyPixels3D[esi*4],eax
|
|
inc esi
|
|
cmp esi,1024
|
|
jb upper_surface_pixel
|
|
ret
|
|
InitUpperSurfaces3D ENDP
|
|
|
|
DrawUpperGameTable3D PROC uses ebx esi edi centreX:DWORD,centreY:DWORD
|
|
local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,legX:DWORD,legY:DWORD
|
|
mov eax,centreX
|
|
sub eax,FP_1
|
|
mov x0,eax
|
|
add eax,2*FP_1
|
|
mov x1,eax
|
|
mov eax,centreY
|
|
sub eax,FP_1/2
|
|
mov y0,eax
|
|
add eax,FP_1
|
|
mov y1,eax
|
|
invoke DrawCityBoxSides3D,x0,x1,y0,y1,FP_1/2,FP_1*13/20,85
|
|
invoke DrawCityHorizontal3D,x0,x1,y0,y1,FP_1*13/20,85
|
|
mov eax,x0
|
|
add eax,FP_1/10
|
|
mov ebx,x1
|
|
sub ebx,FP_1/10
|
|
mov ecx,y0
|
|
add ecx,FP_1/10
|
|
mov edx,y1
|
|
sub edx,FP_1/10
|
|
invoke DrawCityHorizontal3D,eax,ebx,ecx,edx,FP_1*33/50,126
|
|
xor esi,esi
|
|
upper_table_leg:
|
|
mov eax,x0
|
|
add eax,FP_1/8
|
|
test esi,1
|
|
jz @F
|
|
mov eax,x1
|
|
sub eax,FP_1/4
|
|
@@:
|
|
mov legX,eax
|
|
mov eax,y0
|
|
add eax,FP_1/8
|
|
test esi,2
|
|
jz @F
|
|
mov eax,y1
|
|
sub eax,FP_1/4
|
|
@@:
|
|
mov legY,eax
|
|
mov ebx,legX
|
|
add ebx,FP_1/8
|
|
add eax,FP_1/8
|
|
invoke DrawCityBoxSides3D,legX,ebx,legY,eax,0,FP_1/2,85
|
|
inc esi
|
|
cmp esi,4
|
|
jb upper_table_leg
|
|
ret
|
|
DrawUpperGameTable3D ENDP
|
|
|
|
BeginWalkableStairs3D PROC route:DWORD,fromFarEnd:DWORD
|
|
mov eax,route
|
|
mov stairRoute3D,eax
|
|
mov engineMode,MODE_STAIRS
|
|
mov interactTargetId,0
|
|
mov interactPromptPtr,0
|
|
cmp route,1
|
|
jne interior_begin_upper
|
|
mov worldMap3D,OFFSET basementStairMap3D
|
|
mov floorTexture3D,94
|
|
sub playerX,25*FP_1
|
|
add playerY,FP_1*21/2
|
|
cmp fromFarEnd,0
|
|
je interior_begin_finish
|
|
add playerX,12*FP_1
|
|
sub playerY,32*FP_1
|
|
jmp interior_begin_finish
|
|
interior_begin_upper:
|
|
mov worldMap3D,OFFSET upperStairMap3D
|
|
mov floorTexture3D,85
|
|
sub playerX,27*FP_1
|
|
cmp fromFarEnd,0
|
|
je interior_begin_finish
|
|
add playerX,39*FP_1
|
|
interior_begin_finish:
|
|
call UpdateStairHeight3D
|
|
ret
|
|
BeginWalkableStairs3D ENDP
|
|
|
|
UpdateInteriorTravel3D PROC
|
|
call BowlingTravel3D
|
|
call UpdateBowling3D
|
|
cmp hallLevel3D,HALL_BOWLING
|
|
je interior_travel_done
|
|
call UpdateRoof3D
|
|
cmp hallLevel3D,HALL_ROOF
|
|
je interior_travel_done
|
|
call UpdateUpperEffects3D
|
|
call UpdateBasementDoor3D
|
|
call UpdateFortunePassage3D
|
|
interior_travel_check:
|
|
cmp engineMode,MODE_STAIRS
|
|
je interior_travel_stairs
|
|
cmp engineMode,MODE_WALK
|
|
jne interior_travel_done
|
|
cmp hallLevel3D,1
|
|
je interior_travel_bunker
|
|
cmp hallLevel3D,2
|
|
je interior_travel_upper
|
|
cmp hallLevel3D,3
|
|
je interior_travel_fortune_room
|
|
cmp fortunePassageTime3D,1400
|
|
jne interior_travel_east
|
|
cmp playerX,FP_1*14/10
|
|
ja interior_travel_east
|
|
cmp playerY,FP_1*92/10
|
|
jb interior_travel_east
|
|
cmp playerY,FP_1*108/10
|
|
ja interior_travel_east
|
|
add playerX,28*FP_1
|
|
mov stairRoute3D,3
|
|
mov engineMode,MODE_STAIRS
|
|
mov worldMap3D,OFFSET fortuneStairMap3D
|
|
mov floorTexture3D,134
|
|
call UpdateStairHeight3D
|
|
ret
|
|
interior_travel_east:
|
|
cmp playerY,20*FP_1
|
|
jb interior_travel_door
|
|
cmp playerY,22*FP_1
|
|
ja interior_travel_done
|
|
cmp playerX,FP_1*303/10
|
|
jb interior_travel_done
|
|
invoke BeginWalkableStairs3D,2,0
|
|
ret
|
|
interior_travel_door:
|
|
cmp basementDoorOpen3D,FP_1*9/10
|
|
jb interior_travel_done
|
|
cmp playerX,29*FP_1
|
|
jb interior_travel_done
|
|
cmp playerY,FP_1*99/10
|
|
jb interior_travel_done
|
|
cmp playerY,FP_1*111/10
|
|
ja interior_travel_done
|
|
invoke BeginWalkableStairs3D,1,0
|
|
ret
|
|
interior_travel_bunker:
|
|
cmp playerY,FP_1*277/10
|
|
jb interior_travel_done
|
|
; Bunker landing (16.5,27.7) continues to the stairwell (16.5,14.7).
|
|
sub playerY,13*FP_1
|
|
mov stairRoute3D,1
|
|
mov engineMode,MODE_STAIRS
|
|
mov worldMap3D,OFFSET basementStairMap3D
|
|
mov floorTexture3D,94
|
|
call UpdateStairHeight3D
|
|
ret
|
|
interior_travel_upper:
|
|
call TryWalkUpperPortal3D
|
|
cmp engineMode,MODE_WALK
|
|
jne interior_travel_done
|
|
cmp playerY,20*FP_1
|
|
jb interior_travel_done
|
|
cmp playerY,22*FP_1
|
|
ja interior_travel_done
|
|
cmp playerX,FP_1*32/10
|
|
ja interior_travel_done
|
|
; Upper west landing and the far east end of its stairwell share an axis.
|
|
add playerX,12*FP_1
|
|
mov stairRoute3D,2
|
|
mov engineMode,MODE_STAIRS
|
|
mov worldMap3D,OFFSET upperStairMap3D
|
|
mov floorTexture3D,85
|
|
call UpdateStairHeight3D
|
|
ret
|
|
interior_travel_fortune_room:
|
|
cmp playerX,FP_1*175/10
|
|
jb interior_travel_done
|
|
cmp playerY,10*FP_1
|
|
jb interior_travel_done
|
|
cmp playerY,12*FP_1
|
|
jae interior_travel_done
|
|
mov stairRoute3D,3
|
|
sub playerY,FP_1
|
|
mov engineMode,MODE_STAIRS
|
|
mov worldMap3D,OFFSET fortuneStairMap3D
|
|
mov floorTexture3D,134
|
|
call UpdateStairHeight3D
|
|
ret
|
|
interior_travel_stairs:
|
|
cmp stairRoute3D,3
|
|
je interior_fortune_thresholds
|
|
cmp stairRoute3D,1
|
|
jne interior_upper_thresholds
|
|
cmp playerX,FP_1*31/10
|
|
jbe interior_exit_basement_top
|
|
cmp playerY,FP_1*143/10
|
|
ja interior_travel_done
|
|
mov hallLevel3D,1
|
|
mov worldMap3D,OFFSET bunkerMap3D
|
|
add playerY,13*FP_1
|
|
mov floorTexture3D,94
|
|
jmp interior_finish
|
|
interior_exit_basement_top:
|
|
mov hallLevel3D,0
|
|
mov worldMap3D,OFFSET casinoMap
|
|
add playerX,25*FP_1
|
|
sub playerY,FP_1*21/2
|
|
mov floorTexture3D,100
|
|
jmp interior_finish
|
|
interior_upper_thresholds:
|
|
cmp playerX,FP_1*31/10
|
|
jbe interior_exit_upper_bottom
|
|
cmp playerX,16*FP_1
|
|
jb interior_travel_done
|
|
mov hallLevel3D,2
|
|
mov worldMap3D,OFFSET upperLoungeMap3D
|
|
sub playerX,12*FP_1
|
|
mov floorTexture3D,124
|
|
jmp interior_finish
|
|
interior_exit_upper_bottom:
|
|
mov hallLevel3D,0
|
|
mov worldMap3D,OFFSET casinoMap
|
|
add playerX,27*FP_1
|
|
mov floorTexture3D,100
|
|
jmp interior_finish
|
|
interior_fortune_thresholds:
|
|
cmp playerX,FP_1*2955/100
|
|
jae interior_fortune_top
|
|
cmp playerX,FP_1*172/10
|
|
ja interior_travel_done
|
|
mov hallLevel3D,3
|
|
add playerY,FP_1
|
|
mov worldMap3D,OFFSET fortuneRoomMap3D
|
|
mov floorTexture3D,134
|
|
jmp interior_finish
|
|
interior_fortune_top:
|
|
mov hallLevel3D,0
|
|
mov worldMap3D,OFFSET casinoMap
|
|
sub playerX,28*FP_1
|
|
mov floorTexture3D,100
|
|
interior_finish:
|
|
mov engineMode,MODE_WALK
|
|
mov interactTargetId,0
|
|
mov interactPromptPtr,0
|
|
call UpdateInteriorEye3D
|
|
interior_travel_done:
|
|
ret
|
|
UpdateInteriorTravel3D ENDP
|
|
|
|
UpdateStairHeight3D PROC
|
|
cmp engineMode,MODE_STAIRS
|
|
jne interior_height_done
|
|
mov viewHorizon3D,HALF_H
|
|
mov viewCeiling3D,FP_1*11/2
|
|
cmp stairRoute3D,3
|
|
jne @F
|
|
mov viewCeiling3D,4*FP_1
|
|
mov eax,playerX
|
|
sub eax,19*FP_1
|
|
jle interior_height_zero
|
|
cmp eax,8*FP_1
|
|
jle interior_height_fortune
|
|
mov eax,8*FP_1
|
|
interior_height_fortune:
|
|
imul eax,3
|
|
cdq
|
|
mov ecx,16
|
|
idiv ecx
|
|
jmp interior_height_store
|
|
@@:
|
|
cmp stairRoute3D,1
|
|
jne interior_height_upper
|
|
mov viewCeiling3D,4*FP_1
|
|
mov eax,13*FP_1
|
|
sub eax,playerX
|
|
jle interior_height_zero
|
|
cmp eax,8*FP_1
|
|
jle @F
|
|
mov eax,8*FP_1
|
|
@@:
|
|
imul eax,3
|
|
cdq
|
|
mov ecx,16
|
|
idiv ecx
|
|
jmp interior_height_store
|
|
interior_height_upper:
|
|
mov eax,playerX
|
|
sub eax,5*FP_1
|
|
jle interior_height_zero
|
|
cmp eax,8*FP_1
|
|
jle @F
|
|
mov eax,8*FP_1
|
|
@@:
|
|
imul eax,13
|
|
cdq
|
|
mov ecx,40
|
|
idiv ecx
|
|
jmp interior_height_store
|
|
interior_height_zero:
|
|
xor eax,eax
|
|
interior_height_store:
|
|
add eax,HALL_STANDING_EYE
|
|
mov viewEye3D,eax
|
|
interior_height_done:
|
|
ret
|
|
UpdateStairHeight3D ENDP
|
|
|
|
UpdateInteriorEye3D PROC
|
|
cmp engineMode,MODE_STAIRS
|
|
je UpdateStairHeight3D
|
|
cmp engineMode,MODE_WALK
|
|
jne interior_eye_done
|
|
cmp hallLevel3D,HALL_BOWLING
|
|
jne @F
|
|
call BowlingEye3D
|
|
ret
|
|
@@:
|
|
cmp hallLevel3D,HALL_ROOF
|
|
jne @F
|
|
call UpdateRoofEye3D
|
|
ret
|
|
@@:
|
|
mov viewHorizon3D,HALF_H
|
|
mov viewEye3D,HALL_STANDING_EYE
|
|
mov viewCeiling3D,FP_1*5/2
|
|
interior_eye_done:
|
|
ret
|
|
UpdateInteriorEye3D ENDP
|
|
|
|
InteriorDoorCanWalk3D PROC px:DWORD,py:DWORD
|
|
cmp px,29*FP_1-FP_1/6
|
|
jb interior_check_steel
|
|
cmp py,FP_1*1955/100
|
|
jb interior_check_steel
|
|
cmp py,20*FP_1+FP_1/6
|
|
jbe interior_portal_blocked
|
|
cmp py,22*FP_1-FP_1/6
|
|
jb interior_check_steel
|
|
cmp py,FP_1*2245/100
|
|
jbe interior_portal_blocked
|
|
interior_check_steel:
|
|
cmp py,9*FP_1
|
|
jb interior_door_clear
|
|
cmp py,12*FP_1
|
|
jae interior_door_clear
|
|
cmp px,FP_1*2875/100
|
|
jb interior_door_clear
|
|
cmp py,FP_1*96/10
|
|
jb interior_portal_blocked
|
|
cmp py,FP_1*114/10
|
|
ja interior_portal_blocked
|
|
cmp basementDoorOpen3D,FP_1*9/10
|
|
jae interior_door_clear
|
|
interior_portal_blocked:
|
|
xor eax,eax
|
|
ret
|
|
interior_door_clear:
|
|
mov eax,1
|
|
ret
|
|
InteriorDoorCanWalk3D ENDP
|
|
|
|
RenderHallPortals3D PROC uses ebx
|
|
; Same east alcove, with a deeper reveal and a stationary iron frame.
|
|
invoke DrawCityBoxSides3D,FP_1*284/10,29*FP_1,9*FP_1,FP_1*975/100,0,FP_1*11/5,102
|
|
invoke DrawCityBoxSides3D,FP_1*284/10,29*FP_1,FP_1*1125/100,12*FP_1,0,FP_1*11/5,102
|
|
invoke DrawCityBoxSides3D,FP_1*284/10,29*FP_1,FP_1*975/100,FP_1*1125/100,FP_1*19/10,FP_1*11/5,102
|
|
invoke DrawCityVertical3D,0,FP_1*2838/100,9*FP_1,12*FP_1,-FP_1/10,FP_1*21/10,131
|
|
; East stair entrance: projecting jambs, a low first tread and overhead lintel.
|
|
invoke DrawCityBoxSides3D,29*FP_1,31*FP_1,FP_1*197/10,20*FP_1,0,FP_1*5/2,102
|
|
invoke DrawCityBoxSides3D,29*FP_1,31*FP_1,22*FP_1,FP_1*223/10,0,FP_1*5/2,102
|
|
invoke DrawCityHorizontal3D,30*FP_1,31*FP_1,20*FP_1,22*FP_1,FP_1/8,85
|
|
invoke DrawCityVertical3D,0,30*FP_1,20*FP_1,22*FP_1,0,FP_1/8,102
|
|
ret
|
|
RenderHallPortals3D ENDP
|
|
|
|
RenderWalkableStairs3D PROC uses ebx esi edi
|
|
local treadStart:DWORD,treadEnd:DWORD,z0:DWORD,z1:DWORD
|
|
cmp stairRoute3D,3
|
|
jne @F
|
|
call RenderFortuneStairs3D
|
|
ret
|
|
@@:
|
|
cmp stairRoute3D,1
|
|
jne interior_render_upper_steps
|
|
; East-facing descent, then a level northward turn into the old bunker.
|
|
xor esi,esi
|
|
interior_concrete_step:
|
|
mov eax,esi
|
|
imul eax,FP_1/3
|
|
add eax,5*FP_1
|
|
mov treadStart,eax
|
|
add eax,FP_1/3
|
|
mov treadEnd,eax
|
|
imul eax,esi,FP_1/16
|
|
neg eax
|
|
add eax,FP_1*3/2
|
|
mov z0,eax
|
|
sub eax,FP_1/16
|
|
mov z1,eax
|
|
invoke DrawCityHorizontal3D,treadStart,treadEnd,20*FP_1,23*FP_1,z1,94
|
|
invoke DrawCityVertical3D,0,treadStart,20*FP_1,23*FP_1,z1,z0,92
|
|
inc esi
|
|
cmp esi,24
|
|
jb interior_concrete_step
|
|
invoke DrawCityHorizontal3D,2*FP_1,5*FP_1,20*FP_1,23*FP_1,FP_1*3/2,94
|
|
invoke DrawCityHorizontal3D,13*FP_1,18*FP_1,20*FP_1,23*FP_1,0,94
|
|
ret
|
|
interior_render_upper_steps:
|
|
xor esi,esi
|
|
interior_wood_step:
|
|
imul eax,esi,FP_1*2/5
|
|
add eax,5*FP_1
|
|
mov treadStart,eax
|
|
add eax,FP_1*2/5
|
|
mov treadEnd,eax
|
|
imul eax,esi,FP_1*13/100
|
|
mov z0,eax
|
|
add eax,FP_1*13/100
|
|
mov z1,eax
|
|
invoke DrawCityHorizontal3D,treadStart,treadEnd,20*FP_1,22*FP_1,z1,85
|
|
invoke DrawCityVertical3D,0,treadStart,20*FP_1,22*FP_1,z0,z1,102
|
|
mov eax,z1
|
|
add eax,FP_1*3/4
|
|
mov ebx,eax
|
|
add eax,FP_1/20
|
|
mov edi,eax
|
|
invoke DrawCityVertical3D,1,FP_1*201/10,treadStart,treadEnd,ebx,edi,110
|
|
invoke DrawCityVertical3D,1,FP_1*219/10,treadStart,treadEnd,ebx,edi,110
|
|
; Posts follow the slope instead of a billboard painted on the wall.
|
|
test esi,3
|
|
jnz @F
|
|
mov eax,z1
|
|
add eax,FP_1*3/4
|
|
mov ebx,eax
|
|
invoke DrawCityVertical3D,0,treadStart,FP_1*201/10,FP_1*202/10,z1,ebx,110
|
|
invoke DrawCityVertical3D,0,treadStart,FP_1*218/10,FP_1*219/10,z1,ebx,110
|
|
@@:
|
|
inc esi
|
|
cmp esi,20
|
|
jb interior_wood_step
|
|
invoke DrawCityHorizontal3D,13*FP_1,18*FP_1,20*FP_1,22*FP_1,FP_1*13/5,85
|
|
invoke DrawCityVertical3D,1,20*FP_1,2*FP_1,18*FP_1,0,FP_1*11/2,102
|
|
invoke DrawCityVertical3D,1,22*FP_1,2*FP_1,18*FP_1,0,FP_1*11/2,102
|
|
ret
|
|
RenderWalkableStairs3D ENDP
|
|
|
|
UpperCanWalk3D PROC px:DWORD,py:DWORD
|
|
; The same station centres drive art, interaction and collision.
|
|
cmp px,10*FP_1-FP_1/5
|
|
jb upper_walk_tables
|
|
cmp px,15*FP_1+FP_1/5
|
|
ja upper_walk_tables
|
|
cmp py,13*FP_1-FP_1/5
|
|
jb upper_walk_tables
|
|
cmp py,15*FP_1+FP_1/5
|
|
jbe upper_walk_block
|
|
upper_walk_tables:
|
|
xor ecx,ecx
|
|
upper_walk_station:
|
|
mov eax,px
|
|
sub eax,upperStationX3D[ecx*4]
|
|
test eax,eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
cmp eax,FP_1*11/10
|
|
ja upper_walk_next
|
|
mov eax,py
|
|
sub eax,upperStationY3D[ecx*4]
|
|
test eax,eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
cmp eax,FP_1*7/10
|
|
jbe upper_walk_block
|
|
upper_walk_next:
|
|
inc ecx
|
|
cmp ecx,2
|
|
jb upper_walk_station
|
|
xor ecx,ecx
|
|
upper_walk_guest:
|
|
mov eax,px
|
|
sub eax,upperGuestX3D[ecx*4]
|
|
test eax,eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
cmp eax,FP_1*2/5
|
|
ja upper_walk_guest_next
|
|
mov eax,py
|
|
sub eax,upperGuestY3D[ecx*4]
|
|
test eax,eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
cmp eax,FP_1*2/5
|
|
jbe upper_walk_block
|
|
upper_walk_guest_next:
|
|
inc ecx
|
|
cmp ecx,3
|
|
jb upper_walk_guest
|
|
cmp upperPortalReady3D,1
|
|
je upper_walk_clear
|
|
cmp py,24*FP_1
|
|
jb upper_walk_clear
|
|
cmp px,FP_1*95/10
|
|
jb upper_walk_clear
|
|
cmp px,FP_1*115/10
|
|
jbe upper_walk_block
|
|
upper_walk_clear:
|
|
mov eax,1
|
|
ret
|
|
upper_walk_block:
|
|
xor eax,eax
|
|
ret
|
|
UpperCanWalk3D ENDP
|
|
|
|
CheckUpperInteractions3D PROC
|
|
mov interactTargetId,0
|
|
mov interactPromptPtr,0
|
|
invoke HallTarget3D,3*FP_1,21*FP_1,0,OFFSET upperExitPrompt3D
|
|
invoke HallTarget3D,upperStationX3D[0],upperStationY3D[0],INTERACT_BUCKSHOT,OFFSET promptBuckshot
|
|
invoke HallTarget3D,upperStationX3D[4],upperStationY3D[4],INTERACT_RUSSIAN_ROULETTE,OFFSET promptRussianRoulette
|
|
test upperLeverMask3D,1
|
|
jnz upper_check_left_release
|
|
invoke HallTarget3D,FP_1*91/10,FP_1*226/10,INTERACT_UPPER_LEFT,OFFSET upperLeftPrompt3D
|
|
jmp upper_check_right
|
|
upper_check_left_release:
|
|
invoke HallTarget3D,FP_1*91/10,FP_1*226/10,INTERACT_UPPER_LEFT,OFFSET upperLeftRelease3D
|
|
upper_check_right:
|
|
test upperLeverMask3D,2
|
|
jnz upper_check_right_release
|
|
invoke HallTarget3D,FP_1*119/10,FP_1*226/10,INTERACT_UPPER_RIGHT,OFFSET upperRightPrompt3D
|
|
jmp upper_check_portal
|
|
upper_check_right_release:
|
|
invoke HallTarget3D,FP_1*119/10,FP_1*226/10,INTERACT_UPPER_RIGHT,OFFSET upperRightRelease3D
|
|
upper_check_portal:
|
|
cmp upperPortalReady3D,1
|
|
jne upper_check_bar
|
|
invoke HallTarget3D,FP_1*105/10,FP_1*237/10,INTERACT_HELL_TOWER,OFFSET upperPortalPrompt3D
|
|
upper_check_bar:
|
|
cmp playerX,10*FP_1
|
|
jb @F
|
|
cmp playerX,15*FP_1
|
|
ja @F
|
|
cmp playerY,15*FP_1
|
|
jb @F
|
|
invoke HallTarget3D,playerX,15*FP_1,INTERACT_BAR,OFFSET hallBarPrompt3D
|
|
@@:
|
|
ret
|
|
CheckUpperInteractions3D ENDP
|
|
|
|
RenderUpperLounge3D PROC uses ebx esi
|
|
; Small midnight lounge: dark panels, brass ribs, a marble-topped straight bar.
|
|
invoke DrawCityBoxSides3D,10*FP_1,15*FP_1,14*FP_1,15*FP_1,0,FP_1*13/20,102
|
|
invoke DrawCityHorizontal3D,10*FP_1,15*FP_1,14*FP_1,15*FP_1,FP_1*13/20,123
|
|
invoke DrawCityVertical3D,1,13*FP_1+FP_1/20,10*FP_1,15*FP_1,FP_1/2,2*FP_1,87
|
|
invoke DrawCityBoxSides3D,10*FP_1,15*FP_1,13*FP_1,FP_1*132/10,0,FP_1/2,102
|
|
invoke DrawCityBoxSides3D,10*FP_1,15*FP_1,13*FP_1,FP_1*132/10,2*FP_1,FP_1*21/10,102
|
|
invoke DrawCityVertical3D,1,FP_1*152/10,10*FP_1,15*FP_1,FP_1/8,FP_1*16/100,110
|
|
mov upperBarTender3D.asset,OFFSET upperBarArt3D
|
|
mov upperBarTender3D.worldW,FP_1*4/5
|
|
mov upperBarTender3D.worldH,FP_1*7/5
|
|
mov upperBarTender3D.groundZ,0
|
|
mov upperBarTender3D.frame,0
|
|
mov upperBarTender3D.posX,FP_1*25/2
|
|
mov upperBarTender3D.posY,FP_1*27/2
|
|
cmp engineMode,MODE_BAR
|
|
jne upper_draw_bartender
|
|
mov upperBarTender3D.posX,FP_1*115/10
|
|
mov upperBarTender3D.asset,OFFSET hallBartender3D
|
|
mov upperBarTender3D.worldW,FP_1
|
|
mov upperBarTender3D.worldH,FP_1
|
|
mov upperBarTender3D.groundZ,FP_1*9/20
|
|
mov eax,barSelection3D
|
|
shl eax,3
|
|
mov upperBarTender3D.frame,eax
|
|
mov eax,barTime3D
|
|
xor edx,edx
|
|
mov ecx,375
|
|
div ecx
|
|
cmp eax,7
|
|
jbe @F
|
|
mov eax,7
|
|
@@:
|
|
add upperBarTender3D.frame,eax
|
|
upper_draw_bartender:
|
|
invoke DrawCityObject3D,OFFSET upperBarTender3D,0
|
|
xor esi,esi
|
|
upper_draw_table:
|
|
mov ebx,upperStationX3D[esi*4]
|
|
mov upperTable3D.posX,ebx
|
|
mov eax,upperStationY3D[esi*4]
|
|
mov upperTable3D.posY,eax
|
|
mov upperTable3D.worldW,2*FP_1
|
|
mov upperTable3D.worldH,FP_1*6/5
|
|
mov upperTable3D.asset,OFFSET upperGamesArt3D
|
|
mov upperTable3D.frame,esi
|
|
invoke DrawCityObject3D,OFFSET upperTable3D,0
|
|
mov upperDealer3D.posX,ebx
|
|
mov eax,upperStationY3D[esi*4]
|
|
sub eax,FP_1*3/4
|
|
mov upperDealer3D.posY,eax
|
|
mov upperDealer3D.frame,esi
|
|
invoke DrawCityObject3D,OFFSET upperDealer3D,0
|
|
inc esi
|
|
cmp esi,2
|
|
jb upper_draw_table
|
|
mov upperPortal3D.frame,0
|
|
cmp upperPortalReady3D,1
|
|
jne upper_draw_portal
|
|
mov eax,animationClock3D
|
|
xor edx,edx
|
|
mov ecx,80
|
|
div ecx
|
|
xor edx,edx
|
|
mov ecx,12
|
|
div ecx
|
|
inc edx
|
|
mov upperPortal3D.frame,edx
|
|
upper_draw_portal:
|
|
invoke DrawCityVertical3D,1,FP_1*249/10,9*FP_1,12*FP_1,0,FP_1*5/2,122
|
|
invoke DrawCityBoxSides3D,FP_1*89/10,FP_1*915/100,FP_1*243/10,25*FP_1,0,FP_1*5/2,122
|
|
invoke DrawCityBoxSides3D,FP_1*1185/100,FP_1*121/10,FP_1*243/10,25*FP_1,0,FP_1*5/2,122
|
|
invoke DrawCityBoxSides3D,9*FP_1,12*FP_1,FP_1*243/10,25*FP_1,FP_1*24/10,FP_1*5/2,122
|
|
invoke DrawCityVertical3D,1,FP_1*247/10,FP_1*925/100,FP_1*1175/100,0,FP_1*245/100,129
|
|
mov eax,animationClock3D
|
|
shr eax,7
|
|
and eax,3
|
|
mov upperBrazier3D.frame,eax
|
|
mov upperBrazier3D.posX,FP_1*84/10
|
|
invoke DrawCityObject3D,OFFSET upperBrazier3D,0
|
|
mov upperBrazier3D.posX,FP_1*126/10
|
|
invoke DrawCityObject3D,OFFSET upperBrazier3D,0
|
|
invoke DrawCityVertical3D,1,FP_1*242/10,FP_1*92/10,FP_1*924/100,FP_1*16/10,FP_1*25/10,110
|
|
invoke DrawCityVertical3D,1,FP_1*242/10,FP_1*1176/100,FP_1*118/10,FP_1*16/10,FP_1*25/10,110
|
|
mov upperLever3D.posX,FP_1*91/10
|
|
mov eax,upperLeverTime3D
|
|
xor edx,edx
|
|
mov ecx,120
|
|
div ecx
|
|
mov upperLever3D.frame,eax
|
|
invoke DrawCityObject3D,OFFSET upperLever3D,0
|
|
mov upperLever3D.posX,FP_1*119/10
|
|
mov eax,upperLeverTime3D[4]
|
|
xor edx,edx
|
|
mov ecx,120
|
|
div ecx
|
|
mov upperLever3D.frame,eax
|
|
invoke DrawCityObject3D,OFFSET upperLever3D,0
|
|
xor esi,esi
|
|
upper_draw_guest:
|
|
mov eax,upperGuestX3D[esi*4]
|
|
mov upperGuest3D.posX,eax
|
|
mov eax,upperGuestY3D[esi*4]
|
|
mov upperGuest3D.posY,eax
|
|
mov eax,upperGuestFrame3D[esi*4]
|
|
xor edx,edx
|
|
mov ecx,6
|
|
div ecx
|
|
invoke ConfigureCharacter3D,OFFSET upperGuest3D,eax,CAST_SEAT_TALK,animationClock3D,0,0
|
|
invoke DrawCityObject3D,OFFSET upperGuest3D,0
|
|
inc esi
|
|
cmp esi,3
|
|
jb upper_draw_guest
|
|
mov upperChair3D.posX,FP_1*56/10
|
|
mov upperChair3D.posY,FP_1*225/10
|
|
mov upperChair3D.worldW,FP_1*3/5
|
|
mov upperChair3D.worldH,FP_1*7/10
|
|
mov upperChair3D.asset,OFFSET hallLampFurniture3D
|
|
invoke DrawCityObject3D,OFFSET upperChair3D,0
|
|
mov upperChair3D.posX,FP_1*143/10
|
|
mov upperChair3D.posY,FP_1*221/10
|
|
invoke DrawCityObject3D,OFFSET upperChair3D,0
|
|
mov upperChair3D.asset,OFFSET hallChairFurniture3D
|
|
mov upperChair3D.worldW,FP_1*3/4
|
|
mov upperChair3D.worldH,FP_1
|
|
mov upperChair3D.posX,15*FP_1
|
|
mov upperChair3D.posY,FP_1*227/10
|
|
invoke DrawCityObject3D,OFFSET upperChair3D,0
|
|
invoke DrawCityObject3D,OFFSET upperSofa3D,0
|
|
cmp engineMode,MODE_BAR
|
|
je upper_bar_stools_done
|
|
xor esi,esi
|
|
upper_bar_stools:
|
|
imul eax,esi,FP_1*14/10
|
|
add eax,FP_1*109/10
|
|
mov upperStool3D.posX,eax
|
|
invoke DrawCityObject3D,OFFSET upperStool3D,0
|
|
inc esi
|
|
cmp esi,3
|
|
jb upper_bar_stools
|
|
upper_bar_stools_done:
|
|
invoke DrawHallLantern3D,3*FP_1+FP_1/50,15*FP_1,1
|
|
invoke DrawHallLantern3D,3*FP_1+FP_1/50,18*FP_1,1
|
|
invoke DrawHallLantern3D,16*FP_1-FP_1/50,17*FP_1,-1
|
|
invoke DrawHallLantern3D,16*FP_1-FP_1/50,22*FP_1,-1
|
|
invoke DrawCityVertical3D,0,16*FP_1-FP_1/40,14*FP_1,16*FP_1,FP_1,2*FP_1,115
|
|
invoke DrawCityVertical3D,0,3*FP_1+FP_1/40,15*FP_1,17*FP_1,FP_1,2*FP_1,115
|
|
invoke DrawCityHorizontal3D,3*FP_1,5*FP_1,20*FP_1,22*FP_1,0,85
|
|
call ApplyUpperPortalGlow3D
|
|
ret
|
|
RenderUpperLounge3D ENDP
|
|
|
|
TryUpperInteraction3D PROC
|
|
cmp hallLevel3D,2
|
|
jne upper_interaction_none
|
|
cmp interactTargetId,INTERACT_UPPER_LEFT
|
|
jne @F
|
|
xor upperLeverMask3D,1
|
|
jmp upper_interaction_lever
|
|
@@:
|
|
cmp interactTargetId,INTERACT_UPPER_RIGHT
|
|
jne @F
|
|
xor upperLeverMask3D,2
|
|
jmp upper_interaction_lever
|
|
@@:
|
|
cmp interactTargetId,INTERACT_HELL_TOWER
|
|
jne upper_interaction_none
|
|
cmp upperPortalReady3D,1
|
|
jne upper_interaction_locked
|
|
mov upperPortalEntered3D,1
|
|
call InitHellTower3D
|
|
jmp upper_interaction_handled
|
|
upper_interaction_lever:
|
|
; Do not wait for the next animation tick to disable both entry paths.
|
|
mov upperPortalReady3D,0
|
|
jmp upper_interaction_handled
|
|
upper_interaction_locked:
|
|
invoke CopyString3D,OFFSET upperPortalLocked3D,OFFSET flashMessage
|
|
mov flashTimer,120
|
|
upper_interaction_handled:
|
|
call ClearKeys3D
|
|
mov eax,1
|
|
ret
|
|
upper_interaction_none:
|
|
xor eax,eax
|
|
ret
|
|
TryUpperInteraction3D ENDP
|
|
|
|
TryWalkUpperPortal3D PROC
|
|
cmp playerY,FP_1*235/10
|
|
jae @F
|
|
mov upperPortalEntered3D,0
|
|
@@:
|
|
cmp upperPortalReady3D,1
|
|
jne upper_portal_walk_done
|
|
cmp upperPortalEntered3D,0
|
|
jne upper_portal_walk_done
|
|
cmp playerX,10*FP_1
|
|
jb upper_portal_walk_done
|
|
cmp playerX,11*FP_1
|
|
ja upper_portal_walk_done
|
|
cmp playerY,FP_1*2425/100
|
|
jb upper_portal_walk_done
|
|
mov upperPortalEntered3D,1
|
|
call InitHellTower3D
|
|
call ClearKeys3D
|
|
upper_portal_walk_done:
|
|
ret
|
|
TryWalkUpperPortal3D ENDP
|
|
|
|
UpdateUpperEffects3D PROC uses ebx esi
|
|
mov eax,animationClock3D
|
|
cmp eax,upperEffectClock3D
|
|
je upper_effects_done
|
|
mov upperEffectClock3D,eax
|
|
xor esi,esi
|
|
mov ebx,1
|
|
upper_effect_lever:
|
|
mov eax,deltaTime3D
|
|
cmp eax,100
|
|
jbe @F
|
|
mov eax,100
|
|
@@:
|
|
test upperLeverMask3D,ebx
|
|
jz upper_effect_release
|
|
add eax,upperLeverTime3D[esi*4]
|
|
cmp eax,600
|
|
jbe @F
|
|
mov eax,600
|
|
@@:
|
|
jmp upper_effect_store
|
|
upper_effect_release:
|
|
mov ecx,upperLeverTime3D[esi*4]
|
|
sub ecx,eax
|
|
jae @F
|
|
xor ecx,ecx
|
|
@@:
|
|
mov eax,ecx
|
|
upper_effect_store:
|
|
mov upperLeverTime3D[esi*4],eax
|
|
upper_effect_next:
|
|
shl ebx,1
|
|
inc esi
|
|
cmp esi,2
|
|
jb upper_effect_lever
|
|
mov upperPortalReady3D,0
|
|
cmp upperLeverMask3D,3
|
|
jne upper_effects_done
|
|
cmp upperLeverTime3D,600
|
|
jne upper_effects_done
|
|
cmp upperLeverTime3D[4],600
|
|
jne upper_effects_done
|
|
mov upperPortalReady3D,1
|
|
upper_effects_done:
|
|
ret
|
|
UpdateUpperEffects3D ENDP
|
|
|
|
ApplyUpperPortalGlow3D PROC uses ebx esi edi
|
|
local row:DWORD,column:DWORD,depth:DWORD,wx:DWORD,amount:DWORD,pixel:DWORD,pulse:DWORD
|
|
mov eax,animationClock3D
|
|
shr eax,7
|
|
and eax,3
|
|
add eax,10
|
|
cmp upperPortalReady3D,1
|
|
jne @F
|
|
add eax,8
|
|
@@:
|
|
mov pulse,eax
|
|
mov eax,viewHorizon3D
|
|
add eax,2
|
|
mov row,eax
|
|
upper_glow_row:
|
|
mov ecx,row
|
|
sub ecx,viewHorizon3D
|
|
mov eax,viewEye3D
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv ecx
|
|
mov depth,eax
|
|
mov eax,row
|
|
imul eax,SCREEN_W*4
|
|
mov edi,eax
|
|
mov column,0
|
|
upper_glow_pixel:
|
|
mov ebx,column
|
|
mov eax,depth
|
|
cmp eax,cityDepthBuffer3D[edi]
|
|
ja upper_glow_next
|
|
imul cityRayX3D[ebx*4]
|
|
shrd eax,edx,16
|
|
add eax,playerX
|
|
sub eax,FP_1*105/10
|
|
test eax,eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
mov wx,eax
|
|
mov eax,depth
|
|
imul cityRayY3D[ebx*4]
|
|
shrd eax,edx,16
|
|
add eax,playerY
|
|
sub eax,FP_1*243/10
|
|
test eax,eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
add eax,wx
|
|
cmp eax,3*FP_1
|
|
jae upper_glow_next
|
|
neg eax
|
|
add eax,3*FP_1
|
|
imul pulse
|
|
shrd eax,edx,16
|
|
mov amount,eax
|
|
mov eax,screenBuffer[edi]
|
|
mov pixel,eax
|
|
shr eax,16
|
|
and eax,255
|
|
add eax,amount
|
|
cmp eax,255
|
|
jbe @F
|
|
mov eax,255
|
|
@@:
|
|
shl eax,16
|
|
mov ebx,pixel
|
|
and ebx,0000FFFFh
|
|
or eax,ebx
|
|
mov screenBuffer[edi],eax
|
|
upper_glow_next:
|
|
add edi,4
|
|
inc column
|
|
cmp column,SCREEN_W
|
|
jb upper_glow_pixel
|
|
inc row
|
|
cmp row,SCREEN_H
|
|
jb upper_glow_row
|
|
ret
|
|
ApplyUpperPortalGlow3D ENDP
|