- 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
459 lines
10 KiB
PHP
459 lines
10 KiB
PHP
; A small native marble surface avoids shipping a second copy of a ball sprite.
|
|
InitBowlingBallSurface3D PROC uses ebx esi edi
|
|
local stripe:DWORD
|
|
xor esi,esi
|
|
lea edi,bpBallSurface3D
|
|
bp_ball_tex_row:
|
|
xor ebx,ebx
|
|
bp_ball_tex_pixel:
|
|
mov eax,esi
|
|
shl eax,3
|
|
and eax,511
|
|
mov eax,tableSin[eax*4]
|
|
sar eax,11
|
|
lea eax,[eax+ebx*8]
|
|
and eax,511
|
|
mov eax,tableSin[eax*4]
|
|
add eax,FP_1
|
|
shr eax,12
|
|
mov stripe,eax
|
|
lea edx,[eax+5]
|
|
shl edx,16
|
|
lea eax,[eax*2+48]
|
|
shl eax,8
|
|
or edx,eax
|
|
mov eax,stripe
|
|
shl eax,1
|
|
add eax,155
|
|
or eax,edx
|
|
or eax,0FF000000h
|
|
stosd
|
|
inc ebx
|
|
cmp ebx,64
|
|
jb bp_ball_tex_pixel
|
|
inc esi
|
|
cmp esi,64
|
|
jb bp_ball_tex_row
|
|
ret
|
|
InitBowlingBallSurface3D ENDP
|
|
|
|
DrawBowlingPlayPin3D PROC uses ebx esi edi pin:DWORD,centre:DWORD
|
|
local x:DWORD,y:DWORD,z:DWORD,headY:DWORD,ry:DWORD,rz:DWORD
|
|
mov esi,pin
|
|
mov ecx,esi
|
|
mov ebx,1
|
|
shl ebx,cl
|
|
mov edi,bpLane3D
|
|
test bwRack3D[edi*4],ebx
|
|
jz bp_pin_done
|
|
mov eax,bpPinX3D[esi*4]
|
|
add eax,centre
|
|
mov x,eax
|
|
mov eax,bpPinY3D[esi*4]
|
|
mov y,eax
|
|
mov headY,eax
|
|
mov z,FP_1*15/100
|
|
mov ry,FP_1/10
|
|
mov rz,FP_1*13/100
|
|
test bpHitMask3D,ebx
|
|
jz bp_pin_draw
|
|
mov z,FP_1*7/100
|
|
mov ry,FP_1*23/100
|
|
mov rz,FP_1*6/100
|
|
sub headY,FP_1/4
|
|
bp_pin_draw:
|
|
invoke DrawRoofEllipsoid3D,x,y,z,FP_1/10,ry,rz,239
|
|
mov eax,FP_1*34/100
|
|
test bpHitMask3D,ebx
|
|
jz @F
|
|
mov eax,FP_1*7/100
|
|
@@:
|
|
invoke DrawRoofEllipsoid3D,x,headY,eax,FP_1*65/1000,FP_1*65/1000,FP_1*6/100,239
|
|
mov eax,z
|
|
add eax,rz
|
|
invoke DrawRoofEllipsoid3D,x,headY,eax,FP_1*45/1000,FP_1*45/1000,FP_1*25/1000,240
|
|
bp_pin_done:
|
|
ret
|
|
DrawBowlingPlayPin3D ENDP
|
|
|
|
; A frame's cumulative score stays unresolved until all its bonuses are known.
|
|
BowlingFrameTotal3D PROC uses ebx esi edi owner:DWORD,wanted:DWORD
|
|
local total:DWORD,index:DWORD,available:DWORD,current:DWORD
|
|
mov ebx,owner
|
|
mov eax,bwRollCount3D[ebx*4]
|
|
mov available,eax
|
|
imul ebx,96
|
|
lea esi,bwRolls3D[ebx]
|
|
mov index,0
|
|
mov current,0
|
|
mov total,0
|
|
bp_frame_loop:
|
|
mov edi,index
|
|
cmp edi,available
|
|
jae bp_frame_pending
|
|
mov eax,[esi+edi*4]
|
|
mov ebx,eax
|
|
inc edi
|
|
cmp edi,available
|
|
jae bp_frame_pending
|
|
add eax,[esi+edi*4]
|
|
inc edi
|
|
cmp ebx,10
|
|
je bp_frame_bonus
|
|
cmp eax,10
|
|
jne bp_frame_open
|
|
bp_frame_bonus:
|
|
cmp edi,available
|
|
jae bp_frame_pending
|
|
add eax,[esi+edi*4]
|
|
bp_frame_open:
|
|
add total,eax
|
|
cmp ebx,10
|
|
jne @F
|
|
dec edi
|
|
@@:
|
|
mov index,edi
|
|
mov eax,current
|
|
cmp eax,wanted
|
|
je bp_frame_ready
|
|
inc current
|
|
jmp bp_frame_loop
|
|
bp_frame_ready:
|
|
mov eax,total
|
|
ret
|
|
bp_frame_pending:
|
|
mov eax,-1
|
|
ret
|
|
BowlingFrameTotal3D ENDP
|
|
|
|
DrawBowlingPlayScores3D PROC uses ebx esi edi
|
|
local x:DWORD,y:DWORD,owner:DWORD
|
|
invoke DrawBoxBorder,4,47,312,139,00151F26h,005BC9BEh,1
|
|
invoke DrawString8x8,12,55,OFFSET bpScoreText,00E8D7ADh
|
|
xor esi,esi
|
|
bp_score_heading:
|
|
imul eax,esi,26
|
|
add eax,44
|
|
mov x,eax
|
|
lea eax,[esi+1]
|
|
invoke FormatNumber,eax,OFFSET bpText3D
|
|
invoke DrawString8x8,x,73,OFFSET bpText3D,00AABDB6h
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_score_heading
|
|
xor edi,edi
|
|
bp_score_owner:
|
|
lea eax,[edi*2]
|
|
imul eax,18
|
|
add eax,96
|
|
mov y,eax
|
|
mov eax,OFFSET bpYou
|
|
test edi,edi
|
|
jz @F
|
|
mov eax,OFFSET bpBot
|
|
@@:
|
|
invoke DrawString8x8,9,y,eax,005BC9BEh
|
|
mov eax,bpLane3D
|
|
shl eax,1
|
|
add eax,edi
|
|
mov owner,eax
|
|
xor esi,esi
|
|
bp_score_cell:
|
|
imul eax,esi,26
|
|
add eax,44
|
|
mov x,eax
|
|
invoke BowlingFrameTotal3D,owner,esi
|
|
cmp eax,-1
|
|
je bp_score_empty
|
|
invoke FormatNumber,eax,OFFSET bpText3D
|
|
invoke DrawString8x8,x,y,OFFSET bpText3D,00FFFFFFh
|
|
jmp bp_score_next
|
|
bp_score_empty:
|
|
invoke DrawBox,x,y,8,1,005C727Bh
|
|
bp_score_next:
|
|
inc esi
|
|
cmp esi,10
|
|
jb bp_score_cell
|
|
inc edi
|
|
cmp edi,2
|
|
jb bp_score_owner
|
|
ret
|
|
DrawBowlingPlayScores3D ENDP
|
|
|
|
DrawBowlingGaugeLine3D PROC uses ebx esi edi x0:DWORD,y0:DWORD,x1:DWORD,y1:DWORD
|
|
local px:DWORD,py:DWORD,stepX:DWORD,stepY:DWORD
|
|
mov eax,x1
|
|
sub eax,x0
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
mov ebx,eax
|
|
mov eax,y1
|
|
sub eax,y0
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,ebx
|
|
jbe @F
|
|
mov ebx,eax
|
|
@@:
|
|
test ebx,ebx
|
|
jnz @F
|
|
inc ebx
|
|
@@:
|
|
mov eax,x1
|
|
sub eax,x0
|
|
shl eax,16
|
|
cdq
|
|
idiv ebx
|
|
mov stepX,eax
|
|
mov eax,y1
|
|
sub eax,y0
|
|
shl eax,16
|
|
cdq
|
|
idiv ebx
|
|
mov stepY,eax
|
|
mov eax,x0
|
|
shl eax,16
|
|
mov px,eax
|
|
mov eax,y0
|
|
shl eax,16
|
|
mov py,eax
|
|
inc ebx
|
|
bp_gauge_line:
|
|
mov eax,px
|
|
sar eax,16
|
|
mov edx,py
|
|
sar edx,16
|
|
invoke DrawBox,eax,edx,1,1,00D8F5B7h
|
|
mov eax,stepX
|
|
add px,eax
|
|
mov eax,stepY
|
|
add py,eax
|
|
dec ebx
|
|
jnz bp_gauge_line
|
|
ret
|
|
DrawBowlingGaugeLine3D ENDP
|
|
|
|
RenderBowlingPlay3D PROC uses ebx esi edi
|
|
local x:DWORD,y:DWORD,color:DWORD,owner:DWORD,startY:DWORD
|
|
mov eax,bpCentre3D
|
|
mov playerX,eax
|
|
mov startY,FP_1*252/10
|
|
mov esi,bpLane3D
|
|
cmp bwTurn3D[esi*4],0
|
|
je @F
|
|
mov startY,FP_1*264/10
|
|
@@:
|
|
mov eax,startY
|
|
mov playerY,eax
|
|
mov playerAngle,384
|
|
call BowlingEye3D
|
|
cmp bpState3D,BP_ROLL
|
|
je bp_camera_follow
|
|
cmp bpState3D,BP_SETTLE
|
|
jne bp_camera_ready
|
|
bp_camera_follow:
|
|
mov eax,bpBallY3D
|
|
add eax,FP_1*27/10
|
|
cmp eax,7*FP_1
|
|
jge @F
|
|
mov eax,7*FP_1
|
|
@@:
|
|
mov playerY,eax
|
|
mov viewEye3D,FP_1*7/10
|
|
cmp bpState3D,BP_ROLL
|
|
jne bp_camera_ready
|
|
mov ebx,bpTime3D
|
|
cmp ebx,500
|
|
jae bp_camera_ready
|
|
sub eax,startY
|
|
imul eax,ebx
|
|
cdq
|
|
mov ecx,500
|
|
idiv ecx
|
|
add eax,startY
|
|
mov playerY,eax
|
|
imul eax,ebx,FP_1*7/20
|
|
cdq
|
|
idiv ecx
|
|
mov edx,HALL_STANDING_EYE
|
|
sub edx,eax
|
|
mov viewEye3D,edx
|
|
bp_camera_ready:
|
|
call UpdateCamera3D
|
|
call RenderBowling3D
|
|
mov esi,bpLane3D
|
|
cmp bwTurn3D[esi*4],1
|
|
jne bp_render_ball
|
|
cmp bpState3D,BP_BOT
|
|
je bp_render_bot_ready
|
|
cmp bpState3D,BP_RELEASE
|
|
je bp_render_bot_throw
|
|
cmp bpState3D,BP_ROLL
|
|
jne bp_render_ball
|
|
invoke ConfigureCharacter3D,OFFSET bwActor3D,6,CAST_THROW,2300,0,-FP_1
|
|
jmp bp_render_bot_draw
|
|
bp_render_bot_throw:
|
|
invoke ConfigureCharacter3D,OFFSET bwActor3D,6,CAST_THROW,bpTime3D,0,-FP_1
|
|
jmp bp_render_bot_draw
|
|
bp_render_bot_ready:
|
|
invoke ConfigureCharacter3D,OFFSET bwActor3D,6,CAST_IDLE,bpTime3D,0,0
|
|
bp_render_bot_draw:
|
|
mov eax,bpCentre3D
|
|
add eax,FP_1*38/100
|
|
mov bwActor3D.posX,eax
|
|
mov bwActor3D.posY,FP_1*235/10
|
|
invoke DrawCityObject3D,OFFSET bwActor3D,0
|
|
bp_render_ball:
|
|
cmp bpState3D,BP_FINISHED
|
|
je bp_render_hud
|
|
mov eax,bpBallX3D
|
|
add eax,bpCentre3D
|
|
invoke DrawBowlingBall3D,eax,bpBallY3D,253
|
|
bp_render_hud:
|
|
invoke DrawBox,0,0,320,17,00121B20h
|
|
invoke DrawString8x8,8,4,OFFSET bpTitle,00E8D7ADh
|
|
mov eax,bpLane3D
|
|
shl eax,1
|
|
mov owner,eax
|
|
mov esi,eax
|
|
invoke DrawString8x8,100,4,OFFSET bpYou,005BC9BEh
|
|
invoke FormatNumber,bwScores3D[esi*4],OFFSET bpText3D
|
|
invoke DrawString8x8,126,4,OFFSET bpText3D,00FFFFFFh
|
|
invoke DrawString8x8,205,4,OFFSET bpBot,00E8D7ADh
|
|
invoke FormatNumber,bwScores3D[esi*4+4],OFFSET bpText3D
|
|
invoke DrawString8x8,248,4,OFFSET bpText3D,00FFFFFFh
|
|
invoke DrawBox,0,221,320,19,00121B20h
|
|
invoke DrawString8x8,268,227,OFFSET bpExitText,00E8D7ADh
|
|
mov esi,bpLane3D
|
|
mov eax,bwTurn3D[esi*4]
|
|
add owner,eax
|
|
mov eax,OFFSET bpYou
|
|
cmp bwTurn3D[esi*4],0
|
|
je @F
|
|
mov eax,OFFSET bpBot
|
|
@@:
|
|
invoke DrawString8x8,8,227,eax,005BC9BEh
|
|
mov ebx,owner
|
|
mov eax,bwFrames3D[ebx*4]
|
|
cmp bpState3D,BP_SETTLE
|
|
jne @F
|
|
cmp bwFrameDone3D[esi*4],0
|
|
je @F
|
|
dec eax
|
|
@@:
|
|
inc eax
|
|
cmp eax,10
|
|
jbe @F
|
|
mov eax,10
|
|
@@:
|
|
invoke FormatNumber,eax,OFFSET bpText3D
|
|
invoke DrawString8x8,60,227,OFFSET bpFrameText,00AABDB6h
|
|
invoke DrawString8x8,116,227,OFFSET bpText3D,00FFFFFFh
|
|
cmp bpState3D,BP_DIRECTION
|
|
je bp_render_direction
|
|
cmp bpState3D,BP_POWER
|
|
je bp_render_power
|
|
cmp bpState3D,BP_SETTLE
|
|
je bp_render_result
|
|
cmp bpState3D,BP_FINISHED
|
|
je bp_render_finished
|
|
invoke DrawString8x8,8,204,OFFSET bpRollText,00E8D7ADh
|
|
jmp bp_render_done
|
|
bp_render_direction:
|
|
invoke DrawString8x8,108,145,OFFSET bpDirectionText,00E8D7ADh
|
|
xor esi,esi
|
|
bp_render_arc:
|
|
lea eax,[esi-70]
|
|
imul eax,eax
|
|
xor edx,edx
|
|
mov ecx,380
|
|
div ecx
|
|
add eax,169
|
|
mov y,eax
|
|
mov color,00D67057h
|
|
cmp esi,27
|
|
jb @F
|
|
cmp esi,113
|
|
ja @F
|
|
mov color,00E7C455h
|
|
cmp esi,59
|
|
jb @F
|
|
cmp esi,81
|
|
ja @F
|
|
mov color,005BC98Ch
|
|
@@:
|
|
lea eax,[esi+90]
|
|
invoke DrawBox,eax,y,1,6,color
|
|
inc esi
|
|
cmp esi,141
|
|
jb bp_render_arc
|
|
mov eax,bpAim3D
|
|
imul eax,52
|
|
sar eax,16
|
|
add eax,160
|
|
mov x,eax
|
|
invoke DrawBowlingGaugeLine3D,160,205,eax,162
|
|
mov eax,x
|
|
lea ebx,[eax-5]
|
|
invoke DrawBowlingGaugeLine3D,eax,162,ebx,168
|
|
mov eax,x
|
|
lea ebx,[eax+5]
|
|
invoke DrawBowlingGaugeLine3D,eax,162,ebx,168
|
|
jmp bp_render_done
|
|
bp_render_power:
|
|
invoke DrawString8x8,246,62,OFFSET bpPowerText,00E8D7ADh
|
|
invoke DrawBoxBorder,276,79,13,124,00121B20h,00AABDB6h,1
|
|
invoke DrawBox,278,82,9,118,00D67057h
|
|
invoke DrawBox,278,128,9,38,00E7C455h
|
|
invoke DrawBox,278,82,9,46,005BC98Ch
|
|
mov eax,bpPower3D
|
|
imul eax,116
|
|
xor edx,edx
|
|
mov ecx,100
|
|
div ecx
|
|
mov edx,198
|
|
sub edx,eax
|
|
mov y,edx
|
|
invoke DrawBox,270,y,25,2,00FFFFFFh
|
|
invoke FormatNumber,bpPower3D,OFFSET bpText3D
|
|
invoke DrawString8x8,246,180,OFFSET bpText3D,00FFFFFFh
|
|
jmp bp_render_done
|
|
bp_render_result:
|
|
mov eax,OFFSET bpResultText
|
|
cmp bpGutter3D,0
|
|
je @F
|
|
mov eax,OFFSET bpGutterText
|
|
@@:
|
|
cmp bpLastKind3D,1
|
|
jne @F
|
|
mov eax,OFFSET bpStrikeText
|
|
@@:
|
|
cmp bpLastKind3D,2
|
|
jne @F
|
|
mov eax,OFFSET bpSpareText
|
|
@@:
|
|
invoke DrawString8x8,104,197,eax,00E8D7ADh
|
|
invoke FormatNumber,bpLast3D,OFFSET bpText3D
|
|
invoke DrawString8x8,192,197,OFFSET bpText3D,00FFFFFFh
|
|
jmp bp_render_done
|
|
bp_render_finished:
|
|
mov eax,bwScores3D[esi*8]
|
|
mov ebx,OFFSET bpDrawText
|
|
cmp eax,bwScores3D[esi*8+4]
|
|
je @F
|
|
mov ebx,OFFSET bpWinText
|
|
ja @F
|
|
mov ebx,OFFSET bpLoseText
|
|
@@:
|
|
invoke DrawBoxBorder,72,150,176,58,00121B20h,005BC9BEh,1
|
|
invoke DrawString8x8,88,161,ebx,00E8D7ADh
|
|
invoke DrawString8x8,136,187,OFFSET bpAgainText,00FFFFFFh
|
|
bp_render_done:
|
|
cmp bpScoreOpen3D,0
|
|
je @F
|
|
call DrawBowlingPlayScores3D
|
|
@@:
|
|
ret
|
|
RenderBowlingPlay3D ENDP
|