/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** 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 *** *********************************************************************************************** * * * Project Name : LevelEdit * * * * $Archive:: /Commando/Code/wwphys/PathfindSector.cpp $* * * * Author:: Patrick Smith * * * * $Modtime:: 4/23/01 11:52a $* * * * $Revision:: 12 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "pathfindsector.h" #include "phys3.h" #include "boxrobj.h" #include "chunkio.h" #include "wwphysids.h" #include "pscene.h" #include "decophys.h" #include "pathfind.h" #include "waypath.h" #include "pathfindportal.h" /////////////////////////////////////////////////////////////////////////// // Save/Load stuff /////////////////////////////////////////////////////////////////////////// enum { CHUNKID_VARIABLES = 0x01060643, CHUNKID_WP_VARIABLES = 0x01030550, CHUNKID_WP_PARENT }; enum { VARID_BOUNDING_BOX = 1, VARID_PORTAL_ID, VARID_WAYPATH_ID = 1, }; //////////////////////////////////////////////////////////////////////////////////// // // ~PathfindSectorClass // //////////////////////////////////////////////////////////////////////////////////// PathfindSectorClass::~PathfindSectorClass (void) { Reset_Portal_List (); return ; } //////////////////////////////////////////////////////////////////////////////////// // // Reset_Portal_List // //////////////////////////////////////////////////////////////////////////////////// void PathfindSectorClass::Reset_Portal_List (void) { m_PortalList.Delete_All (); return ; } /////////////////////////////////////////////////////////////////////////// // // Save // /////////////////////////////////////////////////////////////////////////// bool PathfindSectorClass::Save (ChunkSaveClass &csave) { csave.Begin_Chunk (CHUNKID_VARIABLES); // // Write the bounding box out to the chunk // AABoxClass bounding_box = Get_Cull_Box (); WRITE_MICRO_CHUNK (csave, VARID_BOUNDING_BOX, bounding_box); // // Write the portal-id for each portal out to the chunk // for (int index = 0; index < m_PortalList.Count (); index ++) { int portal_id = m_PortalList[index]; if (portal_id < PathfindClass::TEMP_PORTAL_ID_START) { WRITE_MICRO_CHUNK (csave, VARID_PORTAL_ID, portal_id); } } csave.End_Chunk (); return true; } /////////////////////////////////////////////////////////////////////////// // // Load // /////////////////////////////////////////////////////////////////////////// bool PathfindSectorClass::Load (ChunkLoadClass &cload) { Reset_Portal_List (); // // Read all the chunks... // while (cload.Open_Chunk ()) { switch (cload.Cur_Chunk_ID ()) { case CHUNKID_VARIABLES: Load_Variables (cload); break; default: WWDEBUG_SAY (("Unknown chunk ID 0x%X\n", cload.Cur_Chunk_ID ())); break; } cload.Close_Chunk (); } return true; } /////////////////////////////////////////////////////////////////////////// // // Load_Variables // /////////////////////////////////////////////////////////////////////////// bool PathfindSectorClass::Load_Variables (ChunkLoadClass &cload) { AABoxClass bounding_box; PathfindSectorClass *old_ptr = NULL; // // Read all the micro chunks... // while (cload.Open_Micro_Chunk ()) { switch (cload.Cur_Micro_Chunk_ID ()) { READ_MICRO_CHUNK (cload, VARID_BOUNDING_BOX, bounding_box); case VARID_PORTAL_ID: { uint32 portal_id = 0; cload.Read (&portal_id, sizeof (portal_id)); if (portal_id < PathfindClass::TEMP_PORTAL_ID_START) { m_PortalList.Add (portal_id); } } break; default: WWDEBUG_SAY (("Unknown micro chunk ID 0x%X\n", cload.Cur_Micro_Chunk_ID ())); break; } cload.Close_Micro_Chunk (); } // // Register our old ptr so other objects can remap to us // if (old_ptr != NULL) { SaveLoadSystemClass::Register_Pointer (old_ptr, this); } Set_Bounding_Box (bounding_box); return true; } /////////////////////////////////////////////////////////////////////////// // // Peek_Portal // /////////////////////////////////////////////////////////////////////////// PathfindPortalClass * PathfindSectorClass::Peek_Portal (int index) { int portal_id = m_PortalList[index]; return PathfindClass::Get_Instance ()->Peek_Portal (portal_id); } /////////////////////////////////////////////////////////////////////////// // // Remove_Portal // /////////////////////////////////////////////////////////////////////////// void PathfindSectorClass::Remove_Portal (uint32 portal_id) { // // Loop over all the portals until we've found the one // we want to remove -- then remove it. // for (int index = 0; index < m_PortalList.Count (); index ++) { if (portal_id == m_PortalList[index]) { m_PortalList.Delete (index); break; } } return ; } /////////////////////////////////////////////////////////////////////////// // // Save // /////////////////////////////////////////////////////////////////////////// bool PathfindWaypathSectorClass::Save (ChunkSaveClass &csave) { csave.Begin_Chunk (CHUNKID_WP_PARENT); PathfindSectorClass::Save (csave); csave.End_Chunk (); csave.Begin_Chunk (CHUNKID_WP_VARIABLES); WRITE_MICRO_CHUNK (csave, VARID_WAYPATH_ID, WaypathID); csave.End_Chunk (); return true; } /////////////////////////////////////////////////////////////////////////// // // Load // /////////////////////////////////////////////////////////////////////////// bool PathfindWaypathSectorClass::Load (ChunkLoadClass &cload) { // // Read all the chunks... // while (cload.Open_Chunk ()) { switch (cload.Cur_Chunk_ID ()) { case CHUNKID_WP_PARENT: PathfindSectorClass::Load (cload); break; case CHUNKID_WP_VARIABLES: Load_Variables (cload); break; default: WWDEBUG_SAY (("Unknown chunk ID 0x%X\n", cload.Cur_Chunk_ID ())); break; } cload.Close_Chunk (); } return true; } /////////////////////////////////////////////////////////////////////////// // // Load_Variables // /////////////////////////////////////////////////////////////////////////// bool PathfindWaypathSectorClass::Load_Variables (ChunkLoadClass &cload) { // // Read all the micro chunks... // while (cload.Open_Micro_Chunk ()) { switch (cload.Cur_Micro_Chunk_ID ()) { READ_MICRO_CHUNK (cload, VARID_WAYPATH_ID, WaypathID); default: WWDEBUG_SAY (("Unknown micro chunk ID 0x%X\n", cload.Cur_Micro_Chunk_ID ())); break; } cload.Close_Micro_Chunk (); } return true; } /////////////////////////////////////////////////////////////////////////// // // Can_Access_Portal // /////////////////////////////////////////////////////////////////////////// bool PathfindWaypathSectorClass::Can_Access_Portal ( PathfindPortalClass *last_portal, PathfindPortalClass *test_portal ) { bool retval = false; // // Check to see if the base class requirements are met // if (PathfindSectorClass::Can_Access_Portal (last_portal, test_portal)) { // // Check to see if the waypath is one-way, if so we need to make sure // the portal we are testing is "ahead" of the portal // WaypathClass *waypath = PathfindClass::Get_Instance ()->Find_Waypath (WaypathID); if (waypath != NULL && waypath->Get_Flag (WaypathClass::FLAG_TWO_WAY) == false) { // // Check to see if the portal we entered is "ahead" of the portal // we are testing // for (int index = 0; index < m_PortalList.Count (); index ++) { if (m_PortalList[index] == last_portal->Get_ID ()) { retval = true; break; } else if (m_PortalList[index] == test_portal->Get_ID ()) { break; } } } else { // // On a two-way waypath, we don't care which direction the portal // is from the one we entered // retval = true; } } return retval; }