//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
// software: you can redistribute it and/or modify it under the terms of 
// the GNU General Public License as published by the Free Software Foundation, 
// either version 3 of the License, or (at your option) any later version.

// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
// in the hope that it will be useful, but with permitted additional restrictions 
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
// distributed with this program. You should have received a copy of the 
// GNU General Public License along with permitted additional restrictions 
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection

/* $Header:   F:\projects\c&c\vcs\code\scenario.cpv   2.17   16 Oct 1995 16:52:08   JOE_BOSTIC  $ */
/***********************************************************************************************
 ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
 ***********************************************************************************************
 *                                                                                             *
 *                 Project Name : Command & Conquer                                            *
 *                                                                                             *
 *                    File Name : SCENARIO.CPP                                                 *
 *                                                                                             *
 *                   Programmer : Joe L. Bostic                                                *
 *                                                                                             *
 *                   Start Date : September 10, 1993                                           *
 *                                                                                             *
 *                  Last Update : August 24, 1995 [JLB]                                        *
 *                                                                                             *
 * This module handles the scenario reading and writing. Scenario related                      *
 * code that is executed between scenario play can also be here.                               *
 *                                                                                             *
 *---------------------------------------------------------------------------------------------*
 * Functions:                                                                                  *
 *   Clear_Scenario -- Clears all data in preparation for scenario load.                       *
 *   Do_Lose -- Display losing comments.                                                       *
 *   Do_Restart -- Handle the restart mission process.                                         *
 *   Do_Win -- Display winning congratulations.                                                *
 *   Fill_In_Data -- Recreate all data that is not loaded with scenario.                       *
 *   Read_Scenario -- Reads a scenario from disk.                                              *
 *   Restate_Mission -- Handles restating the mission objective.                               *
 *   Start_Scenario -- Starts the scenario.                                                    *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include	"function.h"
extern int PreserveVQAScreen;


/***********************************************************************************************
 * Start_Scenario -- Starts the scenario.                                                      *
 *                                                                                             *
 *    This routine will start the scenario. In addition to loading the scenario data, it will  *
 *    play the briefing and action movies.                                                     *
 *                                                                                             *
 * INPUT:   root     -- Pointer to the filename root for this scenario (e.g., "SCG01EA").      *
 *                                                                                             *
 *          briefing -- Should the briefing be played? Normally this is true except when the   *
 *                      scenario is restarting.                                                *
 *                                                                                             *
 * OUTPUT:  Was the scenario started without error?                                            *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   07/04/1995 JLB : Created.                                                                 *
 *=============================================================================================*/
bool Start_Scenario(char *root, bool briefing)
{

	if (!Read_Scenario(root)) {
		CCDebugString ("C&C95 - Failed to read scenario.\n");
		return(false);
	}
	CCDebugString ("C&C95 - Scenario read OK.\n");

#ifdef DEMO

	if (briefing) {
		Play_Movie(BriefMovie);
		Play_Movie(ActionMovie, TransitTheme);
	}
	Theme.Queue_Song(THEME_AOI);

#else

	/*
	** Install some hacks around the movie playing to account for the choose-
	** sides introduction.  We don't want an intro movie on scenario 1, and
	** we don't want a briefing movie on GDI scenario 1.
	*/
	if (Scenario < 20 && (!Special.IsJurassic || !AreThingiesEnabled)) {
		if (Scenario != 1 || Whom == HOUSE_GOOD) {
			Play_Movie(IntroMovie);
		}

		if (briefing) {
			PreserveVQAScreen = (Scenario == 1);
			Play_Movie(BriefMovie);
		}
		Play_Movie(ActionMovie, TransitTheme);
		if (TransitTheme == THEME_NONE) {
			Theme.Queue_Song(THEME_AOI);
		}
	} else {
		Play_Movie(BriefMovie);
		Play_Movie(ActionMovie, TransitTheme);

#ifdef NEWMENU

		char buffer[25];
		sprintf(buffer, "%s.VQA", BriefMovie);
		CCFileClass file(buffer);

		if (GameToPlay == GAME_NORMAL && !file.Is_Available()) {
			VisiblePage.Clear();
			Set_Palette(GamePalette);
//			Show_Mouse();
			/*
			** Show the mission briefing. Pretend we are inside the main loop so the palette
			** will be correct on the textured buttons.
			*/
			bool oldinmain = InMainLoop;
			InMainLoop = true;
			
			// TO_FIX - Covert ops missions want to pop up a dialog box. ST - 9/6/2019 1:48PM
			//Restate_Mission(ScenarioName, TXT_OK, TXT_NONE);
			
			
			InMainLoop = oldinmain;
//			Hide_Mouse();
			if (TransitTheme == THEME_NONE) {
				Theme.Queue_Song(THEME_AOI);
			}
		}

#endif
	}
#endif

	/*
	** Set the options values, since the palette has been initialized by Read_Scenario
	*/
	CCDebugString ("C&C95 - About to call Options.Set.\n");
	Options.Set();
	CCDebugString ("C&C95 - About to return from Start_Scenario.\n");
	return(true);
}


