navnet.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // navnet.cpp
  19. // Project: Nostril (aka Postal)
  20. //
  21. // This module implements the bouy marker for use with the network navagation
  22. // system that will help the enemy guys get around the world.
  23. //
  24. // History:
  25. // 01/28/97 BRH Added navigation net objects as the thing that holds
  26. // a group of bouys together in a navigational network.
  27. //
  28. // 02/02/97 BRH Added Ping routine that gives the miniumum number of hops
  29. // from src to dst nodes in the network. Added
  30. // FindNearestBouy function to locate the closest Bouy to
  31. // a given position. This may later be optimized using
  32. // collision regions. Also added UpdateRoutingTables()
  33. // function which asks for each destination node from each
  34. // Bouy so that each Bouy will discover a route and add it
  35. // to its routing table. This will give a fully connected
  36. // routing table for faster access rather than building
  37. // the routing tables as we go.
  38. //
  39. // 02/03/97 BRH Changed Load and Save functions to call the base
  40. // class load and save to preserve the instance ID's
  41. // and also saved the number of nodes in the network
  42. // to be used later to reinitialize the network after
  43. // a load of the NavNet and the Bouys. Added the
  44. // startup code to update the routing tables after the load
  45. // is done.
  46. //
  47. // 02/04/97 JMI Changed LoadDib() call to Load() (which now supports
  48. // loading of DIBs).
  49. //
  50. // 02/04/97 BRH Sets itself to be the current Nav Net in the realm on
  51. // construction, Startup, and EditModify.
  52. //
  53. // 02/05/97 BRH Fixed problem with the FindNearestBouy function and
  54. // fixed a problem with Ping where it wasn't adding 1
  55. // if it pinged a link from a routing table entry.
  56. //
  57. // 02/06/97 BRH Added SetAsDefault() function which sets this NavNet
  58. // as the default one in its realm. This was needed
  59. // by the editor when deleteing the default NavNet, the
  60. // editor didn't have access to the realm's protected
  61. // current NavNet pointer. Also added DeleteNetwork()
  62. // which frees all of the bouys in this network. This
  63. // is also called by the editor when deleting a NavNet.
  64. //
  65. // 02/18/97 JMI Changed GetResources() to use the resmgr.
  66. //
  67. // 02/23/97 BRH Moved Render() functionality to EditRender and made
  68. // Render do nothing so that it isn't drawing during gameplay.
  69. //
  70. // 02/24/97 JMI No longer sets the m_type member of the m_sprite b/c it
  71. // is set by m_sprite's constructor.
  72. //
  73. // 03/04/97 BRH Added a string name to the NavNet so it can be displayed
  74. // in a listbox int eh editor to indicate the current
  75. // NavNet and be able to tell them apart.
  76. //
  77. // 03/06/97 BRH Changed Ping to include a visited nodes list to detect
  78. // loops faster. The old method was extremely slow, as in
  79. // days of checking for a network of 45 bouys. The new one
  80. // is still somewhat slow at 3 minutes for that number, but
  81. // the bouys will save their route tables to save time when
  82. // the level is loaded.
  83. //
  84. // 03/13/97 BRH Made a few modifications to Ping and verified that it
  85. // correctly builds routing tables for several networks.
  86. // It is still slow for large looped networks so I will
  87. // be adding a hops table to the bouys to cut down on the
  88. // number of pings required to complete the tables. Then
  89. // the hops tables can be freed at some point.
  90. //
  91. // 03/13/97 JMI Load now takes a version number.
  92. //
  93. // 04/10/97 BRH Updated this to work with the new multi layer attribute
  94. // maps.
  95. //
  96. // 04/15/97 BRH Changing over to the new BFS tree method of routing, and
  97. // getting rid of the old code like Ping(). Also added
  98. // dialog box that allows you to set the name of the NavNet
  99. // as well as to set it as the default Network.
  100. //
  101. // 04/18/97 BRH Fixed problem in Save where it saved the number of nodes
  102. // using the last index, rather than the size of the node map
  103. // which would be off if some bouys were deleted from the
  104. // network. Changed it to save the size of the m_NodeMap.
  105. //
  106. // 05/29/97 JMI Removed ASSERT on m_pRealm->m_pAttribMap which no longer
  107. // exists.
  108. //
  109. // 06/27/97 BRH Changed FindNearestBouy to use the new bouy tree nodes
  110. // to build a sorted list of nearest bouys. It then checks
  111. // to see if the closest is reachable without terrain
  112. // terrain blocking the path, and if so returns that bouy.
  113. // If it is blocked, then it will try the next one in the
  114. // list.
  115. //
  116. // 06/29/97 JMI Converted EditRect(), EditRender(), and/or Render() to
  117. // use Map3Dto2D().
  118. // Moved EditRect() here from navnet.h and added EditHotSpot().
  119. //
  120. // 06/30/97 BRH Fixed bug where the wrong overloaded version of IsPathClear
  121. // was being called.
  122. //
  123. // 07/09/97 JMI Now uses m_pRealm->Make2dResPath() to get the fullpath
  124. // for 2D image components.
  125. //
  126. // 07/14/97 JMI FindNearestBouy() was deleting a NULL tree, if no bouys.
  127. // Fixed.
  128. //
  129. // 07/25/97 BRH Fixed problem of > 254 bouys being created in the editor.
  130. //
  131. // 08/05/97 JMI Changed priority to use Z position rather than 2D
  132. // projected Y position.
  133. //
  134. // 08/08/97 BRH Added EditPostLoad function which adds the Nav Net name
  135. // to the editor's list box, just as it does when EditNew is
  136. // called. This way the NavNets loaded from the realm file
  137. // are now correctly displayed.
  138. //
  139. ////////////////////////////////////////////////////////////////////////////////
  140. #define NAVIGATIONNET_CPP
  141. #include "RSPiX.h"
  142. #include <math.h>
  143. #include "navnet.h"
  144. #include "bouy.h"
  145. #include "gameedit.h"
  146. ////////////////////////////////////////////////////////////////////////////////
  147. // Macros/types/etc.
  148. ////////////////////////////////////////////////////////////////////////////////
  149. #define IMAGE_FILE "nnet.bmp"
  150. // Minimum elapsed time (in milliseconds)
  151. #define MIN_ELAPSED_TIME 10
  152. ////////////////////////////////////////////////////////////////////////////////
  153. // Variables/data
  154. ////////////////////////////////////////////////////////////////////////////////
  155. // These are default values -- actually values are set using the editor!
  156. // Let this auto-init to 0
  157. short CNavigationNet::ms_sFileCount;
  158. ////////////////////////////////////////////////////////////////////////////////
  159. // Load object (should call base class version!)
  160. ////////////////////////////////////////////////////////////////////////////////
  161. short CNavigationNet::Load( // Returns 0 if successfull, non-zero otherwise
  162. RFile* pFile, // In: File to load from
  163. bool bEditMode, // In: True for edit mode, false otherwise
  164. short sFileCount, // In: File count (unique per file, never 0)
  165. ULONG ulFileVersion) // In: Version of file format to load.
  166. {
  167. // Call the base class load to get the instance ID
  168. short sResult = CThing::Load(pFile, bEditMode, sFileCount, ulFileVersion);
  169. if (sResult == 0)
  170. {
  171. // Load common data just once per file (not with each object)
  172. if (ms_sFileCount != sFileCount)
  173. {
  174. ms_sFileCount = sFileCount;
  175. // Load static data
  176. switch (ulFileVersion)
  177. {
  178. default:
  179. case 1:
  180. break;
  181. }
  182. }
  183. // Load object data
  184. switch (ulFileVersion)
  185. {
  186. default:
  187. case 1:
  188. pFile->Read(&m_dX);
  189. pFile->Read(&m_dY);
  190. pFile->Read(&m_dZ);
  191. // Load the number of bouys that were saved
  192. pFile->Read(&m_ucNumSavedBouys);
  193. m_rstrNetName.Load(pFile);
  194. break;
  195. }
  196. // Make sure there were no file errors or format errors . . .
  197. if (!pFile->Error() && sResult == 0)
  198. {
  199. // Get resources
  200. sResult = GetResources();
  201. }
  202. else
  203. {
  204. sResult = -1;
  205. TRACE("CNavigationNet::Load(): Error reading from file!\n");
  206. }
  207. }
  208. else
  209. {
  210. TRACE("CNavigationNet::Load(): CThing::Load() failed.\n");
  211. }
  212. return sResult;
  213. }
  214. ////////////////////////////////////////////////////////////////////////////////
  215. // Save object (should call base class version!)
  216. ////////////////////////////////////////////////////////////////////////////////
  217. short CNavigationNet::Save( // Returns 0 if successfull, non-zero otherwise
  218. RFile* pFile, // In: File to save to
  219. short sFileCount) // In: File count (unique per file, never 0)
  220. {
  221. // Call the base class save to save the instance ID
  222. CThing::Save(pFile, sFileCount);
  223. // Save common data just once per file (not with each object)
  224. if (ms_sFileCount != sFileCount)
  225. {
  226. ms_sFileCount = sFileCount;
  227. // Save static data
  228. }
  229. // Save object data
  230. pFile->Write(&m_dX);
  231. pFile->Write(&m_dY);
  232. pFile->Write(&m_dZ);
  233. // Save the number of nodes so we can check after load to see if all
  234. // of the Bouys have been loaded yet.
  235. // pFile->Write(&m_ucNextID);
  236. UCHAR ucNumNodes = m_NodeMap.size();
  237. pFile->Write(&ucNumNodes);
  238. m_rstrNetName.Save(pFile);
  239. return 0;
  240. }
  241. ////////////////////////////////////////////////////////////////////////////////
  242. // Startup object
  243. ////////////////////////////////////////////////////////////////////////////////
  244. short CNavigationNet::Startup(void) // Returns 0 if successfull, non-zero otherwise
  245. {
  246. short sReturn = 0;
  247. // At this point we can assume the CHood was loaded, so we init our height
  248. m_dY = m_pRealm->GetHeight((short) m_dX, (short) m_dZ);
  249. // Set yourself to be the new current Nav Net
  250. m_pRealm->m_pCurrentNavNet = this;
  251. // Init other stuff
  252. if (m_ucNextID <= m_ucNumSavedBouys)
  253. {
  254. m_sCallStartup = 1;
  255. sReturn = 0;
  256. }
  257. else
  258. UpdateRoutingTables();
  259. return sReturn;
  260. }
  261. ////////////////////////////////////////////////////////////////////////////////
  262. // Shutdown object
  263. ////////////////////////////////////////////////////////////////////////////////
  264. short CNavigationNet::Shutdown(void) // Returns 0 if successfull, non-zero otherwise
  265. {
  266. return 0;
  267. }
  268. ////////////////////////////////////////////////////////////////////////////////
  269. // Suspend object
  270. ////////////////////////////////////////////////////////////////////////////////
  271. void CNavigationNet::Suspend(void)
  272. {
  273. m_sSuspend++;
  274. }
  275. ////////////////////////////////////////////////////////////////////////////////
  276. // Resume object
  277. ////////////////////////////////////////////////////////////////////////////////
  278. void CNavigationNet::Resume(void)
  279. {
  280. m_sSuspend--;
  281. // If we're actually going to start updating again, we need to reset
  282. // the time so as to ignore any time that passed while we were suspended.
  283. // This method is far from precise, but I'm hoping it's good enough.
  284. }
  285. ////////////////////////////////////////////////////////////////////////////////
  286. // Update object
  287. ////////////////////////////////////////////////////////////////////////////////
  288. void CNavigationNet::Update(void)
  289. {
  290. }
  291. ////////////////////////////////////////////////////////////////////////////////
  292. // Render object
  293. ////////////////////////////////////////////////////////////////////////////////
  294. void CNavigationNet::Render(void)
  295. {
  296. }
  297. ////////////////////////////////////////////////////////////////////////////////
  298. // Called by editor after load to set up the nav net list box in the editor
  299. // similar to EditNew but without the positioning.
  300. ////////////////////////////////////////////////////////////////////////////////
  301. short CNavigationNet::EditPostLoad(void)
  302. {
  303. short sResult = 0;
  304. CListNode<CThing>* pEditorList = m_pRealm->m_aclassHeads[CThing::CGameEditThingID].m_pnNext;
  305. CGameEditThing* peditor = (CGameEditThing*) pEditorList->m_powner;
  306. RListBox* plb = peditor->m_plbNavNetList;
  307. if (plb != NULL)
  308. {
  309. RGuiItem* pgui = plb->AddString((char*) m_rstrNetName);
  310. pgui->m_lId = GetInstanceID();
  311. pgui->m_bcUser = NavNetListPressedCall;
  312. pgui->m_ulUserInstance = (unsigned long) this;
  313. plb->AdjustContents();
  314. plb->SetSel(pgui);
  315. }
  316. else
  317. {
  318. sResult = -1;
  319. TRACE("CNavigationNet::EditLoad - Error setting up NavNet list box in editor\n");
  320. }
  321. return sResult;
  322. }
  323. ////////////////////////////////////////////////////////////////////////////////
  324. // Called by editor to init new object at specified position
  325. ////////////////////////////////////////////////////////////////////////////////
  326. short CNavigationNet::EditNew( // Returns 0 if successfull, non-zero otherwise
  327. short sX, // In: New x coord
  328. short sY, // In: New y coord
  329. short sZ) // In: New z coord
  330. {
  331. short sResult = 0;
  332. // Use specified position
  333. m_dX = (double)sX;
  334. m_dY = (double)sY;
  335. m_dZ = (double)sZ;
  336. // Load resources
  337. sResult = GetResources();
  338. if (sResult == SUCCESS)
  339. {
  340. CListNode<CThing>* pEditorList = m_pRealm->m_aclassHeads[CThing::CGameEditThingID].m_pnNext;
  341. CGameEditThing* peditor = (CGameEditThing*) pEditorList->m_powner;
  342. RListBox* plb = peditor->m_plbNavNetList;
  343. if (plb != NULL)
  344. {
  345. RGuiItem* pgui = plb->AddString((char*) m_rstrNetName);
  346. pgui->m_lId = GetInstanceID();
  347. pgui->m_bcUser = NavNetListPressedCall;
  348. pgui->m_ulUserInstance = (unsigned long) this;
  349. plb->AdjustContents();
  350. plb->SetSel(pgui);
  351. }
  352. }
  353. return sResult;
  354. }
  355. ////////////////////////////////////////////////////////////////////////////////
  356. // Helper inline to get a GUI, set its text to the value, and recompose it.
  357. ////////////////////////////////////////////////////////////////////////////////
  358. inline
  359. void SetText( // Returns nothing.
  360. RGuiItem* pguiRoot, // In: Root GUI.
  361. long lId, // In: ID of GUI to set text.
  362. char* str) // In: Value to set text to.
  363. {
  364. RGuiItem* pgui = pguiRoot->GetItemFromId(lId);
  365. if (pgui != NULL)
  366. {
  367. pgui->SetText(str);
  368. pgui->Compose();
  369. }
  370. }
  371. ////////////////////////////////////////////////////////////////////////////////
  372. // Edit Modify
  373. ////////////////////////////////////////////////////////////////////////////////
  374. short CNavigationNet::EditModify(void)
  375. {
  376. short sResult = 0;
  377. RGuiItem* pGui = RGuiItem::LoadInstantiate(FullPathVD("res/editor/network.gui"));
  378. if (pGui)
  379. {
  380. SetText(pGui, 3, (char*) m_rstrNetName);
  381. sResult = DoGui(pGui);
  382. if (sResult == 1)
  383. {
  384. SetAsDefault();
  385. m_rstrNetName.Grow(256);
  386. pGui->GetText(3, (char*) m_rstrNetName, 255);
  387. m_rstrNetName.Update();
  388. CListNode<CThing>* pEditorList = m_pRealm->m_aclassHeads[CThing::CGameEditThingID].m_pnNext;
  389. CGameEditThing* peditor = (CGameEditThing*) pEditorList->m_powner;
  390. RListBox* plb = peditor->m_plbNavNetList;
  391. SetText(plb, GetInstanceID(), (char*) m_rstrNetName);
  392. plb->SetSel(plb->GetItemFromId(GetInstanceID()));
  393. // RGuiItem* pguiRemove = plb->GetItemFromId(GetInstanceID());
  394. // SetText(pguiRemove,
  395. }
  396. }
  397. return 0;
  398. }
  399. /*
  400. RGuiItem* pguiRemove;
  401. if (pview != NULL)
  402. {
  403. pguiRemove = plb->GetItemFromId((long)pview);
  404. }
  405. else
  406. {
  407. pguiRemove = plb->GetSel();
  408. }
  409. if (pguiRemove != NULL)
  410. {
  411. KillView((View*)(pguiRemove->m_lId));
  412. plb->RemoveItem(pguiRemove);
  413. plb->AdjustContents();
  414. */
  415. ////////////////////////////////////////////////////////////////////////////////
  416. // Called by editor to move object to specified position
  417. ////////////////////////////////////////////////////////////////////////////////
  418. short CNavigationNet::EditMove( // Returns 0 if successfull, non-zero otherwise
  419. short sX, // In: New x coord
  420. short sY, // In: New y coord
  421. short sZ) // In: New z coord
  422. {
  423. m_dX = (double)sX;
  424. m_dY = (double)sY;
  425. m_dZ = (double)sZ;
  426. return 0;
  427. }
  428. ////////////////////////////////////////////////////////////////////////////////
  429. // Called by editor to update object
  430. ////////////////////////////////////////////////////////////////////////////////
  431. void CNavigationNet::EditUpdate(void)
  432. {
  433. }
  434. ////////////////////////////////////////////////////////////////////////////////
  435. // Called by editor to render object
  436. ////////////////////////////////////////////////////////////////////////////////
  437. void CNavigationNet::EditRender(void)
  438. {
  439. // No special flags
  440. m_sprite.m_sInFlags = 0;
  441. // Map from 3d to 2d coords
  442. Map3Dto2D(
  443. (short) m_dX,
  444. (short) m_dY,
  445. (short) m_dZ,
  446. &m_sprite.m_sX2,
  447. &m_sprite.m_sY2);
  448. // Priority is based on bottom edge of sprite
  449. m_sprite.m_sPriority = m_dZ;
  450. // Center on image.
  451. m_sprite.m_sX2 -= m_pImage->m_sWidth / 2;
  452. m_sprite.m_sY2 -= m_pImage->m_sHeight;
  453. // Layer should be based on info we get from attribute map.
  454. m_sprite.m_sLayer = CRealm::GetLayerViaAttrib(m_pRealm->GetLayer((short) m_dX, (short) m_dZ));
  455. // Image would normally animate, but doesn't for now
  456. m_sprite.m_pImage = m_pImage;
  457. // Update sprite in scene
  458. m_pRealm->m_scene.UpdateSprite(&m_sprite);
  459. }
  460. ////////////////////////////////////////////////////////////////////////////////
  461. // Give Edit a rectangle around this object
  462. ////////////////////////////////////////////////////////////////////////////////
  463. void CNavigationNet::EditRect(RRect* pRect)
  464. {
  465. Map3Dto2D(
  466. m_dX,
  467. m_dY,
  468. m_dZ,
  469. &(pRect->sX),
  470. &(pRect->sY) );
  471. pRect->sW = 10; // Safety.
  472. pRect->sH = 10; // Safety.
  473. if (m_pImage != NULL)
  474. {
  475. pRect->sW = m_pImage->m_sWidth;
  476. pRect->sH = m_pImage->m_sHeight;
  477. }
  478. pRect->sX -= pRect->sW / 2;
  479. pRect->sY -= pRect->sH;
  480. }
  481. ////////////////////////////////////////////////////////////////////////////////
  482. // Called by editor to get the hotspot of an object in 2D.
  483. ////////////////////////////////////////////////////////////////////////////////
  484. void CNavigationNet::EditHotSpot( // Returns nothiing.
  485. short* psX, // Out: X coord of 2D hotspot relative to
  486. // EditRect() pos.
  487. short* psY) // Out: Y coord of 2D hotspot relative to
  488. // EditRect() pos.
  489. {
  490. // Base of navnet is hotspot.
  491. *psX = (m_pImage->m_sWidth / 2);
  492. *psY = m_pImage->m_sHeight;
  493. }
  494. ////////////////////////////////////////////////////////////////////////////////
  495. // Get all required resources
  496. ////////////////////////////////////////////////////////////////////////////////
  497. short CNavigationNet::GetResources(void) // Returns 0 if successfull, non-zero otherwise
  498. {
  499. short sResult = 0;
  500. if (m_pImage == 0)
  501. {
  502. sResult = rspGetResource(&g_resmgrGame, m_pRealm->Make2dResPath(IMAGE_FILE), &m_pImage);
  503. if (sResult == 0)
  504. {
  505. // This is a questionable action on a resource managed item, but it's
  506. // okay if EVERYONE wants it to be an FSPR8.
  507. if (m_pImage->Convert(RImage::FSPR8) != RImage::FSPR8)
  508. {
  509. sResult = -1;
  510. TRACE("CNavigationNet::GetResource(): Couldn't convert to FSPR8!\n");
  511. }
  512. }
  513. }
  514. return sResult;
  515. }
  516. ////////////////////////////////////////////////////////////////////////////////
  517. // Free all resources
  518. ////////////////////////////////////////////////////////////////////////////////
  519. short CNavigationNet::FreeResources(void) // Returns 0 if successfull, non-zero otherwise
  520. {
  521. short sResult = 0;
  522. if (m_pImage != 0)
  523. {
  524. rspReleaseResource(&g_resmgrGame, &m_pImage);
  525. }
  526. return sResult;
  527. }
  528. ////////////////////////////////////////////////////////////////////////////////
  529. // AddBouy - Returns zero if there are no bouys left.
  530. ////////////////////////////////////////////////////////////////////////////////
  531. UCHAR CNavigationNet::AddBouy(CBouy* pBouy)
  532. {
  533. UCHAR ucID = 0;
  534. if (m_ucNextID < 254)
  535. {
  536. pBouy->m_ucID = m_ucNextID;
  537. pBouy->m_pParentNavNet = this;
  538. m_NodeMap.insert(nodeMap::value_type(m_ucNextID, pBouy));
  539. m_ucNextID++;
  540. ucID = pBouy->m_ucID;
  541. }
  542. return ucID;
  543. }
  544. ////////////////////////////////////////////////////////////////////////////////
  545. // RemoveBouy
  546. ////////////////////////////////////////////////////////////////////////////////
  547. void CNavigationNet::RemoveBouy(UCHAR ucBouyID)
  548. {
  549. m_NodeMap.erase(ucBouyID);
  550. UpdateRoutingTables();
  551. }
  552. ////////////////////////////////////////////////////////////////////////////////
  553. // GetBouy
  554. ////////////////////////////////////////////////////////////////////////////////
  555. CBouy* CNavigationNet::GetBouy(UCHAR ucBouyID)
  556. {
  557. CBouy* pBouy = NULL;
  558. nodeMap::iterator i;
  559. i = m_NodeMap.find(ucBouyID);
  560. if (i != m_NodeMap.end())
  561. pBouy = (*i).second;
  562. return pBouy;
  563. }
  564. ////////////////////////////////////////////////////////////////////////////////
  565. // FindNearestBouy - Go through the list and get the ID of the nearest
  566. // bouy to the given x, z position
  567. //
  568. // This has been modified to return the closest available
  569. // bouy - one that is not blocked by terrain.
  570. ////////////////////////////////////////////////////////////////////////////////
  571. UCHAR CNavigationNet::FindNearestBouy(short sX, short sZ)
  572. {
  573. nodeMap::iterator i;
  574. double dSqDist;
  575. double dX;
  576. double dZ;
  577. CBouy* pBouy;
  578. TreeListNode* pRoot = NULL;
  579. TreeListNode* pCurrent = NULL;
  580. UCHAR ucNode = 0;
  581. // Build the sorted list of bouys
  582. for (i = m_NodeMap.begin(); i != m_NodeMap.end(); i++)
  583. {
  584. pBouy = (CBouy*) (*i).second;
  585. dX = pBouy->m_dX - sX;
  586. dZ = pBouy->m_dZ - sZ;
  587. dSqDist = (dX * dX) + (dZ * dZ);
  588. pBouy->m_TreeNode.m_sortkey = dSqDist;
  589. pBouy->m_TreeNode.m_powner = pBouy;
  590. if (pRoot == NULL)
  591. {
  592. pRoot = &pBouy->m_TreeNode;
  593. //m_BouyTreeListHead.AddAfter(&pBouy->m_TreeNode);
  594. pBouy->m_TreeNode.AddAfter(&m_BouyTreeListHead);
  595. }
  596. else
  597. pRoot->Add(&pBouy->m_TreeNode);
  598. }
  599. pCurrent = m_BouyTreeListHead.m_pnNext;
  600. bool bSearching = true;
  601. // Get the height at the startling location for path checking
  602. short sY = m_pRealm->GetHeight(sX, sZ);
  603. // Go through the sorted list of bouys and check to see if you could
  604. // get to it from where you are standing. If not, check the next one.
  605. while (pCurrent && bSearching)
  606. {
  607. pBouy = pCurrent->m_powner;
  608. // ASSERT(pBouy != NULL);
  609. if (pBouy)
  610. {
  611. if (m_pRealm->IsPathClear(sX, sY, sZ, 4.0, (short) pBouy->GetX(), (short) pBouy->GetZ()))
  612. {
  613. ucNode = pBouy->m_ucID;
  614. bSearching = false;
  615. }
  616. else
  617. pCurrent = pCurrent->m_pnNext;
  618. }
  619. else
  620. pCurrent = pCurrent->m_pnNext;
  621. }
  622. // If we built a tree . . .
  623. if (pRoot)
  624. {
  625. // Get rid of the tree, its useless now
  626. pRoot->DeleteTree();
  627. }
  628. return ucNode;
  629. }
  630. #if 0
  631. UCHAR CNavigationNet::FindNearestBouy(short sX, short sZ)
  632. {
  633. nodeMap::iterator i;
  634. double dSqDist;
  635. double dMinDist = 1.0E+200;
  636. double dX;
  637. double dZ;
  638. CBouy* pBouy;
  639. UCHAR ucNode = 0;
  640. for (i = m_NodeMap.begin(); i != m_NodeMap.end(); i++)
  641. {
  642. pBouy = (CBouy*) (*i).second;
  643. dX = pBouy->m_dX - sX;
  644. dZ = pBouy->m_dZ - sZ;
  645. dSqDist = (dX * dX) + (dZ * dZ);
  646. if (dSqDist < dMinDist)
  647. {
  648. dMinDist = dSqDist;
  649. ucNode = (*i).first;
  650. }
  651. }
  652. return ucNode;
  653. }
  654. #endif
  655. ////////////////////////////////////////////////////////////////////////////////
  656. // UpdateRoutingTables - Ping all of the bouys from the list in this network
  657. // which will force them all to build up complete
  658. // routing tables
  659. ////////////////////////////////////////////////////////////////////////////////
  660. void CNavigationNet::UpdateRoutingTables(void)
  661. {
  662. nodeMap::iterator i;
  663. // orig
  664. for (i = m_NodeMap.begin(); i != m_NodeMap.end(); i++)
  665. ((*i).second)->BuildRoutingTable();
  666. #if 0
  667. char szLine[256];
  668. FILE* fp;
  669. fp = fopen("c:\\temp\\net.txt", "wt");
  670. if (fp != NULL)
  671. {
  672. for (i = m_NodeMap.begin(); i != m_NodeMap.end(); i++)
  673. {
  674. sprintf(szLine, "Node %d\n", ((*i).second)->m_ucID);
  675. fwrite(szLine, sizeof(char), strlen(szLine), fp);
  676. ((*i).second)->BuildRoutingTable();
  677. }
  678. fclose(fp);
  679. }
  680. else
  681. {
  682. TRACE("*********** Nav Net unable to open log file\n");
  683. }
  684. #endif
  685. // PrintRoutingTables();
  686. }
  687. void CNavigationNet::PrintRoutingTables(void)
  688. {
  689. nodeMap::iterator i;
  690. char szLine[256];
  691. FILE* fp;
  692. fp = fopen("c:\\temp\\links.txt", "wt");
  693. if (fp != NULL)
  694. {
  695. for (i = m_NodeMap.begin(); i != m_NodeMap.end(); i++)
  696. {
  697. sprintf(szLine, "\nNode %d\n----------------------\n", ((*i).second)->m_ucID);
  698. fwrite(szLine, sizeof(char), strlen(szLine), fp);
  699. ((*i).second)->PrintRouteTable(fp);
  700. // ((*i).second)->PrintDirectLinks(fp);
  701. }
  702. fclose(fp);
  703. }
  704. else
  705. {
  706. TRACE("*********** Nav Net unable to open log file\n");
  707. }
  708. }
  709. ////////////////////////////////////////////////////////////////////////////////
  710. // DeleteNetwork - Delte all bouys from this network
  711. ////////////////////////////////////////////////////////////////////////////////
  712. short CNavigationNet::DeleteNetwork(void)
  713. {
  714. short sReturn = SUCCESS;
  715. nodeMap::iterator i;
  716. for (i = m_NodeMap.begin(); i != m_NodeMap.end(); i++)
  717. {
  718. delete (*i).second;
  719. }
  720. m_NodeMap.erase(m_NodeMap.begin(), m_NodeMap.end());
  721. return sReturn;
  722. }
  723. ////////////////////////////////////////////////////////////////////////////////
  724. // EOF
  725. ////////////////////////////////////////////////////////////////////////////////