KAZIK/src_graphics/buckshot.inc
Artvasil09 4f8ae0893b Implement native slots, coin toss, European roulette and hall furniture
Add native assembly scenes and assets for Slots (777), Coin flip, and European Roulette; add 3D hall furniture packs and prompts; improve Russian UI strings in CP1251; update launcher hash and rebuild shipping binaries.
2026-10-10 14:43:30 +03:00

1403 lines
32 KiB
PHP

.code
FreeBuckshotAssets3D PROC uses esi
xor esi, esi
bs_free_pack:
invoke FreeAnimPack3D, bs3d_packs[esi*4]
inc esi
cmp esi, BS_ASSET_COUNT
jb bs_free_pack
ret
FreeBuckshotAssets3D ENDP
LoadBuckshotAssets3D PROC uses ebx esi
xor esi, esi
bs_load_pack:
invoke LoadAnimPack3D, bs3d_packs[esi*4], bs3d_paths[esi*4]
test eax, eax
jz bs_pack_failed
mov ebx, bs3d_packs[esi*4]
mov eax, [ebx].AnimPack3D.frames
cmp eax, bs3d_frameCounts[esi*4]
jne bs_pack_failed
mov eax, [ebx].AnimPack3D.imageWidth
cmp eax, bs3d_frameWidths[esi*4]
jne bs_pack_failed
mov eax, [ebx].AnimPack3D.height
cmp eax, bs3d_frameHeights[esi*4]
jne bs_pack_failed
inc esi
cmp esi, BS_ASSET_COUNT
jb bs_load_pack
mov eax, 1
ret
bs_pack_failed:
call FreeBuckshotAssets3D
xor eax, eax
ret
LoadBuckshotAssets3D ENDP
InitBuckshot3D PROC
call LoadBuckshotAssets3D
test eax, eax
jz bs_init_error
mov bs3d_state, BS_READY
mov bs3d_hpPlayer, 4
mov bs3d_hpDealer, 4
mov bs3d_shellCount, 0
mov bs3d_shellIndex, 0
mov bs3d_liveCount, 0
mov bs3d_blankCount, 0
mov bs3d_timer, 0
mov bs3d_clock, 0
mov bs3d_error, 0
mov bs3d_message, 0
mov bs3d_payout, 0
mov bs3d_result, 0
mov bs3d_pitch, 0
mov eax, 1
ret
bs_init_error:
mov bs3d_state, BS_ERROR
xor eax, eax
ret
InitBuckshot3D ENDP
BuckshotReload3D PROC uses ebx esi
invoke RandomRange3D, 5
add eax, 4
mov bs3d_shellCount, eax
mov bs3d_shellIndex, 0
mov bs3d_liveCount, 0
mov bs3d_blankCount, 0
mov bs3d_known, -1
mov bs3d_known[4], -1
xor esi, esi
bs_reload_shell:
invoke RandomRange3D, 2
mov bs3d_shells[esi*4], eax
test eax, eax
jz bs_reload_blank
inc bs3d_liveCount
jmp bs_reload_next
bs_reload_blank:
inc bs3d_blankCount
bs_reload_next:
inc esi
cmp esi, bs3d_shellCount
jb bs_reload_shell
cmp bs3d_liveCount, 0
jne @F
mov bs3d_shells, 1
inc bs3d_liveCount
dec bs3d_blankCount
@@:
cmp bs3d_blankCount, 0
jne @F
mov bs3d_shells[4], 0
inc bs3d_blankCount
dec bs3d_liveCount
@@:
; The loading motion loops once per actual cartridge, then racks the pump.
mov eax, bs3d_shellCount
imul eax, 330
add eax, 920
mov bs3d_loadDuration, eax
mov eax, bs3d_turn
mov bs3d_loadActor, eax
inc eax
mov bs3d_afterAnim, eax
mov bs3d_timer, 0
mov bs3d_state, BS_LOAD
invoke PlayCasinoSound3D, OFFSET bs3d_pumpSound, 0, 20003h
ret
BuckshotReload3D ENDP
; Animation queues a shot; the cartridge and health change exactly once at the trigger frame.
BuckshotShoot3D PROC target:DWORD
mov eax, bs3d_shellIndex
cmp eax, bs3d_shellCount
jae bs_shoot_done
cmp target, 1
ja bs_shoot_done
mov eax, target
mov bs3d_target, eax
mov eax, bs3d_turn
mov bs3d_shooter, eax
mov bs3d_effectDone, 0
mov bs3d_timer, 0
mov bs3d_state, BS_SHOT
bs_shoot_done:
ret
BuckshotShoot3D ENDP
CommitBuckshotShot3D PROC uses ebx esi edi
cmp bs3d_effectDone, 0
jne bs_commit_done
mov bs3d_effectDone, 1
mov esi, bs3d_shooter
mov edi, esi
mov ebx, bs3d_shellIndex
cmp ebx, bs3d_shellCount
jae bs_commit_done
mov eax, bs3d_shells[ebx*4]
mov bs3d_lastShot, eax
inc bs3d_shellIndex
test eax, eax
jz bs_commit_blank
dec bs3d_liveCount
mov ecx, bs3d_damage[esi*4]
cmp bs3d_target, 0
jne bs_commit_dealer_hit
sub bs3d_hpPlayer, ecx
cmp bs3d_hpPlayer, 0
jg bs_commit_live_turn
mov bs3d_hpPlayer, 0
mov bs3d_afterAnim, BS_LOSE
jmp bs_commit_live_sound
bs_commit_dealer_hit:
sub bs3d_hpDealer, ecx
cmp bs3d_hpDealer, 0
jg bs_commit_live_turn
mov bs3d_hpDealer, 0
mov bs3d_afterAnim, BS_WIN
jmp bs_commit_live_sound
bs_commit_live_turn:
xor esi, 1
mov bs3d_turn, esi
inc esi
mov bs3d_afterAnim, esi
bs_commit_live_sound:
mov bs3d_message, OFFSET bs3d_textShot
invoke PlayCasinoSound3D, OFFSET rrFireSound3D, 0, 20003h
jmp bs_commit_cleanup
bs_commit_blank:
dec bs3d_blankCount
; Only a blank directed at the shooter's own side keeps the current turn.
mov eax, bs3d_target
cmp eax, esi
je @F
xor esi, 1
@@:
mov bs3d_turn, esi
inc esi
mov bs3d_afterAnim, esi
mov bs3d_message, OFFSET bs3d_textDry
invoke PlayCasinoSound3D, OFFSET rrDrySound3D, 0, 20003h
bs_commit_cleanup:
mov bs3d_damage[edi*4], 1
mov bs3d_known, -1
mov bs3d_known[4], -1
mov bs3d_messageTime, 1800
bs_commit_done:
ret
CommitBuckshotShot3D ENDP
FinishBuckshotAction3D PROC uses ebx
cmp bs3d_state, BS_SHOT
jne bs_finish_done
mov eax, bs3d_afterAnim
cmp eax, BS_WIN
je bs_finish_win
cmp eax, BS_LOSE
je bs_finish_lose
mov ebx, bs3d_turn
cmp bs3d_skip[ebx*4], 0
je @F
dec bs3d_skip[ebx*4]
xor ebx, 1
mov bs3d_turn, ebx
@@:
mov eax, bs3d_shellIndex
cmp eax, bs3d_shellCount
jae bs_finish_reload
lea eax, [ebx+1]
mov bs3d_state, eax
mov bs3d_timer, 0
ret
bs_finish_reload:
call BuckshotReload3D
ret
bs_finish_win:
mov bs3d_state, BS_DEATH
mov bs3d_result, BS_WIN
mov bs3d_victim, 1
mov bs3d_timer, 800
mov eax, bs3d_bet
imul eax, 3
mov bs3d_payout, eax
add bankroll, eax
cmp bankroll, 1000000000
jbe @F
mov bankroll, 1000000000
@@:
call SaveProgress3D
ret
bs_finish_lose:
mov bs3d_state, BS_DEATH
mov bs3d_result, BS_LOSE
mov bs3d_victim, 0
mov bs3d_timer, 800
call SaveProgress3D
bs_finish_done:
ret
FinishBuckshotAction3D ENDP
UseBuckshotItem3D PROC uses ebx esi item:DWORD
mov eax, bs3d_state
cmp eax, BS_PLAYER
je @F
cmp eax, BS_DEALER
jne bs_item_invalid
@@:
mov eax, bs3d_shellIndex
cmp eax, bs3d_shellCount
jae bs_item_invalid
cmp item, 3
ja bs_item_invalid
mov esi, bs3d_turn
mov ebx, esi
shl ebx, 2
add ebx, item
cmp bs3d_items[ebx*4], 0
je bs_item_invalid
cmp item, 1
jne @F
cmp bs3d_damage[esi*4], 2
je bs_item_invalid
@@:
cmp item, 3
jne @F
mov eax, esi
xor eax, 1
cmp bs3d_skip[eax*4], 0
jne bs_item_invalid
@@:
dec bs3d_items[ebx*4]
mov eax, item
mov bs3d_item, eax
mov bs3d_timer, 0
mov bs3d_effectDone, 0
lea eax, [esi+1]
mov bs3d_afterAnim, eax
mov bs3d_state, BS_ITEM
mov eax, 1
ret
bs_item_invalid:
cmp bs3d_turn, 0
jne @F
mov bs3d_message, OFFSET bs3d_textItemEmpty
mov bs3d_messageTime, 1500
@@:
xor eax, eax
ret
UseBuckshotItem3D ENDP
CommitBuckshotItem3D PROC uses ebx esi
cmp bs3d_effectDone, 0
jne bs_item_commit_done
mov bs3d_effectDone, 1
mov esi, bs3d_turn
mov eax, bs3d_item
test eax, eax
jz bs_item_glass
cmp eax, 1
je bs_item_saw
cmp eax, 2
je bs_item_beer
mov eax, esi
xor eax, 1
mov bs3d_skip[eax*4], 1
mov bs3d_message, OFFSET bs3d_textCuffs
jmp bs_item_committed
bs_item_glass:
mov ebx, bs3d_shellIndex
mov eax, bs3d_shells[ebx*4]
mov bs3d_known[esi*4], eax
mov bs3d_message, OFFSET bs3d_textKnownBlank
test eax, eax
jz bs_item_committed
mov bs3d_message, OFFSET bs3d_textKnownLive
jmp bs_item_committed
bs_item_saw:
mov bs3d_damage[esi*4], 2
mov bs3d_message, OFFSET bs3d_textSaw
jmp bs_item_committed
bs_item_beer:
mov ebx, bs3d_shellIndex
mov eax, bs3d_shells[ebx*4]
mov bs3d_lastShot, eax
inc bs3d_shellIndex
test eax, eax
jz @F
dec bs3d_liveCount
jmp bs_item_beer_counts
@@:
dec bs3d_blankCount
bs_item_beer_counts:
mov bs3d_known, -1
mov bs3d_known[4], -1
mov bs3d_message, OFFSET bs3d_textBeer
bs_item_committed:
mov bs3d_messageTime, 1800
invoke PlayCasinoSound3D, OFFSET bs3d_pumpSound, 0, 20003h
bs_item_commit_done:
ret
CommitBuckshotItem3D ENDP
; The dealer reasons from the revealed shell or remaining counts, never from hidden order.
ChooseBuckshotDealer3D PROC
mov eax, bs3d_shellIndex
cmp eax, bs3d_shellCount
jae bs_dealer_reload
cmp bs3d_known[4], -1
jne bs_dealer_saw
cmp bs3d_items[16], 0
je bs_dealer_saw
invoke UseBuckshotItem3D, 0
ret
bs_dealer_saw:
cmp bs3d_known[4], 1
jne bs_dealer_beer
cmp bs3d_items[20], 0
je bs_dealer_cuffs
cmp bs3d_damage[4], 1
jne bs_dealer_cuffs
invoke UseBuckshotItem3D, 1
ret
bs_dealer_beer:
cmp bs3d_known[4], 0
jne bs_dealer_cuffs
cmp bs3d_items[24], 0
je bs_dealer_cuffs
invoke UseBuckshotItem3D, 2
ret
bs_dealer_cuffs:
cmp bs3d_skip, 0
jne bs_dealer_target
cmp bs3d_items[28], 0
je bs_dealer_target
invoke UseBuckshotItem3D, 3
ret
bs_dealer_target:
cmp bs3d_known[4], 0
je bs_dealer_self
cmp bs3d_known[4], 1
je bs_dealer_player
cmp bs3d_liveCount, 0
je bs_dealer_self
mov eax, bs3d_blankCount
cmp eax, bs3d_liveCount
jbe bs_dealer_player
invoke RandomRange3D, 100
cmp eax, 60
jae bs_dealer_player
bs_dealer_self:
invoke BuckshotShoot3D, 1
ret
bs_dealer_player:
invoke BuckshotShoot3D, 0
ret
bs_dealer_reload:
call BuckshotReload3D
ret
ChooseBuckshotDealer3D ENDP
BuckshotMouse3D PROC uses ebx
cmp mouseClick3D, 0
je bs_mouse_done
mov mouseClick3D, 0
mov eax, mouseX3D
shl eax, 1
mov ebx, mouseY3D
shl ebx, 1
cmp bs3d_state, BS_READY
je bs_mouse_start
cmp bs3d_state, BS_WIN
je bs_mouse_start
cmp bs3d_state, BS_LOSE
je bs_mouse_start
cmp bs3d_state, BS_PLAYER
jne bs_mouse_done
cmp ebx, 396
jb bs_mouse_done
cmp ebx, 443
jae bs_mouse_shoot
sub eax, 160
js bs_mouse_done
xor edx, edx
mov ecx, 112
div ecx
cmp eax, 3
ja bs_mouse_done
add eax, 33h
mov pressedKeys3D[eax], 1
ret
bs_mouse_shoot:
cmp ebx, 476
jae bs_mouse_done
cmp eax, 32
jb bs_mouse_done
cmp eax, 132
jb bs_mouse_self
cmp eax, 150
jb bs_mouse_done
cmp eax, 270
jae bs_mouse_done
mov pressedKeys3D[32h], 1
ret
bs_mouse_self:
mov pressedKeys3D[31h], 1
ret
bs_mouse_start:
cmp ebx, 442
jb bs_mouse_amount
cmp ebx, 476
jae bs_mouse_done
cmp eax, 246
jb bs_mouse_done
cmp eax, 382
jae bs_mouse_done
mov pressedKeys3D[20h], 1
ret
bs_mouse_amount:
cmp bs3d_state, BS_READY
jne bs_mouse_done
cmp ebx, 442
jae bs_mouse_done
cmp ebx, 408
jb bs_mouse_done
cmp eax, 30
jb bs_mouse_done
cmp eax, 60
jb bs_mouse_down
cmp eax, 112
jb bs_mouse_done
cmp eax, 144
jae bs_mouse_done
mov pressedKeys3D[26h], 1
ret
bs_mouse_down:
mov pressedKeys3D[28h], 1
bs_mouse_done:
ret
BuckshotMouse3D ENDP
HandleBuckshot3D PROC uses ebx esi
call BuckshotMouse3D
mov eax, deltaTime3D
add bs3d_clock, eax
cmp bs3d_messageTime, eax
ja @F
mov bs3d_messageTime, 0
jmp bs_update_state
@@:
sub bs3d_messageTime, eax
bs_update_state:
mov eax, bs3d_state
cmp eax, BS_READY
je bs_input_ready
cmp eax, BS_PLAYER
je bs_input_player
cmp eax, BS_DEALER
je bs_input_dealer
cmp eax, BS_LOAD
je bs_input_loading
cmp eax, BS_SHOT
je bs_input_shot
cmp eax, BS_ITEM
je bs_input_item
cmp eax, BS_DEATH
je bs_input_death
cmp eax, BS_RECOVERY
je bs_input_recovery
cmp eax, BS_ERROR
je bs_input_done
invoke Pressed3D, 20h
test eax, eax
jz bs_input_done
call InitBuckshot3D
test eax, eax
jz bs_input_done
jmp bs_input_start
bs_input_ready:
invoke Pressed3D, 26h
test eax, eax
jz @F
add bs3d_bet, 50
cmp bs3d_bet, 5000
jbe bs_input_done
mov bs3d_bet, 5000
ret
@@:
invoke Pressed3D, 28h
test eax, eax
jz @F
cmp bs3d_bet, 50
jbe bs_input_done
sub bs3d_bet, 50
ret
@@:
invoke Pressed3D, 20h
test eax, eax
jz bs_input_done
bs_input_start:
mov eax, bs3d_bet
cmp eax, 0
je bs_input_no_cash
cmp eax, bankroll
ja bs_input_no_cash
sub bankroll, eax
mov bs3d_hpPlayer, 4
mov bs3d_hpDealer, 4
mov bs3d_turn, 0
mov bs3d_damage, 1
mov bs3d_damage[4], 1
mov bs3d_skip, 0
mov bs3d_skip[4], 0
mov bs3d_error, 0
mov bs3d_messageTime, 0
mov bs3d_payout, 0
xor esi, esi
bs_give_item:
mov bs3d_items[esi*4], 1
inc esi
cmp esi, 8
jb bs_give_item
call BuckshotReload3D
call SaveProgress3D
ret
bs_input_no_cash:
mov bs3d_error, 1
ret
bs_input_player:
mov eax, bs3d_shellIndex
cmp eax, bs3d_shellCount
jae bs_input_reload
mov bs3d_turn, 0
invoke Pressed3D, 31h
test eax, eax
jz @F
invoke BuckshotShoot3D, 0
ret
@@:
invoke Pressed3D, 32h
test eax, eax
jz @F
invoke BuckshotShoot3D, 1
ret
@@:
xor esi, esi
bs_item_key:
lea ebx, [esi+33h]
invoke Pressed3D, ebx
test eax, eax
jz @F
invoke UseBuckshotItem3D, esi
ret
@@:
inc esi
cmp esi, 4
jb bs_item_key
ret
bs_input_dealer:
mov eax, deltaTime3D
add bs3d_timer, eax
cmp bs3d_timer, 850
jb bs_input_done
mov bs3d_turn, 1
call ChooseBuckshotDealer3D
ret
bs_input_reload:
call BuckshotReload3D
ret
bs_input_loading:
mov eax, deltaTime3D
add bs3d_timer, eax
mov eax, bs3d_timer
cmp eax, bs3d_loadDuration
jb bs_input_done
mov eax, bs3d_afterAnim
mov bs3d_state, eax
mov bs3d_timer, 0
call ClearKeys3D
ret
bs_input_shot:
mov eax, deltaTime3D
add bs3d_timer, eax
cmp bs3d_timer, 450
jb bs_input_done
call CommitBuckshotShot3D
cmp bs3d_timer, 1250
jb bs_input_done
call FinishBuckshotAction3D
call ClearKeys3D
ret
bs_input_item:
mov eax, deltaTime3D
add bs3d_timer, eax
cmp bs3d_timer, 430
jb bs_input_done
call CommitBuckshotItem3D
cmp bs3d_timer, 1000
jb bs_input_done
mov eax, bs3d_shellIndex
cmp eax, bs3d_shellCount
jae bs_input_reload
mov eax, bs3d_afterAnim
mov bs3d_state, eax
mov bs3d_timer, 0
call ClearKeys3D
ret
bs_input_death:
mov eax, deltaTime3D
add bs3d_timer, eax
cmp bs3d_timer, 1800
jb bs_input_done
mov bs3d_timer, 0
mov bs3d_state, BS_RECOVERY
invoke PlayCasinoSound3D, OFFSET bs3d_pumpSound, 0, 20003h
ret
bs_input_recovery:
mov eax, deltaTime3D
add bs3d_timer, eax
cmp bs3d_timer, 3600
jb bs_input_done
mov eax, bs3d_result
mov bs3d_state, eax
mov bs3d_hpPlayer, 4
mov bs3d_hpDealer, 4
mov bs3d_timer, 0
cmp eax, BS_WIN
jne @F
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 20003h
jmp bs_recovery_done
@@:
invoke PlayCasinoSound3D, OFFSET soundRoundLose, 0, 20003h
bs_recovery_done:
call ClearKeys3D
bs_input_done:
ret
HandleBuckshot3D ENDP
; This scene's HUD uses physical 640x480 coordinates, unlike the legacy doubled primitives.
DrawBuckshotPanel3D PROC uses ebx x:DWORD,y:DWORD,w:DWORD,h:DWORD,ink:DWORD
mov eax, x
sar eax, 1
mov edx, y
sar edx, 1
mov ecx, w
shr ecx, 1
mov ebx, h
shr ebx, 1
invoke DrawBox, eax, edx, ecx, ebx, ink
ret
DrawBuckshotPanel3D ENDP
DrawBuckshotText3D PROC uses ebx esi edi x:DWORD,y:DWORD,source:DWORD,ink:DWORD
local px:DWORD,rowPx:DWORD,glyphBits:DWORD
mov esi, source
test esi, esi
jz bs_text_done
mov eax, x
mov px, eax
bs_text_char:
movzx eax, byte ptr [esi]
test eax, eax
jz bs_text_done
lea edi, font8x8[eax*8]
xor ebx, ebx
bs_text_row:
movzx eax, byte ptr [edi+ebx]
mov glyphBits, eax
mov edx, y
add edx, ebx
cmp edx, 480
jae bs_text_next_row
imul edx, 640
mov rowPx, edx
xor ecx, ecx
bs_text_pixel:
mov eax, px
add eax, ecx
cmp eax, 640
jae bs_text_skip
test glyphBits, 80h
jz bs_text_skip
add eax, rowPx
mov edx, ink
mov screenBuffer[eax*4], edx
bs_text_skip:
shl glyphBits, 1
inc ecx
cmp ecx, 8
jb bs_text_pixel
bs_text_next_row:
inc ebx
cmp ebx, 8
jb bs_text_row
add px, 8
inc esi
jmp bs_text_char
bs_text_done:
ret
DrawBuckshotText3D ENDP
DrawBuckshotNumber3D PROC x:DWORD,y:DWORD,value:DWORD,ink:DWORD
invoke FormatNumber, value, OFFSET hudNumBuffer
invoke DrawBuckshotText3D, x, y, OFFSET hudNumBuffer, ink
ret
DrawBuckshotNumber3D ENDP
; Keep each pose anchored; move the whole silhouette smoothly as hands rise and settle.
DrawBuckshotHand3D PROC pack:DWORD,frame:DWORD,x:DWORD,y:DWORD,w:DWORD,h:DWORD
invoke DrawAnimSprite3D, pack, frame, x, y, w, h
ret
DrawBuckshotHand3D ENDP
ResolveBuckshotPose3D PROC uses ebx
mov eax, bs3d_timer
cmp bs3d_state, BS_LOAD
jne bs_resolve_shot
cmp eax, 220
jb bs_pose_first
sub eax, 220
mov ecx, bs3d_shellCount
imul ecx, 330
cmp eax, ecx
jae bs_pose_pump
xor edx, edx
mov ecx, 330
div ecx
and eax, 1
imul ebx, eax, 3
mov eax, edx
xor edx, edx
mov ecx, 110
div ecx
inc eax
add eax, ebx
ret
bs_pose_pump:
sub eax, ecx
xor edx, edx
cmp eax, 100
jb bs_pose_settle
sub eax, 100
mov ecx, 150
div ecx
cmp eax, 3
jbe @F
mov eax, 3
@@:
add eax, 8
ret
bs_pose_settle:
mov eax, 7
ret
bs_pose_first:
xor eax, eax
ret
bs_resolve_shot:
cmp eax, 140
jb bs_pose_first
cmp eax, 300
jb bs_pose_aim
cmp eax, 450
jb bs_pose_steady
cmp eax, 535
jb bs_pose_flash
cmp eax, 700
jb bs_pose_smoke
cmp eax, 890
jb bs_pose_rack
cmp eax, 1080
jb bs_pose_return
mov eax, 7
ret
bs_pose_aim:
mov eax, 1
ret
bs_pose_steady:
mov eax, 2
ret
bs_pose_flash:
cmp bs3d_lastShot, 0
je bs_pose_steady
mov eax, 3
ret
bs_pose_smoke:
cmp bs3d_lastShot, 0
je bs_pose_steady
mov eax, 4
ret
bs_pose_rack:
mov eax, 5
ret
bs_pose_return:
mov eax, 6
ret
ResolveBuckshotPose3D ENDP
RenderBuckshot3D PROC uses ebx esi edi
local handY:DWORD,pose:DWORD,actor:DWORD
mov animOpacity3D, 255
cmp bs3d_room.pixels, 0
je bs_render_error
mov eax, bs3d_turn
cmp bs3d_state, BS_SHOT
jne @F
mov eax, bs3d_shooter
@@:
mov actor, eax
mov bs3d_pitch, 0
cmp bs3d_state, BS_SHOT
jne bs_pitch_death
cmp actor, 0
jne bs_pitch_done
cmp bs3d_target, 0
jne bs_pitch_done
mov eax, bs3d_timer
cmp eax, 300
jb bs_pitch_rise
mov bs3d_pitch, 120
cmp eax, 900
jb bs_pitch_done
cmp bs3d_hpPlayer, 0
je bs_pitch_done
mov ecx, 1250
sub ecx, eax
jle bs_pitch_clear
imul eax, ecx, 120
xor edx, edx
mov ecx, 350
div ecx
mov bs3d_pitch, eax
jmp bs_pitch_done
bs_pitch_clear:
mov bs3d_pitch, 0
jmp bs_pitch_done
bs_pitch_rise:
imul eax, 120
xor edx, edx
mov ecx, 300
div ecx
mov bs3d_pitch, eax
jmp bs_pitch_done
bs_pitch_death:
cmp bs3d_state, BS_DEATH
je bs_pitch_dead_player
cmp bs3d_state, BS_RECOVERY
jne bs_pitch_done
bs_pitch_dead_player:
cmp bs3d_victim, 0
jne bs_pitch_done
mov bs3d_pitch, 120
bs_pitch_done:
cmp bs3d_pitch, 0
jne bs_render_pitched_room
mov esi, bs3d_room.pixels
lea edi, screenBuffer
mov ecx, SCREEN_SIZE
rep movsd
jmp bs_render_room_done
bs_render_pitched_room:
mov eax, bs3d_pitch
neg eax
mov ecx, bs3d_pitch
add ecx, 480
invoke DrawAnimSprite3D, OFFSET bs3d_room, 0, 0, eax, 640, ecx
bs_render_room_done:
mov bs3d_dealerFrame, 0
mov eax, bs3d_clock
xor edx, edx
mov ecx, 3100
div ecx
cmp edx, 150
jae @F
mov bs3d_dealerFrame, 1
@@:
cmp bs3d_state, BS_DEALER
jne @F
mov bs3d_dealerFrame, 2
@@:
cmp bs3d_state, BS_LOAD
jne @F
mov bs3d_dealerFrame, 4
@@:
cmp bs3d_state, BS_SHOT
jne @F
mov bs3d_dealerFrame, 6
cmp actor, 1
je @F
mov bs3d_dealerFrame, 0
cmp bs3d_timer, 450
jb @F
cmp bs3d_target, 1
jne @F
cmp bs3d_lastShot, 0
je @F
mov bs3d_dealerFrame, 12
@@:
cmp bs3d_state, BS_ITEM
jne @F
cmp bs3d_turn, 1
jne @F
mov bs3d_dealerFrame, 7
@@:
cmp bs3d_state, BS_WIN
jne @F
mov bs3d_dealerFrame, 14
@@:
cmp bs3d_state, BS_LOSE
jne @F
mov bs3d_dealerFrame, 11
@@:
cmp bs3d_state, BS_DEATH
jne bs_dealer_death_shot
cmp bs3d_victim, 1
jne bs_dealer_normal
mov eax, bs3d_timer
jmp bs_dealer_death_pose
bs_dealer_death_shot:
cmp bs3d_state, BS_SHOT
jne bs_dealer_medical
cmp bs3d_hpDealer, 0
jne bs_dealer_normal
mov eax, bs3d_timer
sub eax, 450
js bs_dealer_normal
jmp bs_dealer_death_pose
bs_dealer_medical:
cmp bs3d_state, BS_RECOVERY
jne bs_dealer_normal
cmp bs3d_victim, 1
jne bs_dealer_normal
cmp bs3d_timer, 2250
jae bs_dealer_normal
mov eax, 1100
bs_dealer_death_pose:
xor edx, edx
mov ecx, 100
div ecx
cmp eax, 11
jbe @F
mov eax, 11
@@:
invoke DrawAnimSprite3D, OFFSET bs3d_death, eax, 192, 2, 256, 224
jmp bs_render_rail
bs_dealer_normal:
cmp bs3d_state, BS_LOAD
jne bs_dealer_forward_pose
cmp bs3d_loadActor, 1
jne bs_dealer_gesture
mov eax, bs3d_timer
cmp eax, 220
jb bs_dealer_reach
sub eax, 220
mov ecx, bs3d_shellCount
imul ecx, 330
cmp eax, ecx
jae bs_dealer_pump_pose
xor edx, edx
mov ecx, 330
div ecx
mov eax, edx
xor edx, edx
mov ecx, 110
div ecx
add eax, 2
jmp bs_dealer_action_draw
bs_dealer_pump_pose:
sub eax, ecx
cmp eax, 100
jb bs_dealer_grip
cmp eax, 400
jb bs_dealer_pull
mov eax, 7
jmp bs_dealer_action_draw
bs_dealer_grip:
mov eax, 5
jmp bs_dealer_action_draw
bs_dealer_pull:
mov eax, 6
jmp bs_dealer_action_draw
bs_dealer_reach:
xor eax, eax
jmp bs_dealer_action_draw
bs_dealer_forward_pose:
cmp bs3d_state, BS_SHOT
jne bs_dealer_gesture
cmp actor, 1
jne bs_dealer_gesture
cmp bs3d_target, 0
jne bs_dealer_gesture
call ResolveBuckshotPose3D
add eax, 8
bs_dealer_action_draw:
invoke DrawAnimSprite3D, OFFSET bs3d_dealerActions, eax, 192, 2, 256, 224
jmp bs_render_rail
bs_dealer_gesture:
mov eax, 2
sub eax, bs3d_pitch
invoke DrawAnimSprite3D, OFFSET bs3d_dealer, bs3d_dealerFrame, 192, eax, 256, 224
bs_render_rail:
; Dealer's torso stops at the far leather rail; hands can overlap its upper edge.
cmp bs3d_pitch, 0
jne bs_render_after_rail
mov esi, bs3d_room.pixels
add esi, 640*222*4
lea edi, screenBuffer[640*222*4]
mov ecx, 640*8
rep movsd
bs_render_after_rail:
cmp bs3d_state, BS_DEATH
je bs_render_death
cmp bs3d_state, BS_RECOVERY
je bs_render_recovery
cmp bs3d_state, BS_LOAD
je bs_render_load
cmp bs3d_state, BS_SHOT
je bs_render_shot
cmp bs3d_state, BS_ITEM
je bs_render_item
jmp bs_render_idle_gun
bs_render_load:
call ResolveBuckshotPose3D
mov pose, eax
cmp bs3d_loadActor, 1
je bs_render_dealer_load
mov handY, 140
mov eax, bs3d_timer
cmp eax, 220
jae @F
mov ecx, 220
sub ecx, eax
imul ecx, 60
mov eax, ecx
xor edx, edx
mov ecx, 220
div ecx
add handY, eax
@@:
invoke DrawBuckshotHand3D, OFFSET bs3d_loading, pose, 166, handY, 320, 280
jmp bs_render_hud
bs_render_dealer_load:
jmp bs_render_hud
bs_render_shot:
call ResolveBuckshotPose3D
mov pose, eax
cmp actor, 1
je bs_render_dealer_shot
mov eax, bs3d_target
test eax, eax
jz bs_render_self_shot
mov handY, 140
mov eax, bs3d_timer
cmp eax, 140
jae @F
mov ecx, 140
sub ecx, eax
imul eax, ecx, 60
xor edx, edx
mov ecx, 140
div ecx
add handY, eax
@@:
invoke DrawBuckshotHand3D, OFFSET bs3d_shots, pose, 158, handY, 320, 280
jmp bs_render_hit_overlay
bs_render_self_shot:
mov handY, 120
mov eax, bs3d_timer
cmp eax, 300
jae @F
mov ecx, 300
sub ecx, eax
imul eax, ecx, 80
xor edx, edx
mov ecx, 300
div ecx
add handY, eax
@@:
mov eax, bs3d_timer
xor edx, edx
mov ecx, 150
div ecx
cmp eax, 7
jbe @F
mov eax, 7
@@:
cmp bs3d_timer, 450
jb @F
cmp bs3d_timer, 900
jae @F
mov eax, 5
@@:
invoke DrawBuckshotHand3D, OFFSET bs3d_self, eax, 156, handY, 328, 287
cmp bs3d_effectDone, 0
je bs_render_hit_overlay
cmp bs3d_lastShot, 0
je bs_render_hit_overlay
cmp bs3d_timer, 900
jae bs_render_hit_overlay
mov eax, bs3d_timer
sub eax, 450
cmp eax, 120
jae bs_self_smoke
xor edx, edx
mov ecx, 30
div ecx
jmp bs_self_flash_draw
bs_self_smoke:
sub eax, 120
xor edx, edx
mov ecx, 90
div ecx
add eax, 4
cmp eax, 7
jbe bs_self_flash_draw
mov eax, 7
bs_self_flash_draw:
; The atlas origin is its center, aligned with the bore rather than the weapon bounds.
mov edx, handY
add edx, 44
invoke DrawAnimSprite3D, OFFSET bs3d_selfFlash, eax, 251, edx, 128, 128
jmp bs_render_hit_overlay
bs_render_dealer_shot:
; The dealer action atlas already owns the raised weapon, including its first pose.
cmp bs3d_target, 1
je bs_render_dealer_self
jmp bs_render_hit_overlay
bs_render_dealer_self:
invoke DrawAnimSprite3D, OFFSET bs3d_props, 1, 206, 78, 176, 94
jmp bs_render_hit_overlay
bs_render_hit_overlay:
cmp bs3d_effectDone, 0
je bs_render_hud
cmp bs3d_lastShot, 0
je bs_render_hud
cmp bs3d_target, 0
jne bs_render_hud
mov eax, bs3d_timer
sub eax, 450
xor edx, edx
mov ecx, 180
div ecx
cmp eax, 7
jbe @F
mov eax, 7
@@:
invoke DrawAnimSprite3D, OFFSET bs3d_blood, eax, 0, 0, 640, 480
ret
bs_render_death:
cmp bs3d_victim, 1
je bs_draw_done
; First-person death keeps the player's body off camera.
lea edi, screenBuffer
mov ecx, SCREEN_SIZE
bs_dim_death:
mov eax, [edi]
shr eax, 2
and eax, 003F3F3Fh
mov [edi], eax
add edi, 4
loop bs_dim_death
mov eax, bs3d_timer
xor edx, edx
mov ecx, 250
div ecx
cmp eax, 7
jbe @F
mov eax, 7
@@:
invoke DrawAnimSprite3D, OFFSET bs3d_blood, eax, 0, 0, 640, 480
ret
bs_render_recovery:
; Both perspectives use all sixteen poses, once, in chronological order.
mov eax, bs3d_timer
imul eax,16
xor edx, edx
mov ecx,3600
div ecx
cmp eax,15
jbe @F
mov eax,15
@@:
cmp bs3d_victim, 0
jne @F
add eax,16
@@:
invoke DrawAnimSprite3D, OFFSET bs3d_medical, eax, 0, 0, 640, 480
ret
bs_render_item:
mov eax, bs3d_item
shl eax, 1
cmp bs3d_timer, 430
jb @F
inc eax
@@:
mov pose, eax
cmp bs3d_turn, 1
je bs_render_dealer_item
invoke DrawBuckshotHand3D, OFFSET bs3d_itemHands, pose, 180, 168, 256, 256
jmp bs_render_hud
bs_render_dealer_item:
mov eax, bs3d_item
add eax, 4
invoke DrawAnimSprite3D, OFFSET bs3d_props, eax, 244, 161, 86, 86
jmp bs_render_hud
bs_render_idle_gun:
invoke DrawAnimSprite3D, OFFSET bs3d_props, 0, 190, 226, 260, 168
bs_render_hud:
invoke DrawBuckshotPanel3D, 0, 0, 640, 32, 00111116h
invoke DrawBuckshotText3D, 14, 12, OFFSET bs3d_textTitle, 00E9C47Ah
invoke DrawBuckshotText3D, 488, 12, OFFSET bs3d_textBank, 00BCBCBCh
invoke DrawBuckshotNumber3D, 540, 12, bankroll, 00F3E4BAh
invoke DrawBuckshotPanel3D, 10, 42, 110, 28, 00151C20h
invoke DrawBuckshotPanel3D, 520, 42, 110, 28, 00151C20h
invoke DrawBuckshotText3D, 16, 48, OFFSET bs3d_textPlayer, 00E2E2E2h
invoke DrawBuckshotText3D, 526, 48, OFFSET bs3d_textDealer, 00E2E2E2h
xor esi, esi
bs_draw_health:
imul ebx, esi, 16
add ebx, 18
mov ecx, 003B3232h
cmp esi, bs3d_hpPlayer
jae @F
mov ecx, 00BD4F46h
@@:
invoke DrawBuckshotPanel3D, ebx, 60, 12, 6, ecx
add ebx, 510
mov ecx, 003B3232h
cmp esi, bs3d_hpDealer
jae @F
mov ecx, 00BD4F46h
@@:
invoke DrawBuckshotPanel3D, ebx, 60, 12, 6, ecx
inc esi
cmp esi, 4
jb bs_draw_health
invoke DrawBuckshotPanel3D, 0, 386, 640, 94, 00111617h
invoke DrawBuckshotPanel3D, 0, 386, 640, 2, 008A794Bh
invoke DrawBuckshotText3D, 16, 396, OFFSET bs3d_textShells, 00C7B88Fh
mov eax, bs3d_shellCount
sub eax, bs3d_shellIndex
invoke DrawBuckshotNumber3D, 78, 396, eax, 00FFFFFFh
invoke DrawBuckshotText3D, 14, 412, OFFSET bs3d_textLive, 00DF6656h
invoke DrawBuckshotNumber3D, 70, 412, bs3d_liveCount, 00DF6656h
invoke DrawBuckshotText3D, 14, 430, OFFSET bs3d_textBlank, 007DBBCCh
invoke DrawBuckshotNumber3D, 86, 430, bs3d_blankCount, 007DBBCCh
xor esi, esi
bs_draw_inventory:
imul ebx, esi, 112
add ebx, 160
invoke DrawBuckshotPanel3D, ebx, 396, 104, 44, 0020292Ch
lea eax, [esi+4]
lea edx, [ebx+4]
invoke DrawAnimSprite3D, OFFSET bs3d_props, eax, edx, 399, 34, 34
lea eax, [ebx+40]
invoke DrawBuckshotText3D, eax, 404, bs3d_textItems[esi*4], 00CFCAACh
lea eax, [ebx+44]
invoke DrawBuckshotNumber3D, eax, 420, bs3d_items[esi*4], 00EEEEEEh
inc esi
cmp esi, 4
jb bs_draw_inventory
cmp bs3d_state, BS_READY
je bs_draw_ready
cmp bs3d_state, BS_WIN
je bs_draw_win
cmp bs3d_state, BS_LOSE
je bs_draw_lose
cmp bs3d_state, BS_PLAYER
je bs_draw_player
cmp bs3d_state, BS_LOAD
je bs_draw_loading
cmp bs3d_state, BS_ITEM
je bs_draw_using
cmp bs3d_state, BS_DEATH
je bs_draw_death
cmp bs3d_state, BS_RECOVERY
je bs_draw_recovery
mov ebx, OFFSET bs3d_textWait
cmp bs3d_state, BS_SHOT
jne bs_draw_message
cmp bs3d_effectDone, 0
je bs_draw_message
mov ebx, bs3d_message
jmp bs_draw_message
bs_draw_loading:
mov ebx, OFFSET bs3d_textLoad
jmp bs_draw_message
bs_draw_using:
mov ebx, OFFSET bs3d_textItem
jmp bs_draw_message
bs_draw_death:
mov ebx, OFFSET bs3d_textDeath
jmp bs_draw_message
bs_draw_recovery:
mov ebx, OFFSET bs3d_textMedical
bs_draw_message:
invoke DrawBuckshotText3D, 24, 455, ebx, 00E1C67Bh
invoke DrawBuckshotText3D, 530, 455, OFFSET bs3d_textPause, 00AFAFAFh
jmp bs_draw_notice
bs_draw_ready:
invoke DrawBuckshotPanel3D, 30, 416, 28, 22, 00404A46h
invoke DrawBuckshotText3D, 40, 423, OFFSET bs3d_minus, 00FFFFFFh
invoke DrawBuckshotPanel3D, 112, 416, 28, 22, 00404A46h
invoke DrawBuckshotText3D, 122, 423, OFFSET bs3d_plus, 00FFFFFFh
invoke DrawBuckshotText3D, 22, 451, OFFSET bs3d_textBet, 00C7B88Fh
invoke DrawBuckshotNumber3D, 92, 451, bs3d_bet, 00FFFFFFh
invoke DrawBuckshotPanel3D, 246, 446, 136, 24, 00363C30h
invoke DrawBuckshotText3D, 258, 454, OFFSET bs3d_textReady, 00E1C67Bh
invoke DrawBuckshotText3D, 548, 454, OFFSET bs3d_textExit, 00AFAFAFh
cmp bs3d_error, 0
je bs_draw_done
invoke DrawBuckshotPanel3D, 232, 348, 176, 22, 00291919h
invoke DrawBuckshotText3D, 260, 355, OFFSET bs3d_textEmpty, 00DD7768h
jmp bs_draw_done
bs_draw_player:
invoke DrawBuckshotPanel3D, 30, 446, 102, 24, 00383E33h
invoke DrawBuckshotPanel3D, 150, 446, 122, 24, 00462E2Eh
invoke DrawBuckshotText3D, 48, 455, OFFSET bs3d_textChoose, 00E9DDC4h
invoke DrawBuckshotText3D, 176, 455, OFFSET bs3d_textOpponent, 00E9DDC4h
invoke DrawBuckshotText3D, 530, 455, OFFSET bs3d_textPause, 00AFAFAFh
jmp bs_draw_notice
bs_draw_win:
invoke DrawBuckshotText3D, 20, 455, OFFSET bs3d_textWin, 007FE395h
invoke DrawBuckshotNumber3D, 120, 455, bs3d_payout, 007FE395h
jmp bs_draw_result
bs_draw_lose:
invoke DrawBuckshotText3D, 20, 455, OFFSET bs3d_textLose, 00E1766Ah
bs_draw_result:
invoke DrawBuckshotPanel3D, 246, 446, 136, 24, 00363C30h
invoke DrawBuckshotText3D, 254, 455, OFFSET bs3d_textResult, 00E1C67Bh
invoke DrawBuckshotText3D, 548, 455, OFFSET bs3d_textExit, 00AFAFAFh
jmp bs_draw_done
bs_draw_notice:
cmp bs3d_turn, 0
jne bs_draw_done
cmp bs3d_known, -1
je @F
mov eax, OFFSET bs3d_textKnownBlank
cmp bs3d_known, 0
je bs_draw_known
mov eax, OFFSET bs3d_textKnownLive
bs_draw_known:
; Drawing primitives may overwrite EAX; preserve the selected string address.
mov ebx, eax
invoke DrawBuckshotPanel3D, 8, 350, 120, 22, 001B2325h
invoke DrawBuckshotText3D, 14, 357, ebx, 00E9C47Ah
@@:
cmp bs3d_messageTime, 0
je bs_draw_done
cmp bs3d_message, 0
je bs_draw_done
invoke DrawBuckshotPanel3D, 170, 354, 280, 22, 001B2325h
invoke DrawBuckshotText3D, 180, 361, bs3d_message, 00E1C67Bh
bs_draw_done:
ret
bs_render_error:
invoke DrawBuckshotPanel3D, 0, 0, 640, 480, 00111719h
invoke DrawBuckshotText3D, 184, 230, OFFSET bs3d_textAssets, 00E1C67Bh
invoke DrawBuckshotText3D, 276, 254, OFFSET bs3d_textExit, 00C7B88Fh
ret
RenderBuckshot3D ENDP