; One immutable hit point drives scoring, dart geometry and the follow camera. .code LoadDarts3D PROC invoke LoadAnimPack3D,OFFSET dtBoard3D,OFFSET dtBoardPath test eax,eax jz dt_load_fail cmp dtBoard3D.imageWidth,512 jne dt_load_fail cmp dtBoard3D.height,512 jne dt_load_fail cmp dtBoard3D.frames,1 jne dt_load_fail invoke LoadAnimPack3D,OFFSET dtHands3D,OFFSET dtHandsPath test eax,eax jz dt_load_fail cmp dtHands3D.imageWidth,256 jne dt_load_fail cmp dtHands3D.height,256 jne dt_load_fail cmp dtHands3D.frames,16 jne dt_load_fail invoke LoadAnimPack3D,OFFSET dtDart3D,OFFSET dtDartPath test eax,eax jz dt_load_fail cmp dtDart3D.imageWidth,256 jne dt_load_fail cmp dtDart3D.height,256 jne dt_load_fail cmp dtDart3D.frames,16 jne dt_load_fail invoke LoadAnimPack3D,OFFSET dtWall3D,OFFSET dtWallPath test eax,eax jz dt_load_fail cmp dtWall3D.imageWidth,512 jne dt_load_fail cmp dtWall3D.height,512 jne dt_load_fail cmp dtWall3D.frames,1 jne dt_load_fail invoke LoadAnimPack3D,OFFSET dtChair3D,OFFSET dtChairPath test eax,eax jz dt_load_fail invoke LoadAnimPack3D,OFFSET dtTable3D,OFFSET dtTablePath test eax,eax jz dt_load_fail invoke LoadAnimPack3D,OFFSET dtRoom3D,OFFSET dtRoomPath test eax,eax jz dt_load_fail cmp dtRoom3D.imageWidth,256 jne dt_load_fail cmp dtRoom3D.height,256 jne dt_load_fail cmp dtRoom3D.frames,12 jne dt_load_fail mov eax,1 ret dt_load_fail: call FreeDarts3D xor eax,eax ret LoadDarts3D ENDP FreeDarts3D PROC invoke FreeAnimPack3D,OFFSET dtBoard3D invoke FreeAnimPack3D,OFFSET dtHands3D invoke FreeAnimPack3D,OFFSET dtDart3D invoke FreeAnimPack3D,OFFSET dtWall3D invoke FreeAnimPack3D,OFFSET dtChair3D invoke FreeAnimPack3D,OFFSET dtTable3D invoke FreeAnimPack3D,OFFSET dtRoom3D ret FreeDarts3D ENDP ResetDarts3D PROC mov dtState3D,DT_AIM mov dtTimer3D,0 mov dtRemaining3D,500 mov dtVisitStart3D,500 mov dtScores3D,500 mov dtScores3D[4],500 mov dtActor3D,0 mov dtWinner3D,0 mov dtBotTimer3D,0 mov dtBotPrepared3D,0 mov dtScoreOpen3D,0 mov dtHistoryRows3D,1 mov dtHistory3D,500 mov dtHistory3D[4],500 mov dtWallDirty3D,1 mov dtCount3D,0 mov dtThrows3D,0 mov dtVisit3D,1 mov dtLast3D,0 mov dtBust3D,0 mov dtHolding3D,0 mov dtMouseReleased3D,0 mov dtHoldTime3D,0 mov dtCamX3D,0 mov dtCamY3D,0 mov dtCamZ3D,0 mov dtLens3D,DT_FOCAL mov dtLookX3D,0 mov dtLookY3D,0 ret ResetDarts3D ENDP BeginDarts3D PROC call LoadDarts3D xor eax,1 mov dtError3D,eax call ResetDarts3D mov engineMode,MODE_DARTS mov paused3D,0 mov mouseX3D,160 mov mouseY3D,107 mov dtCursorX3D,320*256 mov dtCursorY3D,214*256 call ClearKeys3D mov mouseClick3D,0 ret BeginDarts3D ENDP DartsAim3D PROC uses ebx local amplitude:DWORD,phase:DWORD,secondary:DWORD ; Smooth mixed phases and gradual hold fatigue; never scatter after release. mov amplitude,10 cmp dtHolding3D,0 je dt_aim_phase mov eax,dtHoldTime3D sub eax,1200 jle dt_aim_phase xor edx,edx mov ecx,350 div ecx cmp eax,8 jbe @F mov eax,8 @@: add amplitude,eax dt_aim_phase: mov eax,dtClock3D xor edx,edx mov ecx,3 div ecx and eax,511 mov phase,eax mov ebx,tableSin[eax*4] imul ebx,amplitude sar ebx,16 mov eax,dtClock3D xor edx,edx mov ecx,5 div ecx add eax,91 and eax,511 mov secondary,eax mov eax,tableSin[eax*4] imul eax,3 sar eax,16 add ebx,eax mov eax,dtCursorX3D sub eax,320*256 imul eax,DT_WALL cdq mov ecx,DT_FOCAL*256 idiv ecx cmp dtActor3D,0 je @F mov eax,dtBotAimX3D @@: add eax,ebx cmp eax,-290 jge @F mov eax,-290 @@: cmp eax,290 jle @F mov eax,290 @@: mov dtAimX3D,eax mov eax,phase mov ebx,tableCos[eax*4] mov ecx,amplitude sub ecx,2 imul ebx,ecx sar ebx,16 mov eax,secondary sub eax,58 and eax,511 mov eax,tableSin[eax*4] imul eax,3 sar eax,16 add ebx,eax mov eax,dtCursorY3D mov edx,214*256 sub edx,eax imul eax,edx,DT_WALL cdq mov ecx,DT_FOCAL*256 idiv ecx cmp dtActor3D,0 je @F mov eax,dtBotAimY3D @@: add eax,ebx cmp eax,-245 jge @F mov eax,-245 @@: cmp eax,245 jle @F mov eax,245 @@: mov dtAimY3D,eax ret DartsAim3D ENDP ; Select a target from the visible score, then commit imperfect aim before release. DartsBotAim3D PROC uses ebx esi local ring:DWORD,target:DWORD mov target,20 mov ring,103 mov eax,dtRemaining3D cmp eax,20 ja dt_bot_double mov target,eax mov ring,53 jmp dt_bot_sector dt_bot_double: cmp eax,40 ja dt_bot_special test eax,1 jnz dt_bot_special shr eax,1 mov target,eax mov ring,166 jmp dt_bot_sector dt_bot_special: cmp eax,50 jne @F mov dtBotDesired3D,50 mov dtBotAimX3D,0 mov dtBotAimY3D,0 jmp dt_bot_scatter @@: cmp eax,25 jne @F mov dtBotDesired3D,25 mov dtBotAimX3D,0 mov dtBotAimY3D,11 jmp dt_bot_scatter @@: cmp eax,60 ja dt_bot_sector xor edx,edx mov ecx,3 div ecx test edx,edx jnz dt_bot_single20 mov target,eax jmp dt_bot_sector dt_bot_single20: mov ring,53 dt_bot_sector: mov eax,target cmp ring,103 jne @F imul eax,3 @@: cmp ring,166 jne @F shl eax,1 @@: mov dtBotDesired3D,eax xor ebx,ebx @@: mov eax,dtSector3D[ebx*4] cmp eax,target je dt_bot_direction inc ebx cmp ebx,20 jb @B xor ebx,ebx dt_bot_direction: imul eax,ebx,512 xor edx,edx mov ecx,20 div ecx mov esi,eax mov eax,tableSin[esi*4] imul eax,ring sar eax,16 mov dtBotAimX3D,eax mov eax,tableCos[esi*4] imul eax,ring sar eax,16 mov dtBotAimY3D,eax dt_bot_scatter: invoke RandomRange3D,17 sub eax,8 add dtBotAimX3D,eax invoke RandomRange3D,17 sub eax,8 add dtBotAimY3D,eax mov dtBotPrepared3D,1 ret DartsBotAim3D ENDP ThrowDarts3D PROC cmp dtState3D,DT_AIM jne dt_throw_done cmp dtError3D,0 jne dt_throw_done mov eax,dtAimX3D mov dtHitX3D,eax mov eax,dtAimY3D mov dtHitY3D,eax mov dtState3D,DT_RELEASE mov dtTimer3D,0 mov dtHolding3D,0 mov dtMouseReleased3D,0 inc dtThrows3D dt_throw_done: ret ThrowDarts3D ENDP ; Board units are millimetres: 6.35/15.9 bull, 99..107 triple, 162..170 double. DartsScore3D PROC uses ebx x:SDWORD,y:SDWORD local angle:DWORD,oldControl:WORD,truncate:WORD cmp x,-170 jl dt_score_miss cmp x,170 jg dt_score_miss cmp y,-170 jl dt_score_miss cmp y,170 jg dt_score_miss mov eax,x imul eax,eax mov ebx,y imul ebx,ebx add ebx,eax cmp ebx,170*170 ja dt_score_miss cmp ebx,40 jbe dt_score_bull cmp ebx,253 jbe dt_score_outer_bull fnstcw oldControl mov ax,oldControl or ax,0C00h mov truncate,ax fldcw truncate fild x fild y fpatan fmul dtAngleFactor3D fistp angle fldcw oldControl mov eax,angle add eax,65536+1638 and eax,65535 imul eax,20 shr eax,16 mov eax,dtSector3D[eax*4] mov edx,1 cmp ebx,162*162 jae dt_score_double cmp ebx,99*99 jb dt_score_done cmp ebx,107*107 ja dt_score_done mov edx,3 imul eax,3 ret dt_score_double: mov edx,2 shl eax,1 ret dt_score_bull: mov eax,50 mov edx,2 ret dt_score_outer_bull: mov eax,25 mov edx,1 ret dt_score_miss: xor eax,eax xor edx,edx dt_score_done: ret DartsScore3D ENDP SettleDarts3D PROC uses ebx cmp dtState3D,DT_FLIGHT jne dt_settle_done invoke DartsScore3D,dtHitX3D,dtHitY3D mov dtLast3D,eax mov dtMultiplier3D,edx mov ebx,dtCount3D cmp ebx,3 jae dt_settle_done mov dtMarkScore3D[ebx*4],eax mov ecx,dtHitX3D mov dtMarkX3D[ebx*4],ecx mov ecx,dtHitY3D mov dtMarkY3D[ebx*4],ecx inc dtCount3D mov ecx,dtRemaining3D sub ecx,eax js dt_bust dt_score_accept: mov dtRemaining3D,ecx jmp dt_begin_impact dt_bust: mov eax,dtVisitStart3D mov dtRemaining3D,eax mov dtBust3D,1 dt_begin_impact: mov ebx,dtActor3D mov eax,dtRemaining3D mov dtScores3D[ebx*4],eax mov dtWallDirty3D,1 test eax,eax jnz @F mov dtWinner3D,ebx @@: cmp dtRemaining3D,0 je dt_record_visit cmp dtCount3D,3 je dt_record_visit cmp dtBust3D,0 je dt_no_record dt_record_visit: call DartsRecordScore3D dt_no_record: mov dtState3D,DT_IMPACT mov dtTimer3D,0 invoke PlayCasinoSound3D,OFFSET soundClick,0,1 dt_settle_done: ret SettleDarts3D ENDP DartsRecordScore3D PROC uses ebx esi edi mov ebx,dtHistoryRows3D cmp ebx,32 jb @F lea esi,dtHistory3D[8] lea edi,dtHistory3D mov ecx,62 cld rep movsd mov ebx,31 @@: mov eax,dtScores3D mov dtHistory3D[ebx*8],eax mov eax,dtScores3D[4] mov dtHistory3D[ebx*8+4],eax inc ebx mov dtHistoryRows3D,ebx mov dtWallDirty3D,1 ret DartsRecordScore3D ENDP HandleDarts3D PROC invoke Pressed3D,9 test eax,eax jz @F xor dtScoreOpen3D,1 mov dtHolding3D,0 mov dtMouseReleased3D,0 @@: cmp dtScoreOpen3D,0 jne dt_handle_done invoke Pressed3D,52h test eax,eax jz @F call ResetDarts3D @@: cmp mouseClick3D,0 je dt_handle_game cmp mouseY3D,218 jb dt_handle_game cmp mouseX3D,230 jb dt_handle_game call ResetDarts3D mov mouseClick3D,0 dt_handle_game: cmp dtError3D,0 jne dt_handle_done mov eax,deltaTime3D add dtClock3D,eax cmp dtState3D,DT_AIM jne dt_animate cmp dtActor3D,0 je dt_player_aim cmp dtBotPrepared3D,0 jne @F call DartsBotAim3D @@: call DartsAim3D mov eax,deltaTime3D add dtBotTimer3D,eax cmp dtBotTimer3D,900 jb dt_handle_done mov dtHolding3D,1 mov eax,dtBotTimer3D sub eax,900 cmp eax,280 jbe @F mov eax,280 @@: mov dtHoldTime3D,eax cmp dtBotTimer3D,1220 jb dt_handle_done invoke DartsScore3D,dtAimX3D,dtAimY3D cmp eax,dtBotDesired3D je dt_bot_commit cmp dtBotTimer3D,1600 jb dt_handle_done dt_bot_commit: call ThrowDarts3D jmp dt_handle_done dt_player_aim: cmp mouseClick3D,0 je @F mov dtHolding3D,1 mov dtHoldTime3D,0 @@: cmp dtHolding3D,0 je dt_player_hover mov eax,deltaTime3D add dtHoldTime3D,eax cmp dtHoldTime3D,4000 jbe @F mov dtHoldTime3D,4000 @@: dt_player_hover: call DartsAim3D cmp dtHolding3D,0 jne dt_player_release mov dtMouseReleased3D,0 jmp dt_handle_done dt_player_release: cmp dtMouseReleased3D,0 je dt_handle_done call ThrowDarts3D jmp dt_handle_done dt_animate: mov eax,deltaTime3D add dtTimer3D,eax cmp dtState3D,DT_RELEASE jne dt_animate_flight cmp dtTimer3D,200 jb dt_handle_done sub dtTimer3D,200 mov dtState3D,DT_FLIGHT jmp dt_handle_done dt_animate_flight: cmp dtState3D,DT_FLIGHT jne dt_animate_impact cmp dtTimer3D,DT_THROW_MS jb dt_handle_done call SettleDarts3D jmp dt_handle_done dt_animate_impact: cmp dtState3D,DT_IMPACT jne dt_animate_return cmp dtTimer3D,1300 jb dt_handle_done mov dtState3D,DT_WIN cmp dtRemaining3D,0 je dt_handle_done mov dtState3D,DT_RETURN mov dtTimer3D,0 jmp dt_handle_done dt_animate_return: cmp dtState3D,DT_RETURN jne dt_handle_done cmp dtTimer3D,750 jb dt_handle_done cmp dtBust3D,0 jne dt_next_visit cmp dtCount3D,3 jb dt_return_aim dt_next_visit: mov dtBust3D,0 mov dtCount3D,0 inc dtVisit3D xor dtActor3D,1 mov eax,dtActor3D mov eax,dtScores3D[eax*4] mov dtRemaining3D,eax mov dtVisitStart3D,eax dt_return_aim: mov dtState3D,DT_AIM mov dtTimer3D,0 mov dtMouseReleased3D,0 mov dtHolding3D,0 mov dtHoldTime3D,0 mov dtBotPrepared3D,0 mov dtBotTimer3D,0 dt_handle_done: mov mouseClick3D,0 ret HandleDarts3D ENDP DartsPath3D PROC uses ebx esi timeMs:DWORD local progress:DWORD,pathX:DWORD,pathY:DWORD,pathZ:DWORD mov eax,timeMs cmp eax,DT_THROW_MS jbe @F mov eax,DT_THROW_MS @@: shl eax,16 xor edx,edx mov ecx,DT_THROW_MS div ecx mov progress,eax mov ebx,eax imul eax,DT_WALL sar eax,16 mov pathZ,eax mov eax,dtHitX3D sub eax,70 imul eax,ebx sar eax,16 add eax,70 mov pathX,eax mov eax,65536 sub eax,ebx imul ebx shrd eax,edx,16 imul eax,280 sar eax,16 mov esi,eax mov eax,dtHitY3D add eax,35 imul eax,ebx sar eax,16 sub eax,35 add eax,esi mov edx,eax mov eax,pathX mov ecx,pathZ ret DartsPath3D ENDP ; Real orbit: behind -> alongside the dart -> behind the impact, with one camera basis. DartsCamera3D PROC uses ebx esi local progress:DWORD,weight:DWORD,timeMs:DWORD,factor:DWORD local length2:DWORD,span:DWORD,targetZ:DWORD,deltaX:DWORD,deltaZ:DWORD mov timeMs,0 cmp dtState3D,DT_FLIGHT jne @F mov eax,dtTimer3D mov timeMs,eax jmp dt_camera_path @@: cmp dtState3D,DT_IMPACT je dt_camera_end cmp dtState3D,DT_WIN je dt_camera_end cmp dtState3D,DT_RETURN jne dt_camera_path dt_camera_end: mov timeMs,DT_THROW_MS dt_camera_path: invoke DartsPath3D,timeMs mov dtShotX3D,eax mov dtShotY3D,edx mov dtShotZ3D,ecx mov eax,timeMs cmp eax,DT_THROW_MS jbe @F mov eax,DT_THROW_MS @@: shl eax,16 xor edx,edx mov ecx,DT_THROW_MS div ecx mov progress,eax mov ebx,eax shr eax,8 mov eax,tableSin[eax*4] imul eax shrd eax,edx,16 mov weight,eax imul eax,260 sar eax,16 mov ecx,420 sub ecx,eax mov eax,dtShotZ3D sub eax,ecx jns @F xor eax,eax @@: mov dtCamZ3D,eax mov eax,weight imul eax,300 sar eax,16 mov ecx,dtShotX3D sub ecx,70 sub ecx,eax mov dtCamX3D,ecx mov eax,weight imul eax,80 sar eax,16 add eax,dtShotY3D add eax,35 mov dtCamY3D,eax mov eax,dtHitX3D imul eax,ebx sar eax,17 mov esi,eax mov ecx,dtShotX3D sub ecx,eax imul ecx,weight sar ecx,16 add ecx,esi mov dtLookX3D,ecx mov eax,dtHitY3D imul eax,ebx sar eax,17 mov esi,eax mov ecx,dtShotY3D sub ecx,eax imul ecx,weight sar ecx,16 add ecx,esi mov dtLookY3D,ecx mov eax,dtShotZ3D sub eax,DT_WALL imul eax,weight sar eax,16 add eax,DT_WALL mov targetZ,eax cmp dtState3D,DT_RETURN jne dt_camera_basis mov eax,dtTimer3D cmp eax,750 jbe @F mov eax,750 @@: mov ecx,750 sub ecx,eax imul eax,ecx,65536 xor edx,edx mov ecx,750 div ecx mov ebx,eax mov eax,dtCamX3D imul eax,ebx sar eax,16 mov dtCamX3D,eax mov eax,dtCamY3D imul eax,ebx sar eax,16 mov dtCamY3D,eax mov eax,dtCamZ3D imul eax,ebx sar eax,16 mov dtCamZ3D,eax mov eax,dtLookX3D imul eax,ebx sar eax,16 mov dtLookX3D,eax mov eax,dtLookY3D imul eax,ebx sar eax,16 mov dtLookY3D,eax dt_camera_basis: mov eax,dtCamZ3D imul eax,550 xor edx,edx mov ecx,DT_WALL-420 div ecx mov ecx,DT_FOCAL sub ecx,eax mov eax,weight imul eax,160 sar eax,16 sub ecx,eax cmp ecx,350 jge @F mov ecx,350 @@: mov dtLens3D,ecx mov eax,dtLookX3D sub eax,dtCamX3D mov deltaX,eax imul eax,eax mov ebx,targetZ sub ebx,dtCamZ3D mov deltaZ,ebx imul ebx,ebx add eax,ebx mov length2,eax fild length2 fsqrt fistp span cmp span,1 jge @F mov span,1 @@: mov eax,deltaX shl eax,16 cdq idiv span mov dtYawSin3D,eax mov eax,deltaZ shl eax,16 cdq idiv span mov dtYawCos3D,eax mov eax,dtLookY3D sub eax,dtCamY3D imul eax,dtLens3D cdq idiv span add eax,214 mov dtScreenY3D,eax mov dtScreenX3D,320 ret DartsCamera3D ENDP DartsProject3D PROC uses ebx x:SDWORD,y:SDWORD,z:SDWORD local deltaX:DWORD,deltaZ:DWORD,depth:DWORD,side:DWORD mov eax,x sub eax,dtCamX3D mov deltaX,eax mov ebx,z sub ebx,dtCamZ3D mov deltaZ,ebx imul eax,dtYawCos3D imul ebx,dtYawSin3D sub eax,ebx sar eax,16 mov side,eax mov eax,deltaX imul eax,dtYawSin3D mov ebx,deltaZ imul ebx,dtYawCos3D add eax,ebx sar eax,16 mov depth,eax cmp eax,16 jg @F mov eax,16 @@: mov ecx,eax mov eax,side imul eax,dtLens3D cdq idiv ecx add eax,320 push eax mov eax,y sub eax,dtCamY3D imul eax,dtLens3D cdq idiv ecx mov edx,dtScreenY3D sub edx,eax pop eax mov ecx,depth ret DartsProject3D ENDP ResolveDartsSurface3D PROC cmp dtBoard3D.pixels,0 jne @F invoke LoadAnimPack3D,OFFSET dtBoard3D,OFFSET dtBoardPath @@: mov eax,dtBoard3D.pixels mov ecx,512 mov edx,512 ret ResolveDartsSurface3D ENDP DrawHallDarts3D PROC cmp hallLevel3D,0 jne @F invoke DrawCityVertical3D,0,FP_1*3098/100,FP_1*275/10,FP_1*285/10,FP_1*115/100,FP_1*215/100,160 @@: ret DrawHallDarts3D ENDP include src_graphics\darts_render.inc