/***********************************************************************************************
 * Set_Scenario_Difficulty -- Sets the difficulty of the scenario.                             *
 *                                                                                             *
 *    Updates the player's difficulty in single-player mode.                                   *
 *                                                                                             *
 * INPUT:   difficulty     -- Scenario difficulty                                              *
 *                                                                                             *
 * OUTPUT:     none                                                                            *
 *                                                                                             *
 * WARNINGS:   Only works in single-player.                                                    *
 *             Must call Start_Scenario first to initialize the player.                        *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   10/02/2019 SKY : Created.                                                                 *
 *=============================================================================================*/
void Set_Scenario_Difficulty(int difficulty)
{
	if (GameToPlay == GAME_NORMAL) {
		switch (difficulty) {
			case 0:
				PlayerPtr->Assign_Handicap(DIFF_EASY);
				break;
			case 1:
				PlayerPtr->Assign_Handicap(DIFF_NORMAL);
				break;
			case 2:
				PlayerPtr->Assign_Handicap(DIFF_HARD);
				break;
			default:
				break;
		}
	}
}


/***********************************************************************************************
 * Read_Scenario -- Reads a scenario from disk.                                                *
 *                                                                                             *
 *    This will read a scenario from disk. Use this to begin a scenario.                       *
 *    It doesn't perform any rendering, it merely sets up the system                           *
 *    with the proper data. Setting of the right game state will start                         *
 *    the scenario running.                                                                    *
 *                                                                                             *
 * INPUT:   root     -- Scenario root filename                                                 *
 *                                                                                             *
 * OUTPUT:     none                                                                            *
 *                                                                                             *
 * WARNINGS:   You must clear out the system variables before calling                          *
 *             this function. Use the Clear_Scenario() function.                               *
 *               It is assumed that Scenario is set to the current scenario number.            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   07/22/1991     : Created.                                                                 *
 *   02/03/1992 JLB : Uses house identification.                                               *
 *=============================================================================================*/
bool Read_Scenario(char *root)
{
	CCDebugString ("C&C95 - In Read_Scenario.\n");
	Clear_Scenario();
	ScenarioInit++;
	if (Read_Scenario_Ini(root)) {

		Fill_In_Data();

		Map.Set_View_Dimensions(0, Map.Get_Tab_Height(), Map.MapCellWidth, Map.MapCellHeight);


		/*
		**	SPECIAL CASE:
		**	Clear out the tutor flags for scenarios one and two. This is designed
		**	so that tutorial message will reappear in scenario two.
		*/
		if (Scenario < 5) {
			TutorFlags[0] = 0L;
			TutorFlags[1] = 0L;
		}

	} else {

#if (1)
		char message[200];
		if (root) {
			sprintf(message, "Failed to load scenario %s", root);
			GlyphX_Debug_Print(message);
		} else {
			GlyphX_Debug_Print("Failed to load scenario");
		}
#else		  
		Fade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);
		Show_Mouse();
		CCMessageBox().Process(TXT_UNABLE_READ_SCENARIO);
		Hide_Mouse();
#endif
		return(false);
	}
	ScenarioInit--;
	CCDebugString ("C&C95 - Leaving Read_Scenario.\n");
	return(true);
}


