KAZIK/src_graphics/bowling_play.inc
Artvasil09 3150d217b5 feat: add playable bowling match mode and calibrate rooftop character scaling
- Add playable ten-frame bowling against bot with two timing gates (direction/power) and fixed-step physics

- Add lane match interaction, shaded ball surface, pin collisions, bonus balls, and live score sheet

- Scale rooftop terrace visitor sprites to eye level according to the taller rooftop standing eye height

- Resolve mode and interaction ID conflicts with Hell FPS (MODE_BOWLING=30, INTERACT_BOWL_PLAY=56)

- Update launcher hash, installer package, and expansion regression test suites
2026-11-01 22:50:33 +03:00

507 lines
10 KiB
PHP

; Two timing gates commit one immutable launch; the same solver serves both players.
BeginBowlingPlay3D PROC uses esi lane:DWORD
cmp bpActive3D,0
jne bp_begin_no
mov esi,lane
cmp esi,BW_LANES
jae bp_begin_no
cmp bwBusy3D[esi*4],0
jne bp_begin_no
mov eax,playerX
mov bpHomeX3D,eax
mov eax,playerY
mov bpHomeY3D,eax
mov eax,playerAngle
mov bpHomeAngle3D,eax
mov bpLane3D,esi
imul eax,esi,BW_LANE_STEP
add eax,3*FP_1
mov bpCentre3D,eax
mov bpActive3D,1
mov bwBusy3D[esi*4],2
mov engineMode,MODE_BOWLING
mov paused3D,0
mov bwSeat3D,0
call ResetBowlingPlay3D
mov eax,1
ret
bp_begin_no:
xor eax,eax
ret
BeginBowlingPlay3D ENDP
ResetBowlingPlay3D PROC uses ebx esi edi
mov esi,bpLane3D
lea ebx,[esi*8]
mov bwFrames3D[ebx],0
mov bwFrames3D[ebx+4],0
mov bwRollCount3D[ebx],0
mov bwRollCount3D[ebx+4],0
mov bwScores3D[ebx],0
mov bwScores3D[ebx+4],0
imul eax,esi,192
lea edi,bwRolls3D[eax]
xor eax,eax
mov ecx,48
rep stosd
mov bwTurn3D[esi*4],0
mov bwBall3D[esi*4],0
mov bwRack3D[esi*4],1023
mov bwState3D[esi*4],0
mov bwHit3D[esi*4],0
mov bwTime3D[esi*4],0
mov bpState3D,BP_DIRECTION
mov bpTime3D,0
call BowlingPlayStartAim3D
mov bpScoreOpen3D,0
mov bpLast3D,0
mov bpLastKind3D,0
call BowlingPlayRack3D
call ClearKeys3D
mov mouseClick3D,0
ret
ResetBowlingPlay3D ENDP
; Randomize only the visible starting phase, never the committed trajectory.
BowlingPlayStartAim3D PROC
mov eax,bwRng3D
imul eax,1664525
add eax,1013904223
mov bwRng3D,eax
shr eax,16
and eax,2047
mov bpClock3D,eax
ret
BowlingPlayStartAim3D ENDP
LeaveBowlingPlay3D PROC uses esi
cmp bpActive3D,0
je bp_leave_done
mov esi,bpLane3D
mov bwBusy3D[esi*4],0
mov bwRack3D[esi*4],1023
mov bwHit3D[esi*4],0
mov bwState3D[esi*4],0
mov bpActive3D,0
mov bpScoreOpen3D,0
mov eax,bpHomeX3D
mov playerX,eax
mov eax,bpHomeY3D
mov playerY,eax
mov eax,bpHomeAngle3D
mov playerAngle,eax
mov engineMode,MODE_WALK
call BowlingEye3D
call UpdateCamera3D
call ClearKeys3D
mov mouseClick3D,0
mov bwMonitorClock3D,-1
bp_leave_done:
ret
LeaveBowlingPlay3D ENDP
BowlingPlayRack3D PROC uses esi
xor esi,esi
bp_rack_pin:
mov eax,bwPinX3D[esi*4]
mov bpPinX3D[esi*4],eax
mov eax,bwPinY3D[esi*4]
mov bpPinY3D[esi*4],eax
mov bpPinVX3D[esi*4],0
mov bpPinVY3D[esi*4],0
inc esi
cmp esi,10
jb bp_rack_pin
mov bpHitMask3D,0
mov bpGutter3D,0
mov bpAccumulator3D,0
mov bpBallX3D,0
mov bpBallY3D,FP_1*225/10
ret
BowlingPlayRack3D ENDP
BowlingPlayLaunch3D PROC
mov bpState3D,BP_RELEASE
mov bpTime3D,0
mov bpAccumulator3D,0
mov eax,bpLockedPower3D
imul eax,6*FP_1
cdq
mov ecx,100
idiv ecx
add eax,3*FP_1
imul eax,16
cdq
mov ecx,1000
idiv ecx
mov ecx,eax
neg eax
mov bpBallVY3D,eax
mov eax,bpLockedAim3D
imul ecx
mov ecx,18*FP_1
idiv ecx
mov bpBallVX3D,eax
ret
BowlingPlayLaunch3D ENDP
BowlingPlayHit3D PROC uses esi pin:DWORD,vx:DWORD,vy:DWORD
mov esi,pin
mov ecx,esi
mov eax,1
shl eax,cl
test bpHitMask3D,eax
jnz bp_hit_done
or bpHitMask3D,eax
mov eax,vx
mov bpPinVX3D[esi*4],eax
mov eax,vy
mov bpPinVY3D[esi*4],eax
bp_hit_done:
ret
BowlingPlayHit3D ENDP
; 16-ms fixed steps, lane-relative 16.16 discs. No random hit selection.
BowlingPlayStep3D PROC uses ebx esi edi
local deltaX:DWORD,deltaY:DWORD,impulseX:DWORD,rackMask:DWORD
mov esi,bpLane3D
mov eax,bwRack3D[esi*4]
mov rackMask,eax
mov eax,bpBallVX3D
add bpBallX3D,eax
mov eax,bpBallVY3D
add bpBallY3D,eax
mov eax,bpBallX3D
cdq
xor eax,edx
sub eax,edx
cmp eax,FP_1*74/100
jbe bp_step_pins
mov bpGutter3D,1
mov eax,FP_1*87/100
cmp bpBallX3D,0
jge @F
neg eax
@@:
mov bpBallX3D,eax
mov bpBallVX3D,0
bp_step_pins:
xor esi,esi
bp_step_pin:
mov ecx,esi
mov ebx,1
shl ebx,cl
test rackMask,ebx
jz bp_step_next_pin
test bpHitMask3D,ebx
jnz bp_step_move_pin
cmp bpGutter3D,0
jne bp_step_next_pin
mov eax,bpPinX3D[esi*4]
sub eax,bpBallX3D
mov deltaX,eax
sar eax,8
imul eax,eax
mov edi,eax
mov eax,bpPinY3D[esi*4]
sub eax,bpBallY3D
sar eax,8
imul eax,eax
add eax,edi
cmp eax,56*56
ja bp_step_next_pin
mov eax,deltaX
sar eax,3
add eax,bpBallVX3D
mov impulseX,eax
mov eax,bpBallVY3D
imul eax,3
sar eax,2
invoke BowlingPlayHit3D,esi,impulseX,eax
bp_step_move_pin:
mov eax,bpPinVX3D[esi*4]
add bpPinX3D[esi*4],eax
imul eax,245
sar eax,8
mov bpPinVX3D[esi*4],eax
mov eax,bpPinVY3D[esi*4]
add bpPinY3D[esi*4],eax
imul eax,245
sar eax,8
mov bpPinVY3D[esi*4],eax
xor edi,edi
bp_step_chain:
mov ecx,edi
mov ebx,1
shl ebx,cl
test rackMask,ebx
jz bp_step_chain_next
test bpHitMask3D,ebx
jnz bp_step_chain_next
mov eax,bpPinX3D[edi*4]
sub eax,bpPinX3D[esi*4]
mov deltaX,eax
sar eax,8
imul eax,eax
mov ebx,eax
mov eax,bpPinY3D[edi*4]
sub eax,bpPinY3D[esi*4]
mov deltaY,eax
sar eax,8
imul eax,eax
add eax,ebx
cmp eax,49*49
ja bp_step_chain_next
mov eax,deltaX
sar eax,8
imul bpPinVX3D[esi*4]
mov ebx,eax
mov eax,deltaY
sar eax,8
imul bpPinVY3D[esi*4]
add eax,ebx
jle bp_step_chain_next
mov eax,bpPinVX3D[esi*4]
sar eax,1
mov ebx,deltaX
sar ebx,3
add eax,ebx
mov impulseX,eax
mov eax,bpPinVY3D[esi*4]
sar eax,1
mov ebx,deltaY
sar ebx,3
add eax,ebx
invoke BowlingPlayHit3D,edi,impulseX,eax
bp_step_chain_next:
inc edi
cmp edi,10
jb bp_step_chain
bp_step_next_pin:
inc esi
cmp esi,10
jb bp_step_pin
ret
BowlingPlayStep3D ENDP
BowlingPlayFinishRoll3D PROC uses esi
mov eax,bpHitMask3D
xor ecx,ecx
bp_finish_count:
test eax,eax
jz bp_finish_register
lea edx,[eax-1]
and eax,edx
inc ecx
jmp bp_finish_count
bp_finish_register:
mov bpLast3D,ecx
mov bpLastKind3D,0
mov esi,bpLane3D
cmp bwBall3D[esi*4],1
jne bp_finish_strike
mov eax,bwFirstHit3D[esi*4]
cmp eax,10
je bp_finish_strike
add eax,ecx
cmp eax,10
jne bp_finish_register_score
mov bpLastKind3D,2
jmp bp_finish_register_score
bp_finish_strike:
cmp ecx,10
jne bp_finish_register_score
mov bpLastKind3D,1
bp_finish_register_score:
invoke BowlingRegisterRoll3D,bpLane3D,ecx
mov bpState3D,BP_SETTLE
mov bpTime3D,0
mov bwMonitorClock3D,-1
ret
BowlingPlayFinishRoll3D ENDP
BowlingPlayNext3D PROC uses ebx esi
mov esi,bpLane3D
mov eax,bpHitMask3D
not eax
and bwRack3D[esi*4],eax
cmp bwNewRack3D[esi*4],0
je @F
mov bwRack3D[esi*4],1023
@@:
cmp bwFrameDone3D[esi*4],0
je bp_next_ready
xor bwTurn3D[esi*4],1
lea ebx,[esi*2]
add ebx,bwTurn3D[esi*4]
cmp bwFrames3D[ebx*4],10
jb bp_next_ready
xor bwTurn3D[esi*4],1
lea ebx,[esi*2]
add ebx,bwTurn3D[esi*4]
cmp bwFrames3D[ebx*4],10
jb bp_next_ready
mov bpState3D,BP_FINISHED
ret
bp_next_ready:
call BowlingPlayRack3D
call BowlingPlayStartAim3D
mov bpTime3D,0
mov bpState3D,BP_DIRECTION
cmp bwTurn3D[esi*4],0
je @F
mov bpState3D,BP_BOT
@@:
ret
BowlingPlayNext3D ENDP
HandleBowlingPlay3D PROC uses ebx esi
local click:DWORD,elapsed:DWORD
invoke Pressed3D,9
test eax,eax
jz @F
xor bpScoreOpen3D,1
@@:
mov eax,mouseClick3D
mov click,eax
mov mouseClick3D,0
cmp click,0
je @F
cmp mouseY3D,224
jb @F
cmp mouseX3D,265
jb @F
call LeaveBowlingPlay3D
ret
@@:
invoke Pressed3D,20h
or click,eax
cmp bpScoreOpen3D,0
jne bp_handle_done
cmp bpState3D,BP_FINISHED
jne bp_handle_clock
cmp click,0
je bp_handle_done
call ResetBowlingPlay3D
ret
bp_handle_clock:
mov eax,deltaTime3D
cmp eax,250
jbe @F
mov eax,250
@@:
mov elapsed,eax
add bpClock3D,eax
add bpTime3D,eax
cmp bpState3D,BP_DIRECTION
jne bp_handle_power
mov eax,bpClock3D
xor edx,edx
mov ecx,4
div ecx
and eax,511
mov eax,tableSin[eax*4]
imul eax,6
cdq
mov ecx,5
idiv ecx
mov bpAim3D,eax
cmp click,0
je bp_handle_done
mov bpLockedAim3D,eax
mov bpState3D,BP_POWER
mov bpClock3D,0
mov bpTime3D,0
ret
bp_handle_power:
cmp bpState3D,BP_POWER
jne bp_handle_release
mov eax,bpClock3D
xor edx,edx
mov ecx,1600
div ecx
mov eax,edx
cmp eax,800
jbe @F
neg eax
add eax,1600
@@:
shr eax,3
mov bpPower3D,eax
cmp click,0
je bp_handle_done
mov bpLockedPower3D,eax
call BowlingPlayLaunch3D
ret
bp_handle_release:
cmp bpState3D,BP_RELEASE
jne bp_handle_roll
mov esi,bpLane3D
mov ecx,350
cmp bwTurn3D[esi*4],0
je @F
mov ecx,2400
@@:
cmp bpTime3D,ecx
jb bp_handle_done
mov bpState3D,BP_ROLL
mov bpTime3D,0
ret
bp_handle_roll:
cmp bpState3D,BP_ROLL
jne bp_handle_settle
mov eax,elapsed
add bpAccumulator3D,eax
bp_handle_fixed_step:
cmp bpAccumulator3D,16
jb bp_handle_roll_end
sub bpAccumulator3D,16
call BowlingPlayStep3D
cmp bpBallY3D,3*FP_1
jl bp_handle_impact_done
jmp bp_handle_fixed_step
bp_handle_roll_end:
cmp bpBallY3D,3*FP_1
jl bp_handle_impact_done
cmp bpTime3D,12000
jb bp_handle_done
bp_handle_impact_done:
call BowlingPlayFinishRoll3D
ret
bp_handle_settle:
cmp bpState3D,BP_SETTLE
jne bp_handle_bot
cmp bpTime3D,1800
jb bp_handle_done
call BowlingPlayNext3D
ret
bp_handle_bot:
cmp bpState3D,BP_BOT
jne bp_handle_done
cmp bpTime3D,1100
jb bp_handle_done
mov eax,bwRng3D
imul eax,1664525
add eax,1013904223
mov bwRng3D,eax
shr eax,16
xor edx,edx
mov ecx,101
div ecx
sub edx,50
imul eax,edx,FP_1
cdq
mov ecx,100
idiv ecx
mov bpLockedAim3D,eax
mov eax,bwRng3D
shr eax,24
and eax,31
add eax,60
mov bpLockedPower3D,eax
call BowlingPlayLaunch3D
bp_handle_done:
ret
HandleBowlingPlay3D ENDP
include src_graphics\bowling_play_render.inc