MISSION.CPP (30951B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/MISSION.CPP 1 3/03/97 10:25a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** 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 *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : MISSION.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : April 23, 1994 * 28 * * 29 * Last Update : September 14, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * MissionClass::AI -- Processes order script. * 34 * MissionClass::Assign_Mission -- Give an order to a unit. * 35 * MissionClass::Commence -- Start script with new order. * 36 * MissionClass::Debug_Dump -- Dumps status values to mono screen. * 37 * MissionClass::Get_Mission -- Fetches the mission that this object is acting under. * 38 * MissionClass::MissionClass -- Default constructor for the mission object type. * 39 * MissionClass::Mission_??? -- Stub mission functions that do nothing. * 40 * MissionClass::Mission_From_Name -- Fetch order pointer from its name. * 41 * MissionClass::Mission_Name -- Converts a mission number into an ASCII string. * 42 * MissionClass::Override_Mission -- temporarily overrides the units mission * 43 * MissionClass::Restore_Mission -- Restores overridden mission * 44 * MissionClass::Set_Mission -- Sets the mission to the specified value. * 45 * MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a te* 46 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 47 48 #include "function.h" 49 50 51 /*********************************************************************************************** 52 * MissionClass::MissionClass -- Default constructor for the mission object type. * 53 * * 54 * This is the default constructor for the mission class object. It sets the mission * 55 * handler into a default -- do nothing -- state. * 56 * * 57 * INPUT: none * 58 * * 59 * OUTPUT: none * 60 * * 61 * WARNINGS: none * 62 * * 63 * HISTORY: * 64 * 01/23/1995 JLB : Created. * 65 * 03/01/1996 JLB : Uses initializer lists. * 66 *=============================================================================================*/ 67 MissionClass::MissionClass(RTTIType rtti, int id) : 68 ObjectClass(rtti, id), 69 Mission(MISSION_NONE), 70 SuspendedMission(MISSION_NONE), 71 MissionQueue(MISSION_NONE), 72 Status(0), 73 Timer(0) 74 { 75 } 76 77 78 /*********************************************************************************************** 79 * MissionClass::Mission_??? -- Stub mission functions that do nothing. * 80 * * 81 * These are the stub routines that handle the mission logic. They do nothing at this * 82 * level. Derived classes will override these routine as necessary. * 83 * * 84 * INPUT: none * 85 * * 86 * OUTPUT: Returns with the number of game frames to delay before calling this mission * 87 * handler again. * 88 * * 89 * WARNINGS: none * 90 * * 91 * HISTORY: * 92 * 01/23/1995 JLB : Created. * 93 *=============================================================================================*/ 94 int MissionClass::Mission_Sleep(void) {return TICKS_PER_SECOND*30;}; 95 int MissionClass::Mission_Ambush(void) {return TICKS_PER_SECOND*30;}; 96 int MissionClass::Mission_Attack(void) {return TICKS_PER_SECOND*30;}; 97 int MissionClass::Mission_Capture(void) {return TICKS_PER_SECOND*30;}; 98 int MissionClass::Mission_Guard(void) {return TICKS_PER_SECOND*30;}; 99 int MissionClass::Mission_Guard_Area(void) {return TICKS_PER_SECOND*30;}; 100 int MissionClass::Mission_Harvest(void) {return TICKS_PER_SECOND*30;}; 101 int MissionClass::Mission_Hunt(void) {return TICKS_PER_SECOND*30;}; 102 int MissionClass::Mission_Move(void) {return TICKS_PER_SECOND*30;}; 103 int MissionClass::Mission_Retreat(void) {return TICKS_PER_SECOND*30;}; 104 int MissionClass::Mission_Return(void) {return TICKS_PER_SECOND*30;}; 105 int MissionClass::Mission_Stop(void) {return TICKS_PER_SECOND*30;}; 106 int MissionClass::Mission_Unload(void) {return TICKS_PER_SECOND*30;}; 107 int MissionClass::Mission_Enter(void) {return TICKS_PER_SECOND*30;}; 108 int MissionClass::Mission_Construction(void) {return TICKS_PER_SECOND*30;}; 109 int MissionClass::Mission_Deconstruction(void) {return TICKS_PER_SECOND*30;}; 110 int MissionClass::Mission_Repair(void) {return TICKS_PER_SECOND*30;}; 111 int MissionClass::Mission_Missile(void) {return TICKS_PER_SECOND*30;}; 112 113 114 /*********************************************************************************************** 115 * MissionClass::Set_Mission -- Sets the mission to the specified value. * 116 * * 117 * Use this routine to set the current mission for this object. This routine will blast * 118 * over the current mission, bypassing the queue method. Call it when the mission needs * 119 * to be changed immediately. * 120 * * 121 * INPUT: mission -- The mission to set to. * 122 * * 123 * OUTPUT: none * 124 * * 125 * WARNINGS: none * 126 * * 127 * HISTORY: * 128 * 01/23/1995 JLB : Created. * 129 *=============================================================================================*/ 130 void MissionClass::Set_Mission(MissionType mission) 131 { 132 assert(IsActive); 133 134 Mission = mission; 135 MissionQueue = MISSION_NONE; 136 } 137 138 139 /*********************************************************************************************** 140 * MissionClass::Get_Mission -- Fetches the mission that this object is acting under. * 141 * * 142 * Use this routine to fetch the mission that this object is CURRENTLY acting under. The * 143 * mission queue may be filled with a imminent mission change, but this routine does not * 144 * consider that. It only returns the CURRENT mission. * 145 * * 146 * INPUT: none * 147 * * 148 * OUTPUT: Returns with the mission that this unit is currently following. * 149 * * 150 * WARNINGS: none * 151 * * 152 * HISTORY: * 153 * 01/23/1995 JLB : Created. * 154 *=============================================================================================*/ 155 MissionType MissionClass::Get_Mission(void) const 156 { 157 assert(IsActive); 158 159 return(Mission == MISSION_NONE ? MissionQueue : Mission); 160 } 161 162 163 #ifdef CHEAT_KEYS 164 /*********************************************************************************************** 165 * MissionClass::Debug_Dump -- Dumps status values to mono screen. * 166 * * 167 * This is a debugging function that dumps this class' status to the monochrome screen * 168 * for review. * 169 * * 170 * INPUT: none * 171 * * 172 * OUTPUT: none * 173 * * 174 * WARNINGS: none * 175 * * 176 * HISTORY: * 177 * 05/28/1994 JLB : Created. * 178 *=============================================================================================*/ 179 void MissionClass::Debug_Dump(MonoClass * mono) const 180 { 181 assert(IsActive); 182 183 mono->Set_Cursor(1, 9);mono->Printf("%-14s", MissionClass::Mission_Name(Mission)); 184 mono->Set_Cursor(16, 9);mono->Printf("%-12s", MissionClass::Mission_Name(MissionQueue)); 185 mono->Set_Cursor(1, 7);mono->Printf("%3d", (long)Timer); 186 mono->Set_Cursor(6, 7);mono->Printf("%2d", Status); 187 188 ObjectClass::Debug_Dump(mono); 189 } 190 #endif 191 192 193 /*********************************************************************************************** 194 * MissionClass::AI -- Processes order script. * 195 * * 196 * This routine will process the order script for as much time as * 197 * possible or until a script delay is detected. This routine should * 198 * be called for every unit once per game loop (if possible). * 199 * * 200 * INPUT: none * 201 * * 202 * OUTPUT: none * 203 * * 204 * WARNINGS: none * 205 * * 206 * HISTORY: * 207 * 04/23/1994 JLB : Created. * 208 * 06/25/1995 JLB : Added new missions. * 209 *=============================================================================================*/ 210 void MissionClass::AI(void) 211 { 212 assert(IsActive); 213 214 ObjectClass::AI(); 215 216 /* 217 ** If this is the kind of object that is "paralyzed with fear" while it is above 218 ** ground level (such as when be paradropped), it will perform no mission AI 219 ** processing. 220 */ 221 if ((What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) && Height > 0) { 222 return; 223 } 224 225 /* 226 ** This is the script AI equivalent processing. 227 */ 228 BStart(BENCH_MISSION); 229 if (Timer == 0 && Strength > 0) { 230 switch (Mission) { 231 default: 232 Timer = Mission_Sleep(); 233 break; 234 235 case MISSION_HARMLESS: 236 case MISSION_SLEEP: 237 Timer = Mission_Sleep(); 238 break; 239 240 case MISSION_STICKY: 241 case MISSION_GUARD: 242 Timer = Mission_Guard(); 243 break; 244 245 case MISSION_ENTER: 246 Timer = Mission_Enter(); 247 break; 248 249 case MISSION_CONSTRUCTION: 250 Timer = Mission_Construction(); 251 break; 252 253 case MISSION_DECONSTRUCTION: 254 Timer = Mission_Deconstruction(); 255 break; 256 257 case MISSION_CAPTURE: 258 case MISSION_SABOTAGE: 259 Timer = Mission_Capture(); 260 break; 261 262 case MISSION_QMOVE: 263 case MISSION_MOVE: 264 Timer = Mission_Move(); 265 break; 266 267 case MISSION_ATTACK: 268 Timer = Mission_Attack(); 269 break; 270 271 case MISSION_RETREAT: 272 Timer = Mission_Retreat(); 273 break; 274 275 case MISSION_HARVEST: 276 Timer = Mission_Harvest(); 277 break; 278 279 case MISSION_GUARD_AREA: 280 Timer = Mission_Guard_Area(); 281 break; 282 283 case MISSION_RETURN: 284 Timer = Mission_Return(); 285 break; 286 287 case MISSION_STOP: 288 Timer = Mission_Stop(); 289 break; 290 291 case MISSION_AMBUSH: 292 Timer = Mission_Ambush(); 293 break; 294 295 case MISSION_HUNT: 296 case MISSION_RESCUE: 297 Timer = Mission_Hunt(); 298 break; 299 300 // case MISSION_TIMED_HUNT: 301 // Timer = Mission_Timed_Hunt(); 302 // break; 303 304 case MISSION_UNLOAD: 305 Timer = Mission_Unload(); 306 break; 307 308 case MISSION_REPAIR: 309 Timer = Mission_Repair(); 310 break; 311 312 case MISSION_MISSILE: 313 Timer = Mission_Missile(); 314 break; 315 } 316 } 317 BEnd(BENCH_MISSION); 318 } 319 320 321 /*********************************************************************************************** 322 * MissionClass::Commence -- Start script with new order. * 323 * * 324 * This routine will start script processing according to any queued * 325 * order it may have. If there is no queued order, then this routine * 326 * does nothing. Call this routine whenever the unit is in a good * 327 * position to change its order (such as when it is stopped). * 328 * * 329 * INPUT: none * 330 * * 331 * OUTPUT: Did the mission actually change? * 332 * * 333 * WARNINGS: none * 334 * * 335 * HISTORY: * 336 * 04/23/1994 JLB : Created. * 337 * 07/14/1994 JLB : Simplified. * 338 * 06/17/1995 JLB : Returns success flag. * 339 *=============================================================================================*/ 340 bool MissionClass::Commence(void) 341 { 342 assert(IsActive); 343 344 if (MissionQueue != MISSION_NONE) { 345 Mission = MissionQueue; 346 MissionQueue = MISSION_NONE; 347 348 /* 349 ** Force immediate state machine processing at the first state machine state value. 350 */ 351 Timer = 0; 352 Status = 0; 353 return(true); 354 } 355 return(false); 356 } 357 358 359 /*********************************************************************************************** 360 * MissionClass::Assign_Mission -- Give an order to a unit. * 361 * * 362 * This routine will assign the specified mission to the mission queue for this object. * 363 * The actual mission logic will then be performed at the first available and legal * 364 * opportunity. * 365 * * 366 * INPUT: order -- Mission to give the unit. * 367 * * 368 * OUTPUT: none * 369 * * 370 * WARNINGS: none * 371 * * 372 * HISTORY: * 373 * 06/04/1991 JLB : Created. * 374 * 04/15/1994 JLB : Converted to member function. * 375 *=============================================================================================*/ 376 void MissionClass::Assign_Mission(MissionType order) 377 { 378 assert(IsActive); 379 380 /* 381 ** Ensure that a MISSION_QMOVE is translated into a MISSION_MOVE. 382 */ 383 if (order == MISSION_QMOVE) order = MISSION_MOVE; 384 385 if (order != MISSION_NONE && Mission != order) { 386 MissionQueue = order; 387 } 388 } 389 390 391 /*********************************************************************************************** 392 * MissionClass::Mission_From_Name -- Fetch order pointer from its name. * 393 * * 394 * This routine is used to convert an ASCII order name into the actual * 395 * order number it represents. Typically, this is used when processing * 396 * a scenario INI file. * 397 * * 398 * INPUT: name -- The ASCII order name to process. * 399 * * 400 * OUTPUT: Returns with the actual order number that the ASCII name * 401 * represents. * 402 * * 403 * WARNINGS: none * 404 * * 405 * HISTORY: * 406 * 10/07/1992 JLB : Created. * 407 * 04/22/1994 JLB : Converted to static member function. * 408 *=============================================================================================*/ 409 MissionType MissionClass::Mission_From_Name(char const * name) 410 { 411 MissionType order; 412 413 if (name) { 414 for (order = MISSION_FIRST; order < MISSION_COUNT; order++) { 415 if (stricmp(Missions[order], name) == 0) { 416 return(order); 417 } 418 } 419 } 420 return(MISSION_NONE); 421 } 422 423 424 /*********************************************************************************************** 425 * MissionClass::Mission_Name -- Converts a mission number into an ASCII string. * 426 * * 427 * Use this routine to convert a mission number into the ASCII string that represents * 428 * it. Typical use of this is when generating an INI file. * 429 * * 430 * INPUT: mission -- The mission number to convert. * 431 * * 432 * OUTPUT: Returns with a pointer to the ASCII string that represents the mission type. * 433 * * 434 * WARNINGS: none * 435 * * 436 * HISTORY: * 437 * 01/23/1995 JLB : Created. * 438 *=============================================================================================*/ 439 char const * MissionClass::Mission_Name(MissionType mission) 440 { 441 if (mission != MISSION_NONE) { 442 return(Missions[mission]); 443 } 444 return("None"); 445 } 446 447 448 /*********************************************************************************************** 449 * MissionClass::Override_Mission -- temporarily overrides the units mission * 450 * * 451 * * 452 * * 453 * INPUT: MissionType mission - the mission we want to override * 454 * TARGET tarcom - the new target we want to override * 455 * TARGET navcom - the new navigation point to override * 456 * * 457 * OUTPUT: none * 458 * * 459 * WARNINGS: If a mission is already overridden, the current mission is * 460 * just re-assigned. * 461 * * 462 * HISTORY: * 463 * 04/28/1995 PWG : Created. * 464 *=============================================================================================*/ 465 void MissionClass::Override_Mission(MissionType mission, TARGET, TARGET) 466 { 467 assert(IsActive); 468 469 if (MissionQueue != MISSION_NONE) { 470 SuspendedMission = MissionQueue; 471 } else { 472 SuspendedMission = Mission; 473 } 474 475 Assign_Mission(mission); 476 } 477 478 479 /*********************************************************************************************** 480 * MissionClass::Restore_Mission -- Restores overridden mission * 481 * * 482 * INPUT: none * 483 * * 484 * OUTPUT: none * 485 * * 486 * WARNINGS: none * 487 * * 488 * HISTORY: * 489 * 04/28/1995 PWG : Created. * 490 *=============================================================================================*/ 491 bool MissionClass::Restore_Mission(void) 492 { 493 assert(IsActive); 494 495 if (SuspendedMission != MISSION_NONE) { 496 Assign_Mission(SuspendedMission); 497 SuspendedMission= MISSION_NONE; 498 return(true); 499 } 500 return(false); 501 } 502 503 504 /*********************************************************************************************** 505 * MissionClass::Is_Recruitable_Mission -- Determines if this mission is recruitable for a tea * 506 * * 507 * Some missions preclude recruitment into a team. This routine will examine the mission * 508 * specified and if not allowed for a team, it will return false. * 509 * * 510 * INPUT: mission -- The mission type to examine. * 511 * * 512 * OUTPUT: bool; Is an object following this mission allowed to be recruited into a team? * 513 * * 514 * WARNINGS: none * 515 * * 516 * HISTORY: * 517 * 09/14/1996 JLB : Created. * 518 *=============================================================================================*/ 519 bool MissionClass::Is_Recruitable_Mission(MissionType mission) 520 { 521 if (mission == MISSION_NONE) { 522 return(true); 523 } 524 return(MissionControl[mission].IsRecruitable); 525 } 526 527 528 529 MissionControlClass::MissionControlClass(void) : 530 Mission(MISSION_NONE), 531 IsNoThreat(false), 532 IsZombie(false), 533 IsRecruitable(true), 534 IsParalyzed(false), 535 IsRetaliate(true), 536 IsScatter(true), 537 Rate(".016"), 538 AARate(".016") 539 { 540 } 541 542 543 char const * MissionControlClass::Name(void) const 544 { 545 if (Mission == MISSION_NONE) { 546 return("<none>"); 547 } 548 return(Missions[Mission]); 549 } 550 551 552 553 bool MissionControlClass::Read_INI(CCINIClass & ini) 554 { 555 if (ini.Is_Present(Name())) { 556 IsNoThreat = ini.Get_Bool(Name(), "NoThreat", IsNoThreat); 557 IsZombie = ini.Get_Bool(Name(), "Zombie", IsZombie); 558 IsRecruitable = ini.Get_Bool(Name(), "Recruitable", IsRecruitable); 559 IsParalyzed = ini.Get_Bool(Name(), "Paralyzed", IsParalyzed); 560 IsRetaliate = ini.Get_Bool(Name(), "Retaliate", IsRetaliate); 561 IsScatter = ini.Get_Bool(Name(), "Scatter", IsScatter); 562 Rate = ini.Get_Fixed(Name(), "Rate", Rate); 563 AARate = ini.Get_Fixed(Name(), "AARate", 0); 564 if (AARate == 0) { 565 AARate = Rate; 566 } 567 return(true); 568 } 569 return(false); 570 }