/***********************************************************************************************
 * Fill_In_Data -- Recreate all data that is not loaded with scenario.                         *
 *                                                                                             *
 *    This routine is called after the INI file for the scenario has been processed. It will   *
 *    infer the game state from the scenario INI data.                                         *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   10/07/1992 JLB : Created.                                                                 *
 *=============================================================================================*/
void Fill_In_Data(void)
{
	/*
	**	The basic scenario data load does not contain the full set of
	**	game data. We now must fill in the missing pieces.
	*/
	ScenarioInit++;

	for (int index = 0; index < Buildings.Count(); index++) {
		Buildings.Ptr(index)->Update_Buildables();
	}

	Map.Flag_To_Redraw(true);

	/*
	**	Bring up the score display on the radar map when starting a multiplayer
	**	game.
	*/
	if (GameToPlay != GAME_NORMAL) {
		Map.Player_Names(1);
	}

	ScenarioInit--;
}


/***********************************************************************************************
 * Clear_Scenario -- Clears all data in preparation for scenario load.                         *
 *                                                                                             *
 *    This routine will clear out all data specific to a scenario in                           *
 *    preparation for a subsequent scenario data load. This will free                          *
 *    all units, animations, and icon maps.                                                    *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   07/22/1991     : Created.                                                                 *
 *   03/21/1992 JLB : Changed buffer allocations, so changes memset code.                      *
 *   07/13/1995 JLB : End count down moved here.                                               *
 *=============================================================================================*/
void Clear_Scenario(void)
{
	EndCountDown = TICKS_PER_SECOND * 30;
	CrateCount = 0;
	CrateTimer = 0;
	CrateMaker = false;

	/*
	** Call everyone's Init routine, except the Map's; for the Map, only call
	** MapClass::Init, which clears the Cell array.  The Display::Init requires
	** a Theater argument, and the theater is not known at this point; also, it
	** would reload MixFiles, which isn't desired.  Display::Read_INI calls its
	** own Init, which will Init the entire Map hierarchy.
	*/
	Map.Init_Clear();
	Score.Init();
	Logic.Init();

	HouseClass::Init();
	ObjectClass::Init();
	TeamTypeClass::Init();
	TeamClass::Init();
	TriggerClass::Init();
	AircraftClass::Init();
	AnimClass::Init();
	BuildingClass::Init();
	BulletClass::Init();
	InfantryClass::Init();
	OverlayClass::Init();
	SmudgeClass::Init();
	TemplateClass::Init();
	TerrainClass::Init();
	UnitClass::Init();

	FactoryClass::Init();

	Base.Init();

	CurrentObject.Clear_All();

	Invalidate_Cached_Icons();
}


/***********************************************************************************************
 * Do_Win -- Display winning congratulations.                                                  *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/05/1992 JLB : Created.                                                                 *
 *   01/01/1995 JLB : Carries money forward into next scenario.                                *
 *=============================================================================================*/
void Do_Win(void)
{
	Map.Set_Default_Mouse(MOUSE_NORMAL);
	Hide_Mouse();

	/*
	** If this is a multiplayer game, clear the game's name so we won't respond
	** to game queries any more (in Call_Back)
	*/
	if (GameToPlay != GAME_NORMAL) {
		MPlayerGameName[0] = 0;
	}

	/*
	**	Determine a cosmetic center point for the text.
	*/
	int x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);
	int y = Map.TacPixelY + (Lepton_To_Pixel(Map.TacLeptonHeight)/2) -32;

	/*
	**	Announce win to player.
	*/
	Set_Logic_Page(SeenBuff);
#if !(GERMAN | FRENCH)
	Fancy_Text_Print(TXT_MISSION, x, y, WHITE, TBLACK, TPF_CENTER|TPF_VCR);
