KAZIK/src_graphics/rooftop.inc
Artvasil09 41ba8f46ed feat: add rooftop city and optimize native terrace rendering
Add rooftop elevator, lounge, volumetric city, river and animated traffic. Prune invisible mesh faces, clip CPU surfaces, streamline compositing and add automatic/F8 roof quality profiles with renderer diagnostics.

Include dartboard/reticle improvements, tracked fortune orb numerals and fate-session visuals, native regression tests, compatible jukebox IDs and updated shipping executables.
2026-10-26 23:20:35 +03:00

1178 lines
30 KiB
PHP

; Elevator phases: shut, opening, open, closing, travelling. Movement stays manual.
InitRoof3D PROC
mov liftPhase3D,0
mov liftDoor3D,0
mov liftTrip3D,0
mov liftRideTime3D,0
mov liftAwayTime3D,0
mov roofSeat3D,0
mov roofLean3D,0
mov roofLeanTime3D,0
mov roofNight3D,0
mov roofAAValid3D,0
mov roofUpdateClock3D,-1
ret
InitRoof3D ENDP
LoadRoofAssets3D PROC
invoke LoadAnimPack3D,OFFSET roofSkyArt3D,OFFSET roofSkyPath3D
invoke LoadAnimPack3D,OFFSET roofMaterialArt3D,OFFSET roofMaterialPath3D
invoke LoadAnimPack3D,OFFSET roofDetailArt3D,OFFSET roofDetailPath3D
invoke LoadAnimPack3D,OFFSET roofCityArt3D,OFFSET roofCityPath3D
invoke LoadAnimPack3D,OFFSET roofCityNightArt3D,OFFSET roofCityNightPath3D
invoke LoadAnimPack3D,OFFSET roofHandsArt3D,OFFSET roofHandsPath3D
invoke LoadAnimPack3D,OFFSET roofNightArt3D,OFFSET roofNightPath3D
invoke LoadAnimPack3D,OFFSET roofLightingArt3D,OFFSET roofLightingPath3D
ret
LoadRoofAssets3D ENDP
FreeRoofAssets3D PROC
call FreeRoofHD3D
invoke FreeAnimPack3D,OFFSET roofSkyArt3D
invoke FreeAnimPack3D,OFFSET roofMaterialArt3D
invoke FreeAnimPack3D,OFFSET roofDetailArt3D
invoke FreeAnimPack3D,OFFSET roofCityArt3D
invoke FreeAnimPack3D,OFFSET roofCityNightArt3D
invoke FreeAnimPack3D,OFFSET roofHandsArt3D
invoke FreeAnimPack3D,OFFSET roofNightArt3D
invoke FreeAnimPack3D,OFFSET roofLightingArt3D
ret
FreeRoofAssets3D ENDP
ResolveRoofSurface3D PROC material:DWORD
mov eax,material
sub eax,ROOF_FACADE
cmp eax,21
ja roof_surface_furniture
cmp roofCityArt3D.pixels,0
je roof_surface_missing
shl eax,20
add eax,roofCityArt3D.pixels
cmp roofNight3D,0
je roof_surface_city_ready
cmp roofCityNightArt3D.pixels,0
je roof_surface_city_ready
sub eax,roofCityArt3D.pixels
add eax,roofCityNightArt3D.pixels
roof_surface_city_ready:
mov ecx,512
mov edx,512
ret
roof_surface_furniture:
mov eax,material
cmp eax,ROOF_SOFA_FRONT
jb @F
sub eax,ROOF_SOFA_FRONT
cmp eax,6
ja roof_surface_missing
add eax,8
cmp roofDetailArt3D.pixels,0
je roof_surface_missing
shl eax,18
add eax,roofDetailArt3D.pixels
jmp roof_surface_size
@@:
cmp eax,ROOF_LIGHT
jne @F
mov eax,OFFSET roofIndicatorPixel3D
mov ecx,1
mov edx,1
ret
@@:
cmp eax,ROOF_INDICATOR
jne @F
mov eax,OFFSET roofIndicatorPixels3D
mov ecx,64
mov edx,64
ret
@@:
sub eax,ROOF_DECK
cmp eax,7
ja roof_surface_detail
cmp roofMaterialArt3D.pixels,0
je roof_surface_missing
shl eax,18
add eax,roofMaterialArt3D.pixels
jmp roof_surface_size
roof_surface_detail:
sub eax,8
cmp eax,7
ja roof_surface_missing
cmp roofDetailArt3D.pixels,0
je roof_surface_missing
shl eax,18
add eax,roofDetailArt3D.pixels
roof_surface_size:
mov ecx,256
mov edx,256
ret
roof_surface_missing:
xor eax,eax
ret
ResolveRoofSurface3D ENDP
DrawRoofSky3D PROC uses ebx esi edi
local row:DWORD,sourceRow:DWORD,offsetX:DWORD,pixels:DWORD
cmp roofSkyArt3D.pixels,0
jne roof_sky_ready
invoke DrawBox,0,0,320,240,00334C6Ah
ret
roof_sky_ready:
mov eax,roofSkyArt3D.pixels
cmp roofNight3D,0
je @F
cmp roofNightArt3D.pixels,0
je @F
mov eax,roofNightArt3D.pixels
@@:
mov pixels,eax
mov eax,playerAngle
shl eax,2
mov offsetX,eax
mov row,0
lea edi,screenBuffer
roof_sky_row:
mov eax,row
add eax,HALF_H
sub eax,viewHorizon3D
shl eax,9
xor edx,edx
mov ecx,480
div ecx
cmp eax,511
jbe @F
mov eax,511
@@:
shl eax,9
mov sourceRow,eax
xor ebx,ebx
roof_sky_pixel:
mov eax,roofSkyColumns3D[ebx*4]
add eax,offsetX
and eax,2047
mov ecx,eax
shr ecx,9
shl ecx,18
and eax,511
add eax,ecx
add eax,sourceRow
mov esi,pixels
mov eax,[esi+eax*4]
and eax,00FFFFFFh
stosd
inc ebx
cmp ebx,640
jb roof_sky_pixel
inc row
cmp row,480
jb roof_sky_row
ret
DrawRoofSky3D ENDP
StandFromRoofSeat3D PROC
cmp roofSeat3D,0
je roof_stand_done
mov eax,roofReturnX3D
mov playerX,eax
mov eax,roofReturnY3D
mov playerY,eax
mov eax,roofReturnAngle3D
mov playerAngle,eax
mov roofSeat3D,0
roof_stand_done:
ret
StandFromRoofSeat3D ENDP
UpdateRoofEye3D PROC
mov viewHorizon3D,HALF_H
mov viewCeiling3D,FP_1*5/2
mov viewEye3D,ROOF_STANDING_EYE
cmp roofLean3D,0
je @F
mov eax,roofLeanTime3D
imul eax,FP_1*28/100
xor edx,edx
mov ecx,1100
div ecx
sub viewEye3D,eax
mov eax,roofLeanTime3D
imul eax,84
xor edx,edx
div ecx
sub viewHorizon3D,eax
ret
@@:
cmp roofSeat3D,0
je roof_eye_done
mov viewEye3D,ROOF_SEATED_EYE
mov eax,roofSeat3D
dec eax
cmp roofSeatKind3D[eax*4],2
jb roof_eye_done
mov viewEye3D,ROOF_STANDING_EYE
roof_eye_done:
ret
UpdateRoofEye3D ENDP
UpdateRoof3D PROC uses ebx
mov eax,animationClock3D
cmp eax,roofUpdateClock3D
je roof_update_done
mov roofUpdateClock3D,eax
cmp engineMode,MODE_WALK
jne roof_update_done
cmp hallLevel3D,0
je roof_update_lift
cmp hallLevel3D,HALL_ROOF
jne roof_update_done
mov eax,deltaTime3D
cmp eax,100
jbe @F
mov eax,100
@@:
invoke UpdateRoofGuests3D,eax
cmp roofLean3D,0
je roof_update_seat
call UpdateRoofLook3D
mov ebx,deltaTime3D
cmp ebx,100
jbe @F
mov ebx,100
@@:
cmp roofLean3D,3
je roof_lean_retract
mov eax,ebx
shr eax,2
inc eax
cmp keys3D[41h],0
je @F
sub playerAngle,eax
@@:
cmp keys3D[44h],0
je @F
add playerAngle,eax
@@:
call UpdateRoofLook3D
cmp keys3D[57h],0
jne roof_lean_release
cmp keys3D[53h],0
jne roof_lean_release
cmp keys3D[26h],0
jne roof_lean_release
cmp keys3D[28h],0
jne roof_lean_release
add roofLeanTime3D,ebx
cmp roofLeanTime3D,1100
jb roof_update_lift
mov roofLeanTime3D,1100
mov roofLean3D,2
jmp roof_update_lift
roof_lean_release:
mov roofLean3D,3
roof_lean_retract:
shl ebx,1
sub roofLeanTime3D,ebx
ja roof_update_lift
mov roofLeanTime3D,0
mov roofLean3D,0
mov eax,roofReturnX3D
mov playerX,eax
mov eax,roofReturnY3D
mov playerY,eax
mov eax,roofReturnAngle3D
mov playerAngle,eax
call ClearKeys3D
jmp roof_update_lift
roof_update_seat:
cmp roofSeat3D,0
je roof_update_lift
cmp keys3D[57h],0
jne roof_update_stand
cmp keys3D[53h],0
jne roof_update_stand
cmp keys3D[26h],0
jne roof_update_stand
cmp keys3D[28h],0
je roof_update_lift
roof_update_stand:
call StandFromRoofSeat3D
roof_update_lift:
cmp hallLevel3D,0
jne roof_update_lift_step
cmp liftPhase3D,2
jne roof_update_lift_step
cmp playerX,FP_1*236/10
jb roof_update_lift_step
cmp playerX,FP_1*252/10
ja roof_update_lift_step
cmp playerY,FP_1*31/10
ja roof_update_lift_step
invoke Pressed3D,31h
test eax,eax
jz @F
mov roofNight3D,0
@@:
invoke Pressed3D,32h
test eax,eax
jz roof_update_lift_step
mov roofNight3D,1
roof_update_lift_step:
mov ebx,deltaTime3D
cmp ebx,100
jbe @F
mov ebx,100
@@:
cmp liftPhase3D,1
je roof_lift_opening
cmp liftPhase3D,2
je roof_lift_open
cmp liftPhase3D,3
je roof_lift_closing
cmp liftPhase3D,4
je roof_lift_ride
ret
roof_lift_opening:
add liftDoor3D,ebx
cmp liftDoor3D,1000
jb roof_update_done
mov liftDoor3D,1000
mov liftPhase3D,2
mov liftAwayTime3D,0
ret
roof_lift_open:
cmp playerX,22*FP_1
jb roof_lift_away
cmp playerX,27*FP_1
ja roof_lift_away
cmp playerY,6*FP_1
ja roof_lift_away
mov liftAwayTime3D,0
ret
roof_lift_away:
add liftAwayTime3D,ebx
cmp liftAwayTime3D,2800
jb roof_update_done
mov liftTrip3D,0
mov liftPhase3D,3
ret
roof_lift_closing:
; An idle close reverses if the player re-enters the doorway.
cmp liftTrip3D,0
jne roof_lift_close_step
cmp playerX,23*FP_1
jb roof_lift_close_step
cmp playerX,26*FP_1
ja roof_lift_close_step
cmp playerY,5*FP_1
ja roof_lift_close_step
mov liftPhase3D,1
ret
roof_lift_close_step:
sub liftDoor3D,ebx
ja roof_update_done
mov liftDoor3D,0
mov liftPhase3D,0
cmp liftTrip3D,0
je roof_update_done
mov liftPhase3D,4
mov liftRideTime3D,0
ret
roof_lift_ride:
add liftRideTime3D,ebx
cmp liftRideTime3D,3200
jb roof_update_done
mov eax,liftDestination3D
mov hallLevel3D,eax
mov worldMap3D,OFFSET casinoMap
mov floorTexture3D,100
test eax,eax
jz @F
mov worldMap3D,OFFSET roofMap3D
mov floorTexture3D,ROOF_DECK
invoke CopyString3D,OFFSET roofArrival3D,OFFSET flashMessage
mov flashTimer,150
@@:
mov liftTrip3D,0
mov liftPhase3D,1
mov liftAwayTime3D,0
mov interactTargetId,0
mov interactPromptPtr,0
call ClearKeys3D
roof_update_done:
ret
UpdateRoof3D ENDP
CheckRoofInteractions3D PROC uses esi
cmp hallLevel3D,0
je roof_check_lift
cmp hallLevel3D,HALL_ROOF
jne roof_check_done
mov interactTargetId,0
mov interactPromptPtr,0
cmp roofLean3D,0
je @F
mov interactTargetId,INTERACT_ROOF_RAIL
mov interactPromptPtr,OFFSET roofLeanLeave3D
ret
@@:
cmp roofSeat3D,0
je @F
mov interactTargetId,INTERACT_ROOF_SEAT
mov interactPromptPtr,OFFSET roofStandPrompt3D
ret
@@:
invoke HallTarget3D,15*FP_1,5*FP_1,INTERACT_BAR,OFFSET roofBarPrompt3D
cmp interactTargetId,INTERACT_BAR
je roof_check_lift
xor esi,esi
roof_check_seat:
invoke HallTarget3D,roofSeatX3D[esi*4],roofSeatY3D[esi*4],INTERACT_ROOF_SEAT,OFFSET roofSeatPrompt3D
cmp interactTargetId,INTERACT_ROOF_SEAT
jne @F
mov roofTargetSeat3D,esi
jmp roof_check_lift
@@:
inc esi
cmp esi,ROOF_SEAT_COUNT
jb roof_check_seat
call CheckRoofRail3D
roof_check_lift:
cmp liftPhase3D,3
jae roof_check_busy
cmp playerX,FP_1*236/10
jb roof_check_call
cmp playerX,FP_1*252/10
ja roof_check_call
cmp playerY,FP_1*31/10
ja roof_check_call
mov interactTargetId,INTERACT_LIFT_TRAVEL
mov interactPromptPtr,OFFSET roofLiftUp3D
cmp hallLevel3D,HALL_ROOF
jne roof_check_done
mov interactPromptPtr,OFFSET roofLiftDown3D
ret
roof_check_call:
invoke HallTarget3D,FP_1*2555/100,LIFT_FRONT_Y,INTERACT_LIFT_CALL,OFFSET roofLiftCall3D
ret
roof_check_busy:
cmp liftTrip3D,0
je roof_check_done
mov interactTargetId,0
mov interactPromptPtr,OFFSET roofLiftBusy3D
cmp liftDestination3D,0
jne roof_check_done
mov interactPromptPtr,OFFSET roofLiftBusyDown3D
roof_check_done:
ret
CheckRoofInteractions3D ENDP
TryRoofInteraction3D PROC uses ebx
cmp hallLevel3D,0
je roof_try_lift
cmp hallLevel3D,HALL_ROOF
jne roof_try_none
cmp interactTargetId,INTERACT_ROOF_RAIL
jne @F
cmp roofLean3D,0
je roof_try_lean
mov roofLean3D,3
jmp roof_try_handled
roof_try_lean:
call StartRoofLean3D
jmp roof_try_handled
@@:
cmp interactTargetId,INTERACT_ROOF_SEAT
jne roof_try_lift
cmp roofSeat3D,0
je roof_try_sit
call StandFromRoofSeat3D
jmp roof_try_handled
roof_try_sit:
mov ebx,roofTargetSeat3D
cmp ebx,ROOF_SEAT_COUNT
jae roof_try_none
mov eax,playerX
mov roofReturnX3D,eax
mov eax,playerY
mov roofReturnY3D,eax
mov eax,playerAngle
mov roofReturnAngle3D,eax
mov eax,roofSeatX3D[ebx*4]
mov playerX,eax
mov eax,roofSeatY3D[ebx*4]
mov playerY,eax
mov playerAngle,384
cmp roofSeatKind3D[ebx*4],3
jne @F
mov playerAngle,256
@@:
inc ebx
mov roofSeat3D,ebx
jmp roof_try_handled
roof_try_lift:
cmp interactTargetId,INTERACT_LIFT_CALL
jne roof_try_travel
cmp liftPhase3D,3
jae roof_try_none
mov liftPhase3D,1
mov liftAwayTime3D,0
jmp roof_try_handled
roof_try_travel:
cmp interactTargetId,INTERACT_LIFT_TRAVEL
jne roof_try_none
cmp liftPhase3D,2
jne roof_try_none
cmp playerX,FP_1*236/10
jb roof_try_none
cmp playerX,FP_1*252/10
ja roof_try_none
cmp playerY,FP_1*31/10
ja roof_try_none
cmp playerY,FP_1*15/10
jb roof_try_none
mov liftDestination3D,HALL_ROOF
cmp hallLevel3D,0
je @F
mov liftDestination3D,0
@@:
mov liftTrip3D,1
mov liftPhase3D,3
mov liftRideTime3D,0
roof_try_handled:
call ClearKeys3D
mov eax,1
ret
roof_try_none:
xor eax,eax
ret
TryRoofInteraction3D ENDP
LiftCanWalk3D PROC px:DWORD,py:DWORD
cmp hallLevel3D,0
je @F
cmp hallLevel3D,HALL_ROOF
jne roof_lift_walk_clear
@@:
cmp py,FP_1*325/100
jb roof_lift_walk_inner
cmp py,FP_1*375/100
ja roof_lift_walk_clear
cmp px,FP_1*2225/100
jb roof_lift_walk_clear
cmp px,FP_1*2655/100
ja roof_lift_walk_clear
cmp px,FP_1*236/10
jb roof_lift_walk_block
cmp px,FP_1*252/10
ja roof_lift_walk_block
roof_lift_walk_inner:
cmp px,FP_1*231/10
jb roof_lift_walk_clear
cmp px,FP_1*257/10
ja roof_lift_walk_clear
cmp py,FP_1*37/10
ja roof_lift_walk_clear
cmp liftTrip3D,0
jne roof_lift_walk_block
cmp px,FP_1*236/10
jb roof_lift_walk_block
cmp px,FP_1*252/10
ja roof_lift_walk_block
cmp py,FP_1*15/10
jb roof_lift_walk_block
cmp py,FP_1*33/10
jb roof_lift_walk_clear
cmp liftDoor3D,950
jb roof_lift_walk_block
roof_lift_walk_clear:
mov eax,1
ret
roof_lift_walk_block:
xor eax,eax
ret
LiftCanWalk3D ENDP
RoofCanWalk3D PROC uses ebx esi px:DWORD,py:DWORD
cmp roofLean3D,0
jne roof_walk_block
cmp roofSeat3D,0
jne roof_walk_block
invoke LiftCanWalk3D,px,py
test eax,eax
jz roof_walk_block
cmp px,FP_1*112/10
jb roof_walk_block
cmp px,FP_1*288/10
ja roof_walk_block
cmp py,FP_1*12/10
jb roof_walk_block
cmp py,FP_1*208/10
ja roof_walk_block
cmp px,FP_1*117/10
jb roof_walk_furniture
cmp px,FP_1*183/10
ja roof_walk_furniture
cmp py,FP_1*51/10
jb roof_walk_block
roof_walk_furniture:
cmp px,FP_1*113/10
jb roof_walk_posts_start
cmp px,FP_1*1255/100
ja roof_walk_posts_start
cmp py,FP_1*113/10
jb roof_walk_posts_start
cmp py,FP_1*167/10
jbe roof_walk_block
roof_walk_posts_start:
xor esi,esi
roof_walk_post:
mov eax,px
sub eax,roofPostX3D[esi*4]
test eax,eax
jns @F
neg eax
@@:
cmp eax,FP_1/4
ja roof_walk_post_next
mov eax,py
sub eax,roofPostY3D[esi*4]
test eax,eax
jns @F
neg eax
@@:
cmp eax,FP_1/4
jbe roof_walk_block
roof_walk_post_next:
inc esi
cmp esi,8
jb roof_walk_post
xor esi,esi
roof_walk_sofa:
mov eax,px
sub eax,roofSeatX3D[esi*4]
test eax,eax
jns @F
neg eax
@@:
mov ebx,FP_1*17/10
cmp roofSeatKind3D[esi*4],0
je @F
mov ebx,FP_1*7/10
cmp roofSeatKind3D[esi*4],2
jb @F
mov ebx,FP_1*45/100
@@:
cmp eax,ebx
ja roof_walk_next
mov eax,py
sub eax,roofSeatY3D[esi*4]
cmp roofSeatKind3D[esi*4],2
jb roof_walk_low_seat
cmp eax,-FP_1*45/100
jl roof_walk_next
cmp eax,FP_1*65/100
jle roof_walk_block
jmp roof_walk_next
roof_walk_low_seat:
cmp eax,-FP_1/2
jl roof_walk_table
cmp eax,FP_1*12/10
jle roof_walk_block
roof_walk_table:
mov ebx,FP_1*18/10
cmp roofSeatKind3D[esi*4],1
jne @F
mov ebx,FP_1*14/10
@@:
add eax,ebx
cmp eax,-FP_1*6/10
jl roof_walk_next
cmp eax,FP_1*6/10
jg roof_walk_next
mov eax,px
sub eax,roofSeatX3D[esi*4]
test eax,eax
jns @F
neg eax
@@:
cmp eax,FP_1*8/10
jbe roof_walk_block
roof_walk_next:
inc esi
cmp esi,ROOF_SEAT_COUNT
jb roof_walk_sofa
xor esi,esi
roof_walk_tree:
mov eax,px
sub eax,roofTreeX3D[esi*4]
test eax,eax
jns @F
neg eax
@@:
cmp eax,FP_1*5/10
ja roof_walk_tree_next
mov eax,py
sub eax,roofTreeY3D[esi*4]
test eax,eax
jns @F
neg eax
@@:
cmp eax,FP_1*5/10
jbe roof_walk_block
roof_walk_tree_next:
inc esi
cmp esi,ROOF_TREE_COUNT
jb roof_walk_tree
mov eax,1
ret
roof_walk_block:
xor eax,eax
ret
RoofCanWalk3D ENDP
RenderLift3D PROC uses ebx esi
local slide:DWORD
call UpdateRoofIndicator3D
; The cabin is real geometry on both landings, never a screen transition.
invoke DrawCityBoxSides3D,FP_1*2325/100,FP_1*2345/100,FP_1*12/10,LIFT_FRONT_Y,0,FP_1*24/10,ROOF_PLASTER
invoke DrawCityBoxSides3D,FP_1*2535/100,FP_1*2555/100,FP_1*12/10,LIFT_FRONT_Y,0,FP_1*24/10,ROOF_PLASTER
invoke DrawCityBoxSides3D,FP_1*2345/100,FP_1*2535/100,FP_1*12/10,FP_1*13/10,0,FP_1*24/10,ROOF_METAL
invoke DrawCityHorizontal3D,FP_1*2345/100,FP_1*2535/100,FP_1*13/10,LIFT_FRONT_Y,FP_1*24/10,ROOF_PLASTER
invoke DrawCityHorizontal3D,24*FP_1,FP_1*248/10,FP_1*17/10,FP_1*29/10,FP_1*238/100,ROOF_LIGHT
invoke DrawCityHorizontal3D,FP_1*2345/100,FP_1*2535/100,FP_1*13/10,LIFT_FRONT_Y,FP_1/50,ROOF_STONE
invoke DrawCityVertical3D,1,FP_1*134/100,FP_1*236/10,FP_1*252/10,FP_1*85/100,FP_1*9/10,ROOF_BRASS
invoke DrawCityVertical3D,0,FP_1*235/10,FP_1*15/10,3*FP_1,FP_1*85/100,FP_1*9/10,ROOF_BRASS
invoke DrawCityVertical3D,0,FP_1*253/10,FP_1*15/10,3*FP_1,FP_1*85/100,FP_1*9/10,ROOF_BRASS
invoke DrawCityVertical3D,0,FP_1*2533/100,FP_1*20/10,FP_1*24/10,FP_1*9/10,FP_1*15/10,ROOF_BUTTON
invoke DrawCityVertical3D,0,FP_1*2533/100,FP_1*19/10,FP_1*24/10,FP_1*17/10,FP_1*21/10,ROOF_INDICATOR
; Exterior call panel and a lit lintel.
invoke DrawCityVertical3D,1,FP_1*358/100,FP_1*254/10,FP_1*258/10,FP_1*9/10,FP_1*15/10,ROOF_BUTTON
invoke DrawCityBoxSides3D,FP_1*232/10,FP_1*256/10,FP_1*34/10,FP_1*35/10,FP_1*225/100,FP_1*24/10,ROOF_BRASS
invoke DrawCityVertical3D,1,FP_1*357/100,FP_1*241/10,FP_1*247/10,FP_1*226/100,FP_1*24/10,ROOF_INDICATOR
mov eax,liftDoor3D
imul eax,FP_1*95/100
xor edx,edx
mov ecx,1000
div ecx
mov slide,eax
mov ebx,LIFT_CENTRE_X-FP_1*95/100
sub ebx,eax
mov esi,LIFT_CENTRE_X
sub esi,eax
invoke DrawCityVertical3D,1,LIFT_FRONT_Y,ebx,esi,0,FP_1*225/100,ROOF_DOOR
mov eax,slide
add eax,LIFT_CENTRE_X
mov ebx,eax
add eax,FP_1*95/100
invoke DrawCityVertical3D,1,LIFT_FRONT_Y,ebx,eax,0,FP_1*225/100,ROOF_DOOR
; These pockets occlude the translated leaves instead of squeezing their artwork.
invoke DrawCityBoxSides3D,FP_1*224/10,FP_1*2345/100,FP_1*344/100,FP_1*356/100,0,FP_1*24/10,ROOF_PLASTER
invoke DrawCityBoxSides3D,FP_1*2535/100,FP_1*264/10,FP_1*344/100,FP_1*356/100,0,FP_1*24/10,ROOF_PLASTER
ret
RenderLift3D ENDP
UpdateRoofIndicator3D PROC uses ebx esi edi
lea edi,roofIndicatorPixels3D
mov eax,0FF101C24h
mov ecx,4096
rep stosd
mov eax,'1'
cmp hallLevel3D,HALL_ROOF
jne @F
mov eax,'R'
@@:
cmp liftPhase3D,4
jne roof_indicator_glyph
mov eax,liftRideTime3D
shr eax,10
inc eax
cmp liftDestination3D,0
jne @F
neg eax
add eax,5
@@:
add eax,'0'
roof_indicator_glyph:
lea esi,font8x8[eax*8]
xor ebx,ebx
roof_indicator_row:
movzx edx,BYTE PTR [esi+ebx]
xor ecx,ecx
roof_indicator_column:
test edx,80h
jz roof_indicator_next
mov eax,ebx
shl eax,2
add eax,16
shl eax,6
mov edi,ecx
shl edi,2
add edi,16
add edi,eax
lea edi,roofIndicatorPixels3D[edi*4]
push ecx
push edx
mov edx,4
roof_indicator_block_row:
mov eax,0FFFFDEA0h
mov ecx,4
rep stosd
add edi,(64-4)*4
dec edx
jnz roof_indicator_block_row
pop edx
pop ecx
roof_indicator_next:
shl edx,1
inc ecx
cmp ecx,8
jb roof_indicator_column
inc ebx
cmp ebx,8
jb roof_indicator_row
ret
UpdateRoofIndicator3D ENDP
DrawRoofSofa3D PROC uses ebx esi centreX:DWORD,frontY:DWORD
invoke DrawRoofUpholstery3D,centreX,frontY,0
ret
DrawRoofSofa3D ENDP
DrawRoofChair3D PROC uses ebx esi centreX:DWORD,frontY:DWORD,kind:DWORD
invoke DrawRoofUpholstery3D,centreX,frontY,kind
ret
DrawRoofChair3D ENDP
DrawRoofCoffee3D PROC uses ebx centreX:DWORD,centreY:DWORD
local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD
mov eax,centreX
sub eax,FP_1*6/10
mov x0,eax
add eax,FP_1*12/10
mov x1,eax
mov eax,centreY
sub eax,FP_1*4/10
mov y0,eax
add eax,FP_1*8/10
mov y1,eax
invoke DrawCityBoxSides3D,x0,x1,y0,y1,FP_1*4/10,FP_1*45/100,ROOF_STONE
invoke DrawCityHorizontal3D,x0,x1,y0,y1,FP_1*45/100,ROOF_MARBLE
mov eax,centreX
sub eax,FP_1*75/100
mov ebx,centreX
add ebx,FP_1*75/100
invoke DrawCityVertical3D,1,centreY,eax,ebx,0,FP_1*9/10,ROOF_TABLE
ret
DrawRoofCoffee3D ENDP
DrawRoofTree3D PROC uses ebx centreX:DWORD,centreY:DWORD,material:DWORD
local loX:DWORD,hiX:DWORD,loY:DWORD,hiY:DWORD
mov eax,centreX
sub eax,FP_1
mov loX,eax
add eax,2*FP_1
mov hiX,eax
mov eax,centreY
sub eax,FP_1
mov loY,eax
add eax,2*FP_1
mov hiY,eax
invoke DrawCityVertical3D,1,centreY,loX,hiX,0,FP_1*24/10,material
invoke DrawCityVertical3D,0,centreX,loY,hiY,0,FP_1*24/10,material
ret
DrawRoofTree3D ENDP
DrawRoofBulb3D PROC uses ebx wx:DWORD,wy:DWORD,wz:DWORD
local endX:DWORD,endY:DWORD,endZ:DWORD
mov eax,wx
add eax,FP_1/12
mov endX,eax
mov eax,wy
add eax,FP_1/12
mov endY,eax
mov eax,wz
add eax,FP_1/10
mov endZ,eax
mov eax,wx
sub eax,FP_1/12
mov ebx,wx
add ebx,FP_1/12
mov ecx,wz
add ecx,FP_1/4
invoke DrawCityVertical3D,1,wy,eax,ebx,wz,ecx,ROOF_LANTERN
ret
DrawRoofBulb3D ENDP
RenderRoof3D PROC uses ebx esi edi
call UpdateRoofQuality3D
call UpdateRoofLook3D
call UpdateRoofEye3D
; Replace the prepass walls: roof boundaries are low physical rails, not DDA walls.
cmp roofHDReady3D,1
jne roof_render_cpu_planes
cmp engineMode,MODE_WALK
jne roof_render_cpu_planes
lea edi,screenBuffer
xor eax,eax
mov ecx,SCREEN_SIZE
rep stosd
jmp roof_render_planes_ready
roof_render_cpu_planes:
call RenderCeilingAndFloor
roof_render_planes_ready:
lea edi,cityDepthBuffer3D
mov eax,ROOF_FAR_DEPTH
mov ecx,SCREEN_SIZE
rep stosd
lea edi,zBuffer
mov ecx,SCREEN_W
rep stosd
lea edi,roofCityMask3D
mov eax,02020202h
mov ecx,SCREEN_SIZE/4
rep stosd
lea edi,roofGlowMask3D
xor eax,eax
mov ecx,SCREEN_SIZE/4
rep stosd
call PrepareCityRays3D
call PrepareRoofFloorDepth3D
cmp roofHDReady3D,1
jne roof_render_software_city
cmp engineMode,MODE_WALK
je roof_render_city_ready
roof_render_software_city:
call PrepareRoofCityAA3D
mov roofCityPass3D,1
call RenderRoofCityGround3D
call RenderRoofDistrict3D
call RenderRoofLandmarks3D
call RenderRoofCityParks3D
call RenderRoofCityLamps3D
call RenderRoofTraffic3D
call RenderRoofCityBloom3D
call FinishRoofCityAA3D
mov roofCityPass3D,0
call PrepareCityRays3D
roof_render_city_ready:
lea esi,screenBuffer
lea edi,roofHDBackdrop3D
mov ecx,SCREEN_SIZE
rep movsd
call RenderLift3D
; Long working bar, lit backbar and a genuine slatted pergola.
invoke DrawCityBoxSides3D,12*FP_1,18*FP_1,4*FP_1,FP_1*48/10,0,FP_1*9/10,ROOF_STONE
invoke DrawCityVertical3D,1,FP_1*481/100,12*FP_1,15*FP_1,0,FP_1*88/100,ROOF_BAR_FRONT
invoke DrawCityVertical3D,1,FP_1*481/100,15*FP_1,18*FP_1,0,FP_1*88/100,ROOF_BAR_FRONT
invoke DrawCityHorizontal3D,12*FP_1,18*FP_1,4*FP_1,5*FP_1,FP_1*9/10,ROOF_MARBLE
invoke DrawCityBoxSides3D,12*FP_1,18*FP_1,FP_1*15/10,FP_1*17/10,0,FP_1*22/10,ROOF_STONE
invoke DrawCityVertical3D,1,FP_1*171/100,12*FP_1,15*FP_1,FP_1*4/10,FP_1*22/10,ROOF_BOTTLES
invoke DrawCityVertical3D,1,FP_1*171/100,15*FP_1,18*FP_1,FP_1*4/10,FP_1*22/10,ROOF_BOTTLES
xor esi,esi
roof_pergola_post:
mov ebx,roofPostX3D[esi*4]
mov ecx,roofPostY3D[esi*4]
mov eax,ebx
add eax,FP_1/8
mov edx,ecx
add edx,FP_1/8
invoke DrawCityBoxSides3D,ebx,eax,ecx,edx,0,FP_1*28/10,ROOF_STONE
inc esi
cmp esi,8
jb roof_pergola_post
xor esi,esi
roof_pergola_slat:
mov eax,esi
imul eax,FP_1*6/10
add eax,12*FP_1
mov ebx,eax
add ebx,FP_1/10
invoke DrawCityHorizontal3D,eax,ebx,FP_1*15/10,FP_1*63/10,FP_1*28/10,ROOF_STONE
inc esi
cmp esi,11
jb roof_pergola_slat
mov eax,animationClock3D
shr eax,8
and eax,1
cmp engineMode,MODE_BAR
jne roof_tender_frame
mov eax,barTime3D
xor edx,edx
mov ecx,375
div ecx
cmp eax,7
jbe @F
mov eax,7
@@:
mov edx,barSelection3D
shl edx,3
add eax,edx
roof_tender_frame:
mov roofTender3D.frame,eax
invoke DrawCityObject3D,OFFSET roofTender3D,0
xor esi,esi
roof_draw_sofas:
cmp roofSeatKind3D[esi*4],0
jne roof_draw_chair
invoke DrawRoofSofa3D,roofSeatX3D[esi*4],roofSeatY3D[esi*4]
jmp roof_draw_seat_coffee
roof_draw_chair:
cmp engineMode,MODE_BAR
jne @F
cmp roofSeatKind3D[esi*4],2
jae roof_draw_next_seat
@@:
invoke DrawRoofChair3D,roofSeatX3D[esi*4],roofSeatY3D[esi*4],roofSeatKind3D[esi*4]
roof_draw_seat_coffee:
cmp roofSeatKind3D[esi*4],2
jae roof_draw_next_seat
mov eax,roofSeatY3D[esi*4]
sub eax,FP_1*18/10
cmp roofSeatKind3D[esi*4],1
jne @F
add eax,FP_1*4/10
@@:
invoke DrawRoofCoffee3D,roofSeatX3D[esi*4],eax
roof_draw_next_seat:
inc esi
cmp esi,ROOF_SEAT_COUNT
jb roof_draw_sofas
; Standing-height counter along the city rail, with three stools and lamps.
invoke DrawCityBoxSides3D,FP_1*115/10,FP_1*122/10,FP_1*115/10,FP_1*165/10,FP_1,FP_1*106/100,ROOF_STONE
invoke DrawCityHorizontal3D,FP_1*115/10,FP_1*122/10,FP_1*115/10,FP_1*165/10,FP_1*106/100,ROOF_MARBLE
xor esi,esi
roof_high_counter_leg:
mov eax,esi
imul eax,FP_1*23/10
add eax,FP_1*116/10
mov ebx,eax
add ebx,FP_1/10
invoke DrawCityBoxSides3D,FP_1*117/10,FP_1*118/10,eax,ebx,0,FP_1,ROOF_METAL
inc esi
cmp esi,3
jb roof_high_counter_leg
invoke DrawRoofBulb3D,FP_1*1185/100,FP_1*124/10,FP_1*107/100
invoke DrawRoofBulb3D,FP_1*1185/100,FP_1*146/10,FP_1*107/100
xor esi,esi
roof_draw_trees:
invoke DrawRoofTree3D,roofTreeX3D[esi*4],roofTreeY3D[esi*4],ROOF_TREE
inc esi
cmp esi,ROOF_TREE_COUNT
jb roof_draw_trees
invoke DrawRoofPlanter3D,12*FP_1,16*FP_1,FP_1*199/10,FP_1*205/10
invoke DrawRoofPlanter3D,23*FP_1,27*FP_1,FP_1*199/10,FP_1*205/10
xor esi,esi
roof_rail_post:
imul eax,esi,FP_1*25/10
add eax,FP_1*112/10
mov ebx,eax
add ebx,FP_1/14
invoke DrawCityBoxSides3D,eax,ebx,FP_1*208/10,21*FP_1,0,ROOF_RAIL_HEIGHT,ROOF_METAL
mov eax,esi
imul eax,FP_1*25/10
add eax,FP_1*112/10
mov ebx,eax
add ebx,FP_1/14
invoke DrawCityBoxSides3D,eax,ebx,FP_1,FP_1*12/10,0,ROOF_RAIL_HEIGHT,ROOF_METAL
inc esi
cmp esi,8
jb roof_rail_post
invoke DrawRoofSolid3D,11*FP_1,29*FP_1,FP_1*2085/100,FP_1*2095/100,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL
invoke DrawRoofSolid3D,11*FP_1,29*FP_1,FP_1*105/100,FP_1*115/100,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL
invoke DrawRoofSolid3D,FP_1*1105/100,FP_1*1115/100,FP_1,21*FP_1,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL
invoke DrawRoofSolid3D,FP_1*2885/100,FP_1*2895/100,FP_1,21*FP_1,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL
xor esi,esi
roof_rail_side_post:
imul eax,esi,FP_1*25/10
add eax,FP_1*12/10
mov ebx,eax
add ebx,FP_1/14
invoke DrawCityBoxSides3D,11*FP_1,FP_1*112/10,eax,ebx,0,ROOF_RAIL_HEIGHT,ROOF_METAL
mov eax,esi
imul eax,FP_1*25/10
add eax,FP_1*12/10
mov ebx,eax
add ebx,FP_1/14
invoke DrawCityBoxSides3D,FP_1*288/10,29*FP_1,eax,ebx,0,ROOF_RAIL_HEIGHT,ROOF_METAL
inc esi
cmp esi,8
jb roof_rail_side_post
; Two suspended strings of small physical lamps, with edge supports.
xor esi,esi
roof_string_bulb:
imul eax,esi,FP_1*13/10
add eax,12*FP_1
invoke DrawRoofBulb3D,eax,7*FP_1,FP_1*235/100
imul eax,esi,FP_1*13/10
add eax,12*FP_1
invoke DrawRoofBulb3D,eax,15*FP_1,FP_1*235/100
inc esi
cmp esi,13
jb roof_string_bulb
invoke DrawCityVertical3D,1,7*FP_1,12*FP_1,28*FP_1,FP_1*26/10,FP_1*261/100,ROOF_METAL
invoke DrawCityVertical3D,1,15*FP_1,12*FP_1,28*FP_1,FP_1*26/10,FP_1*261/100,ROOF_METAL
xor esi,esi
roof_guest_draw:
mov eax,roofGuestX3D[esi*4]
mov roofActor3D.posX,eax
mov eax,roofGuestY3D[esi*4]
mov roofActor3D.posY,eax
mov eax,roofGuestFrame3D[esi*4]
mov roofActor3D.frame,eax
mov roofActor3D.asset,OFFSET npcGuestArt3D
cmp roofGuestMoving3D[esi*4],0
je roof_guest_idle
cmp npcWalkArt3D.pixels,0
je roof_guest_idle
xor edx,edx
mov ecx,6
div ecx
shl eax,3
mov ebx,eax
mov eax,roofGuestDistance3D[esi*4]
xor edx,edx
mov ecx,FP_1*3/32
div ecx
and eax,7
add eax,ebx
mov roofActor3D.frame,eax
mov roofActor3D.asset,OFFSET npcWalkArt3D
mov eax,roofGuestDir3D[esi*4]
mov ecx,playerDirY
neg ecx
cmp eax,0
je roof_guest_facing
neg ecx
cmp eax,1
je roof_guest_facing
mov ecx,playerDirX
cmp eax,2
je roof_guest_facing
neg ecx
roof_guest_facing:
test ecx,ecx
jns roof_guest_draw_sprite
mov roofActor3D.asset,OFFSET npcWalkLeftArt3D
jmp roof_guest_draw_sprite
roof_guest_idle:
mov eax,roofGuestClock3D
shr eax,10
add eax,esi
and eax,1
add roofActor3D.frame,eax
roof_guest_draw_sprite:
invoke DrawCityObject3D,OFFSET roofActor3D,0
inc esi
cmp esi,ROOF_GUEST_COUNT
jb roof_guest_draw
call ShadeRoofNight3D
call RenderRoofLean3D
call RenderRoofQualityToast3D
ret
RenderRoof3D ENDP
include src_graphics\rooftop_details.inc
include src_graphics\rooftop_atmosphere.inc
include src_graphics\rooftop_surfaces.inc
include src_graphics\rooftop_city_life.inc
include src_graphics\rooftop_gl.inc
include src_graphics\rooftop_quality.inc