TEAMTYPE.CPP 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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\teamtype.cpv 2.17 16 Oct 1995 16:48:52 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 : TEAMTYPE.CPP *
  22. * *
  23. * Programmer : Bill Randolph *
  24. * *
  25. * Start Date : December 7, 1994 *
  26. * *
  27. * Last Update : July 21, 1995 [JLB] *
  28. * *
  29. *-------------------------------------------------------------------------*
  30. * Functions: *
  31. * TeamTypeClass::TeamTypeClass -- class constructor *
  32. * TeamTypeClass::~TeamTypeClass -- class destructor *
  33. * TeamTypeClass::Init -- pre-scenario initialization *
  34. * TeamTypeClass::Read_INI -- reads INI data *
  35. * TeamTypeClass::Write_INI -- writes INI data *
  36. * TeamTypeClass::Read_Old_INI -- reads old INI format *
  37. * TeamTypeClass::As_Pointer -- gets ptr for team type with given name *
  38. * TeamTypeClass::Remove -- removes this team from the system *
  39. * TeamTypeClass::Mission_From_Name -- returns mission for given name *
  40. * TeamTypeClass::Name_From_Mission -- returns name for given mission *
  41. * TeamTypeClass::operator new -- 'new' operator *
  42. * TeamTypeClass::operator delete -- 'delete' operator *
  43. * TeamTypeClass::Suggested_New_Team -- Suggests a new team to create. *
  44. * TeamTypeClass::Validate -- validates teamtype pointer *
  45. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  46. #include "function.h"
  47. /*
  48. ********************************** Globals **********************************
  49. */
  50. char const * TeamTypeClass::TMissions[TMISSION_COUNT] = {
  51. "Attack Base",
  52. "Attack Units",
  53. "Attack Civil.",
  54. "Rampage",
  55. "Defend Base",
  56. // "Harvest",
  57. "Move",
  58. "Move to Cell",
  59. "Retreat",
  60. "Guard",
  61. "Loop",
  62. "Attack Tarcom",
  63. "Unload",
  64. };
  65. /*
  66. ** This contains the value of the Virtual Function Table Pointer
  67. */
  68. void * TeamTypeClass::VTable;
  69. /***********************************************************************************************
  70. * TeamTypeClass::Validate -- validates teamtype pointer *
  71. * *
  72. * INPUT: *
  73. * none. *
  74. * *
  75. * OUTPUT: *
  76. * 1 = ok, 0 = error *
  77. * *
  78. * WARNINGS: *
  79. * none. *
  80. * *
  81. * HISTORY: *
  82. * 08/09/1995 BRR : Created. *
  83. *=============================================================================================*/
  84. #ifdef CHEAT_KEYS
  85. int TeamTypeClass::Validate(void) const
  86. {
  87. int num;
  88. num = TeamTypes.ID(this);
  89. if (num < 0 || num >= TEAMTYPE_MAX) {
  90. Validate_Error("TEAMTYPE");
  91. return (0);
  92. }
  93. else
  94. return (1);
  95. }
  96. #else
  97. #define Validate()
  98. #endif
  99. /***************************************************************************
  100. * TeamTypeClass::TeamTypeClass -- class constructor *
  101. * *
  102. * INPUT: *
  103. * *
  104. * OUTPUT: *
  105. * *
  106. * WARNINGS: *
  107. * *
  108. * HISTORY: *
  109. * 12/07/1994 BR : Created. *
  110. *=========================================================================*/
  111. TeamTypeClass::TeamTypeClass(void)
  112. {
  113. IsPrebuilt = true;
  114. IsReinforcable = true;
  115. IsRoundAbout = false;
  116. IsLearning = false;
  117. IsSuicide = false;
  118. IsAutocreate = false;
  119. IsTransient = false;
  120. IsMercenary = false;
  121. RecruitPriority = 7;
  122. MaxAllowed = 0;
  123. Fear = 0;
  124. InitNum = 0;
  125. House = HOUSE_NONE;
  126. MissionCount = 0;
  127. IniName[0] = '\0';
  128. ClassCount = 0;
  129. for (int i = 0; i < MAX_TEAM_CLASSCOUNT; i++) {
  130. Class[i] = NULL;
  131. DesiredNum[i] = 0;
  132. }
  133. }
  134. /***************************************************************************
  135. * TeamTypeClass::Init -- pre-scenario initialization *
  136. * *
  137. * INPUT: *
  138. * *
  139. * OUTPUT: *
  140. * *
  141. * WARNINGS: *
  142. * *
  143. * HISTORY: *
  144. * 12/07/1994 BR : Created. *
  145. *=========================================================================*/
  146. void TeamTypeClass::Init(void)
  147. {
  148. TeamTypeClass *ptr;
  149. TeamTypes.Free_All();
  150. ptr = new TeamTypeClass();
  151. VTable = ((void **)(((char *)ptr) + sizeof(AbstractTypeClass) - 4))[0];
  152. delete ptr;
  153. }
  154. /***************************************************************************
  155. * TeamTypeClass::Read_INI -- reads INI data *
  156. * *
  157. * INI entry format: *
  158. * TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary, *
  159. * RecruitPriority,MaxAllowed,InitNum,Fear, *
  160. * ClassCount,Class:Num,Class:Num,..., *
  161. * MissionCount,Mission:Arg,Mission:Arg,Mission:Arg,... *
  162. * *
  163. * INPUT: *
  164. * buffer buffer to hold the INI data *
  165. * *
  166. * OUTPUT: *
  167. * none. *
  168. * *
  169. * WARNINGS: *
  170. * none. *
  171. * *
  172. * HISTORY: *
  173. * 12/07/1994 BR : Created. *
  174. * 02/01/1995 BR : No del team if no classes (editor needs empty teams!) *
  175. *=========================================================================*/
  176. void TeamTypeClass::Read_INI(char *buffer)
  177. {
  178. TeamTypeClass * team; // Working team pointer.
  179. char *tbuffer; // Accumulation buffer of team names.
  180. int len; // Length of data in buffer.
  181. char buf[500]; // INI entry buffer
  182. /*------------------------------------------------------------------------
  183. Set 'tbuffer' to point just past the INI buffer
  184. ------------------------------------------------------------------------*/
  185. len = strlen(buffer) + 2;
  186. tbuffer = buffer + len;
  187. /*------------------------------------------------------------------------
  188. Read all TeamType entry names into 'tbuffer'
  189. ------------------------------------------------------------------------*/
  190. WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-len, buffer);
  191. /*
  192. ----------------------- Loop for all team entries ------------------------
  193. */
  194. while (*tbuffer != '\0') {
  195. /*
  196. ....................... Create a new team type ........................
  197. */
  198. team = new TeamTypeClass();
  199. /*
  200. ......................... Get the team entry ..........................
  201. */
  202. WWGetPrivateProfileString(INI_Name(), tbuffer, NULL, buf, sizeof(buf)-1, buffer);
  203. /*
  204. .......................... Fill the team in ...........................
  205. */
  206. team->Fill_In(tbuffer, buf);
  207. /*
  208. ...................... Go to the next INI entry .......................
  209. */
  210. tbuffer += strlen(tbuffer)+1;
  211. }
  212. /*
  213. ** If no teams were read in, try reading the old INI format.
  214. */
  215. if (TeamTypes.Count()==0) {
  216. Read_Old_INI(buffer);
  217. }
  218. }
  219. /***********************************************************************************************
  220. * TeamTypeClass::Fill_In -- fills in trigger from the given INI entry *
  221. * *
  222. * This routine fills in the given teamtype with the given name, and values from *
  223. * the given INI entry. *
  224. * *
  225. * (This routine is used by the scenario editor, to import teams from the MASTER.INI file.) *
  226. * *
  227. * INI entry format: *
  228. * TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary, *
  229. * RecruitPriority,MaxAllowed,InitNum,Fear, *
  230. * ClassCount,Class:Num,Class:Num,..., *
  231. * MissionCount,Mission:Arg,Mission:Arg,Mission:Arg,... *
  232. * *
  233. * INPUT: *
  234. * name mnemonic for the desired trigger *
  235. * entry INI entry to parse *
  236. * *
  237. * OUTPUT: *
  238. * none. *
  239. * *
  240. * WARNINGS: *
  241. * none. *
  242. * *
  243. * HISTORY: *
  244. * 11/28/1994 BR : Created. *
  245. *=============================================================================================*/
  246. void TeamTypeClass::Fill_In(char * name, char *entry)
  247. {
  248. Validate();
  249. int num_classes;
  250. char *p1; // parsing pointer
  251. char *p2; // parsing pointer
  252. int i; // loop counter
  253. TechnoTypeClass const *otype; // ptr to type of object
  254. InfantryType i_id; // infantry ID
  255. UnitType u_id; // unit ID
  256. AircraftType a_id; // aircraft ID
  257. TeamMissionStruct mission;
  258. /*
  259. ------------------------------ Set its name ------------------------------
  260. */
  261. Set_Name(name);
  262. /*
  263. ---------------------------- 1st token: House ----------------------------
  264. */
  265. House = HouseTypeClass::From_Name(strtok(entry,","));
  266. /*
  267. -------------------------- 2nd token: RoundAbout -------------------------
  268. */
  269. IsRoundAbout = atoi(strtok(NULL,","));
  270. /*
  271. --------------------------- 3rd token: Learning --------------------------
  272. */
  273. IsLearning = atoi(strtok(NULL,","));
  274. /*
  275. --------------------------- 4th token: Suicide ---------------------------
  276. */
  277. IsSuicide = atoi(strtok(NULL,","));
  278. /*
  279. ----------------------------- 5th token: Spy -----------------------------
  280. */
  281. IsAutocreate = atoi(strtok(NULL,","));
  282. /*
  283. -------------------------- 6th token: Mercenary --------------------------
  284. */
  285. IsMercenary = atoi(strtok(NULL,","));
  286. /*
  287. ----------------------- 7th token: RecruitPriority -----------------------
  288. */
  289. RecruitPriority = atoi(strtok(NULL,","));
  290. /*
  291. -------------------------- 8th token: MaxAllowed -------------------------
  292. */
  293. MaxAllowed = atoi(strtok(NULL,","));
  294. /*
  295. --------------------------- 9th token: InitNum ---------------------------
  296. */
  297. InitNum = atoi(strtok(NULL,","));
  298. /*
  299. ------------------------- 10th token: Fear level -------------------------
  300. */
  301. Fear = atoi(strtok(NULL,","));
  302. /*
  303. ------------------------ 11th token: Class count -------------------------
  304. */
  305. num_classes = atoi(strtok(NULL,","));
  306. /*
  307. -------------- Loop through entries, setting class ptr & num -------------
  308. */
  309. ClassCount = 0;
  310. for (i = 0; i < num_classes; i++) {
  311. p1 = strtok(NULL,",:");
  312. p2 = strtok(NULL,",:");
  313. otype = NULL;
  314. /*
  315. ------------------- See if this is an infantry name -------------------
  316. */
  317. i_id = InfantryTypeClass::From_Name(p1);
  318. if (i_id != INFANTRY_NONE) {
  319. otype = &InfantryTypeClass::As_Reference(i_id);
  320. }
  321. /*
  322. ---------------------- See if this is a unit name ---------------------
  323. */
  324. u_id = UnitTypeClass::From_Name(p1);
  325. if (u_id != UNIT_NONE) {
  326. otype = &UnitTypeClass::As_Reference(u_id);
  327. }
  328. /*
  329. ------------------- See if this is an aircraft name -------------------
  330. */
  331. a_id = AircraftTypeClass::From_Name(p1);
  332. if (a_id != AIRCRAFT_NONE) {
  333. otype = &AircraftTypeClass::As_Reference(a_id);
  334. }
  335. /*
  336. --------------- If the name was resolved, add this class --------------
  337. */
  338. if (otype) {
  339. if (ClassCount < MAX_TEAM_CLASSCOUNT) {
  340. Class[ClassCount] = otype;
  341. DesiredNum[ClassCount] = atoi(p2);
  342. ClassCount++;
  343. }
  344. }
  345. }
  346. /*
  347. ----------------------- next token: Mission count ------------------------
  348. */
  349. MissionCount = atoi(strtok(NULL,","));
  350. for (i = 0; i < MissionCount; i++) {
  351. p1 = strtok(NULL,",:");
  352. p2 = strtok(NULL,",:");
  353. mission.Mission = Mission_From_Name(p1);
  354. mission.Argument = atoi(p2);
  355. MissionList[i] = mission;
  356. }
  357. char * ptr = strtok(NULL, ",");
  358. if (ptr) {
  359. IsReinforcable = atoi(ptr);
  360. }
  361. ptr = strtok(NULL, ",");
  362. if (ptr) {
  363. IsPrebuilt = atoi(ptr);
  364. }
  365. }
  366. /***************************************************************************
  367. * TeamTypeClass::Write_INI -- writes INI data *
  368. * *
  369. * INI entry format: *
  370. * TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary, *
  371. * RecruitPriority,MaxAllowed,InitNum,Fear, *
  372. * ClassCount,Class:Num,Class:Num,..., *
  373. * MissionCount,Mission,Arg,Mission,Arg,Mission,Arg,... *
  374. * *
  375. * INPUT: *
  376. * buffer buffer to store INI data in *
  377. * *
  378. * OUTPUT: *
  379. * none. *
  380. * *
  381. * WARNINGS: *
  382. * none. *
  383. * *
  384. * HISTORY: *
  385. * 12/07/1994 BR : Created. *
  386. *=========================================================================*/
  387. void TeamTypeClass::Write_INI(char *buffer, bool refresh)
  388. {
  389. int index;
  390. int i;
  391. char buf[500];
  392. TeamTypeClass * team;
  393. char const *hname;
  394. /*------------------------------------------------------------------------
  395. First, clear out all existing teamtypes in the old-style format.
  396. ------------------------------------------------------------------------*/
  397. WWWritePrivateProfileString("Teams", NULL, NULL, buffer);
  398. /*------------------------------------------------------------------------
  399. Clear out all existing teamtype data from the INI file.
  400. ------------------------------------------------------------------------*/
  401. if (refresh) {
  402. WWWritePrivateProfileString(INI_Name(), NULL, NULL, buffer);
  403. }
  404. /*------------------------------------------------------------------------
  405. Now write all the team data out
  406. ------------------------------------------------------------------------*/
  407. buf[0] = 0;
  408. for (index = 0; index < TeamTypes.Count(); index++) {
  409. /*
  410. .................. Get ptr to next active teamtype ....................
  411. */
  412. team = TeamTypes.Ptr(index);
  413. /*
  414. .......................... Find house's name ..........................
  415. */
  416. if (team->House==HOUSE_NONE) {
  417. hname = "None";
  418. } else {
  419. hname = HouseClass::As_Pointer(team->House)->Class->IniName;
  420. }
  421. /*
  422. ......................... Generate INI entry ..........................
  423. */
  424. sprintf(buf,"%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
  425. hname,
  426. team->IsRoundAbout,
  427. team->IsLearning,
  428. team->IsSuicide,
  429. team->IsAutocreate,
  430. team->IsMercenary,
  431. team->RecruitPriority,
  432. team->MaxAllowed,
  433. team->InitNum,
  434. team->Fear,
  435. team->ClassCount);
  436. /*.....................................................................
  437. For every class in the team, record the class's name & desired count
  438. .....................................................................*/
  439. for (i = 0; i < team->ClassCount; i++) {
  440. sprintf (buf + strlen(buf), ",%s:%d",
  441. team->Class[i]->IniName,
  442. team->DesiredNum[i]);
  443. }
  444. /*.....................................................................
  445. Record the # of missions, and each mission name & argument value.
  446. .....................................................................*/
  447. sprintf(buf + strlen(buf),",%d",team->MissionCount);
  448. for (i = 0; i < team->MissionCount; i++) {
  449. sprintf (buf + strlen(buf), ",%s:%d",
  450. Name_From_Mission(team->MissionList[i].Mission),
  451. team->MissionList[i].Argument);
  452. }
  453. if (team->IsReinforcable) {
  454. strcat(buf, ",1");
  455. } else {
  456. strcat(buf, ",0");
  457. }
  458. if (team->IsPrebuilt) {
  459. strcat(buf, ",1");
  460. } else {
  461. strcat(buf, ",0");
  462. }
  463. WWWritePrivateProfileString(INI_Name(), team->IniName, buf, buffer);
  464. }
  465. }
  466. /***************************************************************************
  467. * TeamTypeClass::Read_Old_INI -- reads old INI format *
  468. * *
  469. * INI entry format: *
  470. * TeamName = Housename,Roundabout,Learning,Suicide,Spy,Mercenary, *
  471. * RecruitPriority,MaxAllowed,InitNum,Class:Num,Class:Num,...,Fear *
  472. * *
  473. * INPUT: *
  474. * buffer buffer to hold the INI data *
  475. * *
  476. * OUTPUT: *
  477. * none. *
  478. * *
  479. * WARNINGS: *
  480. * none. *
  481. * *
  482. * HISTORY: *
  483. * 12/07/1994 BR : Created. *
  484. * 02/01/1995 BR : No del team if no classes (editor needs empty teams!) *
  485. *=========================================================================*/
  486. void TeamTypeClass::Read_Old_INI(char *buffer)
  487. {
  488. TeamTypeClass * team; // Working team pointer.
  489. char *tbuffer; // Accumulation buffer of team names.
  490. int len; // Length of data in buffer.
  491. char buf[256]; // INI entry buffer
  492. char *p1; // parsing pointer
  493. char *p2; // parsing pointer
  494. int index;
  495. TechnoTypeClass const *otype; // ptr to type of object
  496. InfantryType i_id; // infantry ID
  497. UnitType u_id; // unit ID
  498. AircraftType a_id; // infantry ID
  499. /*------------------------------------------------------------------------
  500. Set 'tbuffer' to point just past the INI buffer
  501. ------------------------------------------------------------------------*/
  502. len = strlen(buffer) + 2;
  503. tbuffer = buffer + len;
  504. /*------------------------------------------------------------------------
  505. Read all TeamType entry names into 'tbuffer'
  506. ------------------------------------------------------------------------*/
  507. WWGetPrivateProfileString("Teams", NULL, NULL, tbuffer, ShapeBufferSize-len, buffer);
  508. /*
  509. ----------------------- Loop for all team entries ------------------------
  510. */
  511. while (*tbuffer != '\0') {
  512. /*
  513. ........................ Create a new trigger .........................
  514. */
  515. team = new TeamTypeClass();
  516. /*
  517. ............................ Set its name .............................
  518. */
  519. team->Set_Name(tbuffer);
  520. /*
  521. ......................... Get the team entry ..........................
  522. */
  523. WWGetPrivateProfileString("Teams", tbuffer, NULL, buf, sizeof(buf)-1, buffer);
  524. /*
  525. .......................... 1st token: House ...........................
  526. */
  527. team->House = HouseTypeClass::From_Name(strtok(buf,","));
  528. /*
  529. ........................ 2nd token: RoundAbout ........................
  530. */
  531. team->IsRoundAbout = atoi(strtok(NULL,","));
  532. /*
  533. ......................... 3rd token: Learning .........................
  534. */
  535. team->IsLearning = atoi(strtok(NULL,","));
  536. /*
  537. ......................... 4th token: Suicide ..........................
  538. */
  539. team->IsSuicide = atoi(strtok(NULL,","));
  540. /*
  541. ........................... 5th token: Spy ............................
  542. */
  543. team->IsAutocreate = atoi(strtok(NULL,","));
  544. /*
  545. ........................ 6th token: Mercenary .........................
  546. */
  547. team->IsMercenary = atoi(strtok(NULL,","));
  548. /*
  549. ..................... 7th token: RecruitPriority ......................
  550. */
  551. team->RecruitPriority = atoi(strtok(NULL,","));
  552. /*
  553. ........................ 8th token: MaxAllowed ........................
  554. */
  555. team->MaxAllowed = atoi(strtok(NULL,","));
  556. /*
  557. ......................... 9th token: InitNum ..........................
  558. */
  559. team->InitNum = atoi(strtok(NULL,","));
  560. /*
  561. ....................... 10th token: Mission name ......................
  562. */
  563. strtok(NULL,","); // just throw it away
  564. /*
  565. ............ Loop through entries, setting class ptr & num ............
  566. */
  567. index = 0;
  568. p1 = strtok(NULL,",:");
  569. p2 = strtok(NULL,",:");
  570. while (p1 && p2) {
  571. otype = NULL;
  572. /*
  573. ................. See if this is an infantry name ..................
  574. */
  575. i_id = InfantryTypeClass::From_Name(p1);
  576. if (i_id!=INFANTRY_NONE) {
  577. otype = &InfantryTypeClass::As_Reference(i_id);
  578. }
  579. /*
  580. .................... See if this is a unit name ....................
  581. */
  582. u_id = UnitTypeClass::From_Name(p1);
  583. if (u_id != UNIT_NONE) {
  584. otype = &UnitTypeClass::As_Reference(u_id);
  585. }
  586. /*
  587. ................. See if this is an aircraft name ..................
  588. */
  589. a_id = AircraftTypeClass::From_Name(p1);
  590. if (a_id != AIRCRAFT_NONE) {
  591. otype = &AircraftTypeClass::As_Reference(a_id);
  592. }
  593. /*
  594. ............. If the name was resolved, add this class .............
  595. */
  596. if (otype) {
  597. team->Class[index] = otype;
  598. team->DesiredNum[index] = atoi(p2);
  599. index++;
  600. team->ClassCount = index;
  601. }
  602. /*
  603. ................. Go to the next entry on the line .................
  604. */
  605. p1 = strtok(NULL,",:");
  606. p2 = strtok(NULL,",:");
  607. }
  608. team->Fear = 0;
  609. /*
  610. ...................... Go to the next INI entry .......................
  611. */
  612. tbuffer += strlen(tbuffer)+1;
  613. }
  614. }
  615. /***************************************************************************
  616. * TeamTypeClass::As_Pointer -- gets ptr for team type with given name *
  617. * *
  618. * INPUT: *
  619. * name name of teamtype *
  620. * *
  621. * OUTPUT: *
  622. * ptr to TeamType with that name *
  623. * *
  624. * WARNINGS: *
  625. * none. *
  626. * *
  627. * HISTORY: *
  628. * 12/07/1994 BR : Created. *
  629. *=========================================================================*/
  630. TeamTypeClass * TeamTypeClass::As_Pointer(char *name)
  631. {
  632. int i;
  633. if (name == NULL) {
  634. return(NULL);
  635. }
  636. for (i = 0; i < TeamTypes.Count(); i++) {
  637. if (!stricmp(name, TeamTypes.Ptr(i)->IniName)) {
  638. return(TeamTypes.Ptr(i));
  639. }
  640. }
  641. return(NULL);
  642. }
  643. /***************************************************************************
  644. * TeamTypeClass::Remove -- removes this team from the system *
  645. * *
  646. * INPUT: *
  647. * none. *
  648. * *
  649. * OUTPUT: *
  650. * none. *
  651. * *
  652. * WARNINGS: *
  653. * none. *
  654. * *
  655. * HISTORY: *
  656. * 12/09/1994 BR : Created. *
  657. *=========================================================================*/
  658. void TeamTypeClass::Remove(void)
  659. {
  660. Validate();
  661. int i;
  662. TriggerClass * trigger;
  663. /*
  664. ** Remove all trigger references to this team.
  665. */
  666. for (i = 0; i < Triggers.Count(); i++) {
  667. trigger = Triggers.Ptr(i);
  668. if (trigger->Team == this) {
  669. trigger->Team = NULL;
  670. }
  671. }
  672. /*
  673. ** Delete myself.
  674. */
  675. delete this;
  676. }
  677. /***************************************************************************
  678. * TeamTypeClass::Mission_From_Name -- returns team mission for given name *
  679. * *
  680. * INPUT: *
  681. * name name to compare *
  682. * *
  683. * OUTPUT: *
  684. * mission for that name *
  685. * *
  686. * WARNINGS: *
  687. * none. *
  688. * *
  689. * HISTORY: *
  690. * 12/13/1994 BR : Created. *
  691. *=========================================================================*/
  692. TeamMissionType TeamTypeClass::Mission_From_Name(char const *name)
  693. {
  694. int order;
  695. if (name) {
  696. for (order = TMISSION_FIRST; order < TMISSION_COUNT; order++) {
  697. if (stricmp(TMissions[order], name) == 0) {
  698. return((TeamMissionType) order);
  699. }
  700. }
  701. }
  702. return(TMISSION_NONE);
  703. }
  704. /***************************************************************************
  705. * TeamTypeClass::Name_From_Mission -- returns name for given mission *
  706. * *
  707. * INPUT: *
  708. * order mission to get name for *
  709. * *
  710. * OUTPUT: *
  711. * name of mission *
  712. * *
  713. * WARNINGS: *
  714. * none. *
  715. * *
  716. * HISTORY: *
  717. * 12/13/1994 BR : Created. *
  718. *=========================================================================*/
  719. char const * TeamTypeClass::Name_From_Mission(TeamMissionType order)
  720. {
  721. if (order <= TMISSION_NONE || order >= TMISSION_COUNT) {
  722. return("None");
  723. } else {
  724. return(TMissions[order]);
  725. }
  726. }
  727. /***************************************************************************
  728. * TeamTypeClass::operator new -- 'new' operator *
  729. * *
  730. * INPUT: *
  731. * none. *
  732. * *
  733. * OUTPUT: *
  734. * pointer to new TeamType *
  735. * *
  736. * WARNINGS: *
  737. * none. *
  738. * *
  739. * HISTORY: *
  740. * 11/28/1994 BR : Created. *
  741. *=========================================================================*/
  742. void * TeamTypeClass::operator new(size_t )
  743. {
  744. void * ptr = TeamTypes.Allocate();
  745. if (ptr) {
  746. ((TeamTypeClass *)ptr)->IsActive = true;
  747. }
  748. return(ptr);
  749. }
  750. /***************************************************************************
  751. * TeamTypeClass::operator delete -- 'delete' operator *
  752. * *
  753. * INPUT: *
  754. * ptr pointer to delete *
  755. * *
  756. * OUTPUT: *
  757. * none. *
  758. * *
  759. * WARNINGS: *
  760. * none. *
  761. * *
  762. * HISTORY: *
  763. * 11/28/1994 BR : Created. *
  764. *=========================================================================*/
  765. void TeamTypeClass::operator delete(void *ptr)
  766. {
  767. if (ptr) {
  768. ((TeamTypeClass *)ptr)->IsActive = false;
  769. }
  770. TeamTypes.Free((TeamTypeClass *)ptr);
  771. }
  772. TeamClass * TeamTypeClass::Create_One_Of(void) const
  773. {
  774. if (ScenarioInit || TeamClass::Number[TeamTypes.ID(this)] < MaxAllowed) {
  775. return(new TeamClass(this, HouseClass::As_Pointer(House)));
  776. }
  777. return(NULL);
  778. }
  779. TARGET TeamTypeClass::As_Target(void) const
  780. {
  781. Validate();
  782. return(Build_Target(KIND_TEAMTYPE, TeamTypes.ID(this)));
  783. }
  784. void TeamTypeClass::Destroy_All_Of(void) const
  785. {
  786. for (int index = 0; index < Teams.Count(); index++) {
  787. TeamClass * team = Teams.Ptr(index);
  788. if (team->Class == this) {
  789. delete team;
  790. index--;
  791. }
  792. }
  793. }
  794. /***********************************************************************************************
  795. * TeamTypeClass::Suggested_New_Team -- Suggests a new team to create. *
  796. * *
  797. * This routine will scan through the team types available and create teams of the *
  798. * type that can best utilize the existing unit mix. *
  799. * *
  800. * INPUT: house -- Pointer to the house that this team is to be created for. *
  801. * *
  802. * utype -- A bit mask of the unit types available for this house. *
  803. * *
  804. * itypes -- A bit mask of the infantry types available for this house. *
  805. * *
  806. * alerted -- Is this house alerted? If true, then the Autocreate teams will be *
  807. * considered in the selection process. *
  808. * *
  809. * OUTPUT: Returns with a pointer to the team type that should be created. If no team should *
  810. * be created, then it returns NULL. *
  811. * *
  812. * WARNINGS: none *
  813. * *
  814. * HISTORY: *
  815. * 07/13/1995 JLB : Created. *
  816. * 07/21/1995 JLB : Will autocreate team even if no members in field. *
  817. *=============================================================================================*/
  818. TeamTypeClass const * TeamTypeClass::Suggested_New_Team(HouseClass * house, long utypes, long itypes, bool alerted)
  819. {
  820. TeamTypeClass const * best = NULL;
  821. int bestvalue = 0;
  822. for (int index = 0; index < TeamTypes.Count(); index++) {
  823. TeamTypeClass const * ttype = TeamTypes.Ptr(index);
  824. if (ttype &&
  825. ttype->House == house->Class->House &&
  826. TeamClass::Number[index] < ((alerted || !ttype->IsAutocreate) ? ttype->MaxAllowed : 0)) {
  827. /*
  828. ** Determine what kind of units this team requires.
  829. */
  830. long uneeded = 0;
  831. long ineeded = 0;
  832. for (int ctype = 0; ctype < ttype->ClassCount; ctype++) {
  833. switch (ttype->Class[ctype]->What_Am_I()) {
  834. case RTTI_INFANTRYTYPE:
  835. ineeded |= (1 << ((InfantryTypeClass *)ttype->Class[ctype])->Type);
  836. break;
  837. case RTTI_UNITTYPE:
  838. uneeded |= (1 << ((UnitTypeClass *)ttype->Class[ctype])->Type);
  839. break;
  840. }
  841. }
  842. /*
  843. ** If this team can use the types required, then consider it a possible
  844. ** team type to create.
  845. */
  846. int value = 0;
  847. if ((ineeded & itypes) || (uneeded & utypes)) {
  848. value = ttype->RecruitPriority;
  849. } else {
  850. value = ttype->RecruitPriority/2;
  851. }
  852. if (!best || bestvalue < value) {
  853. bestvalue = value;
  854. best = ttype;
  855. }
  856. }
  857. }
  858. return(best);
  859. }