820 lines
No EOL
31 KiB
C++
820 lines
No EOL
31 KiB
C++
//
|
|
// 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;
|
|
}
|
|
} |