- 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
482 lines
10 KiB
PHP
482 lines
10 KiB
PHP
; Symmetric normal impulses and overlap correction follow the existing billiards
|
|
; solver. Four 4-ms substeps prevent tunnelling; angular rocking is separate.
|
|
include src_graphics\bowling_deck.inc
|
|
|
|
NormalizeBowlingPinAxis3D PROC uses esi pin:DWORD
|
|
local axisLength:REAL8
|
|
mov esi,pin
|
|
mov eax,bpPinAxisX3D[esi*4]
|
|
or eax,bpPinAxisY3D[esi*4]
|
|
jnz bp_axis_length
|
|
mov bpPinAxisY3D[esi*4],-FP_1
|
|
ret
|
|
bp_axis_length:
|
|
fild bpPinAxisX3D[esi*4]
|
|
fmul st,st
|
|
fild bpPinAxisY3D[esi*4]
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fsqrt
|
|
fstp axisLength
|
|
fild bpPinAxisX3D[esi*4]
|
|
fdiv axisLength
|
|
fmul roofFloatFP3D
|
|
fistp bpPinAxisX3D[esi*4]
|
|
fild bpPinAxisY3D[esi*4]
|
|
fdiv axisLength
|
|
fmul roofFloatFP3D
|
|
fistp bpPinAxisY3D[esi*4]
|
|
ret
|
|
NormalizeBowlingPinAxis3D ENDP
|
|
|
|
BowlingPlayHit3D PROC pin:DWORD,vx:DWORD,vy:DWORD
|
|
invoke BowlingPlayKick3D,pin,vx,vy
|
|
ret
|
|
BowlingPlayHit3D ENDP
|
|
|
|
BowlingPlayKick3D PROC uses ebx esi edi pin:DWORD,vx:DWORD,vy:DWORD
|
|
local energy:DWORD
|
|
mov esi,pin
|
|
cmp esi,10
|
|
jae bp_kick_done
|
|
; Preserve fractional impulses: signed pre-rounding can collapse the basis.
|
|
fild vx
|
|
fmul st,st
|
|
fild vy
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fsqrt
|
|
fistp energy
|
|
mov eax,energy
|
|
cmp eax,128
|
|
jb bp_kick_done
|
|
cmp eax,bpImpactEnergy3D
|
|
jbe @F
|
|
mov bpImpactEnergy3D,eax
|
|
@@:
|
|
cmp eax,128
|
|
jb bp_kick_done
|
|
mov edx,bpPhysicsTicks3D
|
|
mov bpPinContactTick3D[esi*4],edx
|
|
mov ecx,2
|
|
cdq
|
|
idiv ecx
|
|
cmp eax,2000
|
|
jbe @F
|
|
mov eax,2000
|
|
@@:
|
|
add bpPinTiltV3D[esi*4],eax
|
|
mov eax,bpPinTiltV3D[esi*4]
|
|
cmp eax,2400
|
|
jle @F
|
|
mov bpPinTiltV3D[esi*4],2400
|
|
@@:
|
|
cmp bpPinTilt3D[esi*4],64*256
|
|
jae bp_kick_done
|
|
mov eax,vx
|
|
mov ecx,FP_1
|
|
imul ecx
|
|
idiv energy
|
|
mov bpPinAxisX3D[esi*4],eax
|
|
mov eax,vy
|
|
imul ecx
|
|
idiv energy
|
|
mov bpPinAxisY3D[esi*4],eax
|
|
invoke NormalizeBowlingPinAxis3D,esi
|
|
mov eax,vx
|
|
sub eax,vy
|
|
sar eax,10
|
|
mov bpPinSpin3D[esi*4],eax
|
|
bp_kick_done:
|
|
ret
|
|
BowlingPlayKick3D ENDP
|
|
|
|
BowlingPlayContact3D PROC uses ebx esi edi a:DWORD,b:DWORD
|
|
local deltaX:DWORD,deltaY:DWORD,radius:DWORD,distance:DWORD,nx:DWORD,ny:DWORD
|
|
local impulse:DWORD,changeA:DWORD,changeB:DWORD,ix:DWORD,iy:DWORD,massSum:DWORD
|
|
local contactLength:REAL8
|
|
mov esi,a
|
|
mov edi,b
|
|
mov eax,bpRadius3D[esi*4]
|
|
add eax,bpRadius3D[edi*4]
|
|
mov radius,eax
|
|
shl eax,8
|
|
mov ebx,eax
|
|
mov eax,bpPinX3D[edi*4]
|
|
sub eax,bpPinX3D[esi*4]
|
|
cmp eax,ebx
|
|
jg bp_contact_done
|
|
neg ebx
|
|
cmp eax,ebx
|
|
jl bp_contact_done
|
|
mov deltaX,eax
|
|
mov eax,bpPinY3D[edi*4]
|
|
sub eax,bpPinY3D[esi*4]
|
|
cmp eax,ebx
|
|
jl bp_contact_done
|
|
neg ebx
|
|
cmp eax,ebx
|
|
jg bp_contact_done
|
|
mov deltaY,eax
|
|
sar eax,8
|
|
imul eax,eax
|
|
mov ebx,deltaX
|
|
sar ebx,8
|
|
imul ebx,ebx
|
|
add eax,ebx
|
|
mov ebx,radius
|
|
imul ebx,ebx
|
|
cmp eax,ebx
|
|
jae bp_contact_done
|
|
fild deltaX
|
|
fmul st,st
|
|
fild deltaY
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fsqrt
|
|
fst contactLength
|
|
fistp distance
|
|
cmp distance,0
|
|
jne @F
|
|
mov deltaX,1
|
|
mov deltaY,0
|
|
mov distance,1
|
|
fild distance
|
|
fstp contactLength
|
|
@@:
|
|
mov eax,radius
|
|
shl eax,8
|
|
cmp distance,eax
|
|
jae bp_contact_done
|
|
fild deltaX
|
|
fdiv contactLength
|
|
fmul roofFloatFP3D
|
|
fistp nx
|
|
fild deltaY
|
|
fdiv contactLength
|
|
fmul roofFloatFP3D
|
|
fistp ny
|
|
mov eax,bpInvMass3D[esi*4]
|
|
add eax,bpInvMass3D[edi*4]
|
|
mov massSum,eax
|
|
mov eax,bpPinVX3D[edi*4]
|
|
sub eax,bpPinVX3D[esi*4]
|
|
imul nx
|
|
shrd eax,edx,16
|
|
mov ebx,eax
|
|
mov eax,bpPinVY3D[edi*4]
|
|
sub eax,bpPinVY3D[esi*4]
|
|
imul ny
|
|
shrd eax,edx,16
|
|
add eax,ebx
|
|
test eax,eax
|
|
jns bp_contact_separate
|
|
neg eax
|
|
mov ecx,FP_1*3/2
|
|
imul ecx
|
|
idiv massSum
|
|
mov impulse,eax
|
|
imul bpInvMass3D[esi*4]
|
|
shrd eax,edx,16
|
|
mov changeA,eax
|
|
mov eax,impulse
|
|
imul bpInvMass3D[edi*4]
|
|
shrd eax,edx,16
|
|
mov changeB,eax
|
|
mov eax,changeA
|
|
imul nx
|
|
shrd eax,edx,16
|
|
sub bpPinVX3D[esi*4],eax
|
|
neg eax
|
|
mov ix,eax
|
|
mov eax,changeA
|
|
imul ny
|
|
shrd eax,edx,16
|
|
sub bpPinVY3D[esi*4],eax
|
|
neg eax
|
|
invoke BowlingPlayKick3D,esi,ix,eax
|
|
mov eax,changeB
|
|
imul nx
|
|
shrd eax,edx,16
|
|
add bpPinVX3D[edi*4],eax
|
|
mov ix,eax
|
|
mov eax,changeB
|
|
imul ny
|
|
shrd eax,edx,16
|
|
add bpPinVY3D[edi*4],eax
|
|
invoke BowlingPlayKick3D,edi,ix,eax
|
|
bp_contact_separate:
|
|
mov eax,radius
|
|
shl eax,8
|
|
sub eax,distance
|
|
jle bp_contact_done
|
|
imul eax,3
|
|
sar eax,2
|
|
mov impulse,eax
|
|
imul bpInvMass3D[esi*4]
|
|
idiv massSum
|
|
mov changeA,eax
|
|
mov eax,impulse
|
|
imul bpInvMass3D[edi*4]
|
|
idiv massSum
|
|
mov changeB,eax
|
|
mov eax,changeA
|
|
imul nx
|
|
shrd eax,edx,16
|
|
sub bpPinX3D[esi*4],eax
|
|
mov eax,changeA
|
|
imul ny
|
|
shrd eax,edx,16
|
|
sub bpPinY3D[esi*4],eax
|
|
mov eax,changeB
|
|
imul nx
|
|
shrd eax,edx,16
|
|
add bpPinX3D[edi*4],eax
|
|
mov eax,changeB
|
|
imul ny
|
|
shrd eax,edx,16
|
|
add bpPinY3D[edi*4],eax
|
|
bp_contact_done:
|
|
ret
|
|
BowlingPlayContact3D ENDP
|
|
|
|
BowlingPlayStep3D PROC uses ebx esi edi
|
|
local substep:DWORD,rack:DWORD
|
|
mov esi,bpLane3D
|
|
mov eax,bwRack3D[esi*4]
|
|
or eax,1024
|
|
mov rack,eax
|
|
mov eax,bpBallX3D
|
|
mov bpPinX3D[40],eax
|
|
mov eax,bpBallY3D
|
|
mov bpPinY3D[40],eax
|
|
mov eax,bpBallVX3D
|
|
mov bpPinVX3D[40],eax
|
|
mov eax,bpBallVY3D
|
|
mov bpPinVY3D[40],eax
|
|
mov substep,0
|
|
bp_physics_substep:
|
|
xor esi,esi
|
|
bp_physics_integrate:
|
|
bt rack,esi
|
|
jnc bp_physics_integrate_next
|
|
mov eax,bpPinVX3D[esi*4]
|
|
sar eax,2
|
|
add bpPinX3D[esi*4],eax
|
|
mov eax,bpPinVY3D[esi*4]
|
|
sar eax,2
|
|
add bpPinY3D[esi*4],eax
|
|
cmp esi,10
|
|
jne bp_physics_integrate_next
|
|
cmp bpPinY3D[40],FP_1*28/10
|
|
jge @F
|
|
mov bpPinVX3D[40],0
|
|
mov bpPinVY3D[40],0
|
|
@@:
|
|
mov eax,bpPinX3D[40]
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,FP_1*74/100
|
|
jbe bp_physics_integrate_next
|
|
mov bpGutter3D,1
|
|
mov eax,FP_1*87/100
|
|
cmp bpPinX3D[40],0
|
|
jge @F
|
|
neg eax
|
|
@@:
|
|
mov bpPinX3D[40],eax
|
|
mov bpPinVX3D[40],0
|
|
bp_physics_integrate_next:
|
|
inc esi
|
|
cmp esi,BP_BODY_COUNT
|
|
jb bp_physics_integrate
|
|
xor esi,esi
|
|
bp_physics_pair_a:
|
|
bt rack,esi
|
|
jnc bp_physics_pair_next_a
|
|
lea edi,[esi+1]
|
|
bp_physics_pair_b:
|
|
bt rack,edi
|
|
jnc bp_physics_pair_next_b
|
|
cmp edi,10
|
|
jne @F
|
|
cmp bpGutter3D,0
|
|
jne bp_physics_pair_next_b
|
|
@@:
|
|
invoke BowlingPlayContact3D,esi,edi
|
|
bp_physics_pair_next_b:
|
|
inc edi
|
|
cmp edi,BP_BODY_COUNT
|
|
jb bp_physics_pair_b
|
|
bp_physics_pair_next_a:
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_physics_pair_a
|
|
xor esi,esi
|
|
bp_physics_substep_limits:
|
|
bt rack,esi
|
|
jnc @F
|
|
invoke BowlingPlayTether3D,esi
|
|
invoke BowlingPlayDeckBounds3D,esi
|
|
@@:
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_physics_substep_limits
|
|
inc substep
|
|
cmp substep,4
|
|
jb bp_physics_substep
|
|
xor esi,esi
|
|
bp_physics_pin:
|
|
bt rack,esi
|
|
jnc bp_physics_pin_next
|
|
mov ecx,246
|
|
mov eax,bpPhysicsTicks3D
|
|
sub eax,bpPinContactTick3D[esi*4]
|
|
cmp eax,10
|
|
jb @F
|
|
bt bpHitMask3D,esi
|
|
jnc @F
|
|
mov ecx,224
|
|
@@:
|
|
mov eax,bpPinVX3D[esi*4]
|
|
imul eax,ecx
|
|
sar eax,8
|
|
mov bpPinVX3D[esi*4],eax
|
|
mov eax,bpPinVY3D[esi*4]
|
|
imul eax,ecx
|
|
sar eax,8
|
|
mov bpPinVY3D[esi*4],eax
|
|
mov eax,bpPinTilt3D[esi*4]
|
|
cmp eax,24*256
|
|
jae bp_physics_topple
|
|
mov edx,eax
|
|
sar edx,6
|
|
sub bpPinTiltV3D[esi*4],edx
|
|
jmp bp_physics_tilt
|
|
bp_physics_topple:
|
|
add bpPinTiltV3D[esi*4],160
|
|
bp_physics_tilt:
|
|
mov edx,bpPinTiltV3D[esi*4]
|
|
imul edx,245
|
|
sar edx,8
|
|
mov bpPinTiltV3D[esi*4],edx
|
|
add eax,edx
|
|
test eax,eax
|
|
jns @F
|
|
xor eax,eax
|
|
mov bpPinTiltV3D[esi*4],0
|
|
@@:
|
|
cmp eax,128*256
|
|
jbe @F
|
|
mov eax,128*256
|
|
mov edx,bpPinTiltV3D[esi*4]
|
|
neg edx
|
|
sar edx,2
|
|
cmp edx,-80
|
|
jl bp_physics_bounce
|
|
xor edx,edx
|
|
bp_physics_bounce:
|
|
mov bpPinTiltV3D[esi*4],edx
|
|
@@:
|
|
mov bpPinTilt3D[esi*4],eax
|
|
cmp eax,64*256
|
|
jb bp_physics_pin_next
|
|
bts bpHitMask3D,esi
|
|
mov bpRadius3D[esi*4],48
|
|
; Slow rolling yaw, independent of the fall's vertical angle.
|
|
mov ecx,bpPinSpin3D[esi*4]
|
|
and ecx,511
|
|
mov eax,bpPinAxisX3D[esi*4]
|
|
imul tableCos[ecx*4]
|
|
shrd eax,edx,16
|
|
mov ebx,eax
|
|
mov eax,bpPinAxisY3D[esi*4]
|
|
imul tableSin[ecx*4]
|
|
shrd eax,edx,16
|
|
sub ebx,eax
|
|
mov eax,bpPinAxisX3D[esi*4]
|
|
imul tableSin[ecx*4]
|
|
shrd eax,edx,16
|
|
mov edi,eax
|
|
mov eax,bpPinAxisY3D[esi*4]
|
|
imul tableCos[ecx*4]
|
|
shrd eax,edx,16
|
|
add eax,edi
|
|
mov bpPinAxisY3D[esi*4],eax
|
|
mov bpPinAxisX3D[esi*4],ebx
|
|
invoke NormalizeBowlingPinAxis3D,esi
|
|
mov eax,bpPinSpin3D[esi*4]
|
|
imul eax,230
|
|
test eax,eax
|
|
jns @F
|
|
add eax,255
|
|
@@:
|
|
sar eax,8
|
|
mov bpPinSpin3D[esi*4],eax
|
|
bp_physics_pin_next:
|
|
bt rack,esi
|
|
jnc @F
|
|
invoke BowlingPlayTether3D,esi
|
|
invoke BowlingPlayDeckBounds3D,esi
|
|
@@:
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_physics_pin
|
|
mov eax,bpPinX3D[40]
|
|
mov bpBallX3D,eax
|
|
mov eax,bpPinY3D[40]
|
|
mov bpBallY3D,eax
|
|
mov eax,bpPinVX3D[40]
|
|
mov bpBallVX3D,eax
|
|
mov eax,bpPinVY3D[40]
|
|
mov bpBallVY3D,eax
|
|
inc bpPhysicsTicks3D
|
|
cmp bpBallY3D,3*FP_1
|
|
jge @F
|
|
inc bpEndTicks3D
|
|
@@:
|
|
ret
|
|
BowlingPlayStep3D ENDP
|
|
|
|
BowlingPlayReady3D PROC uses esi
|
|
cmp bpPhysicsTicks3D,900
|
|
jae bp_physics_ready
|
|
cmp bpEndTicks3D,100
|
|
jb bp_physics_not_ready
|
|
xor esi,esi
|
|
bp_physics_quiet:
|
|
mov eax,bpPinVX3D[esi*4]
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,96
|
|
ja bp_physics_not_ready
|
|
mov eax,bpPinTilt3D[esi*4]
|
|
cmp eax,128*256
|
|
jae @F
|
|
cmp eax,24*256
|
|
jae bp_physics_not_ready
|
|
mov eax,bpPinTiltV3D[esi*4]
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,32
|
|
ja bp_physics_not_ready
|
|
@@:
|
|
mov eax,bpPinVY3D[esi*4]
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,96
|
|
ja bp_physics_not_ready
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_physics_quiet
|
|
bp_physics_ready:
|
|
mov eax,1
|
|
ret
|
|
bp_physics_not_ready:
|
|
xor eax,eax
|
|
ret
|
|
BowlingPlayReady3D ENDP
|