// // 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: /CounterStrike/MISSION.CPP 1 3/03/97 10:25a 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 : MISSION.CPP * * * * Programmer : Joe L. Bostic * * * * Start Date : April 23, 1994 * * * * Last Update : September 14, 1996 [JLB] * * * *---------------------------------------------------------------------------------------------* * Functions: * * MissionClass::AI -- Processes order script. * * MissionClass::Assign_Mission -- Give an order to a unit. * * MissionClass::Commence -- Start script with new order. * * MissionClass::Debug_Dump -- Dumps status values to mono screen. * * MissionClass::Get_Mission -- Fetches the mission that this object is acting under. * * MissionClass::MissionClass -- Default constructor for the mission object type. * * MissionClass::Mission_??? -- Stub mission functions that do nothing. * * MissionClass::Mission_From_Name -- Fetch order pointer from its name. * * MissionClass::Mission_Name -- Converts a mission number into an ASCII string. * * MissionClass::Override_Mission -- temporarily overrides the units mission * * MissionClass::Restore_Mission -- Restores overridden mission * * MissionClass::Set_Mission -- Sets the mission to the specified value. * * MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a te* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" /*********************************************************************************************** * MissionClass::MissionClass -- Default constructor for the mission object type. * * * * This is the default constructor for the mission class object. It sets the mission * * handler into a default -- do nothing -- state. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 01/23/1995 JLB : Created. * * 03/01/1996 JLB : Uses initializer lists. * *=============================================================================================*/ MissionClass::MissionClass(RTTIType rtti, int id) : ObjectClass(rtti, id), Mission(MISSION_NONE), SuspendedMission(MISSION_NONE), MissionQueue(MISSION_NONE), Status(0), Timer(0) { } /*********************************************************************************************** * MissionClass::Mission_??? -- Stub mission functions that do nothing. * * * * These are the stub routines that handle the mission logic. They do nothing at this * * level. Derived classes will override these routine as necessary. * * * * INPUT: none * * * * OUTPUT: Returns with the number of game frames to delay before calling this mission * * handler again. * * * * WARNINGS: none * * * * HISTORY: * * 01/23/1995 JLB : Created. * *=============================================================================================*/ int MissionClass::Mission_Sleep(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Ambush(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Attack(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Capture(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Guard(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Guard_Area(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Harvest(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Hunt(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Move(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Retreat(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Return(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Stop(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Unload(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Enter(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Construction(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Deconstruction(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Repair(void) {return TICKS_PER_SECOND*30;}; int MissionClass::Mission_Missile(void) {return TICKS_PER_SECOND*30;}; /*********************************************************************************************** * MissionClass::Set_Mission -- Sets the mission to the specified value. * * * * Use this routine to set the current mission for this object. This routine will blast * * over the current mission, bypassing the queue method. Call it when the mission needs * * to be changed immediately. * * * * INPUT: mission -- The mission to set to. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 01/23/1995 JLB : Created. * *=============================================================================================*/ void MissionClass::Set_Mission(MissionType mission) { assert(IsActive); Mission = mission; MissionQueue = MISSION_NONE; } /*********************************************************************************************** * MissionClass::Get_Mission -- Fetches the mission that this object is acting under. * * * * Use this routine to fetch the mission that this object is CURRENTLY acting under. The * * mission queue may be filled with a imminent mission change, but this routine does not * * consider that. It only returns the CURRENT mission. * * * * INPUT: none * * * * OUTPUT: Returns with the mission that this unit is currently following. * * * * WARNINGS: none * * * * HISTORY: * * 01/23/1995 JLB : Created. * *=============================================================================================*/ MissionType MissionClass::Get_Mission(void) const { assert(IsActive); return(Mission == MISSION_NONE ? MissionQueue : Mission); } #ifdef CHEAT_KEYS /*********************************************************************************************** * MissionClass::Debug_Dump -- Dumps status values to mono screen. * * * * This is a debugging function that dumps this class' status to the monochrome screen * * for review. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 05/28/1994 JLB : Created. * *=============================================================================================*/ void MissionClass::Debug_Dump(MonoClass * mono) const { assert(IsActive); mono->Set_Cursor(1, 9);mono->Printf("%-14s", MissionClass::Mission_Name(Mission)); mono->Set_Cursor(16, 9);mono->Printf("%-12s", MissionClass::Mission_Name(MissionQueue)); mono->Set_Cursor(1, 7);mono->Printf("%3d", (long)Timer); mono->Set_Cursor(6, 7);mono->Printf("%2d", Status); ObjectClass::Debug_Dump(mono); } #endif /*********************************************************************************************** * MissionClass::AI -- Processes order script. * * * * This routine will process the order script for as much time as * * possible or until a script delay is detected. This routine should * * be called for every unit once per game loop (if possible). * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 04/23/1994 JLB : Created. * * 06/25/1995 JLB : Added new missions. * *=============================================================================================*/ void MissionClass::AI(void) { assert(IsActive); ObjectClass::AI(); /* ** If this is the kind of object that is "paralyzed with fear" while it is above ** ground level (such as when be paradropped), it will perform no mission AI ** processing. */ if ((What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) && Height > 0) { return; } /* ** This is the script AI equivalent processing. */ BStart(BENCH_MISSION); if (Timer == 0 && Strength > 0) { switch (Mission) { default: Timer = Mission_Sleep(); break; case MISSION_HARMLESS: case MISSION_SLEEP: Timer = Mission_Sleep(); break; case MISSION_STICKY: case MISSION_GUARD: Timer = Mission_Guard(); break; case MISSION_ENTER: Timer = Mission_Enter(); break; case MISSION_CONSTRUCTION: Timer = Mission_Construction(); break; case MISSION_DECONSTRUCTION: Timer = Mission_Deconstruction(); break; case MISSION_CAPTURE: case MISSION_SABOTAGE: Timer = Mission_Capture(); break; case MISSION_QMOVE: case MISSION_MOVE: Timer = Mission_Move(); break; case MISSION_ATTACK: Timer = Mission_Attack(); break; case MISSION_RETREAT: Timer = Mission_Retreat(); break; case MISSION_HARVEST: Timer = Mission_Harvest(); break; case MISSION_GUARD_AREA: Timer = Mission_Guard_Area(); break; case MISSION_RETURN: Timer = Mission_Return(); break; case MISSION_STOP: Timer = Mission_Stop(); break; case MISSION_AMBUSH: Timer = Mission_Ambush(); break; case MISSION_HUNT: case MISSION_RESCUE: Timer = Mission_Hunt(); break; // case MISSION_TIMED_HUNT: // Timer = Mission_Timed_Hunt(); // break; case MISSION_UNLOAD: Timer = Mission_Unload(); break; case MISSION_REPAIR: Timer = Mission_Repair(); break; case MISSION_MISSILE: Timer = Mission_Missile(); break; } } BEnd(BENCH_MISSION); } /*********************************************************************************************** * MissionClass::Commence -- Start script with new order. * * * * This routine will start script processing according to any queued * * order it may have. If there is no queued order, then this routine * * does nothing. Call this routine whenever the unit is in a good * * position to change its order (such as when it is stopped). * * * * INPUT: none * * * * OUTPUT: Did the mission actually change? * * * * WARNINGS: none * * * * HISTORY: * * 04/23/1994 JLB : Created. * * 07/14/1994 JLB : Simplified. * * 06/17/1995 JLB : Returns success flag. * *=============================================================================================*/ bool MissionClass::Commence(void) { assert(IsActive); if (MissionQueue != MISSION_NONE) { Mission = MissionQueue; MissionQueue = MISSION_NONE; /* ** Force immediate state machine processing at the first state machine state value. */ Timer = 0; Status = 0; return(true); } return(false); } /*********************************************************************************************** * MissionClass::Assign_Mission -- Give an order to a unit. * * * * This routine will assign the specified mission to the mission queue for this object. * * The actual mission logic will then be performed at the first available and legal * * opportunity. * * * * INPUT: order -- Mission to give the unit. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 06/04/1991 JLB : Created. * * 04/15/1994 JLB : Converted to member function. * *=============================================================================================*/ void MissionClass::Assign_Mission(MissionType order) { assert(IsActive); /* ** Ensure that a MISSION_QMOVE is translated into a MISSION_MOVE. */ if (order == MISSION_QMOVE) order = MISSION_MOVE; if (order != MISSION_NONE && Mission != order) { MissionQueue = order; } } /*********************************************************************************************** * MissionClass::Mission_From_Name -- Fetch order pointer from its name. * * * * This routine is used to convert an ASCII order name into the actual * * order number it represents. Typically, this is used when processing * * a scenario INI file. * * * * INPUT: name -- The ASCII order name to process. * * * * OUTPUT: Returns with the actual order number that the ASCII name * * represents. * * * * WARNINGS: none * * * * HISTORY: * * 10/07/1992 JLB : Created. * * 04/22/1994 JLB : Converted to static member function. * *=============================================================================================*/ MissionType MissionClass::Mission_From_Name(char const * name) { MissionType order; if (name) { for (order = MISSION_FIRST; order < MISSION_COUNT; order++) { if (stricmp(Missions[order], name) == 0) { return(order); } } } return(MISSION_NONE); } /*********************************************************************************************** * MissionClass::Mission_Name -- Converts a mission number into an ASCII string. * * * * Use this routine to convert a mission number into the ASCII string that represents * * it. Typical use of this is when generating an INI file. * * * * INPUT: mission -- The mission number to convert. * * * * OUTPUT: Returns with a pointer to the ASCII string that represents the mission type. * * * * WARNINGS: none * * * * HISTORY: * * 01/23/1995 JLB : Created. * *=============================================================================================*/ char const * MissionClass::Mission_Name(MissionType mission) { if (mission != MISSION_NONE) { return(Missions[mission]); } return("None"); } /*********************************************************************************************** * MissionClass::Override_Mission -- temporarily overrides the units mission * * * * * * * * INPUT: MissionType mission - the mission we want to override * * TARGET tarcom - the new target we want to override * * TARGET navcom - the new navigation point to override * * * * OUTPUT: none * * * * WARNINGS: If a mission is already overridden, the current mission is * * just re-assigned. * * * * HISTORY: * * 04/28/1995 PWG : Created. * *=============================================================================================*/ void MissionClass::Override_Mission(MissionType mission, TARGET, TARGET) { assert(IsActive); if (MissionQueue != MISSION_NONE) { SuspendedMission = MissionQueue; } else { SuspendedMission = Mission; } Assign_Mission(mission); } /*********************************************************************************************** * MissionClass::Restore_Mission -- Restores overridden mission * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 04/28/1995 PWG : Created. * *=============================================================================================*/ bool MissionClass::Restore_Mission(void) { assert(IsActive); if (SuspendedMission != MISSION_NONE) { Assign_Mission(SuspendedMission); SuspendedMission= MISSION_NONE; return(true); } return(false); } /*********************************************************************************************** * MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a tea * * * * Some missions preclude recruitment into a team. This routine will examine the mission * * specified and if not allowed for a team, it will return false. * * * * INPUT: mission -- The mission type to examine. * * * * OUTPUT: bool; Is an object following this mission allowed to be recruited into a team? * * * * WARNINGS: none * * * * HISTORY: * * 09/14/1996 JLB : Created. * *=============================================================================================*/ bool MissionClass::Is_Recruitable_Mission(MissionType mission) { if (mission == MISSION_NONE) { return(true); } return(MissionControl[mission].IsRecruitable); } MissionControlClass::MissionControlClass(void) : Mission(MISSION_NONE), IsNoThreat(false), IsZombie(false), IsRecruitable(true), IsParalyzed(false), IsRetaliate(true), IsScatter(true), Rate(".016"), AARate(".016") { } char const * MissionControlClass::Name(void) const { if (Mission == MISSION_NONE) { return(""); } return(Missions[Mission]); } bool MissionControlClass::Read_INI(CCINIClass & ini) { if (ini.Is_Present(Name())) { IsNoThreat = ini.Get_Bool(Name(), "NoThreat", IsNoThreat); IsZombie = ini.Get_Bool(Name(), "Zombie", IsZombie); IsRecruitable = ini.Get_Bool(Name(), "Recruitable", IsRecruitable); IsParalyzed = ini.Get_Bool(Name(), "Paralyzed", IsParalyzed); IsRetaliate = ini.Get_Bool(Name(), "Retaliate", IsRetaliate); IsScatter = ini.Get_Bool(Name(), "Scatter", IsScatter); Rate = ini.Get_Fixed(Name(), "Rate", Rate); AARate = ini.Get_Fixed(Name(), "AARate", 0); if (AARate == 0) { AARate = Rate; } return(true); } return(false); }