#endif
	Fancy_Text_Print(TXT_SCENARIO_WON, x, y+30, WHITE, TBLACK, TPF_CENTER|TPF_VCR);
	CountDownTimer.Set(TIMER_SECOND * 3);
	Stop_Speaking();
	Speak(VOX_ACCOMPLISHED);
	while (CountDownTimer.Time() || Is_Speaking()) {
		Call_Back();
	}

	/*
	** Stop here if this is a multiplayer game.
	*/
	if (GameToPlay != GAME_NORMAL) {
		if (!PlaybackGame) {
			MPlayerGamesPlayed++;
			Multi_Score_Presentation();
			MPlayerCurGame++;
			if (MPlayerCurGame >= MAX_MULTI_GAMES) {
				MPlayerCurGame = MAX_MULTI_GAMES - 1;
			}
		}
		GameActive = 0;
		Show_Mouse();
		return;
	}

	/*
	**	Play the winning movie and then start the next scenario.
	*/
	if (RequiredCD != -2) {
		if (Scenario >= 20 && Scenario <60 && GameToPlay == GAME_NORMAL) {
			RequiredCD = 2;
		} else {
			if (Scenario >=60){
				RequiredCD = -1;
			}else{
				if (PlayerPtr->Class->House == HOUSE_GOOD) {
					RequiredCD = 0;
				} else {
					RequiredCD = 1;
				}
			}
		}
	}

#ifndef DEMO
	Play_Movie(WinMovie);
#endif

	Keyboard::Clear();

	/*
	**	Do the ending screens only if not playing back a recorded game.
	*/
	if (!PlaybackGame) {

#ifdef DEMO

		switch (Scenario) {
			case 1:
				Score.Presentation();
				Scenario = 10;
				break;

			case 10:
				Score.Presentation();
				Scenario = 6;
				break;

			default:
				Score.Presentation();
				GDI_Ending();
				GameActive = false;
				Show_Mouse();
				return;
//				Prog_End();
//				exit(0);
//				break;
		}

#else

#ifdef NEWMENU
		if (Scenario >= 20) {
			Keyboard::Clear();
			Score.Presentation();
			GameActive = false;
			Show_Mouse();
			return;
		}
#endif

		if (PlayerPtr->Class->House == HOUSE_BAD && Scenario == 13) {
			Nod_Ending();
			//Prog_End();
			//exit(0);
			SeenBuff.Clear();
			Show_Mouse();
			GameActive = false;
			return;
		}
		if (PlayerPtr->Class->House == HOUSE_GOOD && Scenario == 15) {
			GDI_Ending();
			//Prog_End();
			//exit(0);
			SeenBuff.Clear();
			Show_Mouse();
			GameActive = false;
			return;
		}

		if ( (Special.IsJurassic && AreThingiesEnabled) && Scenario == 5) {
			Prog_End("Do_Win - Last Jurassic mission complete");
			if (!RunningAsDLL) {
				exit(0);
			}
			return;
		}

		if (!Special.IsJurassic || !AreThingiesEnabled) {
			Keyboard::Clear();
			InterpolationPaletteChanged = TRUE;
			InterpolationPalette = Palette;
			Score.Presentation();

			/*
			**	Skip scenario #7 if the airfield was blown up.
			*/
			if (Scenario == 6 && PlayerPtr->Class->House == HOUSE_GOOD && SabotagedType == STRUCT_AIRSTRIP) {
				Scenario++;
			}

			Map_Selection();
		}
		Scenario++;
#endif
		Keyboard::Clear();
	}

	CarryOverMoney = PlayerPtr->Credits;

	int pieces = PlayerPtr->NukePieces;

	/*
	** Generate a new scenario filename
	*/
	Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir, ScenVar);
	Start_Scenario(ScenarioName);

	PlayerPtr->NukePieces = pieces;

	/*
	**	Destroy the building that was sabotaged in the previous scenario. This only
	**	applies to GDI mission #7.
	*/
	int index;
	if (SabotagedType != STRUCT_NONE && Scenario == 7 && PlayerPtr->Class->House == HOUSE_GOOD) {
		for (index = 0; index < Buildings.Count(); index++) {
			BuildingClass * building = Buildings.Ptr(index);

			if (building && !building->IsInLimbo && building->House != PlayerPtr && building->Class->Type == SabotagedType) {
				building->Limbo();
				delete building;
				break;
			}
		}

		/*
		**	Remove the building from the prebuild list.
		*/
		for (index = 0; index < Base.Nodes.Count(); index++) {
			BaseNodeClass * node = Base.Get_Node(index);

			if (node && node->Type == SabotagedType) {
				Base.Nodes.Delete(index);
				break;
			}
		}
	}
	SabotagedType = STRUCT_NONE;

	Map.Render();
	Fade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);
	Show_Mouse();
}


