1 #include "Local.h"
2 #include "GameLoop.h"
3 #include "VSurface.h"
4 #include "WorldDef.h"
5 #include "Input.h"
6 #include "Font.h"
7 #include "Screens.h"
8 #include "Overhead.h"
9 #include "SysUtil.h"
10 #include "Event_Pump.h"
11 #include "Font_Control.h"
12 #include "Debug_Pages.h"
13 #include "Timer_Control.h"
14 #include "Radar_Screen.h"
15 #include "Render_Dirty.h"
16 #include "Interface.h"
17 #include "Handle_UI.h"
18 #include "Cursors.h"
19 #include "VObject_Blitters.h"
20 #include "Button_System.h"
21 #include "RenderWorld.h"
22 #include "Sys_Globals.h"
23 #include "Environment.h"
24 #include "Bullets.h"
25 #include "Assignments.h"
26 #include "Message.h"
27 #include "Overhead_Map.h"
28 #include "Strategic_Exit_GUI.h"
29 #include "Strategic_Movement.h"
30 #include "Tactical_Placement_GUI.h"
31 #include "Game_Clock.h"
32 #include "Game_Init.h"
33 #include "Interface_Control.h"
34 #include "Physics.h"
35 #include "Fade_Screen.h"
36 #include "Dialogue_Control.h"
37 #include "Soldier_Macros.h"
38 #include "Faces.h"
39 #include "StrategicMap.h"
40 #include "GameScreen.h"
41 #include "Cursor_Control.h"
42 #include "Strategic_Turns.h"
43 #include "Merc_Entering.h"
44 #include "Soldier_Create.h"
45 #include "Soldier_Init_List.h"
46 #include "Interface_Panels.h"
47 #include "Map_Information.h"
48 #include "Squads.h"
49 #include "Interface_Dialogue.h"
50 #include "Auto_Bandage.h"
51 #include "Meanwhile.h"
52 #include "Strategic_AI.h"
53 #include "HelpScreen.h"
54 #include "PreBattle_Interface.h"
55 #include "Sound_Control.h"
56 #include "Text.h"
57 #include "Debug.h"
58 #include "Video.h"
59 #include "JAScreens.h"
60 #include "UILayout.h"
61 #include "GameState.h"
62 #include "EditScreen.h"
63 #include "Logger.h"
64 
65 #define ARE_IN_FADE_IN( )		( gfFadeIn || gfFadeInitialized )
66 
67 BOOLEAN gfTacticalDoHeliRun = FALSE;
68 
69 
70 // VIDEO OVERLAYS
71 VIDEO_OVERLAY* g_fps_overlay            = NULL;
72 VIDEO_OVERLAY* g_counter_period_overlay = NULL;
73 
74 
75 BOOLEAN	gfGameScreenLocateToSoldier = FALSE;
76 BOOLEAN	gfEnteringMapScreen					= FALSE;
77 SOLDIERTYPE* gPreferredInitialSelectedGuy = NULL;
78 
79 static BOOLEAN      gfTacticalIsModal             = FALSE;
80 static MOUSE_REGION gTacticalDisableRegion;
81 static BOOLEAN      gfTacticalDisableRegionActive = FALSE;
82 MODAL_HOOK          gModalDoneCallback;
83 BOOLEAN             gfBeginEndTurn = FALSE;
84 extern BOOLEAN      gfFirstHeliRun;
85 extern BOOLEAN      gfRenderFullThisFrame;
86 
87 
88 // The InitializeGame function is responsible for setting up all data and Gaming Engine
89 // tasks which will run the game
90 static RENDER_HOOK gRenderOverride = 0;
91 
92 
93 static ScreenID guiTacticalLeaveScreenID = ERROR_SCREEN; // XXX TODO001A had no explicit initialisation
94 static BOOLEAN  guiTacticalLeaveScreen   = FALSE;
95 
96 
BlitMFont(VIDEO_OVERLAY * const ovr)97 static void BlitMFont(VIDEO_OVERLAY* const ovr)
98 {
99 	SetFontAttributes(ovr->uiFontID, ovr->ubFontFore, DEFAULT_SHADOW, ovr->ubFontBack);
100 	SGPVSurface::Lock l(ovr->uiDestBuff);
101 	MPrintBuffer(l.Buffer<UINT16>(), l.Pitch(), ovr->sX, ovr->sY, ovr->codepoints);
102 }
103 
104 
MainGameScreenInit(void)105 void MainGameScreenInit(void)
106 {
107 	// all blit functions expect z-buffer pitch to match framebuffer pitch
108 	gZBufferPitch = FRAME_BUFFER->surface_->pitch / FRAME_BUFFER->surface_->format->BytesPerPixel;
109 	gpZBuffer = InitZBuffer(gZBufferPitch, SCREEN_HEIGHT);
110 	gZBufferPitch *= sizeof(*gpZBuffer);
111 	InitializeBackgroundRects();
112 
113 	//EnvSetTimeInHours(ENV_TIME_12);
114 
115 	SetRenderFlags(RENDER_FLAG_FULL);
116 
117 	// Init Video Overlays
118 	// FIRST, FRAMERATE
119 	g_fps_overlay = RegisterVideoOverlay(
120 					BlitMFont,
121 					DEBUG_PAGE_SCREEN_OFFSET_X,
122 					DEBUG_PAGE_SCREEN_OFFSET_Y,
123 					DEBUG_PAGE_FONT,
124 					DEBUG_PAGE_TEXT_COLOR,
125 					0,
126 					L"90"
127 	);
128 	EnableVideoOverlay(false, g_fps_overlay);
129 
130 	// SECOND, PERIOD COUNTER
131 	g_counter_period_overlay = RegisterVideoOverlay(
132 					BlitMFont,
133 					DEBUG_PAGE_SCREEN_OFFSET_X,
134 					DEBUG_PAGE_SCREEN_OFFSET_Y+DEBUG_PAGE_LINE_HEIGHT,
135 					DEBUG_PAGE_FONT,
136 					DEBUG_PAGE_TEXT_COLOR,
137 					0,
138 					L"Levelnodes: 100000"
139 	);
140 	EnableVideoOverlay(false, g_counter_period_overlay);
141 }
142 
143 
144 // The ShutdownGame function will free up/undo all things that were started in InitializeGame()
145 // It will also be responsible to making sure that all Gaming Engine tasks exit properly
MainGameScreenShutdown(void)146 void MainGameScreenShutdown(void)
147 {
148 	ShutdownZBuffer(gpZBuffer);
149 	RemoveVideoOverlay(g_fps_overlay);
150 	RemoveVideoOverlay(g_counter_period_overlay);
151 	ShutdownBackgroundRects();
152 }
153 
154 
FadeInGameScreen()155 void FadeInGameScreen( )
156 {
157 	fFirstTimeInGameScreen = TRUE;
158 
159 	FadeInNextFrame( );
160 }
161 
FadeOutGameScreen()162 void FadeOutGameScreen( )
163 {
164 	FadeOutNextFrame( );
165 }
166 
167 
EnterTacticalScreen(void)168 void EnterTacticalScreen(void)
169 {
170 	guiTacticalLeaveScreen = FALSE;
171 
172 	SetPositionSndsActive( );
173 
174 	// Set pending screen
175 	SetPendingNewScreen( GAME_SCREEN );
176 
177 	// Set as active...
178 	gTacticalStatus.uiFlags |= ACTIVE;
179 
180 	fInterfacePanelDirty = DIRTYLEVEL2;
181 
182 	//Disable all faces
183 	SetAllAutoFacesInactive( );
184 
185 	// CHECK IF OURGUY IS NOW OFF DUTY
186 	const SOLDIERTYPE* sel = GetSelectedMan();
187 	if (sel != NULL)
188 	{
189 		if (!OK_CONTROLLABLE_MERC(sel))
190 		{
191 			SelectNextAvailSoldier(sel);
192 			sel = GetSelectedMan();
193 		}
194 		// ATE: If the current guy is sleeping, change....
195 		if (sel != NULL && sel->fMercAsleep) SelectNextAvailSoldier(sel);
196 	}
197 	else
198 	{
199 		// otherwise, make sure interface is team panel...
200 		SetCurrentInterfacePanel(TEAM_PANEL);
201 	}
202 
203 	if (!gfTacticalPlacementGUIActive) gRadarRegion.Enable();
204 	gViewportRegion.Enable();
205 
206 	// set default squad on sector entry
207 	// ATE: moved these 2 call after initalizing the interface!
208 	//SetDefaultSquadOnSectorEntry( FALSE );
209 	//ExamineCurrentSquadLights( );
210 
211 	// Init interface ( ALWAYS TO TEAM PANEL.  DEF changed it to go back to the previous panel )
212 	if( !gfTacticalPlacementGUIActive )
213 	{
214 		//make sure the gsCurInterfacePanel is valid
215 		if( gsCurInterfacePanel < 0 || gsCurInterfacePanel >= NUM_UI_PANELS )
216 			gsCurInterfacePanel = TEAM_PANEL;
217 
218 		SetCurrentInterfacePanel(gsCurInterfacePanel);
219 	}
220 
221 	// set default squad on sector entry
222 	SetDefaultSquadOnSectorEntry( FALSE );
223 	ExamineCurrentSquadLights( );
224 
225 
226 
227 	fFirstTimeInGameScreen = FALSE;
228 
229 	// Make sure it gets re-created....
230 	DirtyTopMessage( );
231 
232 	// Set compression to normal!
233 	//SetGameTimeCompressionLevel( TIME_COMPRESS_X1 );
234 
235 	// Select current guy...
236 	//gfGameScreenLocateToSoldier = TRUE;
237 
238 	// Locate if in meanwhile...
239 	if ( AreInMeanwhile( ) )
240 	{
241 		LocateToMeanwhileCharacter( );
242 	}
243 
244 	if ( gTacticalStatus.uiFlags & IN_DEIDRANNA_ENDGAME )
245 	{
246 		InternalLocateGridNo( 4561, TRUE );
247 	}
248 
249 	// Clear tactical message q
250 	ClearTacticalMessageQueue( );
251 
252 	// ATE: Enable messages again...
253 	EnableScrollMessages( );
254 }
255 
256 
LeaveTacticalScreen(ScreenID const uiNewScreen)257 void LeaveTacticalScreen(ScreenID const uiNewScreen)
258 {
259 	guiTacticalLeaveScreenID = uiNewScreen;
260 	guiTacticalLeaveScreen = TRUE;
261 }
262 
263 
InternalLeaveTacticalScreen(ScreenID const uiNewScreen)264 void InternalLeaveTacticalScreen(ScreenID const uiNewScreen)
265 {
266 	gpCustomizableTimerCallback = NULL;
267 
268 	// unload the sector they teleported out of
269 	if ( !gfAutomaticallyStartAutoResolve )
270 	{
271 		CheckAndHandleUnloadingOfCurrentWorld();
272 	}
273 
274 	SetPositionSndsInActive( );
275 
276 	// Turn off active flag
277 	gTacticalStatus.uiFlags &= ( ~ACTIVE );
278 
279 	fFirstTimeInGameScreen = TRUE;
280 
281 	SetPendingNewScreen( uiNewScreen );
282 
283 	//Disable all faces
284 	SetAllAutoFacesInactive( );
285 
286 	ResetInterfaceAndUI( );
287 
288 	// Remove cursor and reset height....
289 	gsGlobalCursorYOffset = 0;
290 	SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
291 
292 	// Shutdown panel
293 	ShutdownCurrentPanel( );
294 
295 	//disable the radar map
296 	gRadarRegion.Disable();
297 	//gViewportRegion.Disable();
298 
299 	// We are leaving... turn off pedning autobadage...
300 	SetAutoBandagePending( FALSE );
301 
302 	// ATE: Disable messages....
303 	DisableScrollMessages( );
304 
305 
306 	if ( uiNewScreen == MAINMENU_SCREEN )
307 	{
308 		//We want to reinitialize the game
309 		ReStartingGame();
310 	}
311 
312 	if ( uiNewScreen != MAP_SCREEN )
313 	{
314 		StopAnyCurrentlyTalkingSpeech( );
315 	}
316 
317 	// If we have some disabled screens up.....remove...
318 	CheckForDisabledRegionRemove( );
319 
320 	// ATE: Record last time we were in tactical....
321 	gTacticalStatus.uiTimeSinceLastInTactical = GetWorldTotalMin( );
322 
323 	FinishAnySkullPanelAnimations( );
324 }
325 
326 
327 static void HandleModalTactical(void);
328 static void TacticalScreenLocateToSoldier(void);
329 
330 
MainGameScreenHandle(void)331 ScreenID MainGameScreenHandle(void)
332 {
333 	//DO NOT MOVE THIS FUNCTION CALL!!!
334 	//This determines if the help screen should be active
335 //	if( ( !gfTacticalDoHeliRun && !gfFirstHeliRun ) && ShouldTheHelpScreenComeUp( HELP_SCREEN_TACTICAL, FALSE ) )
336 	if( !gfPreBattleInterfaceActive && ShouldTheHelpScreenComeUp( HELP_SCREEN_TACTICAL, FALSE ) )
337 	{
338 		// handle the help screen
339 		HelpScreenHandler();
340 		return( GAME_SCREEN );
341 	}
342 
343 
344 	if ( HandleAutoBandage( ) )
345 	{
346 		#ifndef VISIBLE_AUTO_BANDAGE
347 			return( GAME_SCREEN );
348 		#endif
349 	}
350 
351 	if ( gfBeginEndTurn )
352 	{
353 		UIHandleEndTurn( NULL );
354 		gfBeginEndTurn = FALSE;
355 	}
356 
357 	if ( gfTacticalIsModal )
358 	{
359 		if ( gfTacticalIsModal == 1 )
360 		{
361 			gfTacticalIsModal++;
362 		}
363 		else
364 		{
365 			HandleModalTactical( );
366 
367 			return( GAME_SCREEN );
368 		}
369 	}
370 
371 	// OK, this is the pause system for when we see a guy...
372 	if ( !ARE_IN_FADE_IN( ) )
373 	{
374 		if ( gTacticalStatus.fEnemySightingOnTheirTurn )
375 		{
376 			if ( ( GetJA2Clock( ) - gTacticalStatus.uiTimeSinceDemoOn ) > 3000 )
377 			{
378 				SOLDIERTYPE* const s = gTacticalStatus.enemy_sighting_on_their_turn_enemy;
379 				if ( gTacticalStatus.ubCurrentTeam != OUR_TEAM )
380 				{
381 					AdjustNoAPToFinishMove(s, FALSE);
382 				}
383 				s->fPauseAllAnimation = FALSE;
384 
385 				gTacticalStatus.fEnemySightingOnTheirTurn = FALSE;
386 			}
387 		}
388 	}
389 
390 	// see if the helicopter is coming in this time for the initial entrance by the mercs
391 	InitHelicopterEntranceByMercs( );
392 
393 	// Handle Environment controller here
394 	EnvironmentController( TRUE );
395 
396 	if ( !ARE_IN_FADE_IN( ) )
397 	{
398 		HandleWaitTimerForNPCTrigger( );
399 
400 		// Check timer that could have been set to do anything
401 		CheckCustomizableTimer();
402 
403 		// HAndle physics engine
404 		SimulateWorld( );
405 
406 		// Handle strategic engine
407 		HandleStrategicTurn( );
408 	}
409 
410 	if ( gfTacticalDoHeliRun )
411 	{
412 		gfGameScreenLocateToSoldier = FALSE;
413 		InternalLocateGridNo( gMapInformation.sNorthGridNo, TRUE );
414 
415 		// Start heli Run...
416 		StartHelicopterRun( gMapInformation.sNorthGridNo );
417 
418 		// Update clock by one so that our DidGameJustStatrt() returns now false for things like LAPTOP, etc...
419 		SetGameTimeCompressionLevel( TIME_COMPRESS_X1 );
420 		//UpdateClock( 1 );
421 
422 		gfTacticalDoHeliRun = FALSE;
423 		//SetMusicMode( MUSIC_TACTICAL_NOTHING );
424 	}
425 
426 
427 	if ( InOverheadMap( ) )
428 	{
429 		HandleOverheadMap( );
430 		return( GAME_SCREEN );
431 	}
432 
433 	if ( gfGameScreenLocateToSoldier )
434 	{
435 		TacticalScreenLocateToSoldier( );
436 		gfGameScreenLocateToSoldier = FALSE;
437 	}
438 
439 	if ( fFirstTimeInGameScreen )
440 	{
441 		EnterTacticalScreen( );
442 
443 		// Select a guy if he hasn;'
444 		if( !gfTacticalPlacementGUIActive )
445 		{
446 			SOLDIERTYPE* const sel = GetSelectedMan();
447 			if (sel != NULL && OK_INTERRUPT_MERC(sel))
448 			{
449 				SelectSoldier(sel, SELSOLDIER_FORCE_RESELECT);
450 			}
451 		}
452 	}
453 
454 	if ( HandleFadeOutCallback( ) )
455 	{
456 		return( GAME_SCREEN );
457 	}
458 
459 	if ( guiCurrentScreen != MSG_BOX_SCREEN )
460 	{
461 		if ( HandleBeginFadeOut( GAME_SCREEN ) )
462 		{
463 			return( GAME_SCREEN );
464 		}
465 	}
466 
467 
468 	HandleHeliDrop( );
469 
470 	if ( !ARE_IN_FADE_IN( ) )
471 	{
472 		HandleAutoBandagePending( );
473 	}
474 
475 
476 	// ATE: CHRIS_C LOOK HERE FOR GETTING AI CONSTANTLY GOING
477 	//	if ( !(gTacticalStatus.uiFlags & ENEMYS_TURN) )
478 	//	{
479 	//		EndTurn( );
480 	//	}
481 
482 
483 	if (!ARE_IN_FADE_IN())
484 	{
485 		UpdateBullets();
486 
487 		// Execute Tactical Overhead
488 		ExecuteOverhead();
489 	}
490 
491 	// Handle animated cursors
492 	if (gfWorldLoaded)
493 	{
494 		HandleAnimatedCursors();
495 
496 		// Handle Interface
497 		ScreenID const uiNewScreen = HandleTacticalUI();
498 
499 		HandleTalkingAutoFaces();
500 
501 		if (uiNewScreen != GAME_SCREEN) return uiNewScreen;
502 	}
503 	else if (gfIntendOnEnteringEditor && GameState::getInstance()->isEditorMode())
504 	{
505 		SLOGI("Aborting normal game mode and entering editor mode...");
506 		SetPendingNewScreen(NO_PENDING_SCREEN);
507 		return EDIT_SCREEN;
508 	}
509 	else if (!gfEnteringMapScreen)
510 	{
511 		gfEnteringMapScreen = TRUE;
512 	}
513 
514 	// Deque all game events
515 	if (!ARE_IN_FADE_IN())
516 	{
517 		DequeAllGameEvents();
518 	}
519 
520 
521 	HandleTopMessages( );
522 
523 	if (!gfScrollPending && !g_scroll_inertia)
524 	{
525 		// Handle Interface Stuff
526 		SetUpInterface( );
527 		HandleTacticalPanelSwitch( );
528 	}
529 
530 	// Handle Scroll Of World
531 	ScrollWorld( );
532 
533 	//SetRenderFlags( RENDER_FLAG_FULL );
534 
535 	RenderWorld( );
536 
537 	if ( gRenderOverride != NULL )
538 	{
539 		gRenderOverride( );
540 	}
541 
542 	if (gfScrollPending || g_scroll_inertia)
543 	{
544 		RenderTacticalInterfaceWhileScrolling( );
545 	}
546 	else
547 	{
548 		// Handle Interface Stuff
549 		//RenderTacticalInterface( );
550 	}
551 
552 	// Render Interface
553 	RenderTopmostTacticalInterface( );
554 
555 	// Render view window
556 	RenderRadarScreen( );
557 
558 	ResetInterface( );
559 
560 	if ( gfScrollPending  )
561 	{
562 		AllocateVideoOverlaysArea( );
563 		SaveVideoOverlaysArea( FRAME_BUFFER );
564 		ExecuteVideoOverlays( );
565 	}
566 	else
567 	{
568 		ExecuteVideoOverlays( );
569 	}
570 
571 	// Adding/deleting of video overlays needs to be done below
572 	// ExecuteVideoOverlays( )....
573 
574 	// Handle dialogue queue system
575 	if ( !ARE_IN_FADE_IN( ) )
576 	{
577 		HandleDialogue( );
578 	}
579 
580 	//Don't render if we have a scroll pending!
581 	if (!gfScrollPending && !g_scroll_inertia && !gfRenderFullThisFrame)
582 	{
583 		RenderButtonsFastHelp( );
584 	}
585 
586 	// Display Framerate
587 	DisplayFrameRate( );
588 
589 	CheckForMeanwhileOKStart( );
590 
591 	ScrollString( );
592 
593 	ExecuteBaseDirtyRectQueue( );
594 
595 	//KillBackgroundRects( );
596 
597 	/////////////////////////////////////////////////////
598 	EndFrameBufferRender( );
599 
600 
601 	if ( HandleFadeInCallback( ) )
602 	{
603 		// Re-render the scene!
604 		SetRenderFlags( RENDER_FLAG_FULL );
605 		fInterfacePanelDirty = DIRTYLEVEL2;
606 	}
607 
608 	if ( HandleBeginFadeIn( GAME_SCREEN ) )
609 	{
610 		guiTacticalLeaveScreenID = FADE_SCREEN;
611 	}
612 
613 	if ( guiTacticalLeaveScreen )
614 	{
615 		guiTacticalLeaveScreen		= FALSE;
616 
617 		InternalLeaveTacticalScreen( guiTacticalLeaveScreenID );
618 	}
619 
620 	// Check if we are to enter map screen
621 	if ( gfEnteringMapScreen == 2 )
622 	{
623 		gfEnteringMapScreen = FALSE;
624 		LeaveTacticalScreen(MAP_SCREEN);
625 	}
626 
627 
628 	// Are we entering map screen? if so, wait a frame!
629 	if ( gfEnteringMapScreen > 0 )
630 	{
631 		gfEnteringMapScreen++;
632 	}
633 
634 	return( GAME_SCREEN );
635 
636 }
637 
638 
SetRenderHook(RENDER_HOOK pRenderOverride)639 void SetRenderHook( RENDER_HOOK pRenderOverride )
640 {
641 	gRenderOverride = pRenderOverride;
642 }
643 
644 
EnableFPSOverlay(BOOLEAN fEnable)645 void EnableFPSOverlay(BOOLEAN fEnable)
646 {
647 	EnableVideoOverlay(fEnable, g_fps_overlay);
648 	EnableVideoOverlay(fEnable, g_counter_period_overlay);
649 }
650 
651 
TacticalScreenLocateToSoldier(void)652 static void TacticalScreenLocateToSoldier(void)
653 {
654 	SOLDIERTYPE* const prefer = gPreferredInitialSelectedGuy;
655 	if (prefer != NULL)
656 	{
657 		gPreferredInitialSelectedGuy = NULL;
658 		if (OK_CONTROLLABLE_MERC(prefer) && OK_INTERRUPT_MERC(prefer))
659 		{
660 			LocateSoldier(prefer, 10);
661 			SelectSoldier(prefer, SELSOLDIER_FORCE_RESELECT);
662 			return;
663 		}
664 	}
665 
666 	// Set locator to first merc
667 	FOR_EACH_IN_TEAM(s, OUR_TEAM)
668 	{
669 		if (OkControllableMerc(s) && OK_INTERRUPT_MERC(s))
670 		{
671 			LocateSoldier(s, 10);
672 			SelectSoldier(s, SELSOLDIER_FORCE_RESELECT);
673 			break;
674 		}
675 	}
676 }
677 
678 
UpdateTeamPanelAssignments()679 void UpdateTeamPanelAssignments( )
680 {
681 	// Remove all players
682 	RemoveAllPlayersFromSlot( );
683 
684 	FOR_EACH_IN_TEAM(s, OUR_TEAM)
685 	{
686 		// Setup team interface
687 		CheckForAndAddMercToTeamPanel(s);
688 	}
689 }
690 
691 
EnterModalTactical(INT8 bMode)692 void EnterModalTactical( INT8 bMode )
693 {
694 	gfTacticalIsModal = TRUE;
695 
696 	if (bMode == TACTICAL_MODAL_NOMOUSE)
697 	{
698 		if ( !gfTacticalDisableRegionActive )
699 		{
700 			gfTacticalDisableRegionActive = TRUE;
701 
702 			MSYS_DefineRegion(&gTacticalDisableRegion, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGH, VIDEO_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK);
703 		}
704 	}
705 
706 	UpdateSaveBuffer();
707 
708 }
709 
EndModalTactical()710 void EndModalTactical( )
711 {
712 	if ( gfTacticalDisableRegionActive )
713 	{
714 		MSYS_RemoveRegion( &gTacticalDisableRegion );
715 
716 		gfTacticalDisableRegionActive = FALSE;
717 	}
718 
719 
720 	if ( gModalDoneCallback != NULL )
721 	{
722 		gModalDoneCallback( );
723 
724 		gModalDoneCallback = NULL;
725 	}
726 
727 	gfTacticalIsModal = FALSE;
728 
729 	SetRenderFlags( RENDER_FLAG_FULL );
730 }
731 
732 
HandleModalTactical(void)733 static void HandleModalTactical(void)
734 {
735 	RestoreBackgroundRects();
736 
737 	RenderWorld( );
738 	RenderRadarScreen( );
739 	ExecuteVideoOverlays( );
740 
741 	// Handle dialogue queue system
742 	HandleDialogue( );
743 
744 	HandleTalkingAutoFaces( );
745 
746 	// Handle faces
747 	HandleAutoFaces( );
748 
749 	if ( gfInSectorExitMenu )
750 	{
751 		RenderSectorExitMenu( );
752 	}
753 	RenderButtons();
754 
755 	SaveBackgroundRects( );
756 	RenderButtonsFastHelp( );
757 	RenderPausedGameBox( );
758 
759 	ExecuteBaseDirtyRectQueue( );
760 	EndFrameBufferRender( );
761 
762 }
763 
764 
InitHelicopterEntranceByMercs(void)765 void InitHelicopterEntranceByMercs( void )
766 {
767 	if( DidGameJustStart() )
768 	{
769 		// Update clock ahead from STARTING_TIME to make mercs arrive!
770 		WarpGameTime( FIRST_ARRIVAL_DELAY, WARPTIME_PROCESS_EVENTS_NORMALLY );
771 
772 		gfTacticalDoHeliRun = TRUE;
773 		gfFirstHeliRun			= TRUE;
774 
775 		gTacticalStatus.fDidGameJustStart = FALSE;
776 	}
777 }
778