TRIGGER.CPP 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: F:\projects\c&c\vcs\code\trigger.cpv 2.17 16 Oct 1995 16:51:20 JOE_BOSTIC $ */
  15. /***********************************************************************************************
  16. *** 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 ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : TRIGGER.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 11/12/94 *
  26. * *
  27. * Last Update : August 27, 1995 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * Do_All_To_Hunt -- Forces all computer controlled units into hunt mode. *
  32. * TriggerClass::Action_From_Name -- retrieves ActionType for given name *
  33. * TriggerClass::Action_Need_Team -- Determines if this action event requires a team. *
  34. * TriggerClass::As_Pointer -- returns pointer for the given trigger name *
  35. * TriggerClass::As_Target -- Converts trigger to a target value *
  36. * TriggerClass::Event_From_Name -- retrieves EventType for given name *
  37. * TriggerClass::Event_Need_Data -- Determines if this event requires a data value. *
  38. * TriggerClass::Event_Need_House -- Determines if this event requires a house identifier. *
  39. * TriggerClass::Event_Need_Object -- Determines if the specified event requires an object. *
  40. * TriggerClass::Init -- clears triggers for new scenario *
  41. * TriggerClass::Name_From_Action -- retrieves name for ActionType *
  42. * TriggerClass::Name_From_Event -- retrieves name for EventType *
  43. * TriggerClass::Read_INI -- reads triggers from the INI file *
  44. * TriggerClass::Remove -- removes this trigger from the game *
  45. * TriggerClass::Spring -- Trigger processing routine for cell-based triggers *
  46. * TriggerClass::Spring -- Trigger processing routine for house-based triggers *
  47. * TriggerClass::Spring -- Trigger processing routine for object-based triggers *
  48. * TriggerClass::TriggerClass -- constructor *
  49. * TriggerClass::Validate -- validates trigger pointer *
  50. * TriggerClass::Write_INI -- writes triggers to the INI file *
  51. * TriggerClass::operator delete -- 'delete' operator *
  52. * TriggerClass::operator new -- 'new' operator *
  53. * TriggerClass::~TriggerClass -- Destructor for trigger objects. *
  54. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  55. #include "function.h"
  56. static void Do_All_To_Hunt(void);
  57. #define FIXUP 0
  58. /*
  59. ********************************** Globals **********************************
  60. */
  61. static const char * EventText[EVENT_COUNT + 1] = {
  62. "None",
  63. "Player Enters",
  64. "Discovered",
  65. "Attacked",
  66. "Destroyed",
  67. "Any",
  68. "House Discov.",
  69. "Units Destr.",
  70. "Bldgs Destr.",
  71. "All Destr.",
  72. "Credits",
  73. "Time",
  74. "# Bldgs Dstr.",
  75. "# Units Dstr.",
  76. "No Factories",
  77. "Civ. Evac.",
  78. "Built It"
  79. };
  80. static const char * ActionText[TriggerClass::ACTION_COUNT + 1] = {
  81. "None",
  82. "Win",
  83. "Lose",
  84. "Production",
  85. "Create Team",
  86. "Dstry Teams",
  87. "All to Hunt",
  88. "Reinforce.",
  89. "DZ at 'Z'",
  90. "Airstrike",
  91. "Nuclear Missile",
  92. "Ion Cannon",
  93. "Dstry Trig 'XXXX'",
  94. "Dstry Trig 'YYYY'",
  95. "Dstry Trig 'ZZZZ'",
  96. "Autocreate",
  97. "Cap=Win/Des=Lose",
  98. "Allow Win"
  99. };
  100. /***********************************************************************************************
  101. * TriggerClass::Validate -- validates trigger pointer *
  102. * *
  103. * INPUT: *
  104. * none. *
  105. * *
  106. * OUTPUT: *
  107. * 1 = ok, 0 = error *
  108. * *
  109. * WARNINGS: *
  110. * none. *
  111. * *
  112. * HISTORY: *
  113. * 08/09/1995 BRR : Created. *
  114. *=============================================================================================*/
  115. #ifdef CHEAT_KEYS
  116. int TriggerClass::Validate(void) const
  117. {
  118. int num;
  119. num = Triggers.ID(this);
  120. if (num < 0 || num >= TRIGGER_MAX) {
  121. Validate_Error("TRIGGER");
  122. return (0);
  123. }
  124. else
  125. return (1);
  126. }
  127. #else
  128. #define Validate()
  129. #endif
  130. /***********************************************************************************************
  131. * TriggerClass::Event_Need_Object -- Determines if the specified event requires an object. *
  132. * *
  133. * This routine determines if the specified event must be attached to an object. Such *
  134. * events can only exist in a parasitic fashion attached to object(s) in the game. *
  135. * *
  136. * INPUT: event -- The event type to examine. *
  137. * *
  138. * OUTPUT: Does the specified event require attachement to an object? *
  139. * *
  140. * WARNINGS: none *
  141. * *
  142. * HISTORY: *
  143. * 08/27/1995 JLB : Created. *
  144. *=============================================================================================*/
  145. bool TriggerClass::Event_Need_Object(EventType event)
  146. {
  147. switch (event) {
  148. case EVENT_PLAYER_ENTERED:
  149. case EVENT_DISCOVERED:
  150. case EVENT_ATTACKED:
  151. case EVENT_DESTROYED:
  152. case EVENT_ANY:
  153. return(true);
  154. }
  155. return(false);
  156. }
  157. /***********************************************************************************************
  158. * TriggerClass::Event_Need_House -- Determines if this event requires a house identifier. *
  159. * *
  160. * This routine is used to determine if the specified event requires a house identifier. *
  161. * All trigger events that affect a house will require a house identifier. *
  162. * *
  163. * INPUT: event -- The event type to examine. *
  164. * *
  165. * OUTPUT: Does the specified event type require a house identifier? *
  166. * *
  167. * WARNINGS: none *
  168. * *
  169. * HISTORY: *
  170. * 08/27/1995 JLB : Created. *
  171. *=============================================================================================*/
  172. bool TriggerClass::Event_Need_House(EventType event)
  173. {
  174. switch (event) {
  175. case EVENT_PLAYER_ENTERED:
  176. case EVENT_HOUSE_DISCOVERED:
  177. case EVENT_UNITS_DESTROYED:
  178. case EVENT_BUILDINGS_DESTROYED:
  179. case EVENT_ALL_DESTROYED:
  180. case EVENT_CREDITS:
  181. case EVENT_TIME:
  182. case EVENT_NBUILDINGS_DESTROYED:
  183. case EVENT_NUNITS_DESTROYED:
  184. case EVENT_NOFACTORIES:
  185. case EVENT_EVAC_CIVILIAN:
  186. case EVENT_BUILD:
  187. return(true);
  188. }
  189. return(false);
  190. }
  191. /***********************************************************************************************
  192. * TriggerClass::Event_Need_Data -- Determines if this event requires a data value. *
  193. * *
  194. * This routine will determine if the specified event requires a data number parameter. *
  195. * This is commonly needed for trigger events. *
  196. * *
  197. * INPUT: event -- The event to examine. *
  198. * *
  199. * OUTPUT: Does the specified event require a data number parameter? *
  200. * *
  201. * WARNINGS: none *
  202. * *
  203. * HISTORY: *
  204. * 08/27/1995 JLB : Created. *
  205. *=============================================================================================*/
  206. bool TriggerClass::Event_Need_Data(EventType event)
  207. {
  208. switch (event) {
  209. case EVENT_CREDITS:
  210. case EVENT_TIME:
  211. case EVENT_NBUILDINGS_DESTROYED:
  212. case EVENT_NUNITS_DESTROYED:
  213. case EVENT_BUILD:
  214. return(true);
  215. }
  216. return(false);
  217. }
  218. /***********************************************************************************************
  219. * TriggerClass::Action_Need_Team -- Determines if this action event requires a team. *
  220. * *
  221. * This routine will determine if the specified action requires a team name parameter. *
  222. * Typically, this is needed for reinforcements or other trigger events that affect *
  223. * a particular team type. *
  224. * *
  225. * INPUT: action -- The action that is to be examined. *
  226. * *
  227. * OUTPUT: Does the specified action require a team type name? *
  228. * *
  229. * WARNINGS: none *
  230. * *
  231. * HISTORY: *
  232. * 08/27/1995 JLB : Created. *
  233. *=============================================================================================*/
  234. bool TriggerClass::Action_Need_Team(TriggerClass::ActionType action)
  235. {
  236. switch (action) {
  237. case ACTION_CREATE_TEAM:
  238. case ACTION_DESTROY_TEAM:
  239. case ACTION_REINFORCEMENTS:
  240. return(true);
  241. }
  242. return(false);
  243. }
  244. /***********************************************************************************************
  245. * TriggerClass::TriggerClass -- constructor *
  246. * *
  247. * INPUT: *
  248. * none. *
  249. * *
  250. * OUTPUT: *
  251. * none. *
  252. * *
  253. * WARNINGS: *
  254. * none. *
  255. * *
  256. * HISTORY: *
  257. * 11/28/1994 BR : Created. *
  258. *=============================================================================================*/
  259. TriggerClass::TriggerClass(void)
  260. {
  261. IsPersistant = VOLATILE;
  262. AttachCount = 0;
  263. Event = EVENT_NONE;
  264. Action = ACTION_NONE;
  265. House = HOUSE_NONE;
  266. DataCopy = Data = 0L;
  267. Name[0] = '\0';
  268. Team = NULL;
  269. }
  270. /***********************************************************************************************
  271. * TriggerClass::~TriggerClass -- Destructor for trigger objects. *
  272. * *
  273. * This destructor will update the house blockage value if necessary. No other action need *
  274. * be performed on trigger destruction. *
  275. * *
  276. * INPUT: none *
  277. * *
  278. * OUTPUT: none *
  279. * *
  280. * WARNINGS: none *
  281. * *
  282. * HISTORY: *
  283. * 07/29/1995 JLB : Created. *
  284. *=============================================================================================*/
  285. TriggerClass::~TriggerClass(void)
  286. {
  287. if (GameActive && House != HOUSE_NONE && Action == ACTION_ALLOWWIN) {
  288. if (Houses.Ptr(House)->Blockage) Houses.Ptr(House)->Blockage--;
  289. Houses.Ptr(House)->BorrowedTime = TICKS_PER_SECOND*4;
  290. }
  291. }
  292. /***********************************************************************************************
  293. * TriggerClass::Init -- clears triggers for new scenario *
  294. * *
  295. * INPUT: *
  296. * none. *
  297. * *
  298. * OUTPUT: *
  299. * none. *
  300. * *
  301. * WARNINGS: *
  302. * none. *
  303. * *
  304. * HISTORY: *
  305. * 11/29/1994 BR : Created. *
  306. *=============================================================================================*/
  307. void TriggerClass::Init(void)
  308. {
  309. Triggers.Free_All();
  310. }
  311. /***********************************************************************************************
  312. * TriggerClass::Spring -- Trigger processing routine *
  313. * *
  314. * Checks whether this trigger should "spring" for the given event & object; *
  315. * If it should, then some really cool undocumented stuff magically happens. *
  316. * *
  317. * INPUT: *
  318. * event EventType: What happened? *
  319. * object Ptr to object containing this trigger: What did it happen to? *
  320. * *
  321. * OUTPUT: *
  322. * 0 = nothing happened; 1 = the trigger was sprung *
  323. * *
  324. * WARNINGS: *
  325. * none. *
  326. * *
  327. * HISTORY: *
  328. * 12/06/1994 BR : Created. *
  329. * 06/25/1995 JLB : Added more trigger events. *
  330. *=============================================================================================*/
  331. bool TriggerClass::Spring(EventType event, ObjectClass *obj)
  332. {
  333. Validate();
  334. /*
  335. ** If this is not the event for this trigger, just return.
  336. */
  337. if (event != Event && Event != EVENT_ANY) {
  338. return(false);
  339. }
  340. /*
  341. ** If time-based, decrement the minute counter; return if it's not time yet
  342. */
  343. if (Event == EVENT_TIME) {
  344. Data--;
  345. if (Data > 0) {
  346. return(false);
  347. }
  348. Data = DataCopy;
  349. }
  350. /*
  351. ** Semi-persistant trigger: first detach it from the calling object, then
  352. ** see if this is the last object we're attached to; if so, the trigger
  353. ** will spring.
  354. */
  355. if (IsPersistant == SEMIPERSISTANT) {
  356. /*
  357. ** Detach ourselves from the object
  358. */
  359. obj->Trigger = NULL;
  360. /*
  361. ** Decrement our attachment counter
  362. */
  363. AttachCount--;
  364. /*
  365. ** If we're attached to more objects, don't spring; otherwise, spring.
  366. ** And, mark ourselves as volatile so we'll completely remove ourselves
  367. ** from the game after we go off.
  368. */
  369. if (AttachCount > 0) {
  370. return(false);
  371. } else {
  372. IsPersistant = VOLATILE;
  373. }
  374. }
  375. /*
  376. ** Otherwise, take an appropriate action.
  377. */
  378. bool success = true;
  379. TriggerClass * trig = NULL;
  380. switch (Action) {
  381. case ACTION_NUKE:
  382. HouseClass::As_Pointer(HOUSE_BAD)->NukeStrike.Enable(true, false);
  383. HouseClass::As_Pointer(HOUSE_BAD)->NukeStrike.Forced_Charge(PlayerPtr->Class->House == HOUSE_BAD);
  384. break;
  385. case ACTION_ION:
  386. HouseClass::As_Pointer(HOUSE_GOOD)->IonCannon.Enable(true, false);
  387. HouseClass::As_Pointer(HOUSE_GOOD)->IonCannon.Forced_Charge(PlayerPtr->Class->House == HOUSE_GOOD);
  388. break;
  389. case ACTION_WINLOSE:
  390. switch (event) {
  391. case EVENT_DESTROYED:
  392. if (!PlayerPtr->IsToWin || PlayerPtr->Blockage > 0) PlayerPtr->Flag_To_Lose();
  393. success = true;
  394. break;
  395. case EVENT_PLAYER_ENTERED:
  396. if (!PlayerPtr->IsToLose) PlayerPtr->Flag_To_Win();
  397. success = true;
  398. break;
  399. default:
  400. success = false;
  401. break;
  402. }
  403. break;
  404. case ACTION_DESTROY_XXXX:
  405. trig = As_Pointer("XXXX");
  406. if (trig) {
  407. trig->Remove();
  408. }
  409. delete trig;
  410. break;
  411. case ACTION_DESTROY_YYYY:
  412. trig = As_Pointer("YYYY");
  413. if (trig) {
  414. trig->Remove();
  415. }
  416. delete trig;
  417. break;
  418. case ACTION_DESTROY_ZZZZ:
  419. trig = As_Pointer("ZZZZ");
  420. if (trig) {
  421. trig->Remove();
  422. }
  423. delete trig;
  424. break;
  425. case ACTION_AIRSTRIKE:
  426. PlayerPtr->IsAirstrikePending = true;
  427. // PlayerPtr->Make_Air_Strike_Available(true);
  428. break;
  429. case ACTION_DZ:
  430. new AnimClass(ANIM_LZ_SMOKE, Cell_Coord(Waypoint[25]));
  431. break;
  432. case ACTION_NONE:
  433. break;
  434. case ACTION_WIN:
  435. PlayerPtr->Flag_To_Win();
  436. break;
  437. case ACTION_LOSE:
  438. PlayerPtr->Flag_To_Lose();
  439. break;
  440. case ACTION_BEGIN_PRODUCTION:
  441. HouseClass::As_Pointer(House)->Begin_Production();
  442. break;
  443. case ACTION_AUTOCREATE:
  444. if (obj && obj->Is_Techno()) {
  445. ((TechnoClass *)obj)->House->IsAlerted = true;
  446. }
  447. break;
  448. case ACTION_CREATE_TEAM:
  449. if (Team) {
  450. ScenarioInit++;
  451. Team->Create_One_Of();
  452. ScenarioInit--;
  453. }
  454. break;
  455. case ACTION_DESTROY_TEAM:
  456. if (Team) {
  457. Team->Destroy_All_Of();
  458. }
  459. break;
  460. case ACTION_REINFORCEMENTS:
  461. if (Team) {
  462. success = Do_Reinforcements(Team);
  463. }
  464. break;
  465. case ACTION_ALL_HUNT:
  466. Do_All_To_Hunt();
  467. break;
  468. default:
  469. break;
  470. }
  471. if (!success && Event == EVENT_TIME) Data = 1;
  472. /*
  473. ** Remove trigger from the game.
  474. */
  475. if (success && IsPersistant == VOLATILE) {
  476. Remove();
  477. }
  478. return(true);
  479. }
  480. /***********************************************************************************************
  481. * TriggerClass::Spring -- Trigger processing routine *
  482. * *
  483. * This version of Spring is for cell-based triggers. *
  484. * *
  485. * INPUT: *
  486. * data elapsed time, or credits, depending on what 'Event' is. *
  487. * *
  488. * OUTPUT: *
  489. * 0 = nothing happened; 1 = the trigger was sprung *
  490. * *
  491. * WARNINGS: *
  492. * none. *
  493. * *
  494. * HISTORY: *
  495. * 12/06/1994 BR : Created. *
  496. *=============================================================================================*/
  497. bool TriggerClass::Spring(EventType event, CELL cell)
  498. {
  499. Validate();
  500. /*
  501. ** If this is not the event for this trigger, just return.
  502. */
  503. if (event != Event) {
  504. return(false);
  505. }
  506. /*
  507. ** If time-based, decrement the minute counter; return if it's not time yet
  508. */
  509. if (Event == EVENT_TIME) {
  510. Data--;
  511. if (Data > 0) {
  512. return(false);
  513. }
  514. Data = DataCopy;
  515. }
  516. /*
  517. ** Semi-persistant trigger: first detach it from the calling cell, then
  518. ** see if this is the last cell we're attached to; if so, the trigger
  519. ** will spring.
  520. */
  521. if (IsPersistant == SEMIPERSISTANT) {
  522. /*
  523. ** Detach ourselves from the cell
  524. */
  525. Map[cell].IsTrigger = 0;
  526. /*
  527. ** Decrement our attachment counter
  528. */
  529. AttachCount--;
  530. /*
  531. ** If we're attached to more cells, don't spring; otherwise, spring.
  532. ** And, mark ourselves as volatile so we'll completely remove ourselves
  533. ** from the game after we go off.
  534. */
  535. if (AttachCount > 0) {
  536. return(false);
  537. } else {
  538. IsPersistant = VOLATILE;
  539. }
  540. }
  541. /*
  542. ** Otherwise, take an appropriate action.
  543. */
  544. bool success = true;
  545. TriggerClass * trig = NULL;
  546. int index;
  547. switch (Action) {
  548. case ACTION_NUKE:
  549. HouseClass::As_Pointer(HOUSE_BAD)->NukeStrike.Enable(true, false);
  550. HouseClass::As_Pointer(HOUSE_BAD)->NukeStrike.Forced_Charge(PlayerPtr->Class->House == HOUSE_BAD);
  551. break;
  552. case ACTION_ION:
  553. HouseClass::As_Pointer(HOUSE_GOOD)->IonCannon.Enable(true, false);
  554. HouseClass::As_Pointer(HOUSE_GOOD)->IonCannon.Forced_Charge(PlayerPtr->Class->House == HOUSE_GOOD);
  555. break;
  556. case ACTION_AUTOCREATE:
  557. for (index = 0; index < Houses.Count(); index++) {
  558. Houses.Ptr(index)->IsAlerted = true;
  559. }
  560. break;
  561. case ACTION_DESTROY_XXXX:
  562. trig = As_Pointer("XXXX");
  563. if (trig) {
  564. trig->Remove();
  565. }
  566. delete trig;
  567. break;
  568. case ACTION_DESTROY_YYYY:
  569. trig = As_Pointer("YYYY");
  570. if (trig) {
  571. trig->Remove();
  572. }
  573. delete trig;
  574. break;
  575. case ACTION_DESTROY_ZZZZ:
  576. trig = As_Pointer("ZZZZ");
  577. if (trig) {
  578. trig->Remove();
  579. }
  580. delete trig;
  581. break;
  582. case ACTION_AIRSTRIKE:
  583. HouseClass::As_Pointer(House)->AirStrike.Enable(false, true);
  584. if (House == PlayerPtr->Class->House) {
  585. PlayerPtr->AirStrike.Forced_Charge(true);
  586. Map.Add(RTTI_SPECIAL, SPC_AIR_STRIKE);
  587. Map.Column[1].Flag_To_Redraw();
  588. }
  589. // PlayerPtr->Make_Air_Strike_Available(true);
  590. break;
  591. case ACTION_DZ:
  592. new AnimClass(ANIM_LZ_SMOKE, Cell_Coord(Waypoint[25]));
  593. break;
  594. case ACTION_NONE:
  595. break;
  596. case ACTION_WIN:
  597. PlayerPtr->Flag_To_Win();
  598. break;
  599. case ACTION_LOSE:
  600. PlayerPtr->Flag_To_Lose();
  601. break;
  602. case ACTION_BEGIN_PRODUCTION:
  603. if (PlayerPtr->Class->House == HOUSE_GOOD) {
  604. HouseClass::As_Pointer(HOUSE_BAD)->Begin_Production();
  605. } else {
  606. HouseClass::As_Pointer(HOUSE_GOOD)->Begin_Production();
  607. }
  608. break;
  609. case ACTION_CREATE_TEAM:
  610. if (Team) {
  611. ScenarioInit++;
  612. Team->Create_One_Of();
  613. ScenarioInit--;
  614. }
  615. break;
  616. case ACTION_DESTROY_TEAM:
  617. if (Team) {
  618. Team->Destroy_All_Of();
  619. }
  620. break;
  621. case ACTION_REINFORCEMENTS:
  622. if (Team) {
  623. success = Do_Reinforcements(Team);
  624. }
  625. break;
  626. case ACTION_ALL_HUNT:
  627. Do_All_To_Hunt();
  628. break;
  629. default:
  630. break;
  631. }
  632. if (!success && Event == EVENT_TIME) Data = 1;
  633. /*
  634. ** Remove trigger from the game.
  635. */
  636. if (success && IsPersistant == VOLATILE) {
  637. Remove();
  638. }
  639. return(true);
  640. }
  641. /***********************************************************************************************
  642. * TriggerClass::Spring -- Trigger processing routine *
  643. * *
  644. * This version of Spring is for house-specific triggers. *
  645. * For a time-based trigger, 'data' will the the current TickCount. *
  646. * For a credit-based trigger, 'data' will be the credits for the HouseClass *
  647. * containing this trigger. *
  648. * *
  649. * INPUT: *
  650. * event the event that happened *
  651. * house house that this event relates to *
  652. * data elapsed time, or credits, depending on what 'Event' is. *
  653. * *
  654. * OUTPUT: *
  655. * 0 = nothing happened; 1 = the trigger was sprung *
  656. * *
  657. * WARNINGS: *
  658. * none. *
  659. * *
  660. * HISTORY: *
  661. * 12/06/1994 BR : Created. *
  662. * 06/25/1995 JLB : Added more trigger events. *
  663. *=============================================================================================*/
  664. bool TriggerClass::Spring(EventType event, HousesType house, long data)
  665. {
  666. Validate();
  667. /*
  668. ** If this is not the event for this trigger, just return.
  669. */
  670. if (event != Event || house != House) {
  671. return(false);
  672. }
  673. /*
  674. ** If credits-based, check 'data'
  675. */
  676. if (Event == EVENT_CREDITS && data < Data) {
  677. return(false);
  678. }
  679. /*
  680. ** Building event check to ensure that the building number matches.
  681. */
  682. if (Event == EVENT_BUILD && data != Data) {
  683. return(false);
  684. }
  685. /*
  686. ** Number of objects destroyed checker. If the data supplied indicates that
  687. ** the correct number of objects have been destroyed, then this trigger
  688. ** will succeed.
  689. */
  690. if (Event == EVENT_NBUILDINGS_DESTROYED || Event == EVENT_NUNITS_DESTROYED) {
  691. if (data < Data) {
  692. return(false);
  693. }
  694. }
  695. /*
  696. ** If time-based, decrement the minute counter; return if it's not time yet
  697. */
  698. if (Event == EVENT_TIME) {
  699. Data--;
  700. if (Data > 0) {
  701. return(false);
  702. }
  703. Data = DataCopy;
  704. }
  705. /*
  706. ** The trigger has gone off; take appropriate action
  707. */
  708. bool success = true;
  709. TriggerClass * trig = NULL;
  710. switch (Action) {
  711. case ACTION_NUKE:
  712. HouseClass::As_Pointer(HOUSE_BAD)->NukeStrike.Enable(true, false);
  713. HouseClass::As_Pointer(HOUSE_BAD)->NukeStrike.Forced_Charge(PlayerPtr->Class->House == HOUSE_BAD);
  714. break;
  715. case ACTION_ION:
  716. HouseClass::As_Pointer(HOUSE_GOOD)->IonCannon.Enable(true, false);
  717. HouseClass::As_Pointer(HOUSE_GOOD)->IonCannon.Forced_Charge(PlayerPtr->Class->House == HOUSE_GOOD);
  718. break;
  719. /*
  720. ** This will remove a blockage to the win condition. No action need
  721. ** be performed here since the act of deleting the trigger will
  722. ** remove the blockage.
  723. */
  724. case ACTION_ALLOWWIN:
  725. break;
  726. case ACTION_AUTOCREATE:
  727. HouseClass::As_Pointer(House)->IsAlerted = true;
  728. break;
  729. case ACTION_DESTROY_XXXX:
  730. trig = As_Pointer("XXXX");
  731. if (trig) {
  732. trig->Remove();
  733. }
  734. delete trig;
  735. break;
  736. case ACTION_DESTROY_YYYY:
  737. trig = As_Pointer("YYYY");
  738. if (trig) {
  739. trig->Remove();
  740. }
  741. delete trig;
  742. break;
  743. case ACTION_DESTROY_ZZZZ:
  744. trig = As_Pointer("ZZZZ");
  745. if (trig) {
  746. trig->Remove();
  747. }
  748. delete trig;
  749. break;
  750. case ACTION_AIRSTRIKE:
  751. PlayerPtr->AirStrike.Enable(false, true);
  752. if (House == PlayerPtr->Class->House) {
  753. PlayerPtr->AirStrike.Forced_Charge(true);
  754. Map.Add(RTTI_SPECIAL, SPC_AIR_STRIKE);
  755. Map.Column[1].Flag_To_Redraw();
  756. }
  757. break;
  758. case ACTION_NONE:
  759. break;
  760. case ACTION_DZ:
  761. new AnimClass(ANIM_LZ_SMOKE, Cell_Coord(Waypoint[25]));
  762. break;
  763. case ACTION_WIN:
  764. PlayerPtr->Flag_To_Win();
  765. break;
  766. case ACTION_LOSE:
  767. PlayerPtr->Flag_To_Lose();
  768. break;
  769. case ACTION_BEGIN_PRODUCTION:
  770. HouseClass::As_Pointer(House)->Begin_Production();
  771. break;
  772. case ACTION_CREATE_TEAM:
  773. if (Team) {
  774. ScenarioInit++;
  775. Team->Create_One_Of();
  776. ScenarioInit--;
  777. }
  778. break;
  779. case ACTION_DESTROY_TEAM:
  780. if (Team) {
  781. Team->Destroy_All_Of();
  782. }
  783. break;
  784. case ACTION_REINFORCEMENTS:
  785. if (Team) {
  786. success = Do_Reinforcements(Team);
  787. }
  788. break;
  789. case ACTION_ALL_HUNT:
  790. Do_All_To_Hunt();
  791. break;
  792. default:
  793. break;
  794. }
  795. if (!success && Event == EVENT_TIME) Data = 1;
  796. /*
  797. ** Remove trigger from the game.
  798. */
  799. if (success && IsPersistant == VOLATILE) {
  800. Remove();
  801. }
  802. return(true);
  803. }
  804. /***********************************************************************************************
  805. * TriggerClass::Remove -- removes this trigger from the game *
  806. * *
  807. * INPUT: *
  808. * none. *
  809. * *
  810. * OUTPUT: *
  811. * 1 = trigger was removed, 0 = it wasn't *
  812. * *
  813. * WARNINGS: *
  814. * none. *
  815. * *
  816. * HISTORY: *
  817. * 12/06/1994 BR : Created. *
  818. *=============================================================================================*/
  819. bool TriggerClass::Remove(void)
  820. {
  821. Validate();
  822. CELL cell;
  823. HousesType h;
  824. int index;
  825. /*
  826. ** Loop through all cells; remove any reference to this trigger
  827. */
  828. for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
  829. if (Map[cell].IsTrigger) {
  830. if (CellTriggers[cell] == this) {
  831. Map[cell].IsTrigger = 0;
  832. CellTriggers[cell] = NULL;
  833. }
  834. }
  835. }
  836. /*
  837. ** Loop through all objects, removing any reference to this trigger
  838. */
  839. for (index = 0; index < Infantry.Count(); index++) {
  840. if (Infantry.Ptr(index)->Trigger == this) {
  841. Infantry.Ptr(index)->Trigger = NULL;
  842. }
  843. }
  844. for (index = 0; index < Buildings.Count(); index++) {
  845. if (Buildings.Ptr(index)->Trigger == this) {
  846. Buildings.Ptr(index)->Trigger = NULL;
  847. }
  848. }
  849. for (index = 0; index < Units.Count(); index++) {
  850. if (Units.Ptr(index)->Trigger == this) {
  851. Units.Ptr(index)->Trigger = NULL;
  852. }
  853. }
  854. for (index = 0; index < Terrains.Count(); index++) {
  855. if (Terrains.Ptr(index)->Trigger == this) {
  856. Terrains.Ptr(index)->Trigger = NULL;
  857. }
  858. }
  859. /*
  860. ** Remove this trigger from any house list it's in. Invoking '-=' with a
  861. ** pointer not in the list has no effect; loop through all houses just to
  862. ** be on the safe side.
  863. */
  864. for (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
  865. HouseTriggers[h].Delete(this);
  866. }
  867. delete this;
  868. return(true);
  869. }
  870. /***********************************************************************************************
  871. * TriggerClass::Read_INI -- reads triggers from the INI file *
  872. * *
  873. * INI entry format: *
  874. * Triggername = Eventname, Actionname, Data, Housename, TeamName, IsPersistant *
  875. * *
  876. * This routine reads in the triggers & creates them. Then, other classes can *
  877. * get pointers to the triggers they're linked to. *
  878. * *
  879. * The routine relies on the TeamTypeClasses already being loaded so it can resolve *
  880. * references to teams in this function. *
  881. * *
  882. * Cell Trigger pointers & IsTrigger flags are set in DisplayClass::Read_INI(), *
  883. * and cleared in the Map::Init() routine (which clears all cell objects to 0's). *
  884. * *
  885. * Object's pointers are set in: *
  886. * InfantryClass::Read_INI() *
  887. * BuildingClass::Read_INI() *
  888. * UnitClass::Read_INI() *
  889. * TerrainClass::Read_INI() *
  890. * The object trigger pointers are cleared in the ObjectClass constructor. *
  891. * *
  892. * The House's EMSListOf triggers is set in this routine, and cleared in the *
  893. * HouseClass::Init() routine. *
  894. * *
  895. * INPUT: *
  896. * buffer buffer to hold the INI data *
  897. * *
  898. * OUTPUT: *
  899. * none. *
  900. * *
  901. * WARNINGS: *
  902. * This function must be called before any other class's Read_INI. *
  903. * *
  904. * HISTORY: *
  905. * 11/28/1994 BR : Created. *
  906. *=============================================================================================*/
  907. void TriggerClass::Read_INI(char *buffer)
  908. {
  909. TriggerClass *trigger; // Working trigger pointer.
  910. char *tbuffer; // Accumulation buffer of trigger IDs.
  911. int len; // Length of data in buffer.
  912. char buf[128];
  913. /*
  914. ** Set 'tbuffer' to point just past the INI buffer
  915. */
  916. len = strlen(buffer) + 2;
  917. tbuffer = buffer + len;
  918. /*
  919. ** Read all TRIGGER entry names into 'tbuffer'
  920. */
  921. WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-len, buffer);
  922. /*
  923. ** Loop for all trigger entries.
  924. */
  925. while (*tbuffer != '\0') {
  926. /*
  927. ** Create a new trigger.
  928. */
  929. trigger = new TriggerClass();
  930. /*
  931. ** Set its name.
  932. */
  933. trigger->Set_Name (tbuffer);
  934. /*
  935. ** Get the trigger entry.
  936. */
  937. WWGetPrivateProfileString(INI_Name(), tbuffer, NULL, buf, sizeof(buf)-1, buffer);
  938. /*
  939. ** Fill in the trigger.
  940. */
  941. trigger->Fill_In(tbuffer,buf);
  942. /*
  943. ** Add 'trigger' to the House's list.
  944. */
  945. // if (trigger->House != HOUSE_NONE && trigger->Event != EVENT_PLAYER_ENTERED) {
  946. // if (Event_Need_House(trigger->Event) && !Event_Need_Object(trigger->Event)) {
  947. if (trigger->House != HOUSE_NONE) {
  948. if (trigger->Action == ACTION_ALLOWWIN) HouseClass::As_Pointer(trigger->House)->Blockage++;
  949. HouseTriggers[trigger->House].Add(trigger);
  950. trigger->AttachCount++;
  951. }
  952. /*
  953. ** Go to next entry.
  954. */
  955. tbuffer += strlen(tbuffer)+1;
  956. }
  957. }
  958. /***********************************************************************************************
  959. * TriggerClass::Fill_In -- fills in trigger from the given INI entry *
  960. * *
  961. * This routine fills in the given trigger with the given name, and values from *
  962. * the given INI entry. *
  963. * *
  964. * (This routine is used by the scenario editor, to import teams from the MASTER.INI file.) *
  965. * *
  966. * INI entry format: *
  967. * Triggername = Eventname, Actionname, Data, Housename, TeamName, IsPersistant *
  968. * *
  969. * INPUT: *
  970. * name mnemonic for the desired trigger *
  971. * entry INI entry to parse *
  972. * *
  973. * OUTPUT: *
  974. * none. *
  975. * *
  976. * WARNINGS: *
  977. * none. *
  978. * *
  979. * HISTORY: *
  980. * 11/28/1994 BR : Created. *
  981. *=============================================================================================*/
  982. void TriggerClass::Fill_In(char * name, char *entry)
  983. {
  984. Validate();
  985. char *p;
  986. /*
  987. ** Set its name.
  988. */
  989. Set_Name(name);
  990. /*
  991. ** 1st token: Event.
  992. */
  993. Event = Event_From_Name(strtok(entry, ","));
  994. /*
  995. ** 2nd token: Action.
  996. */
  997. Action = Action_From_Name(strtok(NULL, ","));
  998. /*
  999. ** 3rd token: Data.
  1000. */
  1001. DataCopy = Data = atol(strtok(NULL, ","));
  1002. /*
  1003. ** 4th token: House.
  1004. */
  1005. House = HouseTypeClass::From_Name(strtok(NULL, ","));
  1006. if (House == HOUSE_NONE && Event == EVENT_PLAYER_ENTERED) {
  1007. House = PlayerPtr->Class->House;
  1008. }
  1009. /*
  1010. ** 5th token: Team.
  1011. */
  1012. Team = TeamTypeClass::As_Pointer(strtok(NULL, ","));
  1013. /*
  1014. ** 6th token: IsPersistant. This token was added later, so we must check
  1015. ** for its existence.
  1016. */
  1017. p = strtok(NULL, ",");
  1018. if (p) {
  1019. IsPersistant = (PersistantType)atoi(p);
  1020. } else {
  1021. IsPersistant = VOLATILE;
  1022. }
  1023. }
  1024. /***********************************************************************************************
  1025. * TriggerClass::Write_INI -- writes triggers to the INI file *
  1026. * *
  1027. * INI entry format: *
  1028. * Triggername = Eventname, Actionname, Data, Housename, TeamName, IsPersistant *
  1029. * *
  1030. * INPUT: *
  1031. * buffer buffer to hold the INI data *
  1032. * *
  1033. * OUTPUT: *
  1034. * none. *
  1035. * *
  1036. * WARNINGS: *
  1037. * none. *
  1038. * *
  1039. * HISTORY: *
  1040. * 11/28/1994 BR : Created. *
  1041. *=============================================================================================*/
  1042. void TriggerClass::Write_INI(char *buffer, bool refresh)
  1043. {
  1044. int index;
  1045. char buf[128];
  1046. TriggerClass *trigger;
  1047. char const *hname;
  1048. char const *tname;
  1049. /*
  1050. ** First, clear out all existing trigger data from the INI file.
  1051. */
  1052. if (refresh) {
  1053. WWWritePrivateProfileString(INI_Name(), NULL, NULL, buffer);
  1054. }
  1055. /*
  1056. ** Now write all the trigger data out
  1057. */
  1058. for (index = 0; index < Triggers.Count(); index++) {
  1059. /*
  1060. ** Get ptr to next active trigger.
  1061. */
  1062. trigger = Triggers.Ptr(index);
  1063. /*
  1064. ** Generate INI entry.
  1065. */
  1066. if (trigger->House==HOUSE_NONE) {
  1067. hname = "None";
  1068. } else {
  1069. hname = HouseClass::As_Pointer(trigger->House)->Class->IniName;
  1070. }
  1071. if (trigger->Team==NULL) {
  1072. tname = "None";
  1073. } else {
  1074. tname = trigger->Team->IniName;
  1075. }
  1076. sprintf(buf,"%s,%s,%ld,%s,%s,%d",
  1077. TriggerClass::Name_From_Event(trigger->Event),
  1078. TriggerClass::Name_From_Action(trigger->Action),
  1079. trigger->Data,
  1080. hname,
  1081. tname,
  1082. trigger->IsPersistant);
  1083. WWWritePrivateProfileString(INI_Name(), trigger->Get_Name(), buf, buffer);
  1084. }
  1085. }
  1086. /***********************************************************************************************
  1087. * TriggerClass::As_Pointer -- returns pointer for the given trigger name *
  1088. * *
  1089. * This function is designed for use at initialization time, ie when the *
  1090. * trigger mnemonics are read from the INI and the Read_INI functions need *
  1091. * to get a pointer to that trigger. *
  1092. * *
  1093. * INPUT: *
  1094. * name mnemonic for the desired trigger *
  1095. * *
  1096. * OUTPUT: *
  1097. * near pointer to that trigger, NULL if not found *
  1098. * *
  1099. * WARNINGS: *
  1100. * none. *
  1101. * *
  1102. * HISTORY: *
  1103. * 11/28/1994 BR : Created. *
  1104. *=============================================================================================*/
  1105. TriggerClass * TriggerClass::As_Pointer(char const * name)
  1106. {
  1107. if (name == NULL) {
  1108. return(NULL);
  1109. }
  1110. for (int i = 0; i < Triggers.Count(); i++) {
  1111. TriggerClass * trigger = Triggers.Ptr(i);
  1112. if (!stricmp(name, trigger->Name)) {
  1113. return(trigger);
  1114. }
  1115. }
  1116. return(NULL);
  1117. }
  1118. /***********************************************************************************************
  1119. * TriggerClass::operator new -- 'new' operator *
  1120. * *
  1121. * INPUT: *
  1122. * none. *
  1123. * *
  1124. * OUTPUT: *
  1125. * pointer to new trigger *
  1126. * *
  1127. * WARNINGS: *
  1128. * none. *
  1129. * *
  1130. * HISTORY: *
  1131. * 11/28/1994 BR : Created. *
  1132. *=============================================================================================*/
  1133. void * TriggerClass::operator new(size_t )
  1134. {
  1135. void * ptr = Triggers.Allocate();
  1136. if (ptr) {
  1137. ((TriggerClass *)ptr)->IsActive = true;
  1138. }
  1139. return(ptr);
  1140. }
  1141. /***********************************************************************************************
  1142. * TriggerClass::operator delete -- 'delete' operator *
  1143. * *
  1144. * INPUT: *
  1145. * ptr pointer to delete *
  1146. * *
  1147. * OUTPUT: *
  1148. * none. *
  1149. * *
  1150. * WARNINGS: *
  1151. * none. *
  1152. * *
  1153. * HISTORY: *
  1154. * 11/28/1994 BR : Created. *
  1155. *=============================================================================================*/
  1156. void TriggerClass::operator delete(void *ptr)
  1157. {
  1158. if (ptr) {
  1159. ((TriggerClass *)ptr)->IsActive = false;
  1160. }
  1161. Triggers.Free((TriggerClass *)ptr);
  1162. }
  1163. /***********************************************************************************************
  1164. * TriggerClass::Event_From_Name -- retrieves EventType for given name *
  1165. * *
  1166. * INPUT: *
  1167. * name name to get event for *
  1168. * *
  1169. * OUTPUT: *
  1170. * EventType for given name *
  1171. * *
  1172. * WARNINGS: *
  1173. * none. *
  1174. * *
  1175. * HISTORY: *
  1176. * 11/29/1994 BR : Created. *
  1177. *=============================================================================================*/
  1178. EventType TriggerClass::Event_From_Name (char const *name)
  1179. {
  1180. int i;
  1181. if (name == NULL) {
  1182. return(EVENT_NONE);
  1183. }
  1184. for (i = EVENT_NONE; i < EVENT_COUNT; i++) {
  1185. if (!stricmp(name,EventText[i + 1])) {
  1186. return((EventType)i);
  1187. }
  1188. }
  1189. return(EVENT_NONE);
  1190. }
  1191. /***********************************************************************************************
  1192. * TriggerClass::Name_From_Event -- retrieves name for EventType *
  1193. * *
  1194. * INPUT: *
  1195. * event EventType to get name for *
  1196. * *
  1197. * OUTPUT: *
  1198. * name for EventType *
  1199. * *
  1200. * WARNINGS: *
  1201. * none. *
  1202. * *
  1203. * HISTORY: *
  1204. * 11/29/1994 BR : Created. *
  1205. *=============================================================================================*/
  1206. char const *TriggerClass::Name_From_Event(EventType event)
  1207. {
  1208. return(EventText[event + 1]);
  1209. }
  1210. /***********************************************************************************************
  1211. * TriggerClass::Action_From_Name -- retrieves ActionType for given name *
  1212. * *
  1213. * INPUT: *
  1214. * name name to get ActionType for *
  1215. * *
  1216. * OUTPUT: *
  1217. * ActionType for given name *
  1218. * *
  1219. * WARNINGS: *
  1220. * none. *
  1221. * *
  1222. * HISTORY: *
  1223. * 11/29/1994 BR : Created. *
  1224. *=============================================================================================*/
  1225. TriggerClass::ActionType TriggerClass::Action_From_Name (char const *name)
  1226. {
  1227. int i;
  1228. if (name == NULL) {
  1229. return(ACTION_NONE);
  1230. }
  1231. for (i = ACTION_NONE; i < ACTION_COUNT; i++) {
  1232. if (!stricmp(name,ActionText[i + 1])) {
  1233. return((ActionType)i);
  1234. }
  1235. }
  1236. return(ACTION_NONE);
  1237. }
  1238. /***********************************************************************************************
  1239. * TriggerClass::Name_From_Action -- retrieves name for ActionType *
  1240. * *
  1241. * INPUT: *
  1242. * action ActionType to get name for *
  1243. * *
  1244. * OUTPUT: *
  1245. * name of ActionType *
  1246. * *
  1247. * WARNINGS: *
  1248. * none. *
  1249. * *
  1250. * HISTORY: *
  1251. * 11/29/1994 BR : Created. *
  1252. *=============================================================================================*/
  1253. char const *TriggerClass::Name_From_Action(ActionType action)
  1254. {
  1255. return(ActionText[action + 1]);
  1256. }
  1257. /***********************************************************************************************
  1258. * TriggerClass::As_Target -- Converts trigger to a target value *
  1259. * *
  1260. * INPUT: none *
  1261. * *
  1262. * OUTPUT: TARGET value *
  1263. * *
  1264. * WARNINGS: none *
  1265. * *
  1266. * HISTORY: *
  1267. * 09/19/1994 JLB : Created. *
  1268. *=============================================================================================*/
  1269. TARGET TriggerClass::As_Target(void) const
  1270. {
  1271. Validate();
  1272. return(Build_Target(KIND_TRIGGER, Triggers.ID(this)));
  1273. }
  1274. /***********************************************************************************************
  1275. * Do_All_To_Hunt -- Forces all computer controlled units into hunt mode. *
  1276. * *
  1277. * This trigger action will cause the computer units and infantry to go into hunt mode. *
  1278. * Use it to bring a scenario to a sudden conclusion. *
  1279. * *
  1280. * INPUT: none *
  1281. * *
  1282. * OUTPUT: none *
  1283. * *
  1284. * WARNINGS: none *
  1285. * *
  1286. * HISTORY: *
  1287. * 04/20/1995 JLB : Created. *
  1288. * 08/14/1995 JLB : Removes the member from a team if necessary. *
  1289. *=============================================================================================*/
  1290. static void Do_All_To_Hunt(void)
  1291. {
  1292. int index;
  1293. for (index = 0; index < Units.Count(); index++) {
  1294. UnitClass * unit = Units.Ptr(index);
  1295. if (!unit->House->IsHuman && unit->IsDown && !unit->IsInLimbo) {
  1296. if (unit->Team) unit->Team->Remove(unit);
  1297. unit->Assign_Mission(MISSION_HUNT);
  1298. }
  1299. }
  1300. for (index = 0; index < Infantry.Count(); index++) {
  1301. InfantryClass * infantry = Infantry.Ptr(index);
  1302. if (!infantry->House->IsHuman && infantry->IsDown && !infantry->IsInLimbo) {
  1303. if (infantry->Team) infantry->Team->Remove(infantry);
  1304. infantry->Assign_Mission(MISSION_HUNT);
  1305. }
  1306. }
  1307. }