Implement 32x32 BFS visitor navigation and daily contracts system with companion .npc journals; add native assembly scenes for Clover slots, Pyramid cards, Blackjack Party and Russian Party; package animation and sprite packs; add comprehensive offline test suites and rebuild shipping binaries.
1306 lines
36 KiB
PHP
1306 lines
36 KiB
PHP
; Room planes use independent ceiling/floor distances; the eye is not the room midpoint.
|
|
RenderCeilingAndFloor PROC uses ebx esi edi
|
|
local row:DWORD,distance:DWORD,sx:DWORD,sy:DWORD,wx:DWORD,wy:DWORD
|
|
local material:DWORD,shade:DWORD
|
|
mov row, 0
|
|
hall_plane_row:
|
|
mov eax, row
|
|
cmp eax, viewHorizon3D
|
|
jge hall_plane_floor
|
|
cmp outdoorRender3D, 0
|
|
jne hall_plane_next_row
|
|
mov ecx, viewHorizon3D
|
|
sub ecx, eax
|
|
mov eax, viewCeiling3D
|
|
sub eax, viewEye3D
|
|
mov material, 101
|
|
cmp hallLevel3D, 0
|
|
je @F
|
|
mov material, 93
|
|
@@:
|
|
jmp hall_plane_distance
|
|
hall_plane_floor:
|
|
sub eax, viewHorizon3D
|
|
inc eax
|
|
mov ecx, eax
|
|
mov eax, viewEye3D
|
|
mov ebx, floorTexture3D
|
|
mov material, ebx
|
|
hall_plane_distance:
|
|
imul eax, SCREEN_H
|
|
cdq
|
|
idiv ecx
|
|
mov distance, eax
|
|
shr eax, 14
|
|
neg eax
|
|
add eax, 256
|
|
cmp eax, 55
|
|
jge @F
|
|
mov eax, 55
|
|
@@:
|
|
mov shade, eax
|
|
cmp hallLevel3D, 0
|
|
je @F
|
|
mov eax, shade
|
|
imul eax, 7
|
|
shr eax, 3
|
|
mov shade, eax
|
|
@@:
|
|
mov eax, playerPlaneX
|
|
shl eax, 1
|
|
imul distance
|
|
shrd eax, edx, 16
|
|
cdq
|
|
mov ecx, SCREEN_W
|
|
idiv ecx
|
|
mov sx, eax
|
|
mov eax, playerPlaneY
|
|
shl eax, 1
|
|
imul distance
|
|
shrd eax, edx, 16
|
|
cdq
|
|
idiv ecx
|
|
mov sy, eax
|
|
mov eax, playerDirX
|
|
sub eax, playerPlaneX
|
|
imul distance
|
|
shrd eax, edx, 16
|
|
add eax, playerX
|
|
mov wx, eax
|
|
mov eax, playerDirY
|
|
sub eax, playerPlaneY
|
|
imul distance
|
|
shrd eax, edx, 16
|
|
add eax, playerY
|
|
mov wy, eax
|
|
mov eax, row
|
|
imul eax, SCREEN_W*4
|
|
lea edi, screenBuffer[eax]
|
|
mov esi, SCREEN_W
|
|
hall_plane_pixel:
|
|
mov ebx, material
|
|
cmp outdoorRender3D, 0
|
|
je hall_plane_sample
|
|
mov eax, wy
|
|
cmp eax, 13*FP_1
|
|
jb hall_plane_crossroad
|
|
cmp eax, 16*FP_1
|
|
jb hall_plane_sample
|
|
hall_plane_crossroad:
|
|
mov eax, wx
|
|
cmp eax, 29*FP_1
|
|
jl hall_plane_sidewalk
|
|
cmp eax, 32*FP_1
|
|
jl hall_plane_sample
|
|
hall_plane_sidewalk:
|
|
mov ebx, 72
|
|
hall_plane_sample:
|
|
cmp outdoorRender3D, 0
|
|
jne hall_plane_low_sample
|
|
mov eax, row
|
|
cmp eax, viewHorizon3D
|
|
jl hall_plane_choose_hd
|
|
cmp hallLevel3D, 0
|
|
jne hall_plane_choose_hd
|
|
cmp wy, 23*FP_1
|
|
jl hall_plane_choose_hd
|
|
cmp wx, 12*FP_1
|
|
jl hall_plane_wood
|
|
cmp wx, 23*FP_1
|
|
jl hall_plane_choose_hd
|
|
hall_plane_wood:
|
|
mov ebx, 85
|
|
hall_plane_choose_hd:
|
|
cmp distance, 6*FP_1
|
|
ja hall_plane_low_sample
|
|
mov ecx, hallRoomHD3D.pixels
|
|
cmp ebx, 80
|
|
jb hall_plane_low_sample
|
|
cmp ebx, 103
|
|
ja hall_plane_low_sample
|
|
cmp ebx, 92
|
|
jb hall_plane_old_hd
|
|
mov ecx, hallArchitectureHD3D.pixels
|
|
sub ebx, 12
|
|
hall_plane_old_hd:
|
|
test ecx, ecx
|
|
jz hall_plane_hd_fallback
|
|
sub ebx, 80
|
|
shl ebx, 18
|
|
add ecx, ebx
|
|
mov eax, wy
|
|
shr eax, 8
|
|
and eax, 255
|
|
shl eax, 8
|
|
mov edx, wx
|
|
shr edx, 8
|
|
and edx, 255
|
|
add eax, edx
|
|
mov eax, [ecx+eax*4]
|
|
jmp hall_plane_shade
|
|
hall_plane_hd_fallback:
|
|
mov ebx, material
|
|
hall_plane_low_sample:
|
|
shl ebx, 16
|
|
mov eax, wy
|
|
shr eax, 9
|
|
and eax, 127
|
|
shl eax, 7
|
|
mov edx, wx
|
|
shr edx, 9
|
|
and edx, 127
|
|
add eax, edx
|
|
lea ebx, texturesBuffer[ebx]
|
|
mov eax, [ebx+eax*4]
|
|
hall_plane_shade:
|
|
cmp outdoorRender3D, 0
|
|
je hall_plane_ambient
|
|
invoke ShadeCityGround3D, eax, wx, wy, shade
|
|
jmp hall_plane_store
|
|
hall_plane_ambient:
|
|
mov ebx, eax
|
|
and eax, 0000FF00h
|
|
imul eax, shade
|
|
shr eax, 8
|
|
and eax, 0000FF00h
|
|
mov ecx, ebx
|
|
and ecx, 0FFh
|
|
imul ecx, shade
|
|
shr ecx, 8
|
|
or eax, ecx
|
|
shr ebx, 16
|
|
and ebx, 0FFh
|
|
imul ebx, shade
|
|
shr ebx, 8
|
|
shl ebx, 16
|
|
or eax, ebx
|
|
hall_plane_store:
|
|
stosd
|
|
mov eax, sx
|
|
add wx, eax
|
|
mov eax, sy
|
|
add wy, eax
|
|
dec esi
|
|
jnz hall_plane_pixel
|
|
hall_plane_next_row:
|
|
inc row
|
|
cmp row, SCREEN_H
|
|
jb hall_plane_row
|
|
ret
|
|
RenderCeilingAndFloor ENDP
|
|
|
|
RenderSprites PROC uses ebx esi edi
|
|
cmp hallLevel3D, 0
|
|
jne hall_sprites_done
|
|
xor esi, esi
|
|
hall_sprite_loop:
|
|
cmp esi, 14
|
|
je hall_sprite_next
|
|
imul ebx, esi, SIZEOF SpriteObject
|
|
mov eax, casinoSprites[ebx].posX
|
|
mov hallSpriteTemp3D.posX, eax
|
|
mov eax, casinoSprites[ebx].posY
|
|
mov hallSpriteTemp3D.posY, eax
|
|
mov eax, hallSpriteWidths3D[esi*4]
|
|
mov hallSpriteTemp3D.worldW, eax
|
|
mov eax, hallSpriteHeights3D[esi*4]
|
|
mov hallSpriteTemp3D.worldH, eax
|
|
mov hallSpriteTemp3D.groundZ, 0
|
|
cmp esi, 3
|
|
jae @F
|
|
mov hallSpriteTemp3D.groundZ, FP_1/8
|
|
@@:
|
|
mov ecx, casinoSprites[ebx].animSpeed
|
|
imul ecx, 40
|
|
test ecx, ecx
|
|
jnz @F
|
|
mov ecx, 40
|
|
@@:
|
|
mov eax, animationClock3D
|
|
cmp esi,3
|
|
jae @F
|
|
mov edx,casinoSprites[ebx].curFrame
|
|
imul edx,ecx
|
|
add eax,edx
|
|
@@:
|
|
xor edx, edx
|
|
div ecx
|
|
mov ecx, casinoSprites[ebx].frameCount
|
|
test ecx, ecx
|
|
jnz @F
|
|
mov ecx, 1
|
|
@@:
|
|
xor edx, edx
|
|
div ecx
|
|
add edx, casinoSprites[ebx].baseTexId
|
|
shl edx, 16
|
|
add edx, OFFSET texturesBuffer
|
|
mov hallLegacyPack3D.pixels, edx
|
|
mov hallSpriteTemp3D.frame, 0
|
|
mov hallSpriteTemp3D.asset, OFFSET hallLegacyPack3D
|
|
mov eax, hallStationPacks3D[esi*4]
|
|
test eax, eax
|
|
jz hall_sprite_draw
|
|
; Missing dedicated art hides the station, never shows a contaminated atlas cell.
|
|
cmp [eax].AnimPack3D.pixels, 0
|
|
je hall_sprite_next
|
|
mov hallSpriteTemp3D.asset, eax
|
|
cmp eax, OFFSET hallSlotFurniture3D
|
|
jne hall_sprite_draw
|
|
mov eax, animationClock3D
|
|
xor edx, edx
|
|
mov ecx, 320
|
|
div ecx
|
|
add eax, esi
|
|
xor edx, edx
|
|
mov ecx, 3
|
|
div ecx
|
|
mov hallSpriteTemp3D.frame, edx
|
|
hall_sprite_draw:
|
|
invoke DrawCityObject3D, OFFSET hallSpriteTemp3D, 0
|
|
hall_sprite_next:
|
|
inc esi
|
|
cmp esi, NUM_SPRITES
|
|
jb hall_sprite_loop
|
|
hall_sprites_done:
|
|
ret
|
|
RenderSprites ENDP
|
|
|
|
InitHall3D PROC uses esi edi
|
|
lea esi, hallLayout3D
|
|
lea edi, casinoMap
|
|
mov ecx, 256
|
|
rep movsd
|
|
mov hallLevel3D, 0
|
|
mov worldMap3D, OFFSET casinoMap
|
|
mov viewEye3D, FP_1*17/20
|
|
mov viewCeiling3D, FP_1*5/2
|
|
mov floorTexture3D, 100
|
|
mov casinoSprites[14*SIZEOF SpriteObject].interactId, 0
|
|
mov patronClock3D, 0
|
|
call InitCasinoNpcMind
|
|
call InitNpcLife3D
|
|
ret
|
|
InitHall3D ENDP
|
|
|
|
LoadHallAssets3D PROC
|
|
invoke LoadAnimPack3D, OFFSET hallCardFurniture3D, OFFSET hallCardFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallWheelFurniture3D, OFFSET hallWheelFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallBackFurniture3D, OFFSET hallBackFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallSkillFurniture3D, OFFSET hallSkillFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallChairFurniture3D, OFFSET hallChairFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallLampFurniture3D, OFFSET hallLampFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallRopeFurniture3D, OFFSET hallRopeFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallSlotFurniture3D, OFFSET hallSlotFurniturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallBartender3D, OFFSET hallBartenderPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallProps3D, OFFSET hallPropsPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallDrink3D, OFFSET hallDrinkPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallCityDetail3D, OFFSET hallCityDetailPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallRoomMaterials3D, OFFSET hallRoomMaterialsPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallPatrons3D, OFFSET hallPatronsPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallStreetLife3D, OFFSET hallStreetLifePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallRoomHD3D, OFFSET hallRoomHDPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallArchitecture3D, OFFSET hallArchitecturePath3D
|
|
invoke LoadAnimPack3D, OFFSET hallArchitectureHD3D, OFFSET hallArchitectureHDPath3D
|
|
invoke LoadAnimPack3D, OFFSET hallDecorPack3D, OFFSET hallDecorPath3D
|
|
cmp hallArchitecture3D.pixels, 0
|
|
je @F
|
|
push esi
|
|
push edi
|
|
mov esi, hallArchitecture3D.pixels
|
|
mov edi, OFFSET texturesBuffer+(92*128*128*4)
|
|
mov ecx, 12*128*128
|
|
rep movsd
|
|
pop edi
|
|
pop esi
|
|
@@:
|
|
cmp hallRoomMaterials3D.pixels, 0
|
|
je @F
|
|
push esi
|
|
push edi
|
|
mov esi, hallRoomMaterials3D.pixels
|
|
mov edi, OFFSET texturesBuffer+(80*128*128*4)
|
|
mov ecx, 12*128*128
|
|
rep movsd
|
|
pop edi
|
|
pop esi
|
|
@@:
|
|
invoke LoadAnimPack3D, OFFSET materialsPack3D, OFFSET materialsPath3D
|
|
cmp materialsPack3D.pixels, 0
|
|
je hall_load_sign
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
xor ebx, ebx
|
|
hall_copy_material:
|
|
mov esi, materialsPack3D.pixels
|
|
mov eax, ebx
|
|
shl eax, 16
|
|
add esi, eax
|
|
mov eax, hallMaterialSlots3D[ebx*4]
|
|
shl eax, 16
|
|
lea edi, texturesBuffer[eax]
|
|
mov ecx, 128*128
|
|
rep movsd
|
|
inc ebx
|
|
cmp ebx, 4
|
|
jb hall_copy_material
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
hall_load_sign:
|
|
ret
|
|
LoadHallAssets3D ENDP
|
|
|
|
FreeHallAssets3D PROC
|
|
call FreeNativeWheelArt3D
|
|
call FreeNativeCoinArt3D
|
|
invoke FreeAnimPack3D, OFFSET hallCardFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallWheelFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallBackFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallSkillFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallChairFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallLampFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallRopeFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallSlotFurniture3D
|
|
invoke FreeAnimPack3D, OFFSET hallBartender3D
|
|
invoke FreeAnimPack3D, OFFSET hallProps3D
|
|
invoke FreeAnimPack3D, OFFSET hallDrink3D
|
|
invoke FreeAnimPack3D, OFFSET hallCityDetail3D
|
|
invoke FreeAnimPack3D, OFFSET hallRoomMaterials3D
|
|
invoke FreeAnimPack3D, OFFSET hallPatrons3D
|
|
invoke FreeAnimPack3D, OFFSET hallStreetLife3D
|
|
invoke FreeAnimPack3D, OFFSET hallRoomHD3D
|
|
invoke FreeAnimPack3D, OFFSET hallArchitecture3D
|
|
invoke FreeAnimPack3D, OFFSET hallArchitectureHD3D
|
|
invoke FreeAnimPack3D, OFFSET hallDecorPack3D
|
|
ret
|
|
FreeHallAssets3D ENDP
|
|
|
|
; EAX=pixels, ECX=width, EDX=height; legacy materials keep their 128px fallback.
|
|
ResolveWorldSurface3D PROC uses esi material:DWORD
|
|
mov eax, material
|
|
cmp eax,110
|
|
jne @F
|
|
mov eax,OFFSET cityBenchMetal3D
|
|
mov ecx,32
|
|
mov edx,32
|
|
ret
|
|
@@:
|
|
cmp eax, 104
|
|
jae surface_decor
|
|
cmp eax, 92
|
|
jae surface_architecture
|
|
cmp eax, 80
|
|
jae surface_room
|
|
cmp eax, 57
|
|
jb surface_legacy
|
|
cmp eax, 72
|
|
ja surface_legacy
|
|
mov esi, OFFSET hallCityDetail3D
|
|
sub eax, 57
|
|
jmp surface_pack
|
|
surface_room:
|
|
mov esi, OFFSET hallRoomHD3D
|
|
sub eax, 80
|
|
jmp surface_pack
|
|
surface_architecture:
|
|
mov esi, OFFSET hallArchitectureHD3D
|
|
sub eax, 92
|
|
jmp surface_pack
|
|
surface_decor:
|
|
cmp eax, 109
|
|
ja surface_missing
|
|
mov esi, OFFSET hallDecorPack3D
|
|
sub eax, 104
|
|
surface_pack:
|
|
cmp [esi].AnimPack3D.pixels, 0
|
|
je surface_legacy
|
|
cmp eax, [esi].AnimPack3D.frames
|
|
jae surface_missing
|
|
mov ecx, [esi].AnimPack3D.imageWidth
|
|
mov edx, [esi].AnimPack3D.height
|
|
imul eax, ecx
|
|
imul eax, edx
|
|
shl eax, 2
|
|
add eax, [esi].AnimPack3D.pixels
|
|
ret
|
|
surface_legacy:
|
|
mov eax, material
|
|
cmp eax, 104
|
|
jae surface_missing
|
|
shl eax, 16
|
|
add eax, OFFSET texturesBuffer
|
|
mov ecx, 128
|
|
mov edx, 128
|
|
ret
|
|
surface_missing:
|
|
xor eax, eax
|
|
mov ecx, 128
|
|
mov edx, 128
|
|
ret
|
|
ResolveWorldSurface3D ENDP
|
|
|
|
RenderHall3D PROC uses ebx esi
|
|
cmp hallLevel3D, 0
|
|
jne hall_render_bunker
|
|
; Fixed bar counter/stage are world geometry, with height and occlusion.
|
|
invoke DrawCityBoxSides3D, 3*FP_1,9*FP_1,23*FP_1,24*FP_1,0,FP_1*13/20,86
|
|
invoke DrawCityHorizontal3D, 3*FP_1,9*FP_1,23*FP_1,24*FP_1,FP_1*13/20,85
|
|
; Three physical panels preserve detail instead of stretching one over the whole bar.
|
|
invoke DrawCityVertical3D,1,24*FP_1,3*FP_1,5*FP_1,0,FP_1*13/20,84
|
|
invoke DrawCityVertical3D,1,24*FP_1,5*FP_1,7*FP_1,0,FP_1*13/20,84
|
|
invoke DrawCityVertical3D,1,24*FP_1,7*FP_1,9*FP_1,0,FP_1*13/20,84
|
|
invoke DrawCityBoxSides3D,3*FP_1,9*FP_1,21*FP_1,22*FP_1,0,FP_1*19/10,86
|
|
invoke DrawCityVertical3D,1,22*FP_1,3*FP_1,5*FP_1,FP_1*3/5,FP_1*19/10,87
|
|
invoke DrawCityVertical3D,1,22*FP_1,5*FP_1,7*FP_1,FP_1*3/5,FP_1*19/10,87
|
|
invoke DrawCityVertical3D,1,22*FP_1,7*FP_1,9*FP_1,FP_1*3/5,FP_1*19/10,87
|
|
invoke DrawCityBoxSides3D, 10*FP_1,22*FP_1,2*FP_1,5*FP_1,0,FP_1/8,2
|
|
invoke DrawCityHorizontal3D, 10*FP_1,22*FP_1,2*FP_1,5*FP_1,FP_1/8,2
|
|
; Cabaret has a solid stage, side wings, stairs and lighting truss.
|
|
invoke DrawCityVertical3D,0,10*FP_1,2*FP_1,5*FP_1,FP_1/8,FP_1*23/10,2
|
|
invoke DrawCityVertical3D,0,22*FP_1,2*FP_1,5*FP_1,FP_1/8,FP_1*23/10,2
|
|
invoke DrawCityVertical3D,1,2*FP_1,10*FP_1,22*FP_1,FP_1/8,FP_1*23/10,2
|
|
invoke DrawCityHorizontal3D,14*FP_1,18*FP_1,5*FP_1,FP_1*11/2,FP_1/12,85
|
|
invoke DrawCityHorizontal3D,14*FP_1,18*FP_1,FP_1*11/2,6*FP_1,FP_1/24,85
|
|
invoke DrawCityBoxSides3D,10*FP_1,22*FP_1,5*FP_1,FP_1*51/10,FP_1*11/5,FP_1*23/10,86
|
|
; Low room boundaries frame dining and billiards without closing their entrances.
|
|
invoke DrawCityBoxSides3D,FP_1*119/10,FP_1*121/10,24*FP_1,FP_1*51/2,0,FP_1*13/20,102
|
|
invoke DrawCityHorizontal3D,FP_1*119/10,FP_1*121/10,24*FP_1,FP_1*51/2,FP_1*13/20,85
|
|
invoke DrawCityBoxSides3D,FP_1*119/10,FP_1*121/10,FP_1*55/2,30*FP_1,0,FP_1*13/20,102
|
|
invoke DrawCityBoxSides3D,23*FP_1,FP_1*116/5,23*FP_1,24*FP_1,0,FP_1*13/20,102
|
|
invoke DrawCityBoxSides3D,23*FP_1,FP_1*116/5,26*FP_1,29*FP_1,0,FP_1*13/20,102
|
|
invoke DrawCityVertical3D,1,6*FP_1,14*FP_1,18*FP_1,FP_1*17/10,FP_1*12/5,109
|
|
invoke DrawCityBoxSides3D,1*FP_1,9*FP_1,FP_1,FP_1*6/5,FP_1*11/5,FP_1*5/2,103
|
|
invoke DrawCityBoxSides3D,23*FP_1,31*FP_1,FP_1,FP_1*6/5,FP_1*11/5,FP_1*5/2,103
|
|
mov eax, animationClock3D
|
|
xor edx, edx
|
|
mov ecx, 220
|
|
div ecx
|
|
and eax, 1
|
|
cmp engineMode, MODE_BAR
|
|
jne hall_bartender_pose
|
|
cmp barPhase3D, 1
|
|
jne hall_bartender_pose
|
|
mov eax, barTime3D
|
|
xor edx, edx
|
|
mov ecx, 375
|
|
div ecx
|
|
cmp eax, 7
|
|
jbe hall_bartender_pose
|
|
mov eax, 7
|
|
jmp hall_bartender_selected
|
|
hall_bartender_pose:
|
|
cmp engineMode, MODE_BAR
|
|
jne hall_bartender_store
|
|
cmp barPhase3D, 1
|
|
je hall_bartender_selected
|
|
cmp barPhase3D, 2
|
|
jne hall_bartender_store
|
|
mov eax,7
|
|
hall_bartender_selected:
|
|
mov ecx, barSelection3D
|
|
shl ecx, 3
|
|
add eax, ecx
|
|
hall_bartender_store:
|
|
mov hallObjects3D[4*SIZEOF CityProp3D].frame, eax
|
|
xor esi, esi
|
|
hall_render_props:
|
|
; The former whole-stage billboard is replaced with world surfaces above.
|
|
cmp esi, 15
|
|
je hall_render_next_prop
|
|
imul eax, esi, SIZEOF CityProp3D
|
|
add eax, OFFSET hallObjects3D
|
|
invoke DrawCityObject3D, eax, 0
|
|
hall_render_next_prop:
|
|
inc esi
|
|
cmp esi, HALL_PROP_COUNT
|
|
jb hall_render_props
|
|
xor esi, esi
|
|
hall_render_lights:
|
|
imul eax, esi, SIZEOF CityProp3D
|
|
add eax, OFFSET hallLights3D
|
|
invoke DrawCityObject3D,eax,0
|
|
inc esi
|
|
cmp esi, HALL_LIGHT_COUNT
|
|
jb hall_render_lights
|
|
xor esi, esi
|
|
hall_render_lounge:
|
|
imul eax, esi, SIZEOF CityProp3D
|
|
add eax, OFFSET hallLoungeDecor3D
|
|
invoke DrawCityObject3D,eax,0
|
|
inc esi
|
|
cmp esi, HALL_DECOR_COUNT
|
|
jb hall_render_lounge
|
|
call RenderPatrons3D
|
|
ret
|
|
hall_render_bunker:
|
|
mov esi, 0
|
|
hall_stair_step:
|
|
mov eax, esi
|
|
imul eax, FP_1/2
|
|
add eax, 24*FP_1
|
|
lea ebx, [eax+FP_1/2]
|
|
lea ecx, [esi+1]
|
|
imul ecx, FP_1/8
|
|
invoke DrawCityHorizontal3D,15*FP_1,18*FP_1,eax,ebx,ecx,88
|
|
mov eax, esi
|
|
imul eax, FP_1/2
|
|
add eax, 24*FP_1
|
|
mov ecx, esi
|
|
imul ecx, FP_1/8
|
|
lea edx, [ecx+FP_1/8]
|
|
invoke DrawCityVertical3D,1,eax,15*FP_1,18*FP_1,ecx,edx,92
|
|
inc esi
|
|
cmp esi, 8
|
|
jb hall_stair_step
|
|
invoke DrawCityBoxSides3D, 14*FP_1,20*FP_1,14*FP_1,15*FP_1,0,FP_1/2,96
|
|
invoke DrawCityHorizontal3D, 14*FP_1,20*FP_1,14*FP_1,15*FP_1,FP_1/2,97
|
|
invoke DrawCityVertical3D,1,11*FP_1+FP_1/10,14*FP_1,16*FP_1,FP_1/4,FP_1*8/5,95
|
|
invoke DrawCityVertical3D,1,11*FP_1+FP_1/10,17*FP_1,19*FP_1+FP_HALF,FP_1/4,FP_1*8/5,95
|
|
invoke DrawCityVertical3D,0,19*FP_1+FP_1*9/10,17*FP_1,20*FP_1,0,FP_1*3/2,99
|
|
; A narrow, stepped vault is real geometry, not a square workshop ceiling.
|
|
invoke DrawCityHorizontal3D,14*FP_1,15*FP_1,11*FP_1,24*FP_1,FP_1*9/5,93
|
|
invoke DrawCityVertical3D,0,15*FP_1,11*FP_1,24*FP_1,FP_1*9/5,FP_1*11/5,93
|
|
invoke DrawCityHorizontal3D,15*FP_1,16*FP_1,11*FP_1,24*FP_1,FP_1*11/5,93
|
|
invoke DrawCityVertical3D,0,16*FP_1,11*FP_1,24*FP_1,FP_1*11/5,FP_1*5/2,93
|
|
invoke DrawCityHorizontal3D,18*FP_1,19*FP_1,11*FP_1,24*FP_1,FP_1*11/5,93
|
|
invoke DrawCityVertical3D,0,18*FP_1,11*FP_1,24*FP_1,FP_1*11/5,FP_1*5/2,93
|
|
invoke DrawCityHorizontal3D,19*FP_1,20*FP_1,11*FP_1,24*FP_1,FP_1*9/5,93
|
|
invoke DrawCityVertical3D,0,19*FP_1,11*FP_1,24*FP_1,FP_1*9/5,FP_1*11/5,93
|
|
mov eax, animationClock3D
|
|
xor edx, edx
|
|
mov ecx, 240
|
|
div ecx
|
|
and eax, 7
|
|
mov bunkerMerchant3D.frame, eax
|
|
invoke DrawCityObject3D, OFFSET bunkerMerchant3D, 0
|
|
invoke DrawCityObject3D, OFFSET bunkerDisplay3D, 0
|
|
invoke DrawCityObject3D, OFFSET bunkerDesk3D, 0
|
|
invoke DrawCityObject3D, OFFSET bunkerDoor3D, 0
|
|
ret
|
|
RenderHall3D ENDP
|
|
|
|
; Extra rooms use the same distance and facing checks as the existing tables.
|
|
HallTarget3D PROC uses ebx wx:DWORD,wy:DWORD,id:DWORD,prompt:DWORD
|
|
mov eax, wx
|
|
sub eax, playerX
|
|
sar eax, 8
|
|
mov ebx, eax
|
|
imul eax, eax
|
|
mov ecx, eax
|
|
mov eax, wy
|
|
sub eax, playerY
|
|
sar eax, 8
|
|
mov edx, eax
|
|
imul eax, eax
|
|
add ecx, eax
|
|
cmp ecx, 262144
|
|
jae hall_target_done
|
|
mov eax, playerDirX
|
|
sar eax, 8
|
|
imul eax, ebx
|
|
mov ebx, playerDirY
|
|
sar ebx, 8
|
|
imul ebx, edx
|
|
add eax, ebx
|
|
cmp eax, 18000
|
|
jl hall_target_done
|
|
mov eax, id
|
|
mov interactTargetId, eax
|
|
mov eax, prompt
|
|
mov interactPromptPtr, eax
|
|
hall_target_done:
|
|
ret
|
|
HallTarget3D ENDP
|
|
|
|
CheckHallInteractions3D PROC
|
|
cmp hallLevel3D, 0
|
|
jne hall_check_bunker
|
|
cmp playerX, 3*FP_1
|
|
jl hall_check_other
|
|
cmp playerX, 9*FP_1
|
|
jg hall_check_other
|
|
cmp playerY, 24*FP_1+9830
|
|
jl hall_check_other
|
|
; A point on the serving edge remains in front even when standing close.
|
|
invoke HallTarget3D, playerX,23*FP_1+FP_HALF,INTERACT_BAR,OFFSET hallBarPrompt3D
|
|
hall_check_other:
|
|
invoke HallTarget3D, 28*FP_1+FP_HALF,10*FP_1+FP_HALF,INTERACT_BASEMENT,OFFSET hallBunkerPrompt3D
|
|
invoke HallTarget3D, 27*FP_1,25*FP_1,INTERACT_BILLIARDS,OFFSET hallPoolPrompt3D
|
|
call CheckNpcInteractions3D
|
|
ret
|
|
hall_check_bunker:
|
|
mov interactTargetId, 0
|
|
mov interactPromptPtr, 0
|
|
invoke HallTarget3D, 16*FP_1,14*FP_1+FP_HALF,INTERACT_SHOP,OFFSET promptShop
|
|
invoke HallTarget3D, 16*FP_1,27*FP_1,INTERACT_UPSTAIRS,OFFSET hallUpPrompt3D
|
|
ret
|
|
CheckHallInteractions3D ENDP
|
|
|
|
TriggerHallInteraction3D PROC
|
|
cmp interactTargetId,INTERACT_NPC
|
|
jne @F
|
|
call OpenNpcDialog3D
|
|
ret
|
|
@@:
|
|
|
|
cmp interactTargetId, INTERACT_BAR
|
|
jne hall_trigger_stairs
|
|
call LoadHallAssets3D
|
|
mov engineMode, MODE_BAR
|
|
mov barPhase3D, 0
|
|
mov barTime3D, 0
|
|
call ClearKeys3D
|
|
mov eax, 1
|
|
ret
|
|
hall_trigger_stairs:
|
|
cmp interactTargetId, INTERACT_BASEMENT
|
|
je hall_begin_stairs
|
|
cmp interactTargetId, INTERACT_UPSTAIRS
|
|
jne hall_trigger_none
|
|
hall_begin_stairs:
|
|
cmp hallLevel3D, 0
|
|
jne @F
|
|
mov eax, playerX
|
|
mov stairsReturnX3D, eax
|
|
mov eax, playerY
|
|
mov stairsReturnY3D, eax
|
|
mov eax, playerAngle
|
|
mov stairsReturnAngle3D, eax
|
|
@@:
|
|
mov engineMode, MODE_STAIRS
|
|
mov stairsTime3D, 0
|
|
call ClearKeys3D
|
|
mov eax, 1
|
|
ret
|
|
hall_trigger_none:
|
|
cmp interactTargetId, INTERACT_BILLIARDS
|
|
jne @F
|
|
call InitPool3D
|
|
mov engineMode, MODE_POOL
|
|
call ClearKeys3D
|
|
mov eax, 1
|
|
ret
|
|
@@:
|
|
xor eax, eax
|
|
ret
|
|
TriggerHallInteraction3D ENDP
|
|
|
|
HandleStairs3D PROC
|
|
mov eax, deltaTime3D
|
|
add stairsTime3D, eax
|
|
cmp stairsTime3D, 1600
|
|
jb stairs_handle_done
|
|
xor hallLevel3D, 1
|
|
cmp hallLevel3D, 0
|
|
je stairs_back_to_hall
|
|
mov worldMap3D, OFFSET bunkerMap3D
|
|
mov floorTexture3D, 94
|
|
mov viewCeiling3D, FP_1*5/2
|
|
mov playerX, 16*FP_1+FP_HALF
|
|
mov playerY, 23*FP_1+FP_HALF
|
|
mov playerAngle, 384
|
|
jmp stairs_complete
|
|
stairs_back_to_hall:
|
|
mov worldMap3D, OFFSET casinoMap
|
|
mov floorTexture3D, 100
|
|
mov viewCeiling3D, FP_1*5/2
|
|
mov eax, stairsReturnX3D
|
|
mov playerX, eax
|
|
mov eax, stairsReturnY3D
|
|
mov playerY, eax
|
|
mov eax, stairsReturnAngle3D
|
|
mov playerAngle, eax
|
|
stairs_complete:
|
|
mov viewEye3D, FP_1*17/20
|
|
mov engineMode, MODE_WALK
|
|
call ClearKeys3D
|
|
stairs_handle_done:
|
|
ret
|
|
HandleStairs3D ENDP
|
|
|
|
RenderStairs3D PROC uses ebx esi
|
|
local oldX:DWORD,oldY:DWORD,oldAngle:DWORD,oldMap:DWORD,oldEye:DWORD,oldCeiling:DWORD,oldLevel:DWORD,oldFloor:DWORD
|
|
mov eax, playerX
|
|
mov oldX, eax
|
|
mov eax, playerY
|
|
mov oldY, eax
|
|
mov eax, playerAngle
|
|
mov oldAngle, eax
|
|
mov eax, worldMap3D
|
|
mov oldMap, eax
|
|
mov eax, viewEye3D
|
|
mov oldEye, eax
|
|
mov eax, viewCeiling3D
|
|
mov oldCeiling, eax
|
|
mov eax, hallLevel3D
|
|
mov oldLevel, eax
|
|
mov eax, floorTexture3D
|
|
mov oldFloor, eax
|
|
mov hallLevel3D, 1
|
|
mov worldMap3D, OFFSET bunkerMap3D
|
|
mov floorTexture3D, 94
|
|
mov viewCeiling3D, FP_1*5/2
|
|
mov playerX, 16*FP_1+FP_HALF
|
|
mov playerAngle, 384
|
|
mov eax, stairsTime3D
|
|
cmp eax, 1600
|
|
jbe @F
|
|
mov eax, 1600
|
|
@@:
|
|
cmp oldLevel, 0
|
|
je @F
|
|
neg eax
|
|
add eax, 1600
|
|
@@:
|
|
imul eax, 4*FP_1
|
|
xor edx, edx
|
|
mov ecx, 1600
|
|
div ecx
|
|
mov ebx, 27*FP_1+FP_HALF
|
|
sub ebx, eax
|
|
mov playerY, ebx
|
|
shr eax, 2
|
|
neg eax
|
|
add eax, FP_1*37/20
|
|
mov viewEye3D, eax
|
|
call UpdateCamera3D
|
|
call RenderCeilingAndFloor
|
|
call RenderWalls
|
|
call PrepareCityDepth3D
|
|
call RenderHall3D
|
|
mov eax, oldX
|
|
mov playerX, eax
|
|
mov eax, oldY
|
|
mov playerY, eax
|
|
mov eax, oldAngle
|
|
mov playerAngle, eax
|
|
mov eax, oldMap
|
|
mov worldMap3D, eax
|
|
mov eax, oldEye
|
|
mov viewEye3D, eax
|
|
mov eax, oldCeiling
|
|
mov viewCeiling3D, eax
|
|
mov eax, oldLevel
|
|
mov hallLevel3D, eax
|
|
mov eax, oldFloor
|
|
mov floorTexture3D, eax
|
|
call UpdateCamera3D
|
|
ret
|
|
RenderStairs3D ENDP
|
|
|
|
BuyBarDrink3D PROC drink:DWORD
|
|
cmp barPhase3D, 0
|
|
jne bar_buy_done
|
|
mov ecx, drink
|
|
cmp ecx, 2
|
|
ja bar_buy_done
|
|
mov eax, barPrice3D[ecx*4]
|
|
cmp bankroll, eax
|
|
jb bar_buy_poor
|
|
sub bankroll, eax
|
|
mov barSelection3D, ecx
|
|
mov barPhase3D, 1
|
|
mov barTime3D, 0
|
|
call SaveProgress3D
|
|
ret
|
|
bar_buy_poor:
|
|
invoke CopyString3D, OFFSET barPoor3D, OFFSET flashMessage
|
|
mov flashTimer, 150
|
|
bar_buy_done:
|
|
ret
|
|
BuyBarDrink3D ENDP
|
|
|
|
HandleBar3D PROC uses ebx
|
|
cmp barPhase3D, 0
|
|
jne bar_animate
|
|
mov ebx, 31h
|
|
bar_select_key:
|
|
invoke Pressed3D, ebx
|
|
test eax, eax
|
|
jz @F
|
|
mov eax, ebx
|
|
sub eax, 31h
|
|
invoke BuyBarDrink3D, eax
|
|
ret
|
|
@@:
|
|
inc ebx
|
|
cmp ebx, 33h
|
|
jbe bar_select_key
|
|
cmp mouseClick3D, 0
|
|
je bar_handle_done
|
|
cmp mouseX3D, 170
|
|
jb bar_handle_done
|
|
cmp mouseY3D, 98
|
|
jb bar_handle_done
|
|
cmp mouseY3D, 155
|
|
jae bar_handle_done
|
|
mov eax, mouseY3D
|
|
sub eax, 98
|
|
xor edx, edx
|
|
mov ecx, 19
|
|
div ecx
|
|
invoke BuyBarDrink3D, eax
|
|
ret
|
|
bar_animate:
|
|
mov eax, deltaTime3D
|
|
add barTime3D, eax
|
|
cmp barPhase3D, 1
|
|
jne bar_after_drink
|
|
cmp barTime3D, 3000
|
|
jb bar_handle_done
|
|
mov barPhase3D, 2
|
|
mov barTime3D, 0
|
|
ret
|
|
bar_after_drink:
|
|
cmp barTime3D, 2400
|
|
jb bar_handle_done
|
|
mov ecx, barSelection3D
|
|
mov eax, barStrength3D[ecx*4]
|
|
test eax, eax
|
|
jnz @F
|
|
mov barIntoxication3D, 0
|
|
@@:
|
|
add barIntoxication3D, eax
|
|
cmp barIntoxication3D, 60000
|
|
jbe @F
|
|
mov barIntoxication3D, 60000
|
|
@@:
|
|
mov barPhase3D, 0
|
|
mov barTime3D, 0
|
|
bar_handle_done:
|
|
ret
|
|
HandleBar3D ENDP
|
|
|
|
RenderBar3D PROC uses ebx
|
|
local oldX:DWORD,oldY:DWORD,oldAngle:DWORD,oldHorizon:DWORD,oldEye:DWORD,oldMode:DWORD
|
|
mov eax, playerX
|
|
mov oldX, eax
|
|
mov eax, playerY
|
|
mov oldY, eax
|
|
mov eax, playerAngle
|
|
mov oldAngle, eax
|
|
mov eax, viewHorizon3D
|
|
mov oldHorizon, eax
|
|
mov eax, viewEye3D
|
|
mov oldEye, eax
|
|
mov eax, engineMode
|
|
mov oldMode, eax
|
|
mov engineMode, MODE_BAR
|
|
mov playerX, 6*FP_1
|
|
mov playerY, 25*FP_1+FP_1/3
|
|
mov playerAngle, 384
|
|
mov viewHorizon3D, HALF_H
|
|
mov viewEye3D, FP_1*17/20
|
|
call UpdateCamera3D
|
|
call RenderCeilingAndFloor
|
|
call RenderWalls
|
|
call PrepareCityDepth3D
|
|
call RenderHall3D
|
|
cmp barPhase3D, 0
|
|
jne bar_active_scene
|
|
invoke DrawBoxBorder, 170,83,146,86,0017201Bh,00836D42h,1
|
|
invoke DrawString8x8, 174,99,OFFSET barDrinks3D,00E4D9BDh
|
|
invoke DrawString8x8, 174,118,OFFSET barDrinks23D,00E4D9BDh
|
|
invoke DrawString8x8, 174,137,OFFSET barDrinks33D,00BCD7D0h
|
|
jmp bar_draw_title
|
|
bar_active_scene:
|
|
mov ebx, OFFSET barMixText3D
|
|
cmp barPhase3D, 2
|
|
jne @F
|
|
mov ebx, OFFSET barDrinkText3D
|
|
@@:
|
|
invoke DrawBox,170,83,146,24,0017201Bh
|
|
invoke DrawString8x8,176,91,ebx,00E7CA88h
|
|
bar_draw_title:
|
|
invoke DrawBox,0,0,320,28,0014191Dh
|
|
invoke DrawString8x8, 18,15,OFFSET barName3D,00E7CA88h
|
|
cmp barPhase3D, 2
|
|
jne bar_render_done
|
|
mov eax, barTime3D
|
|
xor edx, edx
|
|
mov ecx, 343
|
|
div ecx
|
|
cmp eax, 6
|
|
jbe @F
|
|
mov eax, 6
|
|
@@:
|
|
mov ecx, barSelection3D
|
|
imul ecx, 7
|
|
add eax, ecx
|
|
invoke DrawAnimSprite3D, OFFSET hallDrink3D,eax,272,170,360,360
|
|
bar_render_done:
|
|
invoke DrawNumber,240,15,bankroll,00E5D6B0h
|
|
mov eax, oldX
|
|
mov playerX, eax
|
|
mov eax, oldY
|
|
mov playerY, eax
|
|
mov eax, oldAngle
|
|
mov playerAngle, eax
|
|
mov eax, oldHorizon
|
|
mov viewHorizon3D, eax
|
|
mov eax, oldEye
|
|
mov viewEye3D, eax
|
|
mov eax, oldMode
|
|
mov engineMode, eax
|
|
call UpdateCamera3D
|
|
ret
|
|
RenderBar3D ENDP
|
|
|
|
RenderCityGuards3D PROC uses ebx
|
|
mov eax, cityClock3D
|
|
xor edx, edx
|
|
mov ecx, 180
|
|
div ecx
|
|
and eax, 7
|
|
mov cityGuardLeft3D.frame, eax
|
|
cmp arrivalState3D, ARRIVAL_WALK
|
|
je city_world_guard_right
|
|
mov cityGuardLeft3D.frame, 15
|
|
cmp arrivalState3D, ARRIVAL_STOP
|
|
jne city_world_guard_invite
|
|
mov eax, arrivalTime3D
|
|
xor edx, edx
|
|
mov ecx, 90
|
|
div ecx
|
|
cmp eax, 7
|
|
jbe @F
|
|
mov eax, 7
|
|
@@:
|
|
add eax, 8
|
|
mov cityGuardLeft3D.frame, eax
|
|
jmp city_world_guard_right
|
|
city_world_guard_invite:
|
|
cmp arrivalState3D, ARRIVAL_ADMIT
|
|
jb city_world_guard_right
|
|
mov eax, arrivalTime3D
|
|
xor edx, edx
|
|
mov ecx, 120
|
|
div ecx
|
|
add eax, 16
|
|
cmp eax, 22
|
|
jbe @F
|
|
mov eax, 22
|
|
@@:
|
|
mov cityGuardLeft3D.frame, eax
|
|
city_world_guard_right:
|
|
mov eax, cityClock3D
|
|
add eax, 590
|
|
xor edx, edx
|
|
mov ecx, 220
|
|
div ecx
|
|
and eax, 7
|
|
cmp arrivalState3D, ARRIVAL_PROFILE
|
|
jne @F
|
|
add eax, 24
|
|
@@:
|
|
mov cityGuardRight3D.frame, eax
|
|
invoke DrawCityObject3D, OFFSET cityGuardLeft3D,0
|
|
invoke DrawCityObject3D, OFFSET cityGuardRight3D,0
|
|
ret
|
|
RenderCityGuards3D ENDP
|
|
|
|
CanWalkHall3D PROC uses esi ebx px:DWORD,py:DWORD
|
|
cmp hallLevel3D, 0
|
|
jne hall_collision_bunker
|
|
xor esi, esi
|
|
hall_collision_decor:
|
|
imul ebx, esi, SIZEOF CityProp3D
|
|
mov eax, px
|
|
sub eax, hallLoungeDecor3D[ebx].posX
|
|
test eax, eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
mov ecx, hallLoungeDecor3D[ebx].worldW
|
|
shr ecx, 1
|
|
add ecx, 9830
|
|
cmp eax, ecx
|
|
ja hall_collision_next_decor
|
|
mov eax, py
|
|
sub eax, hallLoungeDecor3D[ebx].posY
|
|
test eax, eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
cmp eax, FP_1*2/5
|
|
jbe hall_collision_blocked
|
|
hall_collision_next_decor:
|
|
inc esi
|
|
cmp esi, HALL_DECOR_COUNT
|
|
jb hall_collision_decor
|
|
; Stage and wings are solid: the audience stays in the cabaret's front aisle.
|
|
cmp px, 10*FP_1-9830
|
|
jl hall_collision_stage_clear
|
|
cmp px, 22*FP_1+9830
|
|
jg hall_collision_stage_clear
|
|
cmp py, 2*FP_1-9830
|
|
jl hall_collision_stage_clear
|
|
cmp py, 5*FP_1+9830
|
|
jle hall_collision_blocked
|
|
hall_collision_stage_clear:
|
|
cmp px, FP_1*47/4
|
|
jl hall_collision_cabinets
|
|
cmp px, FP_1*49/4
|
|
jg hall_collision_pool_divider
|
|
cmp py, 24*FP_1-9830
|
|
jl hall_collision_cabinets
|
|
cmp py, FP_1*51/2+9830
|
|
jle hall_collision_blocked
|
|
cmp py, FP_1*55/2-9830
|
|
jl hall_collision_cabinets
|
|
cmp py, 30*FP_1+9830
|
|
jle hall_collision_blocked
|
|
hall_collision_pool_divider:
|
|
cmp px, 23*FP_1-9830
|
|
jl hall_collision_cabinets
|
|
cmp px, FP_1*116/5+9830
|
|
jg hall_collision_cabinets
|
|
cmp py, 23*FP_1-9830
|
|
jl hall_collision_cabinets
|
|
cmp py, 24*FP_1+9830
|
|
jle hall_collision_blocked
|
|
cmp py, 26*FP_1-9830
|
|
jl hall_collision_cabinets
|
|
cmp py, 29*FP_1+9830
|
|
jle hall_collision_blocked
|
|
hall_collision_cabinets:
|
|
; The work aisle is staff-only; player interaction is from the serving side.
|
|
cmp px, 3*FP_1-9830
|
|
jl hall_collision_counter
|
|
cmp px, 9*FP_1+9830
|
|
jg hall_collision_counter
|
|
cmp py, 21*FP_1-9830
|
|
jl hall_collision_counter
|
|
cmp py, 24*FP_1+9830
|
|
jle hall_collision_blocked
|
|
hall_collision_counter:
|
|
cmp px, 3*FP_1-9830
|
|
jl hall_collision_dining
|
|
cmp px, 9*FP_1+9830
|
|
jg hall_collision_pool
|
|
cmp py, 23*FP_1-9830
|
|
jl hall_collision_clear
|
|
cmp py, 24*FP_1+9830
|
|
jg hall_collision_dining
|
|
xor eax, eax
|
|
ret
|
|
hall_collision_pool:
|
|
cmp px, 26*FP_1-9830
|
|
jl hall_collision_dining
|
|
cmp px, 28*FP_1+9830
|
|
jg hall_collision_dining
|
|
cmp py, 24*FP_1-9830
|
|
jl hall_collision_clear
|
|
cmp py, 26*FP_1+9830
|
|
jg hall_collision_dining
|
|
xor eax, eax
|
|
ret
|
|
hall_collision_bunker:
|
|
cmp px, 14*FP_1-9830
|
|
jl hall_collision_clear
|
|
cmp px, 20*FP_1+9830
|
|
jg hall_collision_clear
|
|
cmp py, 14*FP_1-9830
|
|
jl hall_collision_clear
|
|
cmp py, 15*FP_1+9830
|
|
jg hall_collision_clear
|
|
hall_collision_blocked:
|
|
xor eax, eax
|
|
ret
|
|
hall_collision_clear:
|
|
mov eax, 1
|
|
ret
|
|
hall_collision_dining:
|
|
cmp py, 26*FP_1+FP_1/3
|
|
jl hall_collision_clear
|
|
cmp py, 29*FP_1+FP_HALF
|
|
jg hall_collision_clear
|
|
cmp px, 2*FP_1
|
|
jl hall_collision_clear
|
|
cmp px, 5*FP_1
|
|
jle hall_collision_blocked
|
|
cmp px, 8*FP_1
|
|
jl hall_collision_clear
|
|
cmp px, 11*FP_1
|
|
jle hall_collision_blocked
|
|
jmp hall_collision_clear
|
|
CanWalkHall3D ENDP
|
|
|
|
RenderCityFacade3D PROC uses ebx esi
|
|
; The original entrance artwork carries CASINO itself, mapped once across the doorway.
|
|
invoke DrawCityBoxSides3D,21*FP_1,24*FP_1,8*FP_1,8*FP_1+FP_1/5,0,FP_1*9/5,57
|
|
invoke DrawCityVertical3D,1,8*FP_1+FP_1/5,21*FP_1,24*FP_1,0,FP_1*9/5,58
|
|
invoke DrawCityBoxSides3D,FP_1*104/5,FP_1*106/5,8*FP_1,8*FP_1+FP_1*2/5,0,2*FP_1,103
|
|
invoke DrawCityBoxSides3D,FP_1*119/5,FP_1*121/5,8*FP_1,8*FP_1+FP_1*2/5,0,2*FP_1,103
|
|
invoke DrawCityBoxSides3D,FP_1*104/5,FP_1*121/5,8*FP_1,8*FP_1+FP_HALF,FP_1*9/5,2*FP_1,86
|
|
invoke DrawCityHorizontal3D,FP_1*104/5,FP_1*121/5,8*FP_1,8*FP_1+FP_HALF,2*FP_1,85
|
|
invoke DrawCityVertical3D,1,8*FP_1+FP_1*41/100,FP_1*101/5,FP_1*104/5,FP_1,FP_1*8/5,105
|
|
invoke DrawCityVertical3D,1,8*FP_1+FP_1*41/100,FP_1*121/5,FP_1*124/5,FP_1,FP_1*8/5,105
|
|
; Recessed street windows, projecting bays and ledges are fixed world surfaces.
|
|
mov esi, 11
|
|
hall_city_pilaster:
|
|
cmp esi, 20
|
|
je hall_city_next_pilaster
|
|
cmp esi, 24
|
|
je hall_city_next_pilaster
|
|
mov ebx, esi
|
|
shl ebx, 16
|
|
lea eax, [ebx+FP_1/5]
|
|
invoke DrawCityBoxSides3D, ebx,eax,12*FP_1,12*FP_1+FP_1/6,0,5*FP_1,57
|
|
lea eax, [ebx+FP_1/5]
|
|
invoke DrawCityBoxSides3D, ebx,eax,17*FP_1-FP_1/6,17*FP_1,0,5*FP_1,57
|
|
lea eax, [ebx+FP_1/5]
|
|
lea edx, [ebx+FP_1*7/5]
|
|
invoke DrawCityBoxSides3D,eax,edx,FP_1*237/20,12*FP_1,FP_1/20,FP_1*13/10,57
|
|
lea eax, [ebx+FP_1/5]
|
|
lea edx, [ebx+FP_1*7/5]
|
|
invoke DrawCityVertical3D,1,12*FP_1+FP_1/25,eax,edx,FP_1/20,FP_1*13/10,62
|
|
lea eax, [ebx+FP_1/5]
|
|
lea edx, [ebx+FP_1*7/5]
|
|
invoke DrawCityBoxSides3D,eax,edx,12*FP_1,12*FP_1+FP_1/5,2*FP_1,FP_1*18/5,57
|
|
lea eax, [ebx+FP_1/5]
|
|
lea edx, [ebx+FP_1*7/5]
|
|
invoke DrawCityVertical3D,1,12*FP_1+FP_1/5,eax,edx,2*FP_1,FP_1*18/5,106
|
|
lea eax, [ebx+FP_1/5]
|
|
lea edx, [ebx+FP_1*7/5]
|
|
invoke DrawCityBoxSides3D,eax,edx,17*FP_1-FP_1/4,17*FP_1,2*FP_1,FP_1*18/5,57
|
|
lea eax, [ebx+FP_1/5]
|
|
lea edx, [ebx+FP_1*7/5]
|
|
invoke DrawCityVertical3D,1,17*FP_1-FP_1/4,eax,edx,2*FP_1,FP_1*18/5,106
|
|
hall_city_next_pilaster:
|
|
add esi, 4
|
|
cmp esi, 29
|
|
jb hall_city_pilaster
|
|
ret
|
|
RenderCityFacade3D ENDP
|
|
|
|
UpdateHall3D PROC
|
|
call UpdatePatrons3D
|
|
mov viewHorizon3D, HALF_H
|
|
mov viewEye3D, FP_1*17/20
|
|
cmp hallLevel3D, 0
|
|
je @F
|
|
mov eax, playerY
|
|
sub eax, 24*FP_1
|
|
jle @F
|
|
shr eax, 2
|
|
cmp eax, FP_1
|
|
jbe hall_step_eye
|
|
mov eax, FP_1
|
|
hall_step_eye:
|
|
add viewEye3D, eax
|
|
@@:
|
|
cmp barIntoxication3D, 0
|
|
je hall_update_done
|
|
mov eax, deltaTime3D
|
|
imul eax, 2
|
|
sub barIntoxication3D, eax
|
|
jnc @F
|
|
mov barIntoxication3D, 0
|
|
@@:
|
|
mov eax, animationClock3D
|
|
shr eax, 3
|
|
and eax, 511
|
|
mov eax, tableSin[eax*4]
|
|
imul barIntoxication3D
|
|
shrd eax, edx, 16
|
|
sar eax, 14
|
|
add viewHorizon3D, eax
|
|
hall_update_done:
|
|
ret
|
|
UpdateHall3D ENDP
|
|
|
|
; Absolute route phase avoids accumulated movement drift and keeps walking FPS-independent.
|
|
UpdatePatrons3D PROC uses ebx esi edi
|
|
call UpdateNpcLife3D
|
|
ret
|
|
IF 0
|
|
local wx:DWORD,wy:DWORD,phase:DWORD
|
|
cmp hallLevel3D, 0
|
|
jne patron_update_done
|
|
mov eax, deltaTime3D
|
|
add eax, patronClock3D
|
|
xor edx, edx
|
|
mov ecx, 20000
|
|
div ecx
|
|
mov patronClock3D, edx
|
|
xor esi, esi
|
|
patron_update_loop:
|
|
mov eax, esi
|
|
imul eax, 10000
|
|
add eax, patronClock3D
|
|
xor edx, edx
|
|
mov ecx, 20000
|
|
div ecx
|
|
mov eax, edx
|
|
xor edx, edx
|
|
mov ecx, 5000
|
|
div ecx
|
|
mov phase, eax
|
|
mov eax, edx
|
|
imul eax, 4*FP_1
|
|
xor edx, edx
|
|
div ecx
|
|
mov wx, 18*FP_1
|
|
mov wy, 18*FP_1
|
|
cmp phase, 0
|
|
jne patron_route_south
|
|
add wx, eax
|
|
jmp patron_route_check
|
|
patron_route_south:
|
|
cmp phase, 1
|
|
jne patron_route_west
|
|
mov wx, 22*FP_1
|
|
shr eax, 1
|
|
add wy, eax
|
|
jmp patron_route_check
|
|
patron_route_west:
|
|
mov wy, 20*FP_1
|
|
cmp phase, 2
|
|
jne patron_route_north
|
|
mov wx, 22*FP_1
|
|
sub wx, eax
|
|
jmp patron_route_check
|
|
patron_route_north:
|
|
shr eax, 1
|
|
sub wy, eax
|
|
patron_route_check:
|
|
invoke CanWalk3D,wx,wy
|
|
test eax, eax
|
|
jz patron_update_next
|
|
imul ebx, esi, SIZEOF CityProp3D
|
|
mov eax, wx
|
|
mov hallGuests3D[ebx].posX, eax
|
|
mov eax, wy
|
|
mov hallGuests3D[ebx].posY, eax
|
|
mov eax, patronClock3D
|
|
xor edx, edx
|
|
mov ecx, 220
|
|
div ecx
|
|
and eax, 3
|
|
lea eax, [eax+esi*4]
|
|
mov hallGuests3D[ebx].frame, eax
|
|
patron_update_next:
|
|
inc esi
|
|
cmp esi, 2
|
|
jb patron_update_loop
|
|
patron_update_done:
|
|
call UpdateCasinoNpcMind
|
|
ret
|
|
ENDIF
|
|
UpdatePatrons3D ENDP
|
|
|
|
RenderPatrons3D PROC uses esi
|
|
call RenderNpcLife3D
|
|
mov esi,8
|
|
patron_render_loop:
|
|
imul eax, esi, SIZEOF CityProp3D
|
|
add eax, OFFSET hallGuests3D
|
|
invoke DrawCityObject3D,eax,0
|
|
inc esi
|
|
cmp esi,12
|
|
jb patron_render_loop
|
|
ret
|
|
RenderPatrons3D ENDP
|