This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/wwphys/PathfindSector.cpp

379 lines
9.6 KiB
C++

/*
** 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 <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** 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;
}