/***********************************************************************************************
 * Do_Lose -- Display losing comments.                                                         *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:                                                                                      *
 *                                                                                             *
 * OUTPUT:                                                                                     *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/05/1992 JLB : Created.                                                                 *
 *=============================================================================================*/
void Do_Lose(void)
{
	Map.Set_Default_Mouse(MOUSE_NORMAL);
	Hide_Mouse();

	/*
	** If this is a multiplayer game, clear the game's name so we won't respond
	** to game queries any more (in Call_Back)
	*/
	if (GameToPlay != GAME_NORMAL) {
		MPlayerGameName[0] = 0;
	}

	/*
	**	Determine a cosmetic center point for the text.
	*/
	int x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2);
	int y = Map.TacPixelY + (Lepton_To_Pixel(Map.TacLeptonHeight)/2) -32;

	/*
	**	Announce win to player.
	*/
	Set_Logic_Page(SeenBuff);
	Fancy_Text_Print(TXT_MISSION, x, y, WHITE, TBLACK, TPF_CENTER|TPF_VCR);
	Fancy_Text_Print(TXT_SCENARIO_LOST, x, y+30, WHITE, TBLACK, TPF_CENTER|TPF_VCR);
	CountDownTimer.Set(TIMER_SECOND * 3);
	Stop_Speaking();
	Speak(VOX_FAIL);
	while (CountDownTimer.Time() || Is_Speaking()) {
		Call_Back();
	}

#ifdef OBSOLETE
	if (Debug_Play_Map) {
		Go_Editor(true);
		Show_Mouse();
		return;
	}
#endif

	/*
	** Stop here if this is a multiplayer game.
	*/
	if (GameToPlay != GAME_NORMAL) {
		if (!PlaybackGame) {
			MPlayerGamesPlayed++;
			Multi_Score_Presentation();
			MPlayerCurGame++;
			if (MPlayerCurGame >= MAX_MULTI_GAMES) {
				MPlayerCurGame = MAX_MULTI_GAMES - 1;
			}
		}
		GameActive = 0;
		Show_Mouse();
		return;
	}

	Play_Movie(LoseMovie);

	/*
	** Start same scenario again
	*/
	Set_Palette(GamePalette);
	Show_Mouse();
	if (!PlaybackGame && !CCMessageBox().Process(TXT_TO_REPLAY, TXT_YES, TXT_NO)) {
		Hide_Mouse();
		Keyboard::Clear();
		Start_Scenario(ScenarioName, false);
		Map.Render();
	} else {
		Hide_Mouse();
		GameActive = 0;
	}

	Fade_Palette_To(GamePalette, FADE_PALETTE_FAST, Call_Back);
	Show_Mouse();
}


/***********************************************************************************************
 * Do_Restart -- Handle the restart mission process.                                           *
 *                                                                                             *
 *    This routine is called in the main game loop when the mission must be restarted. This    *
 *    routine will throw away the current game and reload the appropriate mission. The         *
 *    game will "resume" at the start of the mission.                                          *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   08/24/1995 JLB : Created.                                                                 *
 *=============================================================================================*/
void Do_Restart(void)
{
	bool hidden = Get_Mouse_State();

	if (hidden) Show_Mouse();
	CCMessageBox().Process(TXT_RESTARTING, TXT_NONE);
	Map.Set_Default_Mouse(MOUSE_NORMAL);
	Keyboard::Clear();
	Start_Scenario(ScenarioName, false);
	if (hidden) Hide_Mouse();
	Keyboard::Clear();
	Map.Render();
}


