conversation.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Combat *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/conversation.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 10/29/01 10:23p $*
  29. * *
  30. * $Revision:: 8 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "conversation.h"
  36. #include "chunkio.h"
  37. #include "soldier.h"
  38. ////////////////////////////////////////////////////////////////
  39. // Constants
  40. ////////////////////////////////////////////////////////////////
  41. enum
  42. {
  43. CHUNKID_BASE_CLASS = 0x08090315,
  44. CHUNKID_VARIABLES,
  45. CHUNKID_ORATOR,
  46. CHUNKID_REMARK
  47. };
  48. enum
  49. {
  50. VARID_NAME = 0,
  51. VARID_ID,
  52. XXXX_VARID_REMARK,
  53. VARID_OLD_PTR,
  54. XXXXX_PLAYERTYPE,
  55. VARID_ISINNATE,
  56. VARID_PROBABILITY,
  57. VARID_AI_STATE,
  58. VARID_CATEGORY_ID,
  59. VARID_LOOKAT_OBJID,
  60. VARID_PRIORITY,
  61. VARID_MAXDIST,
  62. VARID_IS_INTERRUPTABLE,
  63. VARID_ISKEY
  64. };
  65. ////////////////////////////////////////////////////////////////
  66. //
  67. // ConversationClass
  68. //
  69. ////////////////////////////////////////////////////////////////
  70. ConversationClass::ConversationClass (void) :
  71. ID (0),
  72. IsInnate (true),
  73. IsKey (false),
  74. Probability (1.0F),
  75. AIState (AI_STATE_IDLE),
  76. CategoryID (0),
  77. LookAtObjID (0),
  78. Priority (30),
  79. MaxDist (0),
  80. IsInterruptable (true)
  81. {
  82. return ;
  83. }
  84. ////////////////////////////////////////////////////////////////
  85. //
  86. // ConversationClass
  87. //
  88. ////////////////////////////////////////////////////////////////
  89. ConversationClass::ConversationClass (const ConversationClass &src) :
  90. ID (0),
  91. IsInnate (true),
  92. IsKey (false),
  93. Probability (1.0F),
  94. AIState (AI_STATE_IDLE),
  95. CategoryID (0),
  96. LookAtObjID (0),
  97. Priority (30),
  98. MaxDist (0),
  99. IsInterruptable (true)
  100. {
  101. (*this) = src;
  102. return ;
  103. }
  104. ////////////////////////////////////////////////////////////////
  105. //
  106. // ~ConversationClass
  107. //
  108. ////////////////////////////////////////////////////////////////
  109. ConversationClass::~ConversationClass (void)
  110. {
  111. Clear_Remarks ();
  112. Clear_Orators ();
  113. return ;
  114. }
  115. ////////////////////////////////////////////////////////////////
  116. //
  117. // operator=
  118. //
  119. ////////////////////////////////////////////////////////////////
  120. const ConversationClass &
  121. ConversationClass::operator= (const ConversationClass &src)
  122. {
  123. //
  124. // Start fresh
  125. //
  126. Clear_Remarks ();
  127. Clear_Orators ();
  128. //
  129. // Copy the simple data
  130. //
  131. Name = src.Name;
  132. ID = src.ID;
  133. LookAtObjID = src.LookAtObjID;
  134. Priority = src.Priority;
  135. MaxDist = src.MaxDist;
  136. IsInterruptable = src.IsInterruptable;
  137. //
  138. // Copy the remark list
  139. //
  140. for (int index = 0; index < src.RemarkList.Count (); index ++) {
  141. const ConversationRemarkClass &remark = src.RemarkList[index];
  142. Add_Remark (remark);
  143. }
  144. //
  145. // Copy the orator list
  146. //
  147. for (index = 0; index < src.OratorList.Count (); index ++) {
  148. const OratorClass &orator = src.OratorList[index];
  149. Add_Orator (orator);
  150. }
  151. return (*this);
  152. }
  153. ////////////////////////////////////////////////////////////////
  154. //
  155. // Clear_Orators
  156. //
  157. ////////////////////////////////////////////////////////////////
  158. void
  159. ConversationClass::Clear_Orators (void)
  160. {
  161. OratorList.Delete_All ();
  162. return ;
  163. }
  164. ////////////////////////////////////////////////////////////////
  165. //
  166. // Clear_Remarks
  167. //
  168. ////////////////////////////////////////////////////////////////
  169. void
  170. ConversationClass::Clear_Remarks (void)
  171. {
  172. RemarkList.Delete_All ();
  173. return ;
  174. }
  175. ////////////////////////////////////////////////////////////////
  176. //
  177. // Get_Orator_Count
  178. //
  179. ////////////////////////////////////////////////////////////////
  180. int
  181. ConversationClass::Get_Orator_Count (void) const
  182. {
  183. return OratorList.Count ();
  184. }
  185. ////////////////////////////////////////////////////////////////
  186. //
  187. // Add_Orator
  188. //
  189. ////////////////////////////////////////////////////////////////
  190. void
  191. ConversationClass::Add_Orator (const OratorClass &orator)
  192. {
  193. OratorList.Add (orator);
  194. return ;
  195. }
  196. ////////////////////////////////////////////////////////////////
  197. //
  198. // Add_Remark
  199. //
  200. ////////////////////////////////////////////////////////////////
  201. void
  202. ConversationClass::Add_Remark (const ConversationRemarkClass &remark)
  203. {
  204. RemarkList.Add (remark);
  205. return ;
  206. }
  207. ////////////////////////////////////////////////////////////////
  208. //
  209. // Get_Remark_Info
  210. //
  211. ////////////////////////////////////////////////////////////////
  212. bool
  213. ConversationClass::Get_Remark_Info (int index, ConversationRemarkClass &remark)
  214. {
  215. bool retval = false;
  216. WWASSERT (index >= 0 && index < RemarkList.Count ());
  217. if (index >= 0 && index < RemarkList.Count ()) {
  218. //
  219. // Return the remark information to the caller
  220. //
  221. remark = RemarkList[index];
  222. retval = true;
  223. }
  224. return retval;
  225. }
  226. ////////////////////////////////////////////////////////////////
  227. //
  228. // Save
  229. //
  230. ////////////////////////////////////////////////////////////////
  231. bool
  232. ConversationClass::Save (ChunkSaveClass &csave)
  233. {
  234. csave.Begin_Chunk (CHUNKID_VARIABLES);
  235. WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_NAME, Name);
  236. WRITE_MICRO_CHUNK (csave, VARID_ID, ID);
  237. WRITE_MICRO_CHUNK (csave, VARID_ISINNATE, IsInnate);
  238. WRITE_MICRO_CHUNK (csave, VARID_ISKEY, IsKey);
  239. WRITE_MICRO_CHUNK (csave, VARID_PROBABILITY, Probability);
  240. WRITE_MICRO_CHUNK (csave, VARID_AI_STATE, AIState);
  241. WRITE_MICRO_CHUNK (csave, VARID_CATEGORY_ID, CategoryID);
  242. WRITE_MICRO_CHUNK (csave, VARID_LOOKAT_OBJID, LookAtObjID);
  243. WRITE_MICRO_CHUNK (csave, VARID_PRIORITY, Priority);
  244. WRITE_MICRO_CHUNK (csave, VARID_MAXDIST, MaxDist);
  245. WRITE_MICRO_CHUNK (csave, VARID_IS_INTERRUPTABLE, IsInterruptable);
  246. //
  247. // Save our current pointer so we can remap it on load
  248. //
  249. ConversationClass *old_ptr = this;
  250. WRITE_MICRO_CHUNK (csave, VARID_OLD_PTR, old_ptr);
  251. csave.End_Chunk ();
  252. //
  253. // Save the orator list
  254. //
  255. for (int index = 0; index < OratorList.Count (); index ++) {
  256. OratorClass &orator = OratorList[index];
  257. //
  258. // Save this orator to its own chunk
  259. //
  260. csave.Begin_Chunk (CHUNKID_ORATOR);
  261. orator.Save (csave);
  262. csave.End_Chunk ();
  263. }
  264. //
  265. // Save the remark list
  266. //
  267. for (index = 0; index < RemarkList.Count (); index ++) {
  268. ConversationRemarkClass &remark = RemarkList[index];
  269. //
  270. // Save this remark to its own chunk
  271. //
  272. csave.Begin_Chunk (CHUNKID_REMARK);
  273. remark.Save (csave);
  274. csave.End_Chunk ();
  275. }
  276. return true;
  277. }
  278. ////////////////////////////////////////////////////////////////
  279. //
  280. // Load
  281. //
  282. ////////////////////////////////////////////////////////////////
  283. bool
  284. ConversationClass::Load (ChunkLoadClass &cload)
  285. {
  286. OratorList.Resize (10);
  287. while (cload.Open_Chunk ()) {
  288. switch (cload.Cur_Chunk_ID ()) {
  289. case CHUNKID_VARIABLES:
  290. Load_Variables (cload);
  291. break;
  292. case CHUNKID_ORATOR:
  293. {
  294. OratorList.Add (OratorClass ());
  295. OratorList[OratorList.Count () - 1].Load (cload);
  296. }
  297. break;
  298. case CHUNKID_REMARK:
  299. {
  300. ConversationRemarkClass remark;
  301. remark.Load (cload);
  302. RemarkList.Add (remark);
  303. }
  304. break;
  305. }
  306. cload.Close_Chunk ();
  307. }
  308. return true;
  309. }
  310. ///////////////////////////////////////////////////////////////////////
  311. //
  312. // Load_Variables
  313. //
  314. ///////////////////////////////////////////////////////////////////////
  315. void
  316. ConversationClass::Load_Variables (ChunkLoadClass &cload)
  317. {
  318. ConversationClass *old_ptr = NULL;
  319. //
  320. // Loop through all the microchunks that define the variables
  321. //
  322. while (cload.Open_Micro_Chunk ()) {
  323. switch (cload.Cur_Micro_Chunk_ID ()) {
  324. READ_MICRO_CHUNK_WWSTRING (cload, VARID_NAME, Name);
  325. READ_MICRO_CHUNK (cload, VARID_ID, ID);
  326. READ_MICRO_CHUNK (cload, VARID_OLD_PTR, old_ptr);
  327. READ_MICRO_CHUNK (cload, VARID_ISINNATE, IsInnate);
  328. READ_MICRO_CHUNK (cload, VARID_ISKEY, IsKey);
  329. READ_MICRO_CHUNK (cload, VARID_PROBABILITY, Probability);
  330. READ_MICRO_CHUNK (cload, VARID_AI_STATE, AIState);
  331. READ_MICRO_CHUNK (cload, VARID_CATEGORY_ID, CategoryID);
  332. READ_MICRO_CHUNK (cload, VARID_LOOKAT_OBJID, LookAtObjID);
  333. READ_MICRO_CHUNK (cload, VARID_PRIORITY, Priority);
  334. READ_MICRO_CHUNK (cload, VARID_MAXDIST, MaxDist);
  335. READ_MICRO_CHUNK (cload, VARID_IS_INTERRUPTABLE, IsInterruptable);
  336. //
  337. // Old-style remark (for backwards compatiblility)
  338. //
  339. case XXXX_VARID_REMARK:
  340. {
  341. struct
  342. {
  343. int OratorID;
  344. int TextID;
  345. } OldRemarkStruct;
  346. //
  347. // Read the old data from the chunk
  348. //
  349. cload.Read (&OldRemarkStruct, sizeof (OldRemarkStruct));
  350. //
  351. // Convert the data
  352. //
  353. ConversationRemarkClass remark;
  354. remark.Set_Orator_ID (OldRemarkStruct.OratorID);
  355. remark.Set_Text_ID (OldRemarkStruct.TextID);
  356. //
  357. // Add this remark to our list
  358. //
  359. Add_Remark (remark);
  360. }
  361. break;
  362. }
  363. cload.Close_Micro_Chunk ();
  364. }
  365. //
  366. // Register our old pointer so other objects can safely remap to it
  367. //
  368. WWASSERT (old_ptr != NULL);
  369. SaveLoadSystemClass::Register_Pointer (old_ptr, this);
  370. return ;
  371. }
  372. ///////////////////////////////////////////////////////////////////////
  373. //
  374. // Get_Orator
  375. //
  376. ///////////////////////////////////////////////////////////////////////
  377. OratorClass *
  378. ConversationClass::Get_Orator (int index)
  379. {
  380. OratorClass *orator = NULL;
  381. if (index >= 0 && index < OratorList.Count ()) {
  382. orator = &OratorList[index];
  383. }
  384. return orator;
  385. }
  386. ///////////////////////////////////////////////////////////////////////
  387. //
  388. // Find_Orator
  389. //
  390. ///////////////////////////////////////////////////////////////////////
  391. OratorClass *
  392. ConversationClass::Find_Orator (int orator_id)
  393. {
  394. OratorClass *orator = NULL;
  395. for (int index = 0; index < OratorList.Count (); index ++) {
  396. OratorClass *curr_orator = &OratorList[index];
  397. //
  398. // Is this the orator we are looking for?
  399. //
  400. if (curr_orator->Get_ID () == orator_id) {
  401. orator = curr_orator;
  402. break;
  403. }
  404. }
  405. return orator;
  406. }