1 #include "Directories.h"
2 #include "Font.h"
3 #include "Font_Control.h"
4 #include "Laptop.h"
5 #include "LoadSaveData.h"
6 #include "History.h"
7 #include "Game_Clock.h"
8 #include "Quests.h"
9 #include "Soldier_Control.h"
10 #include "VObject.h"
11 #include "Debug.h"
12 #include "WordWrap.h"
13 #include "Render_Dirty.h"
14 #include "Cursors.h"
15 #include "Soldier_Profile.h"
16 #include "StrategicMap.h"
17 #include "QuestText.h"
18 #include "Text.h"
19 #include "Message.h"
20 #include "LaptopSave.h"
21 #include "Button_System.h"
22 #include "VSurface.h"
23 #include "MemMan.h"
24 #include "FileMan.h"
25
26 #include "ContentManager.h"
27 #include "GameInstance.h"
28
29 #include <string_theory/format>
30 #include <string_theory/string>
31
32
33 #define HISTORY_QUEST_TEXT_SIZE 80
34
35
36 struct HistoryUnit
37 {
38 UINT8 ubCode; // the code index in the finance code table
39 UINT8 ubSecondCode; // secondary code
40 UINT32 uiDate; // time in the world in global time
41 INT16 sSectorX; // sector X this took place in
42 INT16 sSectorY; // sector Y this took place in
43 INT8 bSectorZ;
44 HistoryUnit* Next; // next unit in the list
45 };
46
47
48 #define TOP_X 0+LAPTOP_SCREEN_UL_X
49 #define TOP_Y LAPTOP_SCREEN_UL_Y
50 #define BOX_HEIGHT 14
51 #define TOP_DIVLINE_Y (STD_SCREEN_Y + 101)
52 #define TITLE_X (STD_SCREEN_X + 140)
53 #define TITLE_Y (STD_SCREEN_Y + 33 )
54 #define PAGE_SIZE 22
55 #define RECORD_Y TOP_DIVLINE_Y
56 #define RECORD_HISTORY_WIDTH 200
57 #define PAGE_NUMBER_X TOP_X+20
58 #define PAGE_NUMBER_Y TOP_Y+33
59 #define HISTORY_DATE_X PAGE_NUMBER_X+85
60 #define HISTORY_DATE_Y PAGE_NUMBER_Y
61 #define RECORD_LOCATION_WIDTH 142//95
62
63 #define HISTORY_HEADER_FONT FONT14ARIAL
64 #define HISTORY_TEXT_FONT FONT12ARIAL
65 #define RECORD_DATE_X TOP_X+10
66 #define RECORD_DATE_WIDTH 31//68
67 #define RECORD_HEADER_Y (STD_SCREEN_Y + 90)
68
69
70 #define NUM_RECORDS_PER_PAGE PAGE_SIZE
71 #define SIZE_OF_HISTORY_FILE_RECORD ( sizeof( UINT8 ) + sizeof( UINT8 ) + sizeof( UINT32 ) + sizeof( UINT16 ) + sizeof( UINT16 ) + sizeof( UINT8 ) + sizeof( UINT8 ) )
72
73 // button positions
74 #define NEXT_BTN_X (STD_SCREEN_X + 577)
75 #define PREV_BTN_X (STD_SCREEN_X + 553)
76 #define BTN_Y (STD_SCREEN_Y + 53 )
77
78 // graphics handles
79 static SGPVObject* guiTITLE;
80 static SGPVObject* guiTOP;
81 static SGPVObject* guiLONGLINE;
82 static SGPVObject* guiSHADELINE;
83
84 enum{
85 PREV_PAGE_BUTTON=0,
86 NEXT_PAGE_BUTTON,
87 };
88
89 // the page flipping buttons
90 static GUIButtonRef giHistoryButton[2];
91
92 static MOUSE_REGION g_scroll_region;
93
94
95 static BOOLEAN fInHistoryMode = FALSE;
96 // current page displayed
97 static INT32 iCurrentHistoryPage = 1;
98
99
100 // the History record list
101 static HistoryUnit* pHistoryListHead = NULL;
102
103
104 void ClearHistoryList( void );
105
106
107 static void AppendHistoryToEndOfFile(void);
108 static BOOLEAN LoadInHistoryRecords(const UINT32 uiPage);
109 static void ProcessAndEnterAHistoryRecord(UINT8 ubCode, UINT32 uiDate, UINT8 ubSecondCode, INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ);
110
111
AddHistoryToPlayersLog(const UINT8 ubCode,const UINT8 ubSecondCode,const UINT32 uiDate,const INT16 sSectorX,const INT16 sSectorY)112 void AddHistoryToPlayersLog(const UINT8 ubCode, const UINT8 ubSecondCode, const UINT32 uiDate, const INT16 sSectorX, const INT16 sSectorY)
113 {
114 ClearHistoryList();
115
116 ProcessAndEnterAHistoryRecord(ubCode, uiDate, ubSecondCode, sSectorX, sSectorY, 0);
117 ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[MSG_HISTORY_UPDATED]);
118
119 AppendHistoryToEndOfFile();
120
121 // if in history mode, reload current page
122 if (fInHistoryMode) LoadInHistoryRecords(iCurrentHistoryPage);
123 }
124
125
GameInitHistory()126 void GameInitHistory()
127 {
128 FileDelete(HISTORY_DATA_FILE);
129 }
130
131
132 static void CreateHistoryButtons(void);
133 static void LoadHistory(void);
134 static void SetHistoryButtonStates(void);
135
136
EnterHistory()137 void EnterHistory()
138 {
139 // load the graphics
140 LoadHistory( );
141
142 // create History buttons
143 CreateHistoryButtons( );
144
145 // reset current to first page
146 iCurrentHistoryPage = LaptopSaveInfo.iCurrentHistoryPage;
147 if (iCurrentHistoryPage <= 0) iCurrentHistoryPage = 1;
148
149 LoadInHistoryRecords(iCurrentHistoryPage);
150
151 // render hbackground
152 RenderHistory( );
153
154
155 // set the fact we are in the history viewer
156 fInHistoryMode=TRUE;
157
158 // build Historys list
159 //OpenAndReadHistoryFile( );
160
161 // force redraw of the entire screen
162 //fReDrawScreenFlag=TRUE;
163
164 // set inital states
165 SetHistoryButtonStates( );
166 }
167
168
169 static void DestroyHistoryButtons(void);
170 static void RemoveHistory(void);
171
172
ExitHistory()173 void ExitHistory()
174 {
175 LaptopSaveInfo.iCurrentHistoryPage = iCurrentHistoryPage;
176
177 // not in History system anymore
178 fInHistoryMode=FALSE;
179
180 // delete graphics
181 RemoveHistory( );
182
183 // delete buttons
184 DestroyHistoryButtons( );
185
186 ClearHistoryList( );
187 }
188
189
190 static void DrawAPageofHistoryRecords(void);
191 static void RenderHistoryBackGround(void);
192
193
RenderHistory(void)194 void RenderHistory( void )
195 {
196 //render the background to the display
197 RenderHistoryBackGround( );
198
199 // render the currentpage of records
200 DrawAPageofHistoryRecords( );
201
202 // title bar icon
203 BlitTitleBarIcons( );
204 }
205
206
LoadHistory(void)207 static void LoadHistory(void)
208 {
209 // load History video objects into memory
210
211 // title bar
212 guiTITLE = AddVideoObjectFromFile(LAPTOPDIR "/programtitlebar.sti");
213
214 // top portion of the screen background
215 guiTOP = AddVideoObjectFromFile(LAPTOPDIR "/historywindow.sti");
216
217 // shaded line
218 guiSHADELINE = AddVideoObjectFromFile(LAPTOPDIR "/historylines.sti");
219
220 // black divider line - long ( 480 length)
221 guiLONGLINE = AddVideoObjectFromFile(LAPTOPDIR "/divisionline480.sti");
222 }
223
224
RemoveHistory(void)225 static void RemoveHistory(void)
226 {
227 // delete history video objects from memory
228 DeleteVideoObject(guiLONGLINE);
229 DeleteVideoObject(guiTOP);
230 DeleteVideoObject(guiTITLE);
231 DeleteVideoObject(guiSHADELINE);
232 }
233
234
RenderHistoryBackGround(void)235 static void RenderHistoryBackGround(void)
236 {
237 // render generic background for history system
238 BltVideoObject(FRAME_BUFFER, guiTITLE, 0, TOP_X, TOP_Y - 2);
239 BltVideoObject(FRAME_BUFFER, guiTOP, 0, TOP_X, TOP_Y + 22);
240 }
241
242
DrawHistoryTitleText(void)243 static void DrawHistoryTitleText(void)
244 {
245 // draw the pages title
246 SetFontAttributes(HISTORY_HEADER_FONT, FONT_WHITE);
247 MPrint(TITLE_X, TITLE_Y, pHistoryTitle);
248 }
249
250
251 static void LoadNextHistoryPage(void);
252 static void LoadPreviousHistoryPage(void);
253
254
ScrollRegionCallback(MOUSE_REGION * const,INT32 const reason)255 static void ScrollRegionCallback(MOUSE_REGION* const, INT32 const reason)
256 {
257 if (reason & MSYS_CALLBACK_REASON_WHEEL_UP)
258 {
259 LoadPreviousHistoryPage();
260 }
261 else if (reason & MSYS_CALLBACK_REASON_WHEEL_DOWN)
262 {
263 LoadNextHistoryPage();
264 }
265 }
266
267
268 static void BtnHistoryDisplayNextPageCallBack(GUI_BUTTON* btn, INT32 reason);
269 static void BtnHistoryDisplayPrevPageCallBack(GUI_BUTTON* btn, INT32 reason);
270
271
CreateHistoryButtons(void)272 static void CreateHistoryButtons(void)
273 {
274 // the prev/next page buttons
275 giHistoryButton[PREV_PAGE_BUTTON] = QuickCreateButtonImg(LAPTOPDIR "/arrows.sti", 0, 1, PREV_BTN_X, BTN_Y, MSYS_PRIORITY_HIGHEST - 1, BtnHistoryDisplayPrevPageCallBack);
276 giHistoryButton[NEXT_PAGE_BUTTON] = QuickCreateButtonImg(LAPTOPDIR "/arrows.sti", 6, 7, NEXT_BTN_X, BTN_Y, MSYS_PRIORITY_HIGHEST - 1, BtnHistoryDisplayNextPageCallBack);
277
278 // set buttons
279 giHistoryButton[0]->SetCursor(CURSOR_LAPTOP_SCREEN);
280 giHistoryButton[1]->SetCursor(CURSOR_LAPTOP_SCREEN);
281
282 UINT16 const x = TOP_X + 8;
283 UINT16 const y = TOP_Y + 53;
284 UINT16 const w = 482;
285 UINT16 const h = 354;
286 MSYS_DefineRegion(&g_scroll_region, x, y, x + w, y + h, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, ScrollRegionCallback);
287 }
288
289
DestroyHistoryButtons(void)290 static void DestroyHistoryButtons(void)
291 {
292 // remove History buttons and images from memory
293 MSYS_RemoveRegion(&g_scroll_region);
294 // next page button
295 RemoveButton(giHistoryButton[1] );
296 // prev page button
297 RemoveButton(giHistoryButton[0] );
298 }
299
300
BtnHistoryDisplayPrevPageCallBack(GUI_BUTTON * btn,INT32 reason)301 static void BtnHistoryDisplayPrevPageCallBack(GUI_BUTTON* btn, INT32 reason)
302 {
303 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
304 {
305 fReDrawScreenFlag = TRUE;
306 }
307
308 if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
309 {
310 LoadPreviousHistoryPage();
311 }
312 }
313
314
BtnHistoryDisplayNextPageCallBack(GUI_BUTTON * btn,INT32 reason)315 static void BtnHistoryDisplayNextPageCallBack(GUI_BUTTON* btn, INT32 reason)
316 {
317 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
318 {
319 fReDrawScreenFlag = TRUE;
320 }
321
322 if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
323 {
324 LoadNextHistoryPage();
325 }
326 }
327
328
ProcessAndEnterAHistoryRecord(const UINT8 ubCode,const UINT32 uiDate,const UINT8 ubSecondCode,const INT16 sSectorX,const INT16 sSectorY,const INT8 bSectorZ)329 static void ProcessAndEnterAHistoryRecord(const UINT8 ubCode, const UINT32 uiDate, const UINT8 ubSecondCode, const INT16 sSectorX, const INT16 sSectorY, const INT8 bSectorZ)
330 {
331 HistoryUnit* const h = new HistoryUnit{};
332 h->Next = NULL;
333 h->ubCode = ubCode;
334 h->ubSecondCode = ubSecondCode;
335 h->uiDate = uiDate;
336 h->sSectorX = sSectorX;
337 h->sSectorY = sSectorY;
338 h->bSectorZ = bSectorZ;
339
340 // Append node to list
341 HistoryUnit** anchor = &pHistoryListHead;
342 while (*anchor != NULL) anchor = &(*anchor)->Next;
343 *anchor = h;
344 }
345
346 // open and read in data to the History list
OpenAndReadHistoryFile(void)347 static void OpenAndReadHistoryFile(void)
348 {
349 ClearHistoryList();
350
351 AutoSGPFile f(GCM->openGameResForReading(HISTORY_DATA_FILE));
352
353 UINT entry_count = FileGetSize(f) / SIZE_OF_HISTORY_FILE_RECORD;
354 while (entry_count-- > 0)
355 {
356 UINT8 ubCode;
357 UINT8 ubSecondCode;
358 UINT32 uiDate;
359 INT16 sSectorX;
360 INT16 sSectorY;
361 INT8 bSectorZ;
362
363 FileRead(f, &ubCode, sizeof(UINT8));
364 FileRead(f, &ubSecondCode, sizeof(UINT8));
365 FileRead(f, &uiDate, sizeof(UINT32));
366 FileRead(f, &sSectorX, sizeof(INT16));
367 FileRead(f, &sSectorY, sizeof(INT16));
368 FileRead(f, &bSectorZ, sizeof(INT8));
369 FileSeek(f, 1, FILE_SEEK_FROM_CURRENT);
370
371 ProcessAndEnterAHistoryRecord(ubCode, uiDate, ubSecondCode, sSectorX, sSectorY, bSectorZ);
372 }
373 }
374
375
ClearHistoryList(void)376 void ClearHistoryList(void)
377 {
378 for (HistoryUnit* h = pHistoryListHead; h != NULL;)
379 {
380 HistoryUnit* const next = h->Next;
381 delete h;
382 h = next;
383 }
384 pHistoryListHead = NULL;
385 }
386
387
DisplayHistoryListHeaders(void)388 static void DisplayHistoryListHeaders(void)
389 {
390 // this procedure will display the headers to each column in History
391 SetFontAttributes(HISTORY_TEXT_FONT, FONT_BLACK, NO_SHADOW);
392
393 INT16 usX;
394 INT16 usY;
395
396 // the date header
397 FindFontCenterCoordinates(RECORD_DATE_X + 5,0,RECORD_DATE_WIDTH,0, pHistoryHeaders[0], HISTORY_TEXT_FONT,&usX, &usY);
398 MPrint(usX, RECORD_HEADER_Y, pHistoryHeaders[0]);
399
400 // the date header
401 FindFontCenterCoordinates(RECORD_DATE_X + RECORD_DATE_WIDTH + 5,0,RECORD_LOCATION_WIDTH,0, pHistoryHeaders[ 3 ], HISTORY_TEXT_FONT,&usX, &usY);
402 MPrint(usX, RECORD_HEADER_Y, pHistoryHeaders[3]);
403
404 // event header
405 FindFontCenterCoordinates(RECORD_DATE_X + RECORD_DATE_WIDTH + RECORD_LOCATION_WIDTH + 5,0,RECORD_LOCATION_WIDTH,0, pHistoryHeaders[ 3 ], HISTORY_TEXT_FONT,&usX, &usY);
406 MPrint(usX, RECORD_HEADER_Y, pHistoryHeaders[4]);
407 // reset shadow
408 SetFontShadow(DEFAULT_SHADOW);
409 }
410
411
DisplayHistoryListBackground(void)412 static void DisplayHistoryListBackground(void)
413 {
414 // this function will display the History list display background
415 INT32 iCounter=0;
416
417 // get shaded line object
418 for(iCounter=0; iCounter <11; iCounter++)
419 {
420 // blt title bar to screen
421 BltVideoObject(FRAME_BUFFER, guiSHADELINE, 0, TOP_X + 15, TOP_DIVLINE_Y + BOX_HEIGHT * 2 * iCounter);
422 }
423
424 // the long hortizontal line int he records list display region
425 BltVideoObject(FRAME_BUFFER, guiLONGLINE, 0,TOP_X + 9, TOP_DIVLINE_Y);
426 BltVideoObject(FRAME_BUFFER, guiLONGLINE, 0,TOP_X + 9, TOP_DIVLINE_Y + BOX_HEIGHT * 2 * 11);
427 }
428
429
430 static ST::string ProcessHistoryTransactionString(const HistoryUnit* h);
431
432
433 // draw the text of the records
DrawHistoryRecordsText(void)434 static void DrawHistoryRecordsText(void)
435 {
436 ST::string sString;
437 INT16 sX;
438 INT16 sY;
439
440 SetFont(HISTORY_TEXT_FONT);
441 SetFontBackground(FONT_BLACK);
442 SetFontShadow(NO_SHADOW);
443
444 UINT entry_count = 0;
445 for (const HistoryUnit* h = pHistoryListHead; h != NULL; h = h->Next)
446 {
447 const UINT8 colour =
448 h->ubCode == HISTORY_CHEAT_ENABLED ||
449 (h->ubCode == HISTORY_QUEST_STARTED && gubQuest[h->ubSecondCode] == QUESTINPROGRESS) ?
450 FONT_RED : FONT_BLACK;
451 SetFontForeground(colour);
452
453 const INT32 y = RECORD_Y + entry_count * BOX_HEIGHT + 3;
454
455 // get and write the date
456 sString = ST::format("{}", h->uiDate / (24 * 60));
457 INT16 usX;
458 INT16 usY;
459 FindFontCenterCoordinates(RECORD_DATE_X + 5, 0, RECORD_DATE_WIDTH, 0, sString, HISTORY_TEXT_FONT, &usX, &usY);
460 MPrint(usX, y, sString);
461
462 if (h->sSectorX == -1 || h->sSectorY == -1)
463 {
464 // no location
465 FindFontCenterCoordinates(RECORD_DATE_X + RECORD_DATE_WIDTH, 0, RECORD_LOCATION_WIDTH + 10, 0, pHistoryLocations, HISTORY_TEXT_FONT, &sX, &sY);
466 MPrint(sX, y, pHistoryLocations);
467 }
468 else
469 {
470 sString = GetSectorIDString(h->sSectorX, h->sSectorY, h->bSectorZ, TRUE);
471 FindFontCenterCoordinates(RECORD_DATE_X + RECORD_DATE_WIDTH, 0, RECORD_LOCATION_WIDTH + 10, 0, sString, HISTORY_TEXT_FONT, &sX, &sY);
472 sString = ReduceStringLength(sString, RECORD_LOCATION_WIDTH + 10, HISTORY_TEXT_FONT);
473 MPrint(sX, y, sString);
474 }
475
476 // the actual history text
477 sString = ProcessHistoryTransactionString(h);
478 MPrint(RECORD_DATE_X + RECORD_LOCATION_WIDTH + RECORD_DATE_WIDTH + 15, y, sString);
479
480 if (++entry_count == NUM_RECORDS_PER_PAGE) break;
481 }
482
483 // restore shadow
484 SetFontShadow(DEFAULT_SHADOW);
485 }
486
487
488 static void DisplayPageNumberAndDateRange(void);
489
490
DrawAPageofHistoryRecords(void)491 static void DrawAPageofHistoryRecords(void)
492 {
493 // this procedure will draw a series of history records to the screen
494
495 // (re-)render background
496
497 // the title bar text
498 DrawHistoryTitleText( );
499
500 // the actual lists background
501 DisplayHistoryListBackground( );
502
503 // the headers to each column
504 DisplayHistoryListHeaders( );
505
506
507 // error check
508 if(iCurrentHistoryPage==-1)
509 {
510 iCurrentHistoryPage=0;
511 }
512
513
514 // current page is found, render from here
515 DrawHistoryRecordsText( );
516
517 // update page numbers, and date ranges
518 DisplayPageNumberAndDateRange( );
519 }
520
521
522 static INT32 GetNumberOfHistoryPages(void);
523
524
525 /* go through the list of 'histories' starting at current until end or
526 * NUM_RECORDS_PER_PAGE and get the date range and the page number */
DisplayPageNumberAndDateRange(void)527 static void DisplayPageNumberAndDateRange(void)
528 {
529 UINT current_page;
530 UINT count_pages;
531 UINT first_date;
532 UINT last_date;
533 const HistoryUnit* h = pHistoryListHead;
534 if (h == NULL)
535 {
536 current_page = 1;
537 count_pages = 1;
538 first_date = 1;
539 last_date = 1;
540 }
541 else
542 {
543 current_page = iCurrentHistoryPage;
544 count_pages = GetNumberOfHistoryPages();
545 first_date = h->uiDate / (24 * 60);
546
547 UINT entry_count = NUM_RECORDS_PER_PAGE;
548 while (--entry_count != 0 && h->Next != NULL) h = h->Next;
549
550 last_date = h->uiDate / (24 * 60);
551 }
552
553 SetFontAttributes(HISTORY_TEXT_FONT, FONT_BLACK, NO_SHADOW);
554 MPrint(PAGE_NUMBER_X, PAGE_NUMBER_Y, ST::format("{} {} / {}", pHistoryHeaders[1], current_page, count_pages));
555 MPrint(HISTORY_DATE_X, HISTORY_DATE_Y, ST::format("{} {} - {}", pHistoryHeaders[2], first_date, last_date));
556 SetFontShadow(DEFAULT_SHADOW);
557 }
558
559
560 static ST::string GetQuestEndedString(UINT8 ubQuestValue);
561 static ST::string GetQuestStartedString(UINT8 ubQuestValue);
562
563
ProcessHistoryTransactionString(const HistoryUnit * h)564 static ST::string ProcessHistoryTransactionString(const HistoryUnit* h)
565 {
566 const UINT8 code = h->ubCode;
567 switch (code)
568 {
569 case HISTORY_QUEST_STARTED:
570 return GetQuestStartedString(h->ubSecondCode);
571
572 case HISTORY_QUEST_FINISHED:
573 return GetQuestEndedString(h->ubSecondCode);
574
575 case HISTORY_LIBERATED_TOWN:
576 case HISTORY_MINE_RAN_OUT:
577 case HISTORY_MINE_REOPENED:
578 case HISTORY_MINE_RUNNING_OUT:
579 case HISTORY_MINE_SHUTDOWN:
580 case HISTORY_TALKED_TO_MINER:
581 return st_format_printf(pHistoryStrings[code], GCM->getTownName(h->ubSecondCode));
582
583 case HISTORY_MERC_KILLED:
584 if (h->ubSecondCode == NO_PROFILE)
585 {
586 break;
587 }
588 return st_format_printf(pHistoryStrings[code], GetProfile(h->ubSecondCode).zName);
589
590 case HISTORY_HIRED_MERC_FROM_AIM:
591 case HISTORY_HIRED_MERC_FROM_MERC:
592 case HISTORY_MERC_CONTRACT_EXPIRED:
593 case HISTORY_RPC_JOINED_TEAM:
594 return st_format_printf(pHistoryStrings[code], GetProfile(h->ubSecondCode).zName);
595
596 case HISTORY_CANCELLED_INSURANCE:
597 case HISTORY_DISQUALIFIED_BOXING:
598 case HISTORY_EXTENDED_CONTRACT_1_DAY:
599 case HISTORY_EXTENDED_CONTRACT_1_WEEK:
600 case HISTORY_EXTENDED_CONTRACT_2_WEEK:
601 case HISTORY_INSURANCE_CLAIM_PAYOUT:
602 case HISTORY_LOST_BOXING:
603 case HISTORY_MERC_FIRED:
604 case HISTORY_MERC_KILLED_CHARACTER:
605 case HISTORY_MERC_MARRIED_OFF:
606 case HISTORY_MERC_QUIT:
607 case HISTORY_NPC_KILLED:
608 case HISTORY_PURCHASED_INSURANCE:
609 case HISTORY_WON_BOXING:
610 return st_format_printf(pHistoryStrings[code], GetProfile(h->ubSecondCode).zNickname);
611
612 // all simple history log msgs, no params
613 case HISTORY_ACCEPTED_ASSIGNMENT_FROM_ENRICO:
614 case HISTORY_ARNOLD:
615 case HISTORY_ASSASSIN:
616 case HISTORY_BOXING_MATCHES:
617 case HISTORY_BUM_KEYCARD:
618 case HISTORY_CHARACTER_GENERATED:
619 case HISTORY_CHEAT_ENABLED:
620 case HISTORY_CREATURESATTACKED:
621 case HISTORY_DAVE:
622 case HISTORY_DEFENDEDTOWNSECTOR:
623 case HISTORY_DEIDRANNA_DEAD_BODIES:
624 case HISTORY_DEVIN:
625 case HISTORY_DISCOVERED_ORTA:
626 case HISTORY_DISCOVERED_TIXA:
627 case HISTORY_ENRICO_COMPLAINED:
628 case HISTORY_ENTERED_HISTORY_MODE:
629 case HISTORY_FATALAMBUSH:
630 case HISTORY_FOUND_MONEY:
631 case HISTORY_FRANZ:
632 case HISTORY_FREDO:
633 case HISTORY_GABBY:
634 case HISTORY_GAVE_CARMEN_HEAD:
635 case HISTORY_GOT_ROCKET_RIFLES:
636 case HISTORY_HOWARD:
637 case HISTORY_HOWARD_CYANIDE:
638 case HISTORY_JAKE:
639 case HISTORY_KEITH:
640 case HISTORY_KEITH_OUT_OF_BUSINESS:
641 case HISTORY_KILLEDBYBLOODCATS:
642 case HISTORY_KINGPIN_MONEY:
643 case HISTORY_KROTT:
644 case HISTORY_KYLE:
645 case HISTORY_LOSTBATTLE:
646 case HISTORY_LOSTTOWNSECTOR:
647 case HISTORY_MADLAB:
648 case HISTORY_MIKE:
649 case HISTORY_PABLO:
650 case HISTORY_PERKO:
651 case HISTORY_RICHGUY_BALIME:
652 case HISTORY_SAM:
653 case HISTORY_SETTLED_ACCOUNTS_AT_MERC:
654 case HISTORY_SLAUGHTEREDBLOODCATS:
655 case HISTORY_SLAY_MYSTERIOUSLY_LEFT:
656 case HISTORY_SOMETHING_IN_MINES:
657 case HISTORY_SUCCESSFULATTACK:
658 case HISTORY_TALKED_TO_FATHER_WALKER:
659 case HISTORY_TONY:
660 case HISTORY_UNSUCCESSFULATTACK:
661 case HISTORY_WALTER:
662 case HISTORY_WIPEDOUTENEMYAMBUSH:
663 case HISTORY_WONBATTLE:
664 return pHistoryStrings[code];
665 }
666 return ST::null;
667 }
668
669
670 // look at what page we are viewing, enable and disable buttons as needed
SetHistoryButtonStates(void)671 static void SetHistoryButtonStates(void)
672 {
673 EnableButton(giHistoryButton[PREV_PAGE_BUTTON], iCurrentHistoryPage != 1);
674 EnableButton(giHistoryButton[NEXT_PAGE_BUTTON], iCurrentHistoryPage < GetNumberOfHistoryPages());
675 }
676
677
678 // loads in records belogning, to page uiPage
LoadInHistoryRecords(const UINT32 uiPage)679 static BOOLEAN LoadInHistoryRecords(const UINT32 uiPage)
680 try
681 {
682 ClearHistoryList();
683
684 // check if bad page
685 if (uiPage == 0) return FALSE;
686
687 AutoSGPFile f(GCM->openGameResForReading(HISTORY_DATA_FILE));
688
689 UINT entry_count = FileGetSize(f) / SIZE_OF_HISTORY_FILE_RECORD;
690 UINT const skip = (uiPage - 1) * NUM_RECORDS_PER_PAGE;
691 if (entry_count <= skip) return FALSE;
692
693 FileSeek(f, skip * SIZE_OF_HISTORY_FILE_RECORD, FILE_SEEK_FROM_START);
694 entry_count -= skip;
695
696 if (entry_count > NUM_RECORDS_PER_PAGE) entry_count = NUM_RECORDS_PER_PAGE;
697
698 while (entry_count-- > 0)
699 {
700 UINT8 ubCode;
701 UINT8 ubSecondCode;
702 UINT32 uiDate;
703 INT16 sSectorX;
704 INT16 sSectorY;
705 INT8 bSectorZ;
706
707 FileRead(f, &ubCode, sizeof(UINT8));
708 FileRead(f, &ubSecondCode, sizeof(UINT8));
709 FileRead(f, &uiDate, sizeof(UINT32));
710 FileRead(f, &sSectorX, sizeof(INT16));
711 FileRead(f, &sSectorY, sizeof(INT16));
712 FileRead(f, &bSectorZ, sizeof(INT8));
713 FileSeek(f, 1, FILE_SEEK_FROM_CURRENT);
714
715 ProcessAndEnterAHistoryRecord(ubCode, uiDate, ubSecondCode, sSectorX, sSectorY, bSectorZ);
716 }
717
718 return TRUE;
719 }
720 catch (...) { return FALSE; }
721
722
723 // clear out old list of records, and load in next page worth of records
LoadNextHistoryPage(void)724 static void LoadNextHistoryPage(void)
725 {
726 // now load in previous page's records, if we can
727 if ( LoadInHistoryRecords( iCurrentHistoryPage + 1 ) )
728 {
729 iCurrentHistoryPage++;
730 }
731 else
732 {
733 LoadInHistoryRecords( iCurrentHistoryPage );
734 }
735 SetHistoryButtonStates();
736 fReDrawScreenFlag = TRUE;
737 }
738
739
740 // clear out old list of records and load in previous page worth of records
LoadPreviousHistoryPage(void)741 static void LoadPreviousHistoryPage(void)
742 {
743 if (iCurrentHistoryPage <= 1) return;
744 LoadInHistoryRecords(--iCurrentHistoryPage);
745 SetHistoryButtonStates();
746 fReDrawScreenFlag = TRUE;
747 }
748
749
AppendHistoryToEndOfFile(void)750 static void AppendHistoryToEndOfFile(void)
751 {
752 AutoSGPFile f(FileMan::openForAppend(HISTORY_DATA_FILE));
753
754 const HistoryUnit* const h = pHistoryListHead;
755
756 BYTE data[12];
757 DataWriter d{data};
758 INJ_U8(d, h->ubCode)
759 INJ_U8(d, h->ubSecondCode)
760 INJ_U32(d, h->uiDate)
761 INJ_I16(d, h->sSectorX)
762 INJ_I16(d, h->sSectorY)
763 INJ_I8(d, h->bSectorZ)
764 INJ_SKIP(d, 1)
765 Assert(d.getConsumed() == lengthof(data));
766
767 FileWrite(f, data, sizeof(data));
768 }
769
770
GetTimeQuestWasStarted(const UINT8 ubCode)771 UINT32 GetTimeQuestWasStarted(const UINT8 ubCode)
772 {
773 iCurrentHistoryPage = 0;
774 OpenAndReadHistoryFile();
775
776 UINT32 uiTime = 0;
777 for (const HistoryUnit* h = pHistoryListHead; h != NULL; h = h->Next)
778 {
779 if (h->ubSecondCode == ubCode && h->ubCode == HISTORY_QUEST_STARTED)
780 {
781 uiTime = h->uiDate;
782 break;
783 }
784 }
785
786 if (fInHistoryMode) LoadInHistoryRecords(iCurrentHistoryPage);
787
788 return uiTime;
789 }
790
791
GetQuestStartedString(const UINT8 ubQuestValue)792 static ST::string GetQuestStartedString(const UINT8 ubQuestValue)
793 {
794 // open the file and copy the string
795 return GCM->loadEncryptedString(BINARYDATADIR "/quests.edt", HISTORY_QUEST_TEXT_SIZE * ubQuestValue * 2, HISTORY_QUEST_TEXT_SIZE);
796 }
797
798
GetQuestEndedString(const UINT8 ubQuestValue)799 static ST::string GetQuestEndedString(const UINT8 ubQuestValue)
800 {
801 // open the file and copy the string
802 return GCM->loadEncryptedString(BINARYDATADIR "/quests.edt", HISTORY_QUEST_TEXT_SIZE * (ubQuestValue * 2 + 1), HISTORY_QUEST_TEXT_SIZE);
803 }
804
GetNumberOfHistoryPages(void)805 static INT32 GetNumberOfHistoryPages(void)
806 {
807 AutoSGPFile f(GCM->openGameResForReading(HISTORY_DATA_FILE));
808
809 const UINT32 uiFileSize = FileGetSize(f);
810
811 if (uiFileSize == 0) return 1;
812
813 return (uiFileSize / SIZE_OF_HISTORY_FILE_RECORD + NUM_RECORDS_PER_PAGE - 1) / NUM_RECORDS_PER_PAGE;
814 }
815