KAZIK/src_graphics/scratch_effects.inc
Игорь Федосеев ca62db53e9 feat: implement native billiards, scratch tickets, first-person dice, and city wake scene
- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests
- Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects
- First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective
- City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation
- World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests
- Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
2026-10-16 12:37:40 +03:00

377 lines
8.1 KiB
PHP

; Presentation state has its own clock and RNG; it never changes ticket odds.
ScratchEase3D PROC elapsed:DWORD,duration:DWORD
mov eax,elapsed
cmp eax,duration
jb @F
mov eax,256
ret
@@:
shl eax,8
xor edx,edx
div duration
mov ecx,eax
imul eax,eax
shl ecx,1
neg ecx
add ecx,768
imul eax,ecx
shr eax,16
ret
ScratchEase3D ENDP
ScratchStartDeal3D PROC
mov scrDealMs3D,900
mov scrPayoutMs3D,0
invoke PlayCasinoSound3D,OFFSET scrPaperSound3D,0,1
ret
ScratchStartDeal3D ENDP
ScratchStartPayout3D PROC
mov scrDealMs3D,0
mov scrPayoutMs3D,0
cmp engineMode,MODE_SCRATCH
jne @F
cmp scrGross3D,0
je @F
mov scrPayoutMs3D,1800
invoke PlayCasinoSound3D,OFFSET scrPayoutSound3D,0,1
@@:
ret
ScratchStartPayout3D ENDP
ScratchTickVisuals3D PROC uses ebx esi
mov eax,deltaTime3D
cmp eax,250
jbe @F
mov eax,250
@@:
sub scrDealMs3D,eax
jns @F
mov scrDealMs3D,0
@@:
sub scrPayoutMs3D,eax
jns @F
mov scrPayoutMs3D,0
@@:
sub scrScrapeCooldown3D,eax
jns @F
mov scrScrapeCooldown3D,0
@@:
cmp eax,100
jbe @F
mov eax,100
@@:
add scrDustStep3D,eax
scratch_visual_step:
cmp scrDustStep3D,8
jb scratch_visual_done
sub scrDustStep3D,8
xor esi,esi
scratch_visual_particle:
cmp scrDustLife3D[esi*4],0
je scratch_visual_next
sub scrDustLife3D[esi*4],8
jns @F
mov scrDustLife3D[esi*4],0
@@:
mov eax,scrDustY3D[esi*4]
cmp eax,scrDustFloor3D[esi*4]
jge scratch_visual_next
mov eax,scrDustVX3D[esi*4]
add scrDustX3D[esi*4],eax
add scrDustVY3D[esi*4],6
mov eax,scrDustVY3D[esi*4]
add scrDustY3D[esi*4],eax
mov eax,scrDustFloor3D[esi*4]
cmp scrDustY3D[esi*4],eax
jl scratch_visual_next
mov scrDustY3D[esi*4],eax
scratch_visual_next:
inc esi
cmp esi,SCR_DUST_COUNT
jb scratch_visual_particle
jmp scratch_visual_step
scratch_visual_done:
ret
ScratchTickVisuals3D ENDP
ScratchSpawnDust3D PROC uses ebx esi edi
cmp scrState3D,1
jne scratch_spawn_begin
cmp scrScrapeCooldown3D,0
jne @F
invoke PlayCasinoSound3D,OFFSET scrScrapeSound3D,0,1
mov scrScrapeCooldown3D,150
@@:
scratch_spawn_begin:
mov edi,3
scratch_spawn_fragment:
mov esi,scrDustIndex3D
mov eax,scrVisualSeed3D
imul eax,1664525
add eax,1013904223
mov scrVisualSeed3D,eax
mov ebx,eax
and eax,511
add eax,1200
mov scrDustLife3D[esi*4],eax
mov eax,scrPointerX3D
shl eax,8
mov scrDustX3D[esi*4],eax
mov eax,scrPointerY3D
shl eax,8
mov scrDustY3D[esi*4],eax
mov eax,ebx
shr eax,12
and eax,255
sub eax,128
mov scrDustVX3D[esi*4],eax
mov eax,ebx
shr eax,20
and eax,127
add eax,64
neg eax
mov scrDustVY3D[esi*4],eax
mov eax,ebx
shr eax,8
and eax,31
add eax,scrPointerY3D
add eax,20
cmp eax,385
jbe @F
mov eax,385
@@:
shl eax,8
mov scrDustFloor3D[esi*4],eax
inc esi
and esi,SCR_DUST_COUNT-1
mov scrDustIndex3D,esi
dec edi
jnz scratch_spawn_fragment
ret
ScratchSpawnDust3D ENDP
ScratchDrawDust3D PROC uses ebx esi edi
xor esi,esi
scratch_draw_fragment:
cmp scrDustLife3D[esi*4],0
je scratch_draw_fragment_next
mov eax,scrDustX3D[esi*4]
sar eax,8
cmp eax,638
jae scratch_draw_fragment_next
mov edx,scrDustY3D[esi*4]
sar edx,8
cmp edx,40
jb scratch_draw_fragment_next
cmp edx,386
jae scratch_draw_fragment_next
imul edx,640
add edx,eax
mov ebx,esi
and ebx,3
mov eax,scrDustInk3D[ebx*4]
mov screenBuffer[edx*4],eax
mov screenBuffer[edx*4+4],eax
test esi,1
jz scratch_draw_fragment_next
mov screenBuffer[edx*4+640*4],00868D89h
scratch_draw_fragment_next:
inc esi
cmp esi,SCR_DUST_COUNT
jb scratch_draw_fragment
ret
ScratchDrawDust3D ENDP
ScratchSaveBackdrop3D PROC uses esi edi
cmp scrDealMs3D,350
jbe @F
lea esi,screenBuffer[640*40*4]
lea edi,scrBackdrop3D[640*40*4]
mov ecx,640*348
rep movsd
@@:
ret
ScratchSaveBackdrop3D ENDP
ScratchDrawDelivery3D PROC uses ebx esi edi
local left:DWORD,top:DWORD,right:DWORD,bottom:DWORD,rowY:DWORD,pointX:DWORD
local offsetX:DWORD,offsetY:DWORD,sourceBase:DWORD
cmp scrDealMs3D,350
jbe scratch_delivery_done
mov eax,900
sub eax,scrDealMs3D
invoke ScratchEase3D,eax,550
neg eax
add eax,256
imul edx,eax,360
sar edx,8
mov offsetY,edx
imul eax,-56
sar eax,8
mov offsetX,eax
lea edi,scrPaperLayer3D
xor eax,eax
mov ecx,640*480
rep stosd
mov left,96
mov top,92
mov right,544
mov bottom,380
cmp scrType3D,4
jae scratch_delivery_portrait
mov eax,scrType3D
imul eax,448*288*4
add eax,scrTicketArt3D.pixels
mov sourceBase,eax
jmp scratch_delivery_bounds
scratch_delivery_portrait:
mov eax,scrViewX3D
mov left,eax
add eax,scrViewW3D
mov right,eax
mov eax,scrViewY3D
mov top,eax
add eax,scrViewH3D
mov bottom,eax
scratch_delivery_bounds:
cmp top,40
jge @F
mov top,40
@@:
cmp bottom,388
jle @F
mov bottom,388
@@:
mov eax,top
mov rowY,eax
scratch_delivery_row:
mov eax,left
mov pointX,eax
scratch_delivery_pixel:
cmp scrType3D,4
jae scratch_delivery_copy
mov eax,rowY
sub eax,92
imul eax,448
add eax,pointX
sub eax,96
mov edi,sourceBase
cmp BYTE PTR [edi+eax*4+3],0
je scratch_delivery_next
scratch_delivery_copy:
imul ebx,rowY,640
add ebx,pointX
mov eax,screenBuffer[ebx*4]
or eax,0FF000000h
mov scrPaperLayer3D[ebx*4],eax
scratch_delivery_next:
inc pointX
mov eax,pointX
cmp eax,right
jb scratch_delivery_pixel
inc rowY
mov eax,rowY
cmp eax,bottom
jb scratch_delivery_row
lea esi,scrBackdrop3D[640*40*4]
lea edi,screenBuffer[640*40*4]
mov ecx,640*348
rep movsd
; A clipped, paper-shaped contact shadow, never a rectangular overlay.
mov eax,top
mov rowY,eax
scratch_delivery_shadow_row:
mov eax,left
mov pointX,eax
scratch_delivery_shadow_pixel:
imul ebx,rowY,640
add ebx,pointX
cmp BYTE PTR scrPaperLayer3D[ebx*4+3],0
je scratch_delivery_shadow_next
mov eax,pointX
add eax,offsetX
add eax,4
cmp eax,640
jae scratch_delivery_shadow_next
mov edx,rowY
add edx,offsetY
add edx,6
cmp edx,40
jb scratch_delivery_shadow_next
cmp edx,388
jae scratch_delivery_shadow_next
imul edx,640
add edx,eax
mov eax,screenBuffer[edx*4]
mov ecx,eax
and ecx,00FCFCFCh
shr ecx,2
sub eax,ecx
mov screenBuffer[edx*4],eax
scratch_delivery_shadow_next:
inc pointX
mov eax,pointX
cmp eax,right
jb scratch_delivery_shadow_pixel
inc rowY
mov eax,rowY
cmp eax,bottom
jb scratch_delivery_shadow_row
invoke DrawAnimSprite3D,OFFSET scrPaperLayerPack3D,0,offsetX,offsetY,640,480
scratch_delivery_done:
ret
ScratchDrawDelivery3D ENDP
ScratchDrawPayout3D PROC uses ebx esi edi
local elapsed:DWORD,progress:DWORD,coinX:DWORD,coinY:DWORD
cmp scrState3D,2
jne scratch_payout_done
cmp scrGross3D,0
je scratch_payout_done
mov eax,1800
sub eax,scrPayoutMs3D
mov elapsed,eax
invoke ScratchEase3D,eax,400
imul eax,96
sar eax,8
sub eax,88
invoke DrawAnimSprite3D,OFFSET scrPayoutArt3D,0,eax,300,88,66
xor esi,esi
scratch_payout_coin:
imul eax,esi,110
add eax,350
mov edx,elapsed
sub edx,eax
js scratch_payout_coin_next
cmp edx,850
jae scratch_payout_coin_next
invoke ScratchEase3D,edx,850
mov progress,eax
imul ebx,eax,60
sar ebx,8
add ebx,40
mov edx,256
sub edx,eax
imul edx,eax
imul edx,80
sar edx,16
add ebx,edx
mov coinX,ebx
imul eax,260
sar eax,8
neg eax
add eax,330
mov coinY,eax
mov eax,elapsed
shr eax,6
add eax,esi
and eax,3
invoke DrawAnimSprite3D,OFFSET scrCoinArt3D,eax,coinX,coinY,20,20
scratch_payout_coin_next:
inc esi
cmp esi,5
jb scratch_payout_coin
scratch_payout_done:
ret
ScratchDrawPayout3D ENDP