- Bowling feel: impulse contact solver, string pinsetter cycle, in-world lengthwise return rack and visible ball return lift - Ball weights: 4/5/6/7 kg selection with equal launch work physics, momentum balance, and projected picking - Audio: dedicated MCI channels with 7 synthesized waveaudio cues (release, rolling, impacts, applause, pinsetter, return) - First-person animations: 33-frame player underarm throw/follow-through sequence (player-underarm-v2) - Visitors: 10 persistent shared cast identities with exclusive reservations, activity transitions, and chair sit/rise animations - Tests & verification: comprehensive native regression test suites and updated documentation - Synchronize binaries and update launcher hash to 536E23BED4055562BC63871826FF44FFED037923A9BE8E0F591131DB4FBD104B
480 lines
10 KiB
PHP
480 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 bpState3D,BP_SELECT_BALL
|
|
call BowlingAudioOpen3D
|
|
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
|
|
mov bpReactionTime3D,0
|
|
mov bpAfterReturn3D,BP_DIRECTION
|
|
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
|
|
call BowlingAudioClose3D
|
|
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
|
|
mov bpPinTilt3D[esi*4],0
|
|
mov bpPinTiltV3D[esi*4],0
|
|
mov bpPinAxisX3D[esi*4],0
|
|
mov bpPinAxisY3D[esi*4],-FP_1
|
|
mov bpPinSpin3D[esi*4],0
|
|
mov bpPinContactTick3D[esi*4],0
|
|
mov bpRadius3D[esi*4],24
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_rack_pin
|
|
mov bpHitMask3D,0
|
|
mov bpGutter3D,0
|
|
mov bpAccumulator3D,0
|
|
mov bpPhysicsTicks3D,0
|
|
mov bpEndTicks3D,0
|
|
mov bpImpactEnergy3D,0
|
|
mov bpImpactCooldown3D,0
|
|
mov bpAudioReleased3D,0
|
|
mov bpBallX3D,FP_1/2
|
|
mov bpBallY3D,24*FP_1
|
|
ret
|
|
BowlingPlayRack3D ENDP
|
|
|
|
BowlingPlayLaunch3D PROC
|
|
local speed:DWORD,aimX:DWORD,aimLength:REAL8
|
|
mov bpState3D,BP_RELEASE
|
|
mov bpTime3D,0
|
|
mov bpAccumulator3D,0
|
|
call BowlingApplyBallMass3D
|
|
mov eax,bpLockedPower3D
|
|
imul eax,6*FP_1
|
|
cdq
|
|
mov ecx,100
|
|
idiv ecx
|
|
add eax,3*FP_1
|
|
mov speed,eax
|
|
; The gauge fixes launch work, calibrated to the existing six-kilogram ball.
|
|
; v = v_reference * sqrt(m_reference / m); no mass-dependent aim noise.
|
|
fild bpReferenceKg3D
|
|
fidiv bpShotWeightKg3D
|
|
fsqrt
|
|
fimul speed
|
|
fist bpLaunchSpeed3D
|
|
fimul bpTickMs3D
|
|
fidiv bpSecondMs3D
|
|
fistp speed
|
|
mov eax,bpLockedAim3D
|
|
sub eax,bpBallX3D
|
|
mov aimX,eax
|
|
fild aimX
|
|
fmul st,st
|
|
fild bpLaneDistance3D
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fsqrt
|
|
fstp aimLength
|
|
fild aimX
|
|
fdiv aimLength
|
|
fimul speed
|
|
fistp bpBallVX3D
|
|
fild bpLaneDistance3D
|
|
fdiv aimLength
|
|
fimul speed
|
|
fchs
|
|
fistp bpBallVY3D
|
|
ret
|
|
BowlingPlayLaunch3D ENDP
|
|
|
|
include src_graphics\bowling_physics.inc
|
|
include src_graphics\bowling_audio.inc
|
|
include src_graphics\bowling_return.inc
|
|
include src_graphics\bowling_weight.inc
|
|
|
|
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 bpReaction3D,CAST_TALK
|
|
cmp ecx,7
|
|
jb @F
|
|
mov bpReaction3D,CAST_CHEER
|
|
@@:
|
|
mov bpReactionTime3D,6500
|
|
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:
|
|
cmp bpLastKind3D,0
|
|
je @F
|
|
mov bpReaction3D,CAST_CHEER
|
|
@@:
|
|
cmp bpReaction3D,CAST_CHEER
|
|
jne @F
|
|
cmp bpAudioReady3D,0
|
|
je @F
|
|
invoke mciSendStringA,OFFSET bpClapPlay,0,0,0
|
|
@@:
|
|
invoke BowlingRegisterRoll3D,bpLane3D,bpLast3D
|
|
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,mousePress:DWORD
|
|
mov eax,deltaTime3D
|
|
sub bpImpactCooldown3D,eax
|
|
jns @F
|
|
mov bpImpactCooldown3D,0
|
|
@@:
|
|
sub bpReactionTime3D,eax
|
|
jns @F
|
|
mov bpReactionTime3D,0
|
|
@@:
|
|
invoke Pressed3D,9
|
|
test eax,eax
|
|
jz @F
|
|
xor bpScoreOpen3D,1
|
|
@@:
|
|
mov eax,mouseClick3D
|
|
mov click,eax
|
|
mov mousePress,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
|
|
mov bpState3D,BP_SELECT_BALL
|
|
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_SELECT_BALL
|
|
jne @F
|
|
cmp mousePress,0
|
|
jne bp_handle_rack_mouse
|
|
cmp click,0
|
|
je bp_handle_rack_mouse
|
|
mov bpState3D,BP_DIRECTION
|
|
ret
|
|
bp_handle_rack_mouse:
|
|
invoke HandleBowlingWeight3D,mousePress
|
|
jmp bp_handle_done
|
|
@@:
|
|
cmp bpState3D,BP_DIRECTION
|
|
jne bp_handle_power
|
|
invoke HandleBowlingWeight3D,mousePress
|
|
test eax,eax
|
|
jnz bp_handle_done
|
|
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,BP_RELEASE_MS
|
|
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
|
|
call BowlingPlayReady3D
|
|
test eax,eax
|
|
jnz bp_handle_impact_done
|
|
jmp bp_handle_fixed_step
|
|
bp_handle_roll_end:
|
|
jmp bp_handle_done
|
|
bp_handle_impact_done:
|
|
call BowlingPlayFinishRoll3D
|
|
ret
|
|
bp_handle_settle:
|
|
cmp bpState3D,BP_SETTLE
|
|
jne bp_handle_reset
|
|
cmp bpTime3D,1600
|
|
jb bp_handle_done
|
|
cmp bpHitMask3D,0
|
|
jne @F
|
|
mov esi,bpLane3D
|
|
cmp bwNewRack3D[esi*4],0
|
|
jne @F
|
|
call CompleteBowlingRoll3D
|
|
ret
|
|
@@:
|
|
mov bpState3D,BP_RESET
|
|
mov bpTime3D,0
|
|
cmp bpAudioReady3D,0
|
|
je bp_handle_done
|
|
invoke mciSendStringA,OFFSET bpResetPlay,0,0,0
|
|
jmp bp_handle_done
|
|
bp_handle_reset:
|
|
cmp bpState3D,BP_RESET
|
|
jne bp_handle_bot
|
|
cmp bpTime3D,BP_RESET_MS
|
|
jb bp_handle_done
|
|
call CompleteBowlingRoll3D
|
|
ret
|
|
bp_handle_bot:
|
|
cmp bpState3D,BP_RETURN
|
|
jne bp_handle_bot_ready
|
|
cmp bpTime3D,BP_RETURN_MS
|
|
jb bp_handle_done
|
|
mov eax,bpAfterReturn3D
|
|
mov bpState3D,eax
|
|
mov bpTime3D,0
|
|
call ClearKeys3D
|
|
jmp bp_handle_done
|
|
bp_handle_bot_ready:
|
|
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:
|
|
call BowlingAudioUpdate3D
|
|
ret
|
|
HandleBowlingPlay3D ENDP
|
|
|
|
include src_graphics\bowling_play_render.inc
|