/***********************************************************************************************
 * Restate_Mission -- Handles restating the mission objective.                                 *
 *                                                                                             *
 *    This routine will display the mission objective (as text). It will also give the         *
 *    option to redisplay the mission briefing video.                                          *
 *                                                                                             *
 * INPUT:   name  -- The scenario name. This is the unique identifier for the scenario         *
 *                   briefing text as it appears in the "MISSION.INI" file.                    *
 *                                                                                             *
 * OUTPUT:  Returns the response from the dialog. This will either be 1 if the video was       *
 *          requested, or 0 if the return to game options button was selected.                 *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   06/23/1995 JLB : Created.                                                                 *
 *   08/06/1995 JLB : Uses preloaded briefing text.                                            *
 *=============================================================================================*/
bool Restate_Mission(char const * name, int button1, int button2)
{
	if (name) {
#ifdef JAPANESE
		char fname[14];
		strcpy(fname, name);
		strcat(fname,".CPS");

		if(CCFileClass(fname).Is_Available()) {
			CCMessageBox box(TXT_NONE, true);
			return(box.Process(fname, button1, button2));
		}
#else
		/*
		**	Make sure that if there is no briefing movie, that the briefing text is
		**	the only option available.
		*/
		bool brief = true;
#ifdef NEWMENU
		char buffer[25];
		char buffer1[25];
		sprintf(buffer, "%s.VQA", BriefMovie);
		sprintf(buffer1, "%s.VQA", ActionMovie);
		CCFileClass file1(buffer);
		CCFileClass file2(buffer1);
		if (!file1.Is_Available() && !file2.Is_Available()) {
			button1 = TXT_OK;
			button2 = TXT_NONE;
			brief = false;
		}
#endif

		/*
		**	If mission object text was found, then display it.
		*/
		if (strlen(BriefingText)) {
			static char _buff[512];

			strcpy(_buff, BriefingText);
//			strcpy(_ShapeBuffer, BriefingText);

			bool hidden = Get_Mouse_State();
			if (hidden) Show_Mouse();

			if (CCMessageBox(TXT_OBJECTIVE).Process(_buff, button1, button2)) {
				if (hidden) Hide_Mouse();
				return(true);
			}
			if (hidden) Hide_Mouse();
			if (!brief) return(true);
			return(false);
		}
#endif
	}
	return(false);
}

void Fixup_Scenario(void)
{
	/*
	** "Fraidycat" civilians avoid wandering into Tiberium for SCG08EB, since they're mission-critical.
	*/
	bool is_scg08ea = GameToPlay == GAME_NORMAL && PlayerPtr->ActLike == HOUSE_GOOD && Scenario == 8 && ScenVar == SCEN_VAR_B;
	for (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {
		InfantryTypeClass& infantry_type = (InfantryTypeClass&)InfantryTypeClass::As_Reference(index);
		if (infantry_type.IsFraidyCat) {
			infantry_type.IsAvoidingTiberium = is_scg08ea;
		}
	}

	/*
	** Laser-firing Orcas in the PATSUX secret mission
	*/
	if (GameToPlay == GAME_NORMAL && Scenario == 72) {
		((AircraftTypeClass&)AircraftTypeClass::As_Reference(AIRCRAFT_ORCA)).Primary = WEAPON_OBELISK_LASER;
	} else {
		((AircraftTypeClass&)AircraftTypeClass::As_Reference(AIRCRAFT_ORCA)).Primary = WEAPON_DRAGON;
	}

	/*
	** Modern Balance
	*/
	if (Special.ModernBalance) {
		/*
		** GDI Weapons Factory has 30% more health.
		*/
		((BuildingTypeClass&)BuildingTypeClass::As_Reference(STRUCT_WEAP)).MaxStrength = 520;

		/*
		** Repair Pad is a pre-requisite for the APC.
		*/
		((UnitTypeClass&)UnitTypeClass::As_Reference(UNIT_APC)).Pre |= STRUCTF_REPAIR;
	} else {
		((BuildingTypeClass&)BuildingTypeClass::As_Reference(STRUCT_WEAP)).MaxStrength = 400;
		((UnitTypeClass&)UnitTypeClass::As_Reference(UNIT_APC)).Pre &= ~STRUCTF_REPAIR;
	}
}