- 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
388 lines
8.8 KiB
PHP
388 lines
8.8 KiB
PHP
BowlingApplyBallMass3D PROC uses esi
|
|
mov esi,bpLane3D
|
|
mov eax,bpWeightKg3D
|
|
cmp bwTurn3D[esi*4],0
|
|
je @F
|
|
mov eax,bpBotWeightKg3D
|
|
@@:
|
|
cmp eax,4
|
|
jae @F
|
|
mov eax,4
|
|
@@:
|
|
cmp eax,7
|
|
jbe @F
|
|
mov eax,7
|
|
@@:
|
|
mov bpShotWeightKg3D,eax
|
|
imul eax,1000
|
|
mov bpBallGrams3D,eax
|
|
mov ecx,eax
|
|
mov eax,BP_PIN_GRAMS*FP_1
|
|
xor edx,edx
|
|
div ecx
|
|
mov bpInvMass3D[BP_BALL_BODY*4],eax
|
|
ret
|
|
BowlingApplyBallMass3D ENDP
|
|
|
|
; Selection consumes its own event, never the direction-lock/throw event.
|
|
HandleBowlingWeight3D PROC uses ebx esi mousePress:DWORD
|
|
xor esi,esi
|
|
bp_weight_key:
|
|
lea eax,[esi+31h]
|
|
invoke Pressed3D,eax
|
|
test eax,eax
|
|
jnz bp_weight_choose
|
|
inc esi
|
|
cmp esi,4
|
|
jb bp_weight_key
|
|
cmp mousePress,0
|
|
je bp_weight_no
|
|
cmp bpState3D,BP_SELECT_BALL
|
|
je bp_weight_rack_hit
|
|
cmp mouseY3D,26
|
|
jb bp_weight_no
|
|
cmp mouseY3D,44
|
|
jae bp_weight_no
|
|
cmp mouseX3D,8
|
|
jb bp_weight_no
|
|
cmp mouseX3D,96
|
|
jae bp_weight_no
|
|
mov bpState3D,BP_SELECT_BALL
|
|
mov eax,1
|
|
ret
|
|
bp_weight_rack_hit:
|
|
call BowlingRackCamera3D
|
|
call UpdateCamera3D
|
|
xor esi,esi
|
|
bp_weight_hit:
|
|
invoke BowlingRackScreen3D,esi
|
|
mov eax,mouseX3D
|
|
sub eax,bpRackHitX3D[esi*4]
|
|
imul eax,eax
|
|
mov ebx,eax
|
|
mov eax,mouseY3D
|
|
sub eax,bpRackHitY3D[esi*4]
|
|
imul eax,eax
|
|
add ebx,eax
|
|
mov eax,bpRackHitRadius3D[esi*4]
|
|
add eax,2
|
|
imul eax,eax
|
|
cmp ebx,eax
|
|
jbe bp_weight_choose
|
|
mov eax,bpRackHitX3D[esi*4]
|
|
sub eax,18
|
|
cmp mouseX3D,eax
|
|
jb bp_weight_hit_next
|
|
add eax,36
|
|
cmp mouseX3D,eax
|
|
jae bp_weight_hit_next
|
|
mov eax,bpRackHitY3D[esi*4]
|
|
add eax,bpRackHitRadius3D[esi*4]
|
|
add eax,2
|
|
cmp mouseY3D,eax
|
|
jb bp_weight_hit_next
|
|
add eax,14
|
|
cmp mouseY3D,eax
|
|
jb bp_weight_choose
|
|
bp_weight_hit_next:
|
|
inc esi
|
|
cmp esi,4
|
|
jb bp_weight_hit
|
|
; Ignore clicks on the floor instead of accidentally locking the direction.
|
|
cmp mouseY3D,193
|
|
jb bp_weight_rack_consumed
|
|
cmp mouseY3D,213
|
|
jae bp_weight_rack_consumed
|
|
cmp mouseX3D,128
|
|
jb bp_weight_rack_consumed
|
|
cmp mouseX3D,192
|
|
jae bp_weight_rack_consumed
|
|
mov bpState3D,BP_DIRECTION
|
|
bp_weight_rack_consumed:
|
|
mov eax,1
|
|
ret
|
|
bp_weight_no:
|
|
xor eax,eax
|
|
ret
|
|
bp_weight_choose:
|
|
lea eax,[esi+4]
|
|
mov bpWeightKg3D,eax
|
|
mov bpState3D,BP_DIRECTION
|
|
mov eax,1
|
|
ret
|
|
HandleBowlingWeight3D ENDP
|
|
|
|
DrawBowlingWeight3D PROC uses ebx esi edi
|
|
local x:DWORD,y:DWORD,edge:DWORD
|
|
cmp bpScoreOpen3D,0
|
|
jne bp_weight_draw_done
|
|
cmp bpState3D,BP_SELECT_BALL
|
|
jne bp_weight_locked_label
|
|
invoke DrawString8x8,120,32,OFFSET bpSelectBallText,00E8D7ADh
|
|
xor esi,esi
|
|
bp_weight_rack_label:
|
|
invoke BowlingRackScreen3D,esi
|
|
mov eax,bpRackHitX3D[esi*4]
|
|
sub eax,18
|
|
mov x,eax
|
|
mov eax,bpRackHitY3D[esi*4]
|
|
add eax,bpRackHitRadius3D[esi*4]
|
|
add eax,2
|
|
mov y,eax
|
|
mov edge,003C4D53h
|
|
lea eax,[esi+4]
|
|
cmp eax,bpWeightKg3D
|
|
jne @F
|
|
mov eax,bpBallColors3D[esi*4]
|
|
mov edge,eax
|
|
@@:
|
|
invoke DrawBoxBorder,x,y,36,14,00121B20h,edge,1
|
|
mov eax,x
|
|
add eax,2
|
|
mov ebx,y
|
|
add ebx,3
|
|
invoke DrawString8x8,eax,ebx,bpWeightLabels3D[esi*4],00FFFFFFh
|
|
inc esi
|
|
cmp esi,4
|
|
jb bp_weight_rack_label
|
|
invoke DrawBoxBorder,128,193,64,20,00121B20h,005BC9BEh,1
|
|
invoke DrawString8x8,136,199,OFFSET bpTakeBallText,00FFFFFFh
|
|
ret
|
|
bp_weight_locked_label:
|
|
mov eax,bpShotWeightKg3D
|
|
cmp bpState3D,BP_DIRECTION
|
|
je bp_weight_selected_label
|
|
cmp bpState3D,BP_POWER
|
|
jne @F
|
|
bp_weight_selected_label:
|
|
mov eax,bpWeightKg3D
|
|
@@:
|
|
cmp bpState3D,BP_BOT
|
|
jne @F
|
|
mov eax,bpBotWeightKg3D
|
|
@@:
|
|
mov esi,eax
|
|
invoke FormatNumber,eax,OFFSET bpText3D
|
|
invoke AppendCString,OFFSET bpText3D,OFFSET bpKilogramsText
|
|
sub esi,4
|
|
cmp esi,3
|
|
ja bp_weight_draw_done
|
|
mov eax,bpBallColors3D[esi*4]
|
|
mov edge,eax
|
|
cmp bpState3D,BP_DIRECTION
|
|
jne bp_weight_static_label
|
|
invoke DrawBoxBorder,8,26,88,18,00121B20h,edge,1
|
|
invoke DrawString8x8,14,31,OFFSET bpChangeBallText,00E8D7ADh
|
|
invoke DrawString8x8,50,31,OFFSET bpText3D,00FFFFFFh
|
|
ret
|
|
bp_weight_static_label:
|
|
invoke DrawBox,8,27,5,7,edge
|
|
invoke DrawString8x8,18,26,OFFSET bpText3D,00E8D7ADh
|
|
bp_weight_draw_done:
|
|
ret
|
|
DrawBowlingWeight3D ENDP
|
|
|
|
BowlingBallMaterial3D PROC kg:DWORD
|
|
mov eax,kg
|
|
sub eax,4
|
|
cmp eax,3
|
|
jbe @F
|
|
mov eax,2
|
|
@@:
|
|
mov eax,bpBallMaterials3D[eax*4]
|
|
ret
|
|
BowlingBallMaterial3D ENDP
|
|
|
|
BowlingRackCamera3D PROC
|
|
mov eax,bpLane3D
|
|
shr eax,1
|
|
imul eax,FP_1*38/10
|
|
add eax,FP_1*585/100
|
|
mov playerX,eax
|
|
mov playerY,FP_1*2583/100
|
|
mov playerAngle,256
|
|
mov viewEye3D,FP_1*102/100
|
|
ret
|
|
BowlingRackCamera3D ENDP
|
|
|
|
; Labels and picking share the actual world projection, not guessed UI slots.
|
|
BowlingRackScreen3D PROC uses ebx esi index:DWORD
|
|
mov esi,index
|
|
imul ebx,esi,-FP_1*245/1000
|
|
add ebx,FP_1*262/10
|
|
mov eax,playerX
|
|
sub eax,FP_1*135/100
|
|
invoke ProjectCityPoint3D,eax,ebx
|
|
sar eax,1
|
|
mov bpRackHitX3D[esi*4],eax
|
|
mov ebx,edx
|
|
mov eax,viewEye3D
|
|
sub eax,FP_1*84/100
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv ebx
|
|
add eax,viewHorizon3D
|
|
sar eax,1
|
|
mov bpRackHitY3D[esi*4],eax
|
|
mov eax,FP_1*12/100*SCREEN_H
|
|
cdq
|
|
idiv ebx
|
|
shr eax,1
|
|
mov bpRackHitRadius3D[esi*4],eax
|
|
ret
|
|
BowlingRackScreen3D ENDP
|
|
|
|
RenderBowlingBallRack3D PROC uses ebx esi edi centre:DWORD,pairIndex:DWORD
|
|
local lo:DWORD,hi:DWORD,x:DWORD,y:DWORD
|
|
; Storage runs lengthwise, alongside (not across) the clear return track.
|
|
mov eax,centre
|
|
add eax,FP_1*43/100
|
|
mov lo,eax
|
|
add eax,FP_1*4/100
|
|
mov hi,eax
|
|
invoke DrawRoofSolid3D,lo,hi,FP_1*253/10,FP_1*264/10,FP_1*70/100,FP_1*75/100,238
|
|
add lo,FP_1*20/100
|
|
add hi,FP_1*20/100
|
|
invoke DrawRoofSolid3D,lo,hi,FP_1*253/10,FP_1*264/10,FP_1*70/100,FP_1*75/100,238
|
|
mov eax,centre
|
|
add eax,FP_1*35/100
|
|
mov lo,eax
|
|
add eax,FP_1*40/100
|
|
mov hi,eax
|
|
invoke DrawRoofSolid3D,lo,hi,FP_1*253/10,FP_1*2538/100,FP_1*6/100,FP_1*73/100,254
|
|
invoke DrawRoofSolid3D,lo,hi,FP_1*2632/100,FP_1*264/10,FP_1*6/100,FP_1*73/100,254
|
|
xor esi,esi
|
|
bp_rack_stock:
|
|
cmp bpActive3D,0
|
|
je bp_rack_stock_draw
|
|
mov eax,bpLane3D
|
|
shr eax,1
|
|
cmp eax,pairIndex
|
|
jne bp_rack_stock_draw
|
|
cmp bpState3D,BP_SELECT_BALL
|
|
je bp_rack_stock_draw
|
|
mov eax,bpWeightKg3D
|
|
cmp bpState3D,BP_DIRECTION
|
|
je @F
|
|
cmp bpState3D,BP_POWER
|
|
je @F
|
|
mov eax,bpShotWeightKg3D
|
|
@@:
|
|
sub eax,4
|
|
cmp eax,esi
|
|
je bp_rack_stock_next
|
|
bp_rack_stock_draw:
|
|
mov eax,centre
|
|
add eax,FP_1*55/100
|
|
mov x,eax
|
|
imul eax,esi,-FP_1*245/1000
|
|
add eax,FP_1*262/10
|
|
mov y,eax
|
|
invoke DrawBowlingBallAt3D,x,y,FP_1*84/100,bpBallMaterials3D[esi*4],45
|
|
bp_rack_stock_next:
|
|
inc esi
|
|
cmp esi,4
|
|
jb bp_rack_stock
|
|
ret
|
|
RenderBowlingBallRack3D ENDP
|
|
|
|
; Reuse the blue marble's luminance; only its hue changes. Preserve alpha.
|
|
BowlingTintBallPixel3D PROC uses ebx ecx pixel:DWORD,kg:DWORD
|
|
mov eax,pixel
|
|
cmp kg,6
|
|
je bp_tint_done
|
|
mov ebx,eax
|
|
and ebx,255
|
|
mov ecx,eax
|
|
shr ecx,16
|
|
and ecx,255
|
|
and eax,0FF00FF00h
|
|
cmp kg,4
|
|
jne @F
|
|
mov edx,pixel
|
|
shr edx,8
|
|
and edx,255
|
|
shl ebx,8
|
|
and eax,0FFFF00FFh
|
|
or eax,ebx
|
|
or eax,edx
|
|
shl ecx,16
|
|
or eax,ecx
|
|
ret
|
|
@@:
|
|
or eax,ecx
|
|
cmp kg,5
|
|
jne bp_tint_gold
|
|
mov edx,eax
|
|
and edx,0000FF00h
|
|
shr edx,1
|
|
and edx,0000FF00h
|
|
and eax,0FFFF00FFh
|
|
or eax,edx
|
|
bp_tint_gold:
|
|
cmp kg,7
|
|
jne @F
|
|
mov edx,pixel
|
|
shr edx,8
|
|
and edx,255
|
|
add edx,ebx
|
|
shr edx,1
|
|
shl edx,8
|
|
and eax,0FFFF00FFh
|
|
or eax,edx
|
|
@@:
|
|
shl ebx,16
|
|
or eax,ebx
|
|
bp_tint_done:
|
|
ret
|
|
BowlingTintBallPixel3D ENDP
|
|
|
|
; A cached single-frame scratch pack keeps skin, sleeve and source assets intact.
|
|
BowlingTintHand3D PROC uses ebx esi edi frame:DWORD,kg:DWORD
|
|
mov eax,frame
|
|
cmp eax,bpRackHandFrame3D
|
|
jne bp_tint_hand_build
|
|
mov eax,kg
|
|
cmp eax,bpRackHandKg3D
|
|
je bp_tint_hand_done
|
|
bp_tint_hand_build:
|
|
mov eax,frame
|
|
mov bpRackHandFrame3D,eax
|
|
shl eax,18
|
|
add eax,bpHandArt3D.pixels
|
|
mov esi,eax
|
|
mov eax,kg
|
|
mov bpRackHandKg3D,eax
|
|
lea edi,bpTintedHandPixels3D
|
|
mov ebx,256*256
|
|
bp_tint_hand_pixel:
|
|
lodsd
|
|
cmp kg,6
|
|
je bp_tint_hand_store
|
|
mov edx,eax
|
|
and edx,255
|
|
mov ecx,eax
|
|
shr ecx,8
|
|
and ecx,255
|
|
add ecx,24
|
|
cmp edx,ecx
|
|
jbe bp_tint_hand_store
|
|
mov ecx,eax
|
|
shr ecx,16
|
|
and ecx,255
|
|
add ecx,24
|
|
cmp edx,ecx
|
|
jbe bp_tint_hand_store
|
|
invoke BowlingTintBallPixel3D,eax,kg
|
|
bp_tint_hand_store:
|
|
stosd
|
|
dec ebx
|
|
jnz bp_tint_hand_pixel
|
|
mov bpTintedHand3D.imageWidth,256
|
|
mov bpTintedHand3D.height,256
|
|
mov bpTintedHand3D.frames,1
|
|
mov bpTintedHand3D.bytes,256*256*4
|
|
mov bpTintedHand3D.pixels,OFFSET bpTintedHandPixels3D
|
|
bp_tint_hand_done:
|
|
ret
|
|
BowlingTintHand3D ENDP
|