1 #include "Directories.h"
2 #include "Font.h"
3 #include "Interface.h"
4 #include "Local.h"
5 #include "Map_Screen_Interface_Bottom.h"
6 #include "Map_Screen_Interface_Border.h"
7 #include "MessageBoxScreen.h"
8 #include "Timer_Control.h"
9 #include "Types.h"
10 #include "VObject.h"
11 #include "VSurface.h"
12 #include "MouseSystem.h"
13 #include "Button_System.h"
14 #include "Message.h"
15 #include "MapScreen.h"
16 #include "StrategicMap.h"
17 #include "Font_Control.h"
18 #include "Radar_Screen.h"
19 #include "Game_Clock.h"
20 #include "SysUtil.h"
21 #include "Render_Dirty.h"
22 #include "Map_Screen_Interface.h"
23 #include "Map_Screen_Interface_Map.h"
24 #include "Text.h"
25 #include "Overhead.h"
26 #include "PreBattle_Interface.h"
27 #include "Options_Screen.h"
28 #include "Cursor_Control.h"
29 #include "GameLoop.h"
30 #include "AI.h"
31 #include "Tactical_Save.h"
32 #include "Campaign_Types.h"
33 #include "Finances.h"
34 #include "LaptopSave.h"
35 #include "Interface_Items.h"
36 #include "WordWrap.h"
37 #include "Dialogue_Control.h"
38 #include "Meanwhile.h"
39 #include "Map_Screen_Helicopter.h"
40 #include "Map_Screen_Interface_TownMine_Info.h"
41 #include "Merc_Contract.h"
42 #include "Map_Screen_Interface_Map_Inventory.h"
43 #include "Explosion_Control.h"
44 #include "Creature_Spreading.h"
45 #include "Soldier_Macros.h"
46 #include "GameSettings.h"
47 #include "SaveLoadScreen.h"
48 #include "Debug.h"
49 #include "JAScreens.h"
50 #include "ScreenIDs.h"
51 #include "UILayout.h"
52
53 #include <string_theory/string>
54
55
56 #define MAP_BOTTOM_X (STD_SCREEN_X + 0)
57 #define MAP_BOTTOM_Y (STD_SCREEN_Y + 359)
58
59 #define MESSAGE_BOX_X (STD_SCREEN_X + 17)
60 #define MESSAGE_BOX_Y (STD_SCREEN_Y + 377)
61 #define MESSAGE_BOX_W 301
62 #define MESSAGE_BOX_H 86
63
64 #define MESSAGE_SCROLL_AREA_START_X (STD_SCREEN_X + 330)
65 #define MESSAGE_SCROLL_AREA_WIDTH 15
66
67 #define MESSAGE_SCROLL_AREA_START_Y (STD_SCREEN_Y + 390)
68 #define MESSAGE_SCROLL_AREA_HEIGHT 59
69
70 #define SLIDER_HEIGHT 11
71 #define SLIDER_WIDTH 11
72
73 #define SLIDER_BAR_RANGE ( MESSAGE_SCROLL_AREA_HEIGHT - SLIDER_HEIGHT )
74
75
76
77 #define MESSAGE_BTN_SCROLL_TIME 100
78
79 // delay for paused flash
80 #define PAUSE_GAME_TIMER 500
81
82 #define MAP_BOTTOM_FONT_COLOR ( 32 * 4 - 9 )
83
84 // button enums
85 enum{
86 MAP_SCROLL_MESSAGE_UP =0,
87 MAP_SCROLL_MESSAGE_DOWN,
88 };
89
90 enum{
91 MAP_TIME_COMPRESS_MORE = 0,
92 MAP_TIME_COMPRESS_LESS,
93 };
94
95
96 BOOLEAN fMapScreenBottomDirty = TRUE;
97
98 static BOOLEAN fMapBottomDirtied = FALSE;
99
100 //Used to flag the transition animation from mapscreen to laptop.
101 BOOLEAN gfStartMapScreenToLaptopTransition = FALSE;
102
103 // leaving map screen
104 BOOLEAN fLeavingMapScreen = FALSE;
105
106 // don't start transition from laptop to tactical stuff
107 BOOLEAN gfDontStartTransitionFromLaptop = FALSE;
108
109 // exiting to laptop?
110 BOOLEAN fLapTop = FALSE;
111
112 static BOOLEAN gfOneFramePauseOnExit = FALSE;
113
114 // exit states
115 static ExitToWhere gbExitingMapScreenToWhere = MAP_EXIT_TO_INVALID;
116
117 static UINT8 gubFirstMapscreenMessageIndex = 0;
118
119 UINT32 guiCompressionStringBaseTime = 0;
120
121 // graphics
122 static SGPVObject* guiMAPBOTTOMPANEL;
123 static SGPVObject* guiSliderBar;
124
125 // buttons
126 GUIButtonRef guiMapBottomExitButtons[3];
127 static GUIButtonRef guiMapBottomTimeButtons[2];
128 static GUIButtonRef guiMapMessageScrollButtons[2];
129
130 // mouse regions
131 static MOUSE_REGION gMapMessageScrollBarRegion;
132 static MOUSE_REGION gMapPauseRegion;
133
134 static MOUSE_REGION gTimeCompressionMask[3];
135
136
137 static void BtnLaptopCallback(GUI_BUTTON *btn, INT32 reason);
138 static void BtnTacticalCallback(GUI_BUTTON *btn, INT32 reason);
139 static void BtnOptionsFromMapScreenCallback(GUI_BUTTON *btn, INT32 reason);
140
141 static void BtnTimeCompressMoreMapScreenCallback(GUI_BUTTON *btn, INT32 reason);
142 static void BtnTimeCompressLessMapScreenCallback(GUI_BUTTON *btn, INT32 reason);
143
144 static void BtnMessageDownMapScreenCallback(GUI_BUTTON *btn, INT32 reason);
145 static void BtnMessageUpMapScreenCallback(GUI_BUTTON *btn, INT32 reason);
146
147
148 static void LoadMessageSliderBar(void);
149
150
HandleLoadOfMapBottomGraphics(void)151 void HandleLoadOfMapBottomGraphics( void )
152 {
153 // will load the graphics needed for the mapscreen interface bottom
154 // will create buttons for interface bottom
155 guiMAPBOTTOMPANEL = AddVideoObjectFromFile(INTERFACEDIR "/map_screen_bottom.sti");
156
157 // load slider bar icon
158 LoadMessageSliderBar( );
159 }
160
161
162 static void CreateButtonsForMapScreenInterfaceBottom(void);
163 static void CreateCompressModePause(void);
164 static void CreateMapScreenBottomMessageScrollBarRegion(void);
165
166
LoadMapScreenInterfaceBottom(void)167 void LoadMapScreenInterfaceBottom(void)
168 {
169 CreateButtonsForMapScreenInterfaceBottom();
170 CreateMapScreenBottomMessageScrollBarRegion( );
171
172 // create pause region
173 CreateCompressModePause( );
174 }
175
176
177 static void DeleteMessageSliderBar(void);
178
179
DeleteMapBottomGraphics(void)180 void DeleteMapBottomGraphics( void )
181 {
182 DeleteVideoObject(guiMAPBOTTOMPANEL);
183 // delete slider bar icon
184 DeleteMessageSliderBar( );
185 }
186
187
188 static void DeleteMapScreenBottomMessageScrollRegion(void);
189 static void DestroyButtonsForMapScreenInterfaceBottom();
190 static void RemoveCompressModePause(void);
191
192
DeleteMapScreenInterfaceBottom(void)193 void DeleteMapScreenInterfaceBottom( void )
194 {
195 // will delete graphics loaded for the mapscreen interface bottom
196
197 DestroyButtonsForMapScreenInterfaceBottom( );
198 DeleteMapScreenBottomMessageScrollRegion( );
199
200 // remove comrpess mode pause
201 RemoveCompressModePause( );
202 }
203
204
205 static void DisplayCompressMode(void);
206 static void DisplayCurrentBalanceForMapBottom(void);
207 static void DisplayCurrentBalanceTitleForMapBottom(void);
208 static void DisplayProjectedDailyMineIncome(void);
209 static void DisplayScrollBarSlider(void);
210 static void DrawNameOfLoadedSector();
211 static void EnableDisableBottomButtonsAndRegions(void);
212 static void EnableDisableMessageScrollButtonsAndRegions(void);
213
214
RenderMapScreenInterfaceBottom(void)215 void RenderMapScreenInterfaceBottom( void )
216 {
217 // will render the map screen bottom interface
218 CHAR8 bFilename[ 32 ];
219
220
221 // render whole panel
222 if (fMapScreenBottomDirty)
223 {
224 BltVideoObject(guiSAVEBUFFER, guiMAPBOTTOMPANEL, 0, MAP_BOTTOM_X, MAP_BOTTOM_Y);
225
226 if (GetSectorFlagStatus(sSelMapX, sSelMapY, iCurrentMapSectorZ, SF_ALREADY_VISITED))
227 {
228 GetMapFileName(sSelMapX, sSelMapY, iCurrentMapSectorZ, bFilename, TRUE);
229 LoadRadarScreenBitmap( bFilename );
230 }
231 else
232 {
233 ClearOutRadarMapImage();
234 }
235
236 fInterfacePanelDirty = DIRTYLEVEL2;
237
238 // display title
239 DisplayCurrentBalanceTitleForMapBottom( );
240
241 // dirty buttons
242 MarkButtonsDirty( );
243
244 // invalidate region
245 RestoreExternBackgroundRect(MAP_BOTTOM_X, MAP_BOTTOM_Y, SCREEN_WIDTH - MAP_BOTTOM_X, SCREEN_HEIGHT - MAP_BOTTOM_Y);
246
247 // re render radar map
248 RenderRadarScreen( );
249
250 // reset dirty flag
251 fMapScreenBottomDirty = FALSE;
252 fMapBottomDirtied = TRUE;
253 }
254
255 DisplayCompressMode( );
256
257 DisplayCurrentBalanceForMapBottom( );
258 DisplayProjectedDailyMineIncome( );
259
260 // draw the name of the loaded sector
261 DrawNameOfLoadedSector( );
262
263 // display slider on the scroll bar
264 DisplayScrollBarSlider( );
265
266 // display messages that can be scrolled through
267 DisplayStringsInMapScreenMessageList( );
268
269 EnableDisableMessageScrollButtonsAndRegions( );
270
271 EnableDisableBottomButtonsAndRegions( );
272
273 fMapBottomDirtied = FALSE;
274 }
275
276
MakeExitButton(INT32 off,INT32 on,INT16 x,INT16 y,GUI_CALLBACK click,const ST::string & help)277 static GUIButtonRef MakeExitButton(INT32 off, INT32 on, INT16 x, INT16 y, GUI_CALLBACK click, const ST::string& help)
278 {
279 GUIButtonRef const btn = QuickCreateButtonImg(INTERFACEDIR "/map_border_buttons.sti", off, on, x, y, MSYS_PRIORITY_HIGHEST - 1, click);
280 btn->SetFastHelpText(help);
281 btn->SetCursor(MSYS_NO_CURSOR);
282 return btn;
283 }
284
285
MakeArrowButton(INT32 grayed,INT32 off,INT32 on,INT16 x,INT16 y,GUI_CALLBACK click,const ST::string & help)286 static GUIButtonRef MakeArrowButton(INT32 grayed, INT32 off, INT32 on, INT16 x, INT16 y, GUI_CALLBACK click, const ST::string& help)
287 {
288 GUIButtonRef const btn = QuickCreateButtonImg(INTERFACEDIR "/map_screen_bottom_arrows.sti", grayed, off, -1, on, -1, x, y, MSYS_PRIORITY_HIGHEST - 2, click);
289 btn->SetFastHelpText(help);
290 btn->SetCursor(MSYS_NO_CURSOR);
291 return btn;
292 }
293
294
CreateButtonsForMapScreenInterfaceBottom(void)295 static void CreateButtonsForMapScreenInterfaceBottom(void)
296 {
297 guiMapBottomExitButtons[MAP_EXIT_TO_LAPTOP] = MakeExitButton( 6, 15, STD_SCREEN_X + 456, STD_SCREEN_Y + 410, BtnLaptopCallback, pMapScreenBottomFastHelp[0]);
298 guiMapBottomExitButtons[MAP_EXIT_TO_TACTICAL] = MakeExitButton( 7, 16, STD_SCREEN_X + 496, STD_SCREEN_Y + 410, BtnTacticalCallback, pMapScreenBottomFastHelp[1]);
299 guiMapBottomExitButtons[MAP_EXIT_TO_OPTIONS] = MakeExitButton(18, 19, STD_SCREEN_X + 458, STD_SCREEN_Y + 372, BtnOptionsFromMapScreenCallback, pMapScreenBottomFastHelp[2]);
300
301 // time compression buttons
302 guiMapBottomTimeButtons[MAP_TIME_COMPRESS_MORE] = MakeArrowButton(10, 1, 3, STD_SCREEN_X + 528, STD_SCREEN_Y + 456, BtnTimeCompressMoreMapScreenCallback, pMapScreenBottomFastHelp[3]);
303 guiMapBottomTimeButtons[MAP_TIME_COMPRESS_LESS] = MakeArrowButton( 9, 0, 2, STD_SCREEN_X + 466, STD_SCREEN_Y + 456, BtnTimeCompressLessMapScreenCallback, pMapScreenBottomFastHelp[4]);
304
305 // scroll buttons
306 guiMapMessageScrollButtons[MAP_SCROLL_MESSAGE_UP] = MakeArrowButton(11, 4, 6, STD_SCREEN_X + 331, STD_SCREEN_Y + 371, BtnMessageUpMapScreenCallback, pMapScreenBottomFastHelp[5]);
307 guiMapMessageScrollButtons[MAP_SCROLL_MESSAGE_DOWN] = MakeArrowButton(12, 5, 7, STD_SCREEN_X + 331, STD_SCREEN_Y + 452, BtnMessageDownMapScreenCallback, pMapScreenBottomFastHelp[6]);
308 }
309
310
DestroyButtonsForMapScreenInterfaceBottom()311 static void DestroyButtonsForMapScreenInterfaceBottom()
312 {
313 FOR_EACH(GUIButtonRef, i, guiMapBottomExitButtons) RemoveButton(*i);
314 FOR_EACH(GUIButtonRef, i, guiMapBottomTimeButtons) RemoveButton(*i);
315 FOR_EACH(GUIButtonRef, i, guiMapMessageScrollButtons) RemoveButton(*i);
316 fMapScreenBottomDirty = TRUE;
317 }
318
319
BtnLaptopCallback(GUI_BUTTON * btn,INT32 reason)320 static void BtnLaptopCallback(GUI_BUTTON *btn, INT32 reason)
321 {
322 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
323 {
324 // redraw region
325 if (btn->Area.uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
326 }
327 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
328 {
329 RequestTriggerExitFromMapscreen(MAP_EXIT_TO_LAPTOP);
330 }
331 }
332
333
BtnTacticalCallback(GUI_BUTTON * btn,INT32 reason)334 static void BtnTacticalCallback(GUI_BUTTON *btn, INT32 reason)
335 {
336 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
337 {
338 // redraw region
339 if (btn->Area.uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
340 }
341 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
342 {
343 RequestTriggerExitFromMapscreen(MAP_EXIT_TO_TACTICAL);
344 }
345 }
346
347
BtnOptionsFromMapScreenCallback(GUI_BUTTON * btn,INT32 reason)348 static void BtnOptionsFromMapScreenCallback(GUI_BUTTON *btn, INT32 reason)
349 {
350 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
351 {
352 // redraw region
353 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
354 }
355 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
356 {
357 fMapScreenBottomDirty = TRUE;
358 RequestTriggerExitFromMapscreen(MAP_EXIT_TO_OPTIONS);
359 }
360 }
361
362
DrawNameOfLoadedSector()363 static void DrawNameOfLoadedSector()
364 {
365 SetFontDestBuffer(FRAME_BUFFER);
366 SGPFont const font = COMPFONT;
367 SetFontAttributes(font, 183);
368
369 ST::string buf = GetSectorIDString(sSelMapX, sSelMapY, iCurrentMapSectorZ, TRUE);
370 buf = ReduceStringLength(buf, 80, font);
371
372 INT16 x;
373 INT16 y;
374 FindFontCenterCoordinates(STD_SCREEN_X + 548, STD_SCREEN_Y + 426, 80, 16, buf, font, &x, &y);
375 MPrint(x, y, buf);
376 }
377
378
CompressModeClickCallback(MOUSE_REGION * pRegion,INT32 iReason)379 static void CompressModeClickCallback(MOUSE_REGION* pRegion, INT32 iReason)
380 {
381 if( iReason & ( MSYS_CALLBACK_REASON_RBUTTON_UP | MSYS_CALLBACK_REASON_LBUTTON_UP ) )
382 {
383 if (CommonTimeCompressionChecks()) return;
384
385 RequestToggleTimeCompression();
386 }
387 }
388
389
BtnTimeCompressMoreMapScreenCallback(GUI_BUTTON * btn,INT32 reason)390 static void BtnTimeCompressMoreMapScreenCallback(GUI_BUTTON *btn, INT32 reason)
391 {
392 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
393 {
394 if (CommonTimeCompressionChecks()) return;
395 // redraw region
396 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
397 }
398 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
399 {
400 fMapScreenBottomDirty = TRUE;
401 RequestIncreaseInTimeCompression();
402 }
403 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
404 {
405 CommonTimeCompressionChecks();
406 }
407 }
408
409
BtnTimeCompressLessMapScreenCallback(GUI_BUTTON * btn,INT32 reason)410 static void BtnTimeCompressLessMapScreenCallback(GUI_BUTTON *btn, INT32 reason)
411 {
412 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
413 {
414 if (CommonTimeCompressionChecks()) return;
415 // redraw region
416 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
417 }
418 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
419 {
420 fMapScreenBottomDirty = TRUE;
421 RequestDecreaseInTimeCompression();
422 }
423 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
424 {
425 CommonTimeCompressionChecks();
426 }
427 }
428
429
BtnMessageDownMapScreenCallback(GUI_BUTTON * btn,INT32 reason)430 static void BtnMessageDownMapScreenCallback(GUI_BUTTON *btn, INT32 reason)
431 {
432 static INT32 iLastRepeatScrollTime = 0;
433
434 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
435 {
436 // redraw region
437 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
438 iLastRepeatScrollTime = 0;
439 }
440 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
441 {
442 // redraw region
443 if (btn ->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
444 MapScreenMsgScrollDown(1);
445 }
446 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_REPEAT)
447 {
448 if (GetJA2Clock() - iLastRepeatScrollTime >= MESSAGE_BTN_SCROLL_TIME)
449 {
450 MapScreenMsgScrollDown(1);
451 iLastRepeatScrollTime = GetJA2Clock();
452 }
453 }
454 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
455 {
456 // redraw region
457 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
458 iLastRepeatScrollTime = 0;
459 }
460 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_UP)
461 {
462 // redraw region
463 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
464 MapScreenMsgScrollDown(MAX_MESSAGES_ON_MAP_BOTTOM);
465 }
466 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_REPEAT)
467 {
468 if (GetJA2Clock() - iLastRepeatScrollTime >= MESSAGE_BTN_SCROLL_TIME)
469 {
470 MapScreenMsgScrollDown(MAX_MESSAGES_ON_MAP_BOTTOM);
471 iLastRepeatScrollTime = GetJA2Clock();
472 }
473 }
474 }
475
476
BtnMessageUpMapScreenCallback(GUI_BUTTON * btn,INT32 reason)477 static void BtnMessageUpMapScreenCallback(GUI_BUTTON *btn, INT32 reason)
478 {
479 static INT32 iLastRepeatScrollTime = 0;
480
481 if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
482 {
483 // redraw region
484 if (btn->Area.uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
485 iLastRepeatScrollTime = 0;
486 }
487 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
488 {
489 // redraw region
490 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
491 MapScreenMsgScrollUp(1);
492 }
493 else if (reason & MSYS_CALLBACK_REASON_LBUTTON_REPEAT)
494 {
495 if (GetJA2Clock() - iLastRepeatScrollTime >= MESSAGE_BTN_SCROLL_TIME)
496 {
497 MapScreenMsgScrollUp(1);
498 iLastRepeatScrollTime = GetJA2Clock();
499 }
500 }
501 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
502 {
503 // redraw region
504 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
505 iLastRepeatScrollTime = 0;
506 }
507 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_UP)
508 {
509 // redraw region
510 if (btn->uiFlags & MSYS_HAS_BACKRECT) fMapScreenBottomDirty = TRUE;
511 MapScreenMsgScrollUp(MAX_MESSAGES_ON_MAP_BOTTOM);
512 }
513 else if (reason & MSYS_CALLBACK_REASON_RBUTTON_REPEAT)
514 {
515 if (GetJA2Clock() - iLastRepeatScrollTime >= MESSAGE_BTN_SCROLL_TIME)
516 {
517 MapScreenMsgScrollUp(MAX_MESSAGES_ON_MAP_BOTTOM);
518 iLastRepeatScrollTime = GetJA2Clock();
519 }
520 }
521 }
522
523
EnableDisableMessageScrollButtonsAndRegions(void)524 static void EnableDisableMessageScrollButtonsAndRegions(void)
525 {
526 UINT8 ubNumMessages;
527
528 ubNumMessages = GetRangeOfMapScreenMessages();
529
530 // if no scrolling required, or already showing the topmost message
531 if( ( ubNumMessages <= MAX_MESSAGES_ON_MAP_BOTTOM ) || ( gubFirstMapscreenMessageIndex == 0 ) )
532 {
533 DisableButton( guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_UP ] );
534 guiMapMessageScrollButtons[MAP_SCROLL_MESSAGE_UP]->uiFlags &= ~BUTTON_CLICKED_ON;
535 }
536 else
537 {
538 EnableButton( guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_UP ] );
539 }
540
541 // if no scrolling required, or already showing the last message
542 if( ( ubNumMessages <= MAX_MESSAGES_ON_MAP_BOTTOM ) ||
543 ( ( gubFirstMapscreenMessageIndex + MAX_MESSAGES_ON_MAP_BOTTOM ) >= ubNumMessages ) )
544 {
545 DisableButton( guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_DOWN ] );
546 guiMapMessageScrollButtons[MAP_SCROLL_MESSAGE_DOWN]->uiFlags &= ~BUTTON_CLICKED_ON;
547 }
548 else
549 {
550 EnableButton( guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_DOWN ] );
551 }
552
553 if( ubNumMessages <= MAX_MESSAGES_ON_MAP_BOTTOM )
554 {
555 gMapMessageScrollBarRegion.Disable();
556 }
557 else
558 {
559 gMapMessageScrollBarRegion.Enable();
560 }
561 }
562
563
DisplayCompressMode(void)564 static void DisplayCompressMode(void)
565 {
566 INT16 sX, sY;
567 static UINT8 usColor = FONT_LTGREEN;
568
569 // get compress speed
570 ST::string Time;
571 if( giTimeCompressMode != NOT_USING_TIME_COMPRESSION )
572 {
573 Time = sTimeStrings[IsTimeBeingCompressed() ? giTimeCompressMode : 0];
574 }
575
576 RestoreExternBackgroundRect( STD_SCREEN_X + 489, STD_SCREEN_Y + 457, 522 - 489, 467 - 454 );
577 SetFontDestBuffer(FRAME_BUFFER);
578
579 if( GetJA2Clock() - guiCompressionStringBaseTime >= PAUSE_GAME_TIMER )
580 {
581 if( usColor == FONT_LTGREEN )
582 {
583 usColor = FONT_WHITE;
584 }
585 else
586 {
587 usColor = FONT_LTGREEN;
588 }
589
590 guiCompressionStringBaseTime = GetJA2Clock();
591 }
592
593 if (giTimeCompressMode != 0 && !GamePaused())
594 {
595 usColor = FONT_LTGREEN;
596 }
597
598 SetFontAttributes(COMPFONT, usColor);
599 FindFontCenterCoordinates(STD_SCREEN_X + 489, STD_SCREEN_Y + 457, 522 - 489, 467 - 454, Time, COMPFONT, &sX, &sY);
600 MPrint(sX, sY, Time);
601 }
602
603
CreateCompressModePause(void)604 static void CreateCompressModePause(void)
605 {
606 MSYS_DefineRegion( &gMapPauseRegion, 487, 456, 522, 467, MSYS_PRIORITY_HIGH,
607 MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressModeClickCallback );
608 gMapPauseRegion.SetFastHelpText(pMapScreenBottomFastHelp[7]);
609 }
610
611
RemoveCompressModePause(void)612 static void RemoveCompressModePause(void)
613 {
614 MSYS_RemoveRegion( &gMapPauseRegion );
615 }
616
617
LoadMessageSliderBar(void)618 static void LoadMessageSliderBar(void)
619 {
620 // this function will load the message slider bar
621 guiSliderBar = AddVideoObjectFromFile(INTERFACEDIR "/map_screen_bottom_arrows.sti");
622 }
623
624
DeleteMessageSliderBar(void)625 static void DeleteMessageSliderBar(void)
626 {
627 // this function will delete message slider bar
628 DeleteVideoObject(guiSliderBar);
629 }
630
631
MapScreenMessageBoxCallBack(MOUSE_REGION * pRegion,INT32 iReason)632 static void MapScreenMessageBoxCallBack(MOUSE_REGION* pRegion, INT32 iReason)
633 {
634 if (iReason & MSYS_CALLBACK_REASON_WHEEL_UP)
635 {
636 MapScreenMsgScrollUp(3);
637 }
638 else if (iReason & MSYS_CALLBACK_REASON_WHEEL_DOWN)
639 {
640 MapScreenMsgScrollDown(3);
641 }
642 }
643
644
645 static MOUSE_REGION MapMessageBoxRegion;
646
647
648 static void MapScreenMessageScrollBarCallBack(MOUSE_REGION* pRegion, INT32 iReason);
649
650
CreateMapScreenBottomMessageScrollBarRegion(void)651 static void CreateMapScreenBottomMessageScrollBarRegion(void)
652 {
653 const INT8 prio = MSYS_PRIORITY_NORMAL;
654 {
655 const UINT16 x = MESSAGE_SCROLL_AREA_START_X;
656 const UINT16 y = MESSAGE_SCROLL_AREA_START_Y;
657 const UINT16 w = MESSAGE_SCROLL_AREA_WIDTH;
658 const UINT16 h = MESSAGE_SCROLL_AREA_HEIGHT;
659 MSYS_DefineRegion(&gMapMessageScrollBarRegion, x, y, x + w, y + h, prio, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenMessageScrollBarCallBack);
660 }
661 {
662 const UINT16 x = MESSAGE_BOX_X;
663 const UINT16 y = MESSAGE_BOX_Y;
664 const UINT16 w = MESSAGE_BOX_W;
665 const UINT16 h = MESSAGE_BOX_H;
666 MSYS_DefineRegion(&MapMessageBoxRegion, x, y, x + w, y + h, prio, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenMessageBoxCallBack);
667 }
668 }
669
670
DeleteMapScreenBottomMessageScrollRegion(void)671 static void DeleteMapScreenBottomMessageScrollRegion(void)
672 {
673 MSYS_RemoveRegion( &gMapMessageScrollBarRegion );
674 MSYS_RemoveRegion(&MapMessageBoxRegion);
675 }
676
677
MapScreenMessageScrollBarCallBack(MOUSE_REGION * pRegion,INT32 iReason)678 static void MapScreenMessageScrollBarCallBack(MOUSE_REGION* pRegion, INT32 iReason)
679 {
680 UINT8 ubDesiredSliderOffset;
681 UINT8 ubDesiredMessageIndex;
682 UINT8 ubNumMessages;
683
684 if ( iReason & ( MSYS_CALLBACK_REASON_LBUTTON_DWN | MSYS_CALLBACK_REASON_LBUTTON_REPEAT ) )
685 {
686 // how many messages are there?
687 ubNumMessages = GetRangeOfMapScreenMessages();
688
689 // region is supposed to be disabled if there aren't enough messages to scroll. Formulas assume this
690 if ( ubNumMessages > MAX_MESSAGES_ON_MAP_BOTTOM )
691 {
692 const UINT8 ubMouseYOffset = pRegion->RelativeYPos;
693
694 // if clicking in the top 5 pixels of the slider bar
695 if ( ubMouseYOffset < ( SLIDER_HEIGHT / 2 ) )
696 {
697 // scroll all the way to the top
698 ubDesiredMessageIndex = 0;
699 }
700 // if clicking in the bottom 6 pixels of the slider bar
701 else if ( ubMouseYOffset >= ( MESSAGE_SCROLL_AREA_HEIGHT - ( SLIDER_HEIGHT / 2 ) ) )
702 {
703 // scroll all the way to the bottom
704 ubDesiredMessageIndex = ubNumMessages - MAX_MESSAGES_ON_MAP_BOTTOM;
705 }
706 else
707 {
708 // somewhere in between
709 ubDesiredSliderOffset = ubMouseYOffset - ( SLIDER_HEIGHT / 2 );
710
711 Assert( ubDesiredSliderOffset <= SLIDER_BAR_RANGE );
712
713 // calculate what the index should be to place the slider at this offset (round fractions of .5+ up)
714 ubDesiredMessageIndex = ( ( ubDesiredSliderOffset * ( ubNumMessages - MAX_MESSAGES_ON_MAP_BOTTOM ) ) + ( SLIDER_BAR_RANGE / 2 ) ) / SLIDER_BAR_RANGE;
715 }
716
717 // if it's a change
718 if ( ubDesiredMessageIndex != gubFirstMapscreenMessageIndex )
719 {
720 ChangeCurrentMapscreenMessageIndex( ubDesiredMessageIndex );
721 }
722 }
723 }
724 else if (iReason & MSYS_CALLBACK_REASON_WHEEL_UP)
725 {
726 MapScreenMsgScrollUp(3);
727 }
728 else if (iReason & MSYS_CALLBACK_REASON_WHEEL_DOWN)
729 {
730 MapScreenMsgScrollDown(3);
731 }
732 }
733
734
DisplayScrollBarSlider(void)735 static void DisplayScrollBarSlider(void)
736 {
737 // will display the scroll bar icon
738 UINT8 ubNumMessages;
739 UINT8 ubSliderOffset;
740
741 ubNumMessages = GetRangeOfMapScreenMessages();
742
743 // only show the slider if there are more messages than will fit on screen
744 if ( ubNumMessages > MAX_MESSAGES_ON_MAP_BOTTOM )
745 {
746 // calculate where slider should be positioned
747 ubSliderOffset = ( SLIDER_BAR_RANGE * gubFirstMapscreenMessageIndex ) / ( ubNumMessages - MAX_MESSAGES_ON_MAP_BOTTOM );
748
749 BltVideoObject(FRAME_BUFFER, guiSliderBar, 8, MESSAGE_SCROLL_AREA_START_X + 2, MESSAGE_SCROLL_AREA_START_Y + ubSliderOffset);
750 }
751 }
752
753
754 static void EnableDisableTimeCompressButtons(void);
755
756
EnableDisableBottomButtonsAndRegions(void)757 static void EnableDisableBottomButtonsAndRegions(void)
758 {
759 // this enables and disables the buttons MAP_EXIT_TO_LAPTOP, MAP_EXIT_TO_TACTICAL, and MAP_EXIT_TO_OPTIONS
760 for (ExitToWhere iExitButtonIndex = MAP_EXIT_TO_LAPTOP; iExitButtonIndex <= MAP_EXIT_TO_OPTIONS; ++iExitButtonIndex)
761 {
762 EnableButton(guiMapBottomExitButtons[iExitButtonIndex], AllowedToExitFromMapscreenTo(iExitButtonIndex));
763 }
764
765 // enable/disable time compress buttons and region masks
766 EnableDisableTimeCompressButtons( );
767 CreateDestroyMouseRegionMasksForTimeCompressionButtons( );
768
769
770 // Enable/Disable map inventory panel buttons
771
772 // if in merc inventory panel
773 if( fShowInventoryFlag )
774 {
775 // and an item is in the cursor
776 EnableButton(giMapInvDoneButton, !fMapInventoryItem && !InKeyRingPopup() && !InItemStackPopup());
777
778 if( fShowDescriptionFlag )
779 {
780 ForceButtonUnDirty( giMapInvDoneButton );
781 }
782 }
783 }
784
785
EnableDisableTimeCompressButtons(void)786 static void EnableDisableTimeCompressButtons(void)
787 {
788 if (!AllowedToTimeCompress())
789 {
790 DisableButton( guiMapBottomTimeButtons[ MAP_TIME_COMPRESS_MORE ] );
791 DisableButton( guiMapBottomTimeButtons[ MAP_TIME_COMPRESS_LESS ] );
792 }
793 else
794 {
795 // disable LESS if time compression is at minimum or OFF
796 EnableButton(guiMapBottomTimeButtons[MAP_TIME_COMPRESS_LESS], IsTimeCompressionOn() && giTimeCompressMode != TIME_COMPRESS_X0);
797
798 // disable MORE if we're not paused and time compression is at maximum
799 // only disable MORE if we're not paused and time compression is at maximum
800 EnableButton(guiMapBottomTimeButtons[MAP_TIME_COMPRESS_MORE], !IsTimeCompressionOn() || giTimeCompressMode != TIME_COMPRESS_60MINS);
801 }
802 }
803
804
EnableDisAbleMapScreenOptionsButton(BOOLEAN fEnable)805 void EnableDisAbleMapScreenOptionsButton( BOOLEAN fEnable )
806 {
807 EnableButton(guiMapBottomExitButtons[MAP_EXIT_TO_OPTIONS], fEnable);
808 }
809
810
AllowedToTimeCompress(void)811 BOOLEAN AllowedToTimeCompress( void )
812 {
813 // if already leaving, disallow any other attempts to exit
814 if ( fLeavingMapScreen )
815 {
816 return( FALSE );
817 }
818
819 // if already going someplace
820 if (gbExitingMapScreenToWhere != MAP_EXIT_TO_INVALID) return FALSE;
821
822 // if we're locked into paused time compression by some event that enforces that
823 if ( PauseStateLocked() )
824 {
825 return( FALSE );
826 }
827
828 // meanwhile coming up
829 if ( gfMeanwhileTryingToStart )
830 {
831 return( FALSE );
832 }
833
834 // someone has something to say
835 if ( !DialogueQueueIsEmpty() )
836 {
837 return( FALSE );
838 }
839
840 // moving / confirming movement
841 if( ( bSelectedDestChar != -1 ) || fPlotForHelicopter || gfInConfirmMapMoveMode || fShowMapScreenMovementList )
842 {
843 return( FALSE );
844 }
845
846 if (fShowAssignmentMenu || fShowTrainingMenu || fShowAttributeMenu || fShowSquadMenu || fShowContractMenu)
847 {
848 return( FALSE );
849 }
850
851 if( fShowUpdateBox || fShowTownInfo || ( sSelectedMilitiaTown != 0 ) )
852 {
853 return( FALSE );
854 }
855
856 // renewing contracts
857 if ( gfContractRenewalSquenceOn )
858 {
859 return( FALSE );
860 }
861
862 // disabled due to battle?
863 if( ( fDisableMapInterfaceDueToBattle ) || ( fDisableDueToBattleRoster ) )
864 {
865 return( FALSE );
866 }
867
868 // if holding an inventory item
869 if ( fMapInventoryItem )
870 {
871 return( FALSE );
872 }
873
874 // show the inventory pool?
875 if( fShowMapInventoryPool )
876 {
877 // prevent time compress (items get stolen over time, etc.)
878 return( FALSE );
879 }
880
881 // no mercs have ever been hired
882 if (!gfAtLeastOneMercWasHired) return FALSE;
883
884
885 // no usable mercs on team!
886 if ( !AnyUsableRealMercenariesOnTeam() )
887 {
888 return( FALSE );
889 }
890
891 // must wait till bombs go off
892 if ( ActiveTimedBombExists() )
893 {
894 return( FALSE );
895 }
896
897 // hostile sector / in battle
898 if( (gTacticalStatus.uiFlags & INCOMBAT ) || ( gTacticalStatus.fEnemyInSector ) )
899 {
900 return( FALSE );
901 }
902
903 if( PlayerGroupIsInACreatureInfestedMine() )
904 {
905 return FALSE;
906 }
907
908 // bloodcat ambush?
909 if (gubEnemyEncounterCode == BLOODCAT_AMBUSH_CODE && HostileBloodcatsPresent())
910 {
911 return FALSE;
912 }
913
914 return( TRUE );
915 }
916
917
DisplayCurrentBalanceTitleForMapBottom(void)918 static void DisplayCurrentBalanceTitleForMapBottom(void)
919 {
920 ST::string sString;
921 INT16 sFontX, sFontY;
922
923 SetFontDestBuffer(guiSAVEBUFFER);
924 SetFontAttributes(COMPFONT, MAP_BOTTOM_FONT_COLOR);
925
926 sString = pMapScreenBottomText;
927 FindFontCenterCoordinates(STD_SCREEN_X + 359, STD_SCREEN_Y + 387 - 14, 437 - 359, 10, sString, COMPFONT, &sFontX, &sFontY);
928 MPrint(sFontX, sFontY, sString);
929
930 sString = zMarksMapScreenText[2];
931 FindFontCenterCoordinates(STD_SCREEN_X + 359, STD_SCREEN_Y + 433 - 14, 437 - 359, 10, sString, COMPFONT, &sFontX, &sFontY);
932 MPrint(sFontX, sFontY, sString);
933
934 SetFontDestBuffer(FRAME_BUFFER);
935 }
936
937
DisplayCurrentBalanceForMapBottom(void)938 static void DisplayCurrentBalanceForMapBottom(void)
939 {
940 // show the current balance for the player on the map panel bottom
941 INT16 sFontX, sFontY;
942
943 SetFontDestBuffer(FRAME_BUFFER);
944 SetFontAttributes(COMPFONT, 183);
945 ST::string sString = SPrintMoney(LaptopSaveInfo.iCurrentBalance);
946 FindFontCenterCoordinates(STD_SCREEN_X + 359, STD_SCREEN_Y + 387 + 2, 437 - 359, 10, sString, COMPFONT, &sFontX, &sFontY);
947 MPrint(sFontX, sFontY, sString);
948 }
949
950
951 static void CompressMaskClickCallback(MOUSE_REGION* pRegion, INT32 iReason);
952
953
CreateDestroyMouseRegionMasksForTimeCompressionButtons()954 void CreateDestroyMouseRegionMasksForTimeCompressionButtons()
955 {
956 static bool created = false;
957
958 // Disable buttons, if not allowed to compress time.
959 bool const disabled = fInMapMode && !AllowedToTimeCompress();
960 if (disabled && !created)
961 {
962 // Mask over compress more, compress less and paus game buttons.
963 MSYS_DefineRegion(&gTimeCompressionMask[0], STD_SCREEN_X + 528, STD_SCREEN_Y + 457, 528 + 13, 457 + 14, MSYS_PRIORITY_HIGHEST - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback);
964 MSYS_DefineRegion(&gTimeCompressionMask[1], STD_SCREEN_X + 466, STD_SCREEN_Y + 457, 466 + 13, 457 + 14, MSYS_PRIORITY_HIGHEST - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback);
965 MSYS_DefineRegion(&gTimeCompressionMask[2], STD_SCREEN_X + 487, STD_SCREEN_Y + 457, 487 + 35, 457 + 11, MSYS_PRIORITY_HIGHEST - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback);
966 created = true;
967 }
968 else if (!disabled && created)
969 {
970 FOR_EACH(MOUSE_REGION, i, gTimeCompressionMask) MSYS_RemoveRegion(&*i);
971 created = false;
972 }
973 }
974
975
CompressMaskClickCallback(MOUSE_REGION * pRegion,INT32 iReason)976 static void CompressMaskClickCallback(MOUSE_REGION* pRegion, INT32 iReason)
977 {
978 if( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
979 {
980 TellPlayerWhyHeCantCompressTime( );
981 }
982 }
983
984
DisplayProjectedDailyMineIncome(void)985 static void DisplayProjectedDailyMineIncome(void)
986 {
987 INT32 iRate = 0;
988 static INT32 iOldRate = -1;
989 INT16 sFontX, sFontY;
990
991 // grab the rate from the financial system
992 iRate = GetProjectedTotalDailyIncome( );
993
994 if( iRate != iOldRate )
995 {
996 iOldRate = iRate;
997 fMapScreenBottomDirty = TRUE;
998
999 // if screen was not dirtied, leave
1000 if (!fMapBottomDirtied) return;
1001 }
1002
1003 SetFontDestBuffer(FRAME_BUFFER);
1004 SetFontAttributes(COMPFONT, 183);
1005 ST::string sString = SPrintMoney(iRate);
1006 FindFontCenterCoordinates(STD_SCREEN_X + 359, STD_SCREEN_Y + 433 + 2, 437 - 359, 10, sString, COMPFONT, &sFontX, &sFontY);
1007 MPrint(sFontX, sFontY, sString);
1008 }
1009
1010
CommonTimeCompressionChecks(void)1011 BOOLEAN CommonTimeCompressionChecks( void )
1012 {
1013 if (bSelectedDestChar != -1 || fPlotForHelicopter)
1014 {
1015 // abort plotting movement
1016 AbortMovementPlottingMode( );
1017 return( TRUE );
1018 }
1019
1020 return( FALSE );
1021 }
1022
1023
AnyUsableRealMercenariesOnTeam()1024 bool AnyUsableRealMercenariesOnTeam()
1025 {
1026 /* Check whether there is a merc on team, who is not a vehicle, robot, POW or
1027 * EPC. */
1028 CFOR_EACH_IN_TEAM(i, OUR_TEAM)
1029 {
1030 SOLDIERTYPE const& s = *i;
1031 if (s.bLife <= 0) continue;
1032 if (IsMechanical(s)) continue;
1033 if (s.bAssignment == ASSIGNMENT_POW) continue;
1034 if (s.bAssignment == ASSIGNMENT_DEAD) continue;
1035 if (s.ubWhatKindOfMercAmI == MERC_TYPE__EPC) continue;
1036 return true;
1037 }
1038 return false;
1039 }
1040
1041
1042
RequestTriggerExitFromMapscreen(ExitToWhere const bExitToWhere)1043 void RequestTriggerExitFromMapscreen(ExitToWhere const bExitToWhere)
1044 {
1045 Assert( ( bExitToWhere >= MAP_EXIT_TO_LAPTOP ) && ( bExitToWhere <= MAP_EXIT_TO_SAVE ) );
1046
1047 // if allowed to do so
1048 if ( AllowedToExitFromMapscreenTo( bExitToWhere ) )
1049 {
1050 //if the screen to exit to is the SAVE screen
1051 if( bExitToWhere == MAP_EXIT_TO_SAVE )
1052 {
1053 //if the game CAN NOT be saved
1054 if( !CanGameBeSaved() )
1055 {
1056 //Display a message saying the player cant save now
1057 DoMapMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__IRON_MAN_CANT_SAVE_NOW ], MAP_SCREEN, MSG_BOX_FLAG_OK, NULL );
1058 return;
1059 }
1060 else if ( gGameOptions.ubGameSaveMode == DIF_DEAD_IS_DEAD )
1061 {
1062 //Display DiD message saying the player cant save now
1063 DoMapMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__DEAD_IS_DEAD_CANT_SAVE_NOW ], MAP_SCREEN, MSG_BOX_FLAG_OK, NULL );
1064 return;
1065 }
1066 }
1067
1068 // permit it, and get the ball rolling
1069 gbExitingMapScreenToWhere = bExitToWhere;
1070
1071 // delay until mapscreen has had a chance to render at least one full frame
1072 gfOneFramePauseOnExit = TRUE;
1073 }
1074 }
1075
1076
AllowedToExitFromMapscreenTo(ExitToWhere const bExitToWhere)1077 BOOLEAN AllowedToExitFromMapscreenTo(ExitToWhere const bExitToWhere)
1078 {
1079 Assert( ( bExitToWhere >= MAP_EXIT_TO_LAPTOP ) && ( bExitToWhere <= MAP_EXIT_TO_SAVE ) );
1080
1081 // if already leaving, disallow any other attempts to exit
1082 if ( fLeavingMapScreen )
1083 {
1084 return( FALSE );
1085 }
1086
1087 // if already going someplace else
1088 if (gbExitingMapScreenToWhere != MAP_EXIT_TO_INVALID &&
1089 gbExitingMapScreenToWhere != bExitToWhere)
1090 {
1091 return( FALSE );
1092 }
1093
1094 // someone has something to say
1095 if ( !DialogueQueueIsEmpty() )
1096 {
1097 return( FALSE );
1098 }
1099
1100 // meanwhile coming up
1101 if ( gfMeanwhileTryingToStart )
1102 {
1103 return( FALSE );
1104 }
1105
1106 // if we're locked into paused time compression by some event that enforces that
1107 if ( PauseStateLocked() )
1108 {
1109 return( FALSE );
1110 }
1111
1112 // if holding an inventory item
1113 if (fMapInventoryItem) return FALSE;
1114
1115 if( fShowUpdateBox || fShowTownInfo || ( sSelectedMilitiaTown != 0 ) )
1116 {
1117 return( FALSE );
1118 }
1119
1120 // renewing contracts
1121 if( gfContractRenewalSquenceOn )
1122 {
1123 return( FALSE );
1124 }
1125
1126 // battle about to occur?
1127 if( ( fDisableDueToBattleRoster ) || ( fDisableMapInterfaceDueToBattle ) )
1128 {
1129 return( FALSE );
1130 }
1131
1132 // the following tests apply to going tactical screen only
1133 if ( bExitToWhere == MAP_EXIT_TO_TACTICAL )
1134 {
1135 // if in battle or bloodcat ambush, the ONLY sector we can go tactical in is the one that's loaded
1136 BOOLEAN fBattleGoingOn = gTacticalStatus.uiFlags & INCOMBAT || gTacticalStatus.fEnemyInSector || (gubEnemyEncounterCode == BLOODCAT_AMBUSH_CODE && HostileBloodcatsPresent());
1137 BOOLEAN fCurrentSectorSelected = sSelMapX == gWorldSectorX && sSelMapY == gWorldSectorY && ((UINT8)iCurrentMapSectorZ) == gbWorldSectorZ;
1138 if (fBattleGoingOn && !fCurrentSectorSelected)
1139 {
1140 return( FALSE );
1141 }
1142
1143 // must have some mercs there
1144 if( !CanGoToTacticalInSector( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ ) )
1145 {
1146 return( FALSE );
1147 }
1148 }
1149
1150 //if we are map screen sector inventory
1151 if( fShowMapInventoryPool )
1152 {
1153 //dont allow it
1154 return( FALSE );
1155 }
1156
1157 // OK to go there, passed all the checks
1158 return( TRUE );
1159 }
1160
1161
HandleExitsFromMapScreen(void)1162 void HandleExitsFromMapScreen( void )
1163 {
1164 // if going somewhere
1165 if (gbExitingMapScreenToWhere == MAP_EXIT_TO_INVALID) return;
1166
1167 // delay all exits by one frame...
1168 if (gfOneFramePauseOnExit)
1169 {
1170 gfOneFramePauseOnExit = FALSE;
1171 return;
1172 }
1173
1174 // make sure it's still legal to do this!
1175 if ( AllowedToExitFromMapscreenTo( gbExitingMapScreenToWhere ) )
1176 {
1177 // see where we're trying to go
1178 switch ( gbExitingMapScreenToWhere )
1179 {
1180 case MAP_EXIT_TO_LAPTOP:
1181 fLapTop = TRUE;
1182 SetPendingNewScreen(LAPTOP_SCREEN);
1183
1184 BltVideoSurface(guiEXTRABUFFER, FRAME_BUFFER, 0, 0, NULL);
1185 gfStartMapScreenToLaptopTransition = TRUE;
1186 break;
1187
1188 case MAP_EXIT_TO_TACTICAL:
1189 SetCurrentWorldSector( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ );
1190 break;
1191
1192 case MAP_EXIT_TO_OPTIONS:
1193 guiPreviousOptionScreen = guiCurrentScreen;
1194 SetPendingNewScreen( OPTIONS_SCREEN );
1195 break;
1196
1197 case MAP_EXIT_TO_SAVE:
1198 case MAP_EXIT_TO_LOAD:
1199 gfCameDirectlyFromGame = TRUE;
1200 guiPreviousOptionScreen = guiCurrentScreen;
1201 SetPendingNewScreen( SAVE_LOAD_SCREEN );
1202 break;
1203
1204 default:
1205 // invalid exit type
1206 Assert( FALSE );
1207 }
1208
1209 // time compression during mapscreen exit doesn't seem to cause any problems, but turn it off as early as we can
1210 StopTimeCompression();
1211
1212 // now leaving mapscreen
1213 fLeavingMapScreen = TRUE;
1214 }
1215
1216 // cancel exit, either we're on our way, or we're not allowed to go
1217 gbExitingMapScreenToWhere = MAP_EXIT_TO_INVALID;
1218 }
1219
1220
1221
MapScreenMsgScrollDown(UINT8 ubLinesDown)1222 void MapScreenMsgScrollDown( UINT8 ubLinesDown )
1223 {
1224 UINT8 ubNumMessages;
1225
1226 ubNumMessages = GetRangeOfMapScreenMessages();
1227
1228 // check if we can go that far, only go as far as we can
1229 if ( ( gubFirstMapscreenMessageIndex + MAX_MESSAGES_ON_MAP_BOTTOM + ubLinesDown ) > ubNumMessages )
1230 {
1231 ubLinesDown = ubNumMessages - gubFirstMapscreenMessageIndex - MIN( ubNumMessages, MAX_MESSAGES_ON_MAP_BOTTOM );
1232 }
1233
1234 if ( ubLinesDown > 0 )
1235 {
1236 ChangeCurrentMapscreenMessageIndex( ( UINT8 ) ( gubFirstMapscreenMessageIndex + ubLinesDown ) );
1237 }
1238 }
1239
1240
MapScreenMsgScrollUp(UINT8 ubLinesUp)1241 void MapScreenMsgScrollUp( UINT8 ubLinesUp )
1242 {
1243 // check if we can go that far, only go as far as we can
1244 if ( gubFirstMapscreenMessageIndex < ubLinesUp )
1245 {
1246 ubLinesUp = gubFirstMapscreenMessageIndex;
1247 }
1248
1249 if ( ubLinesUp > 0 )
1250 {
1251 ChangeCurrentMapscreenMessageIndex( ( UINT8 ) ( gubFirstMapscreenMessageIndex - ubLinesUp ) );
1252 }
1253 }
1254
1255
1256
MoveToEndOfMapScreenMessageList(void)1257 void MoveToEndOfMapScreenMessageList( void )
1258 {
1259 UINT8 ubDesiredMessageIndex;
1260 UINT8 ubNumMessages;
1261
1262 ubNumMessages = GetRangeOfMapScreenMessages();
1263
1264 ubDesiredMessageIndex = ubNumMessages - MIN( ubNumMessages, MAX_MESSAGES_ON_MAP_BOTTOM );
1265 ChangeCurrentMapscreenMessageIndex( ubDesiredMessageIndex );
1266 }
1267
1268
1269
ChangeCurrentMapscreenMessageIndex(UINT8 ubNewMessageIndex)1270 void ChangeCurrentMapscreenMessageIndex( UINT8 ubNewMessageIndex )
1271 {
1272 Assert( ubNewMessageIndex + MAX_MESSAGES_ON_MAP_BOTTOM <= MAX( MAX_MESSAGES_ON_MAP_BOTTOM, GetRangeOfMapScreenMessages() ) );
1273
1274 gubFirstMapscreenMessageIndex = ubNewMessageIndex;
1275 gubCurrentMapMessageString = ( gubStartOfMapScreenMessageList + gubFirstMapscreenMessageIndex ) % 256;
1276
1277 // refresh screen
1278 fMapScreenBottomDirty = TRUE;
1279 }
1280