waypath.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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 : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/waypath.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 8/20/01 7:48p $*
  29. * *
  30. * $Revision:: 6 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "waypath.h"
  36. #include "persistfactory.h"
  37. #include "wwphysids.h"
  38. #include "waypoint.h"
  39. #include "wwhack.h"
  40. #include "waypathposition.h"
  41. #include "pathfind.h"
  42. DECLARE_FORCE_LINK(waypath);
  43. //////////////////////////////////////////////////////////////////////////////
  44. // Persist factory
  45. //////////////////////////////////////////////////////////////////////////////
  46. SimplePersistFactoryClass<WaypathClass, PHYSICS_CHUNKID_WAYPATH> _WaypathPersistFactory;
  47. enum
  48. {
  49. CHUNKID_VARIABLES = 0x04290219,
  50. CHUNKID_BASE_CLASS
  51. };
  52. enum
  53. {
  54. VARID_OLD_PTR = 0x01,
  55. VARID_FLAGS,
  56. VARID_ID,
  57. VARID_WAYPOINT_PTR
  58. };
  59. ////////////////////////////////////////////////////////////////
  60. //
  61. // WaypathClass
  62. //
  63. ////////////////////////////////////////////////////////////////
  64. WaypathClass::WaypathClass (void)
  65. : m_ID (0),
  66. m_Flags (FLAG_TWO_WAY | FLAG_HUMAN | FLAG_GROUND_VEHICLE)
  67. {
  68. return ;
  69. }
  70. ////////////////////////////////////////////////////////////////
  71. //
  72. // WaypathClass
  73. //
  74. ////////////////////////////////////////////////////////////////
  75. WaypathClass::WaypathClass (const WaypathPositionClass &start, const WaypathPositionClass &end)
  76. : m_ID (0),
  77. m_Flags (FLAG_TWO_WAY | FLAG_HUMAN | FLAG_GROUND_VEHICLE)
  78. {
  79. //
  80. // Check to ensure the two endpoints refer to the same path
  81. //
  82. int waypath_id = start.Get_Waypath_ID ();
  83. if (waypath_id == end.Get_Waypath_ID ()) {
  84. //
  85. // Lookup the path we will use as our reference
  86. //
  87. WaypathClass *whole_path = PathfindClass::Get_Instance ()->Find_Waypath (waypath_id);
  88. if (whole_path != NULL) {
  89. //
  90. // Copy the flags from the complete path
  91. //
  92. m_Flags = whole_path->Get_Flags ();
  93. //
  94. // Find the world-space positions of the endpoints of our path segment
  95. //
  96. Vector3 start_pos (0, 0, 0);
  97. Vector3 end_pos (0, 0, 0);
  98. whole_path->Evaluate_Position (start, &start_pos);
  99. whole_path->Evaluate_Position (end, &end_pos);
  100. //
  101. // Add the starting point to our waypath
  102. //
  103. m_Waypoints.Add (new WaypointClass (start_pos));
  104. //
  105. // Add all the points between the start and end point to the path
  106. //
  107. /*int start_index = start.Get_Waypoint_Index ();
  108. int end_index = end.Get_Waypoint_Index ();
  109. int count = WWMath::Fabs (end_index - start_index) - 2;
  110. int inc = (end_index > start_index) ? 1 : -1;
  111. for (int index = start_index + inc; count >= 0; index += inc, count --) {
  112. WaypointClass *waypoint = whole_path->Get_Point (index);
  113. m_Waypoints.Add (new WaypointClass (*waypoint));
  114. }*/
  115. //
  116. // Get the start and end indices from the path
  117. //
  118. int start_index = start.Get_Waypoint_Index ();
  119. int end_index = end.Get_Waypoint_Index ();
  120. //
  121. // Are we moving forwards or backwards along the path?
  122. //
  123. if (end_index > start_index) {
  124. //
  125. // Add all the points between the start and end point to the path
  126. //
  127. for (int index = start_index + 1; index <= end_index; index ++) {
  128. WaypointClass *waypoint = whole_path->Get_Point (index);
  129. m_Waypoints.Add (new WaypointClass (*waypoint));
  130. }
  131. } else {
  132. //
  133. // Add all the points between the start and end point to the path
  134. //
  135. for (int index = start_index - 1; index > end_index; index --) {
  136. WaypointClass *waypoint = whole_path->Get_Point (index);
  137. m_Waypoints.Add (new WaypointClass (*waypoint));
  138. }
  139. }
  140. //
  141. // Add the ending point to our waypath
  142. //
  143. m_Waypoints.Add (new WaypointClass (end_pos));
  144. }
  145. }
  146. return ;
  147. }
  148. ////////////////////////////////////////////////////////////////
  149. //
  150. // WaypathClass
  151. //
  152. ////////////////////////////////////////////////////////////////
  153. WaypathClass::~WaypathClass (void)
  154. {
  155. Free ();
  156. return ;
  157. }
  158. ////////////////////////////////////////////////////////////////
  159. //
  160. // Get_Factory
  161. //
  162. ////////////////////////////////////////////////////////////////
  163. const PersistFactoryClass &
  164. WaypathClass::Get_Factory (void) const
  165. {
  166. return _WaypathPersistFactory;
  167. }
  168. /////////////////////////////////////////////////////////////////
  169. //
  170. // Save
  171. //
  172. /////////////////////////////////////////////////////////////////
  173. bool
  174. WaypathClass::Save (ChunkSaveClass &csave)
  175. {
  176. csave.Begin_Chunk (CHUNKID_VARIABLES);
  177. WaypathClass *this_ptr = this;
  178. WRITE_MICRO_CHUNK (csave, VARID_OLD_PTR, this_ptr);
  179. WRITE_MICRO_CHUNK (csave, VARID_FLAGS, m_Flags);
  180. WRITE_MICRO_CHUNK (csave, VARID_ID, m_ID);
  181. //
  182. // Write out each waypoint pointer so we can remap them
  183. // on load.
  184. //
  185. for (int index = 0; index < m_Waypoints.Count (); index ++) {
  186. WaypointClass *waypoint = m_Waypoints[index];
  187. WRITE_MICRO_CHUNK (csave, VARID_WAYPOINT_PTR, waypoint);
  188. }
  189. csave.End_Chunk ();
  190. return true;
  191. }
  192. /////////////////////////////////////////////////////////////////
  193. //
  194. // Load
  195. //
  196. /////////////////////////////////////////////////////////////////
  197. bool
  198. WaypathClass::Load (ChunkLoadClass &cload)
  199. {
  200. while (cload.Open_Chunk ()) {
  201. switch (cload.Cur_Chunk_ID ()) {
  202. case CHUNKID_VARIABLES:
  203. Load_Variables (cload);
  204. break;
  205. }
  206. cload.Close_Chunk ();
  207. }
  208. SaveLoadSystemClass::Register_Post_Load_Callback (this);
  209. return true;
  210. }
  211. ///////////////////////////////////////////////////////////////////////
  212. //
  213. // Load_Variables
  214. //
  215. ///////////////////////////////////////////////////////////////////////
  216. bool
  217. WaypathClass::Load_Variables (ChunkLoadClass &cload)
  218. {
  219. //
  220. // Loop through all the microchunks that define the variables
  221. //
  222. while (cload.Open_Micro_Chunk ()) {
  223. switch (cload.Cur_Micro_Chunk_ID ()) {
  224. READ_MICRO_CHUNK (cload, VARID_FLAGS, m_Flags);
  225. READ_MICRO_CHUNK (cload, VARID_ID, m_ID);
  226. case VARID_WAYPOINT_PTR:
  227. {
  228. //
  229. // Read the old waypoint ptr from the chunk and add it to our
  230. // list. We will remap it later.
  231. //
  232. WaypointClass *waypoint = NULL;
  233. cload.Read (&waypoint, sizeof (waypoint));
  234. m_Waypoints.Add (waypoint);
  235. }
  236. break;
  237. case VARID_OLD_PTR:
  238. {
  239. //
  240. // Read the old pointer from the chunk and submit it
  241. // to the remapping system.
  242. //
  243. WaypathClass *old_ptr = NULL;
  244. cload.Read (&old_ptr, sizeof (old_ptr));
  245. SaveLoadSystemClass::Register_Pointer (old_ptr, this);
  246. }
  247. break;
  248. }
  249. cload.Close_Micro_Chunk ();
  250. }
  251. //
  252. // Register each of the pointers in our waypoint list for remapping
  253. //
  254. for (int index = 0; index < m_Waypoints.Count (); index ++) {
  255. REQUEST_POINTER_REMAP ((void **)&m_Waypoints[index]);
  256. }
  257. return true;
  258. }
  259. ///////////////////////////////////////////////////////////////////////
  260. //
  261. // On_Post_Load
  262. //
  263. ///////////////////////////////////////////////////////////////////////
  264. void
  265. WaypathClass::On_Post_Load (void)
  266. {
  267. //
  268. // Add a reference count to each of the waypoints
  269. //
  270. /*for (int index = 0; index < m_Waypoints.Count (); index ++) {
  271. WaypointClass *waypoint = m_Waypoints[index];
  272. waypoint->Add_Ref ();
  273. }*/
  274. return ;
  275. }
  276. ///////////////////////////////////////////////////////////////////////
  277. //
  278. // Free
  279. //
  280. ///////////////////////////////////////////////////////////////////////
  281. void
  282. WaypathClass::Free (void)
  283. {
  284. //
  285. // Release our hold on each of the waypoints
  286. //
  287. for (int index = 0; index < m_Waypoints.Count (); index ++) {
  288. WaypointClass *waypoint = m_Waypoints[index];
  289. REF_PTR_RELEASE (waypoint);
  290. }
  291. return ;
  292. }
  293. ///////////////////////////////////////////////////////////////////////
  294. //
  295. // Add_Point
  296. //
  297. ///////////////////////////////////////////////////////////////////////
  298. void
  299. WaypathClass::Add_Point (const WaypointClass &point)
  300. {
  301. //
  302. // Allocate a copy of the given waypoint and add it to
  303. // our waypoint list.
  304. //
  305. WaypointClass *new_waypoint = new WaypointClass (point);
  306. m_Waypoints.Add (new_waypoint);
  307. return ;
  308. }
  309. ///////////////////////////////////////////////////////////////////////
  310. //
  311. // Add_Point
  312. //
  313. ///////////////////////////////////////////////////////////////////////
  314. void
  315. WaypathClass::Add_Point (const Vector3 &point)
  316. {
  317. //
  318. // Allocate a copy of the given waypoint and add it to
  319. // our waypoint list.
  320. //
  321. WaypointClass *new_waypoint = new WaypointClass (point);
  322. m_Waypoints.Add (new_waypoint);
  323. return ;
  324. }
  325. //////////////////////////////////////////////////////////////////////////////
  326. //
  327. // Set_Flag
  328. //
  329. //////////////////////////////////////////////////////////////////////////////
  330. void
  331. WaypathClass::Set_Flag (int flag, bool onoff)
  332. {
  333. m_Flags &= ~flag;
  334. if (onoff) {
  335. m_Flags |= flag;
  336. }
  337. return ;
  338. }
  339. //////////////////////////////////////////////////////////////////////////////
  340. //
  341. // Evaluate_Position
  342. //
  343. //////////////////////////////////////////////////////////////////////////////
  344. bool
  345. WaypathClass::Evaluate_Position (const WaypathPositionClass &pos, Vector3 *position)
  346. {
  347. bool retval = false;
  348. //
  349. // Check to ensure this is the right waypath
  350. //
  351. if (pos.Get_Waypath_ID () == m_ID) {
  352. //
  353. // Lookup the start point of the segment
  354. //
  355. int index = pos.Get_Waypoint_Index ();
  356. WaypointClass *seg_pt1 = Get_Point (index);
  357. if (seg_pt1 != NULL) {
  358. //
  359. // Get the world-space position of the start point of the segment
  360. //
  361. const Vector3 &pt1 = seg_pt1->Get_Position ();
  362. //
  363. // Do a quick check to see if we should just return the
  364. // start point
  365. //
  366. if (pos.Get_Percent () == 0) {
  367. (*position) = pt1;
  368. retval = true;
  369. } else {
  370. //
  371. // Lookup the end point of the segment
  372. //
  373. WaypointClass *seg_pt2 = Get_Point (index + 1);
  374. if (seg_pt2 != NULL) {
  375. //
  376. // Get the world-space position of the end point of the segment
  377. //
  378. const Vector3 &pt2 = seg_pt2->Get_Position ();
  379. //
  380. // Evaluate the line segment at the given percent
  381. //
  382. (*position) = pt1 + (pt2 - pt1) * pos.Get_Percent ();
  383. retval = true;
  384. }
  385. }
  386. }
  387. }
  388. return retval;
  389. }