NpcDate3D PROC IFDEF CASINO_ACTION_TEST mov eax,npcDateOverride3D test eax,eax jnz npc_date_done ENDIF invoke GetLocalTime,OFFSET npcSystemTime3D movzx eax,npcSystemTime3D imul eax,10000 movzx ecx,npcSystemTime3D[2] imul ecx,100 add eax,ecx movzx ecx,npcSystemTime3D[6] add eax,ecx npc_date_done: ret NpcDate3D ENDP NpcJournalSignature3D PROC uses esi source:DWORD mov esi,source mov ecx,(NPC_JOURNAL_SIZE-4)/4 mov eax,4E504351h npc_signature_word: rol eax,5 xor eax,[esi] add eax,9E3779B9h add esi,4 loop npc_signature_word ret NpcJournalSignature3D ENDP ; Failed, truncated or mismatched journals cannot change the player's balance. NpcEnsureJournal3D PROC uses ebx esi edi local date:DWORD,io:DWORD call NpcDate3D mov date,eax mov esi,OFFSET savePath3D cmp nativeProfileActive3D,0 je @F mov esi,OFFSET saveFullPath @@: IFDEF CASINO_ACTION_TEST cmp npcJournalBasePtr3D,0 je @F mov esi,npcJournalBasePtr3D @@: ENDIF xor ecx,ecx npc_journal_path_length: cmp ecx,250 jae npc_journal_invalid_path cmp BYTE PTR [esi+ecx],0 je npc_journal_build_path inc ecx jmp npc_journal_path_length npc_journal_build_path: invoke CopyCString,OFFSET npcJournalNextPath3D,esi invoke AppendCString,OFFSET npcJournalNextPath3D,OFFSET npcJournalSuffix3D invoke lstrcmpiA,OFFSET npcJournalPath3D,OFFSET npcJournalNextPath3D test eax,eax jnz npc_journal_reset cmp npcJournalLoaded3D,1 jne npc_journal_reset mov eax,date cmp eax,npcJournalDay3D je npc_journal_ready npc_journal_reset: mov npcAccepted3D,0 mov npcClaimed3D,0 lea edi,npcProgress3D mov ecx,NPC_IDENTITY_COUNT xor eax,eax rep stosd mov eax,date mov npcJournalDay3D,eax invoke CopyCString,OFFSET npcJournalPath3D,OFFSET npcJournalNextPath3D mov npcJournalLoaded3D,1 invoke CreateFileA,OFFSET npcJournalPath3D,80000000h,1,0,3,80h,0 cmp eax,-1 je npc_journal_ready mov ebx,eax invoke GetFileSize,ebx,0 cmp eax,NPC_JOURNAL_SIZE jne npc_journal_close invoke ReadFile,ebx,OFFSET npcJournalRead3D,NPC_JOURNAL_SIZE,ADDR io,0 test eax,eax jz npc_journal_close cmp io,NPC_JOURNAL_SIZE jne npc_journal_close cmp DWORD PTR npcJournalRead3D,3151504Eh jne npc_journal_close mov eax,date cmp DWORD PTR npcJournalRead3D[4],eax jne npc_journal_close mov eax,DWORD PTR npcJournalRead3D[8] or eax,DWORD PTR npcJournalRead3D[12] test eax,0FFFFF000h jnz npc_journal_close mov eax,DWORD PTR npcJournalRead3D[12] not eax or eax,DWORD PTR npcJournalRead3D[8] cmp eax,-1 jne npc_journal_close invoke NpcJournalSignature3D,OFFSET npcJournalRead3D cmp eax,DWORD PTR npcJournalRead3D[NPC_JOURNAL_SIZE-4] jne npc_journal_close xor esi,esi npc_journal_validate_progress: invoke NpcContractType3D,esi mov eax,npcQuestGoals3D[eax*4] cmp DWORD PTR npcJournalRead3D[16+esi*4],eax ja npc_journal_close inc esi cmp esi,NPC_IDENTITY_COUNT jb npc_journal_validate_progress lea esi,npcJournalRead3D lea edi,npcJournal3D mov ecx,NPC_JOURNAL_SIZE/4 rep movsd npc_journal_close: invoke CloseHandle,ebx npc_journal_ready: mov eax,1 ret npc_journal_invalid_path: mov npcJournalLoaded3D,0 mov npcJournalIoError3D,1 xor eax,eax ret NpcEnsureJournal3D ENDP NpcSaveJournal3D PROC uses ebx local io:DWORD,ok:DWORD mov npcJournalIoError3D,0 cmp npcJournalLoaded3D,1 jne npc_journal_write_fail invoke NpcJournalSignature3D,OFFSET npcJournal3D mov npcJournalChecksum3D,eax invoke CreateDirectoryA,OFFSET runtime3D,0 invoke CreateFileA,OFFSET npcJournalPath3D,40000000h,0,0,2,80h,0 cmp eax,-1 je npc_journal_write_fail mov ebx,eax invoke WriteFile,ebx,OFFSET npcJournal3D,NPC_JOURNAL_SIZE,ADDR io,0 mov ok,eax invoke CloseHandle,ebx cmp ok,0 je npc_journal_write_fail cmp io,NPC_JOURNAL_SIZE jne npc_journal_write_fail mov eax,1 ret npc_journal_write_fail: mov npcJournalIoError3D,1 xor eax,eax ret NpcSaveJournal3D ENDP NpcContractType3D PROC identity:DWORD mov eax,npcJournalDay3D mov ecx,identity imul ecx,7 add eax,ecx xor edx,edx mov ecx,NPC_IDENTITY_COUNT div ecx mov eax,edx ret NpcContractType3D ENDP NpcAcceptContract3D PROC uses ebx identity:DWORD mov npcJournalIoError3D,0 cmp identity,NPC_IDENTITY_COUNT jae npc_accept_fail call NpcEnsureJournal3D test eax,eax jz npc_accept_fail mov ebx,identity bt npcAccepted3D,ebx jc npc_accept_fail bts npcAccepted3D,ebx call NpcSaveJournal3D test eax,eax jnz npc_accept_done btr npcAccepted3D,ebx npc_accept_fail: xor eax,eax npc_accept_done: ret NpcAcceptContract3D ENDP NpcRecordRound3D PROC uses ebx esi edi game:DWORD,won:DWORD call NpcEnsureJournal3D test eax,eax jz npc_event_done cmp npcAccepted3D,0 je npc_event_done xor esi,esi xor edi,edi npc_event_contract: bt npcAccepted3D,esi jnc npc_event_next bt npcClaimed3D,esi jc npc_event_next invoke NpcContractType3D,esi mov ebx,eax mov eax,npcQuestGames3D[ebx*4] cmp eax,-1 je @F cmp eax,game jne npc_event_next @@: cmp npcQuestWins3D[ebx*4],0 je @F cmp won,0 je npc_event_next @@: mov eax,npcQuestGoals3D[ebx*4] cmp npcProgress3D[esi*4],eax jae npc_event_next inc npcProgress3D[esi*4] mov edi,1 npc_event_next: inc esi cmp esi,NPC_IDENTITY_COUNT jb npc_event_contract test edi,edi jz npc_event_done call NpcSaveJournal3D npc_event_done: ret NpcRecordRound3D ENDP NpcClaimContract3D PROC uses ebx esi identity:DWORD mov npcJournalIoError3D,0 cmp identity,NPC_IDENTITY_COUNT jae npc_claim_fail call NpcEnsureJournal3D test eax,eax jz npc_claim_fail mov ebx,identity bt npcAccepted3D,ebx jnc npc_claim_fail bt npcClaimed3D,ebx jc npc_claim_fail invoke NpcContractType3D,ebx mov ecx,npcQuestGoals3D[eax*4] cmp npcProgress3D[ebx*4],ecx jb npc_claim_fail mov esi,npcQuestRewards3D[eax*4] bts npcClaimed3D,ebx call NpcSaveJournal3D test eax,eax jnz npc_claim_credit btr npcClaimed3D,ebx jmp npc_claim_fail npc_claim_credit: add bankroll,esi jc @F cmp bankroll,1000000000 jbe npc_claim_save @@: mov bankroll,1000000000 npc_claim_save: call SaveProgress3D mov eax,1 ret npc_claim_fail: xor eax,eax ret NpcClaimContract3D ENDP OpenNpcDialog3D PROC uses ebx cmp npcSelected3D,NPC_LIFE_COUNT jae npc_dialog_open_fail imul ebx,npcSelected3D,SIZEOF NpcLife3D cmp npcLife3D[ebx].state,NPC_AWAY je npc_dialog_open_fail mov eax,npcLife3D[ebx].identity mov npcDialogIdentity3D,eax mov npcDialogError3D,0 call NpcEnsureJournal3D test eax,eax jnz @F mov npcDialogError3D,1 @@: mov engineMode,MODE_NPC_DIALOG call ClearKeys3D mov eax,1 ret npc_dialog_open_fail: xor eax,eax ret OpenNpcDialog3D ENDP CloseNpcDialog3D PROC mov engineMode,MODE_WALK mov paused3D,0 call ClearKeys3D ret CloseNpcDialog3D ENDP HandleNpcDialog3D PROC cmp engineMode,MODE_NPC_DIALOG jne npc_dialog_handle_done call NpcEnsureJournal3D cmp mouseClick3D,0 je npc_dialog_keys mov mouseClick3D,0 cmp mouseY3D,169 jb npc_dialog_keys cmp mouseY3D,190 jae npc_dialog_keys cmp mouseX3D,40 jb npc_dialog_keys cmp mouseX3D,112 jb npc_dialog_accept cmp mouseX3D,120 jb npc_dialog_keys cmp mouseX3D,198 jb npc_dialog_claim cmp mouseX3D,208 jb npc_dialog_keys cmp mouseX3D,280 jb npc_dialog_close npc_dialog_keys: invoke Pressed3D,30h test eax,eax jnz npc_dialog_close invoke Pressed3D,31h test eax,eax jnz npc_dialog_accept invoke Pressed3D,32h test eax,eax jnz npc_dialog_claim invoke Pressed3D,0Dh test eax,eax jz npc_dialog_handle_done mov ecx,npcDialogIdentity3D bt npcAccepted3D,ecx jnc npc_dialog_accept jmp npc_dialog_claim npc_dialog_accept: invoke NpcAcceptContract3D,npcDialogIdentity3D jmp npc_dialog_result npc_dialog_claim: invoke NpcClaimContract3D,npcDialogIdentity3D npc_dialog_result: mov eax,npcJournalIoError3D mov npcDialogError3D,eax ret npc_dialog_close: call CloseNpcDialog3D npc_dialog_handle_done: ret HandleNpcDialog3D ENDP ; Preserve original personality names, removing unsupported quote glyphs for the HUD. NpcNameText3D PROC uses esi edi identity:DWORD mov eax,identity cmp eax,NPC_IDENTITY_COUNT jae npc_name_empty mov esi,npcNames3D[eax*4] lea edi,npcNameBuffer3D mov ecx,60 npc_name_copy: lodsb test al,al jz npc_name_finish cmp al,0ABh je npc_name_copy cmp al,0BBh je npc_name_copy stosb loop npc_name_copy npc_name_finish: mov BYTE PTR [edi],0 mov eax,OFFSET npcNameBuffer3D ret npc_name_empty: mov npcNameBuffer3D,0 mov eax,OFFSET npcNameBuffer3D ret NpcNameText3D ENDP RenderNpcDialog3D PROC uses ebx esi cmp engineMode,MODE_NPC_DIALOG jne npc_dialog_render_done call RenderCeilingAndFloor call RenderWalls call PrepareCityDepth3D call RenderSprites call RenderHall3D invoke DrawBoxBorder,30,48,260,151,00141B1Dh,00BA9955h,1 mov ebx,npcDialogIdentity3D invoke NpcNameText3D,ebx invoke DrawString8x8,42,59,eax,00F4DF9Eh mov eax,ebx xor edx,edx mov ecx,6 div ecx invoke DrawString8x8,42,76,npcGreetings3D[edx*4],00CED8D5h invoke DrawString8x8,42,97,OFFSET npcContractTitle3D,00D3C08Fh invoke NpcContractType3D,ebx mov esi,eax invoke DrawString8x8,42,112,npcQuestTexts3D[esi*4],00FFFFFFh invoke DrawString8x8,42,130,OFFSET npcProgressText3D,00CED8D5h invoke DrawNumber,112,130,npcProgress3D[ebx*4],00FFFFFFh invoke DrawString8x8,123,130,OFFSET npcSlashText3D,00CED8D5h invoke DrawNumber,149,130,npcQuestGoals3D[esi*4],00FFFFFFh invoke DrawString8x8,178,130,OFFSET npcRewardText3D,00D3C08Fh invoke DrawNumber,244,130,npcQuestRewards3D[esi*4],00FFFFFFh mov eax,OFFSET npcAvailableText3D bt npcAccepted3D,ebx jnc npc_dialog_status mov eax,OFFSET npcActiveText3D mov ecx,npcQuestGoals3D[esi*4] cmp npcProgress3D[ebx*4],ecx jb npc_dialog_status mov eax,OFFSET npcReadyText3D bt npcClaimed3D,ebx jnc npc_dialog_status mov eax,OFFSET npcDoneText3D npc_dialog_status: invoke DrawString8x8,42,150,eax,0087D4A5h invoke DrawBoxBorder,40,170,72,18,002D3A32h,0087AA8Eh,1 invoke DrawString8x8,51,175,OFFSET npcAcceptText3D,00FFFFFFh invoke DrawBoxBorder,120,170,78,18,003B3024h,00BA9955h,1 invoke DrawString8x8,131,175,OFFSET npcClaimText3D,00FFFFFFh invoke DrawBoxBorder,208,170,72,18,00212A2Dh,008B999Ah,1 invoke DrawString8x8,216,175,OFFSET npcCloseText3D,00FFFFFFh cmp npcDialogError3D,0 je npc_dialog_render_done invoke DrawString8x8,42,150,OFFSET npcIoErrorText3D,00F89880h npc_dialog_render_done: ret RenderNpcDialog3D ENDP