2021-12-05 17:54:36 +00:00
# include "Zone.h"
# include "Level.h"
# include <fstream>
# include <sstream>
# include "Game.h"
# include "dLogger.h"
# include "GeneralUtils.h"
# include "BinaryIO.h"
2023-01-07 05:17:05 +00:00
# include "LUTriggers.h"
2021-12-05 17:54:36 +00:00
2022-11-01 18:21:26 +00:00
# include "AssetManager.h"
2021-12-05 17:54:36 +00:00
# include "CDClientManager.h"
# include "CDZoneTableTable.h"
# include "Spawner.h"
# include "dZoneManager.h"
2023-08-06 22:41:38 +00:00
# include "dpWorld.h"
2021-12-05 17:54:36 +00:00
2023-02-10 08:29:53 +00:00
# include "eTriggerCommandType.h"
# include "eTriggerEventType.h"
2023-08-10 02:37:36 +00:00
# include "eWaypointCommandType.h"
2023-02-10 08:29:53 +00:00
2021-12-05 17:54:36 +00:00
Zone : : Zone ( const LWOMAPID & mapID , const LWOINSTANCEID & instanceID , const LWOCLONEID & cloneID ) :
m_ZoneID ( mapID , instanceID , cloneID ) {
m_NumberOfScenesLoaded = 0 ;
m_NumberOfObjectsLoaded = 0 ;
m_NumberOfSceneTransitionsLoaded = 0 ;
m_CheckSum = 0 ;
m_WorldID = 0 ;
m_SceneCount = 0 ;
}
Zone : : ~ Zone ( ) {
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Zone " , " Destroying zone %i " , m_ZoneID . GetMapID ( ) ) ;
2021-12-05 17:54:36 +00:00
for ( std : : map < LWOSCENEID , SceneRef > : : iterator it = m_Scenes . begin ( ) ; it ! = m_Scenes . end ( ) ; + + it ) {
if ( it - > second . level ! = nullptr ) delete it - > second . level ;
}
}
void Zone : : Initalize ( ) {
LoadZoneIntoMemory ( ) ;
LoadLevelsIntoMemory ( ) ;
m_CheckSum = CalculateChecksum ( ) ;
}
void Zone : : LoadZoneIntoMemory ( ) {
m_ZoneFilePath = GetFilePathForZoneID ( ) ;
m_ZonePath = m_ZoneFilePath . substr ( 0 , m_ZoneFilePath . rfind ( ' / ' ) + 1 ) ;
if ( m_ZoneFilePath = = " ERR " ) return ;
2022-11-01 18:21:26 +00:00
AssetMemoryBuffer buffer = Game : : assetManager - > GetFileAsBuffer ( m_ZoneFilePath . c_str ( ) ) ;
2022-11-10 18:59:31 +00:00
if ( ! buffer . m_Success ) {
Game : : logger - > Log ( " Zone " , " Failed to load %s " , m_ZoneFilePath . c_str ( ) ) ;
throw std : : runtime_error ( " Aborting Zone loading due to no Zone File. " ) ;
}
2022-11-01 18:21:26 +00:00
std : : istream file ( & buffer ) ;
2021-12-05 17:54:36 +00:00
if ( file ) {
2023-08-10 21:35:12 +00:00
BinaryIO : : BinaryRead ( file , m_FileFormatVersion ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
uint32_t mapRevision = 0 ;
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : Alpha ) BinaryIO : : BinaryRead ( file , mapRevision ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , m_WorldID ) ;
2022-07-25 02:26:51 +00:00
if ( ( uint16_t ) m_WorldID ! = m_ZoneID . GetMapID ( ) ) Game : : logger - > Log ( " Zone " , " WorldID: %i doesn't match MapID %i! Is this intended? " , m_WorldID , m_ZoneID . GetMapID ( ) ) ;
2021-12-05 17:54:36 +00:00
AddRevision ( LWOSCENEID_INVALID , mapRevision ) ;
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : Beta ) {
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , m_Spawnpoint ) ;
BinaryIO : : BinaryRead ( file , m_SpawnpointRotation ) ;
}
2022-07-25 02:26:51 +00:00
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion < = Zone : : FileFormatVersion : : LateAlpha ) {
2021-12-05 17:54:36 +00:00
uint8_t sceneCount ;
BinaryIO : : BinaryRead ( file , sceneCount ) ;
m_SceneCount = sceneCount ;
} else BinaryIO : : BinaryRead ( file , m_SceneCount ) ;
for ( uint32_t i = 0 ; i < m_SceneCount ; + + i ) {
LoadScene ( file ) ;
}
//Read generic zone info:
uint8_t stringLength ;
BinaryIO : : BinaryRead ( file , stringLength ) ;
m_ZonePath = BinaryIO : : ReadString ( file , stringLength ) ;
BinaryIO : : BinaryRead ( file , stringLength ) ;
m_ZoneRawPath = BinaryIO : : ReadString ( file , stringLength ) ;
BinaryIO : : BinaryRead ( file , stringLength ) ;
m_ZoneName = BinaryIO : : ReadString ( file , stringLength ) ;
BinaryIO : : BinaryRead ( file , stringLength ) ;
m_ZoneDesc = BinaryIO : : ReadString ( file , stringLength ) ;
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : PreAlpha ) {
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , m_NumberOfSceneTransitionsLoaded ) ;
for ( uint32_t i = 0 ; i < m_NumberOfSceneTransitionsLoaded ; + + i ) {
LoadSceneTransition ( file ) ;
}
}
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : EarlyAlpha ) {
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , m_PathDataLength ) ;
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , m_PathChunkVersion ) ; // always should be 1
2021-12-05 17:54:36 +00:00
2022-11-12 14:44:03 +00:00
uint32_t pathCount ;
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , pathCount ) ;
2022-11-12 14:44:03 +00:00
for ( uint32_t i = 0 ; i < pathCount ; + + i ) LoadPath ( file ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
for ( Path path : m_Paths ) {
if ( path . pathType = = PathType : : Spawner ) {
SpawnerInfo info = SpawnerInfo ( ) ;
for ( PathWaypoint waypoint : path . pathWaypoints ) {
SpawnerNode * node = new SpawnerNode ( ) ;
node - > position = waypoint . position ;
node - > rotation = waypoint . rotation ;
node - > nodeID = 0 ;
node - > config = waypoint . config ;
for ( LDFBaseData * data : waypoint . config ) {
if ( data ) {
if ( data - > GetKey ( ) = = u " spawner_node_id " ) {
node - > nodeID = std : : stoi ( data - > GetValueAsString ( ) ) ;
} else if ( data - > GetKey ( ) = = u " spawner_max_per_node " ) {
node - > nodeMax = std : : stoi ( data - > GetValueAsString ( ) ) ;
} else if ( data - > GetKey ( ) = = u " groupID " ) { // Load object group
std : : string groupStr = data - > GetValueAsString ( ) ;
info . groups = GeneralUtils : : SplitString ( groupStr , ' ; ' ) ;
info . groups . erase ( info . groups . end ( ) - 1 ) ;
} else if ( data - > GetKey ( ) = = u " grpNameQBShowBricks " ) {
if ( data - > GetValueAsString ( ) = = " " ) continue ;
/*std::string groupStr = data->GetValueAsString();
info . groups . push_back ( groupStr ) ; */
info . grpNameQBShowBricks = data - > GetValueAsString ( ) ;
} else if ( data - > GetKey ( ) = = u " spawner_name " ) {
info . name = data - > GetValueAsString ( ) ;
}
}
}
info . nodes . push_back ( node ) ;
}
info . templateID = path . spawner . spawnedLOT ;
info . spawnerID = path . spawner . spawnerObjID ;
info . respawnTime = path . spawner . respawnTime ;
info . amountMaintained = path . spawner . amountMaintained ;
info . maxToSpawn = path . spawner . maxToSpawn ;
info . activeOnLoad = path . spawner . spawnerNetActive ;
info . isNetwork = true ;
Spawner * spawner = new Spawner ( info ) ;
2023-07-17 22:55:33 +00:00
Game : : zoneManager - > AddSpawner ( info . spawnerID , spawner ) ;
2021-12-05 17:54:36 +00:00
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
}
}
} else {
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Zone " , " Failed to open: %s " , m_ZoneFilePath . c_str ( ) ) ;
2021-12-05 17:54:36 +00:00
}
m_ZonePath = m_ZoneFilePath . substr ( 0 , m_ZoneFilePath . rfind ( ' / ' ) + 1 ) ;
2022-11-01 18:21:26 +00:00
buffer . close ( ) ;
2021-12-05 17:54:36 +00:00
}
std : : string Zone : : GetFilePathForZoneID ( ) {
//We're gonna go ahead and presume we've got the db loaded already:
2023-03-17 14:36:21 +00:00
CDZoneTableTable * zoneTable = CDClientManager : : Instance ( ) . GetTable < CDZoneTableTable > ( ) ;
2021-12-05 17:54:36 +00:00
const CDZoneTable * zone = zoneTable - > Query ( this - > GetZoneID ( ) . GetMapID ( ) ) ;
if ( zone ! = nullptr ) {
2022-11-01 18:21:26 +00:00
std : : string toReturn = " maps/ " + zone - > zoneName ;
2021-12-07 08:25:19 +00:00
std : : transform ( toReturn . begin ( ) , toReturn . end ( ) , toReturn . begin ( ) , : : tolower ) ;
2021-12-05 17:54:36 +00:00
return toReturn ;
}
return std : : string ( " ERR " ) ;
}
//Based off code from: https://www.liquisearch.com/fletchers_checksum/implementation/optimizations
uint32_t Zone : : CalculateChecksum ( ) {
uint32_t sum1 = 0xffff , sum2 = 0xffff ;
for ( std : : map < LWOSCENEID , uint32_t > : : const_iterator it = m_MapRevisions . cbegin ( ) ; it ! = m_MapRevisions . cend ( ) ; + + it ) {
uint32_t sceneID = it - > first . GetSceneID ( ) ;
sum2 + = sum1 + = ( sceneID > > 16 ) ;
sum2 + = sum1 + = ( sceneID & 0xffff ) ;
uint32_t layerID = it - > first . GetLayerID ( ) ;
sum2 + = sum1 + = ( layerID > > 16 ) ;
sum2 + = sum1 + = ( layerID & 0xffff ) ;
uint32_t revision = it - > second ;
sum2 + = sum1 + = ( revision > > 16 ) ;
sum2 + = sum1 + = ( revision & 0xffff ) ;
}
sum1 = ( sum1 & 0xffff ) + ( sum1 > > 16 ) ;
sum2 = ( sum2 & 0xffff ) + ( sum2 > > 16 ) ;
return sum2 < < 16 | sum1 ;
}
void Zone : : LoadLevelsIntoMemory ( ) {
for ( std : : map < LWOSCENEID , SceneRef > : : iterator it = m_Scenes . begin ( ) ; it ! = m_Scenes . end ( ) ; + + it ) {
if ( it - > second . level = = nullptr ) {
it - > second . level = new Level ( this , m_ZonePath + it - > second . filename ) ;
if ( it - > second . level - > m_ChunkHeaders . size ( ) > 0 ) {
it - > second . level - > m_ChunkHeaders . begin ( ) - > second . lwoSceneID = it - > first ;
AddRevision ( it - > second . level - > m_ChunkHeaders . begin ( ) - > second . lwoSceneID , it - > second . level - > m_ChunkHeaders . begin ( ) - > second . fileInfo - > revision ) ;
}
}
}
}
void Zone : : AddRevision ( LWOSCENEID sceneID , uint32_t revision ) {
for ( std : : pair < LWOSCENEID , uint32_t > item : m_MapRevisions ) {
if ( item . first = = sceneID ) return ;
}
m_MapRevisions [ LWOSCENEID ( sceneID ) ] = revision ;
}
const void Zone : : PrintAllGameObjects ( ) {
for ( std : : pair < LWOSCENEID , SceneRef > scene : m_Scenes ) {
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Zone " , " In sceneID: %i " , scene . first . GetSceneID ( ) ) ;
2021-12-05 17:54:36 +00:00
scene . second . level - > PrintAllObjects ( ) ;
}
}
2022-11-01 18:21:26 +00:00
void Zone : : LoadScene ( std : : istream & file ) {
2021-12-05 17:54:36 +00:00
SceneRef scene ;
scene . level = nullptr ;
LWOSCENEID lwoSceneID ( LWOZONEID_INVALID , 0 ) ;
uint8_t sceneFilenameLength ;
BinaryIO : : BinaryRead ( file , sceneFilenameLength ) ;
scene . filename = BinaryIO : : ReadString ( file , sceneFilenameLength ) ;
std : : string luTriggersPath = scene . filename . substr ( 0 , scene . filename . size ( ) - 4 ) + " .lutriggers " ;
2022-11-12 14:44:37 +00:00
std : : vector < LUTriggers : : Trigger * > triggers ;
2022-11-14 18:55:40 +00:00
if ( Game : : assetManager - > HasFile ( ( m_ZonePath + luTriggersPath ) . c_str ( ) ) ) triggers = LoadLUTriggers ( luTriggersPath , scene . id ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
for ( LUTriggers : : Trigger * trigger : triggers ) {
scene . triggers . insert ( { trigger - > id , trigger } ) ;
}
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : LatePreAlpha | | m_FileFormatVersion < Zone : : FileFormatVersion : : PrePreAlpha ) {
BinaryIO : : BinaryRead ( file , scene . id ) ;
lwoSceneID . SetSceneID ( scene . id ) ;
}
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : LatePreAlpha ) {
BinaryIO : : BinaryRead ( file , scene . sceneType ) ;
lwoSceneID . SetLayerID ( scene . sceneType ) ;
2021-12-05 17:54:36 +00:00
2023-08-10 21:35:12 +00:00
uint8_t sceneNameLength ;
BinaryIO : : BinaryRead ( file , sceneNameLength ) ;
scene . name = BinaryIO : : ReadString ( file , sceneNameLength ) ;
}
2021-12-05 17:54:36 +00:00
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion = = Zone : : FileFormatVersion : : LatePreAlpha ) {
BinaryIO : : BinaryRead ( file , scene . unknown1 ) ;
BinaryIO : : BinaryRead ( file , scene . unknown2 ) ;
}
if ( m_FileFormatVersion > = Zone : : FileFormatVersion : : LatePreAlpha ) {
BinaryIO : : BinaryRead ( file , scene . color_r ) ;
BinaryIO : : BinaryRead ( file , scene . color_b ) ;
BinaryIO : : BinaryRead ( file , scene . color_g ) ;
}
2021-12-05 17:54:36 +00:00
m_Scenes . insert ( std : : make_pair ( lwoSceneID , scene ) ) ;
m_NumberOfScenesLoaded + + ;
}
std : : vector < LUTriggers : : Trigger * > Zone : : LoadLUTriggers ( std : : string triggerFile , LWOSCENEID sceneID ) {
std : : vector < LUTriggers : : Trigger * > lvlTriggers ;
2022-11-01 18:21:26 +00:00
auto buffer = Game : : assetManager - > GetFileAsBuffer ( ( m_ZonePath + triggerFile ) . c_str ( ) ) ;
2022-11-10 18:59:31 +00:00
if ( ! buffer . m_Success ) {
Game : : logger - > Log ( " Zone " , " Failed to load %s from disk. Skipping loading triggers " , ( m_ZonePath + triggerFile ) . c_str ( ) ) ;
return lvlTriggers ;
}
2022-11-01 18:21:26 +00:00
std : : istream file ( & buffer ) ;
2021-12-05 17:54:36 +00:00
std : : stringstream data ;
data < < file . rdbuf ( ) ;
2022-11-01 18:21:26 +00:00
buffer . close ( ) ;
2021-12-05 17:54:36 +00:00
if ( data . str ( ) . size ( ) = = 0 ) return lvlTriggers ;
tinyxml2 : : XMLDocument * doc = new tinyxml2 : : XMLDocument ( ) ;
if ( ! doc ) return lvlTriggers ;
if ( doc - > Parse ( data . str ( ) . c_str ( ) , data . str ( ) . size ( ) ) = = 0 ) {
2022-07-25 02:26:51 +00:00
//Game::logger->Log("Zone", "Loaded LUTriggers from file %s!", triggerFile.c_str());
2021-12-05 17:54:36 +00:00
} else {
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " Zone " , " Failed to load LUTriggers from file %s " , triggerFile . c_str ( ) ) ;
2021-12-05 17:54:36 +00:00
return lvlTriggers ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
tinyxml2 : : XMLElement * triggers = doc - > FirstChildElement ( " triggers " ) ;
if ( ! triggers ) return lvlTriggers ;
auto currentTrigger = triggers - > FirstChildElement ( " trigger " ) ;
while ( currentTrigger ) {
LUTriggers : : Trigger * newTrigger = new LUTriggers : : Trigger ( ) ;
currentTrigger - > QueryAttribute ( " enabled " , & newTrigger - > enabled ) ;
currentTrigger - > QueryAttribute ( " id " , & newTrigger - > id ) ;
auto currentEvent = currentTrigger - > FirstChildElement ( " event " ) ;
while ( currentEvent ) {
LUTriggers : : Event * newEvent = new LUTriggers : : Event ( ) ;
2023-02-10 08:29:53 +00:00
newEvent - > id = TriggerEventType : : StringToTriggerEventType ( currentEvent - > Attribute ( " id " ) ) ;
2021-12-05 17:54:36 +00:00
auto currentCommand = currentEvent - > FirstChildElement ( " command " ) ;
while ( currentCommand ) {
LUTriggers : : Command * newCommand = new LUTriggers : : Command ( ) ;
2023-02-10 08:29:53 +00:00
newCommand - > id = TriggerCommandType : : StringToTriggerCommandType ( currentCommand - > Attribute ( " id " ) ) ;
2021-12-05 17:54:36 +00:00
newCommand - > target = currentCommand - > Attribute ( " target " ) ;
if ( currentCommand - > Attribute ( " targetName " ) ! = NULL ) {
newCommand - > targetName = currentCommand - > Attribute ( " targetName " ) ;
}
if ( currentCommand - > Attribute ( " args " ) ! = NULL ) {
newCommand - > args = currentCommand - > Attribute ( " args " ) ;
}
newEvent - > commands . push_back ( newCommand ) ;
currentCommand = currentCommand - > NextSiblingElement ( " command " ) ;
}
newTrigger - > events . push_back ( newEvent ) ;
currentEvent = currentEvent - > NextSiblingElement ( " event " ) ;
}
currentTrigger = currentTrigger - > NextSiblingElement ( " trigger " ) ;
lvlTriggers . push_back ( newTrigger ) ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
delete doc ;
return lvlTriggers ;
}
LUTriggers : : Trigger * Zone : : GetTrigger ( uint32_t sceneID , uint32_t triggerID ) {
if ( m_Scenes . find ( sceneID ) = = m_Scenes . end ( ) ) return nullptr ;
if ( m_Scenes [ sceneID ] . triggers . find ( triggerID ) = = m_Scenes [ sceneID ] . triggers . end ( ) ) return nullptr ;
return m_Scenes [ sceneID ] . triggers [ triggerID ] ;
}
const Path * Zone : : GetPath ( std : : string name ) const {
for ( const auto & path : m_Paths ) {
if ( name = = path . pathName ) {
return & path ;
}
}
return nullptr ;
}
2022-11-01 18:21:26 +00:00
void Zone : : LoadSceneTransition ( std : : istream & file ) {
2021-12-05 17:54:36 +00:00
SceneTransition sceneTrans ;
2023-08-10 21:35:12 +00:00
if ( m_FileFormatVersion < Zone : : FileFormatVersion : : Auramar ) {
2021-12-05 17:54:36 +00:00
uint8_t length ;
BinaryIO : : BinaryRead ( file , length ) ;
sceneTrans . name = BinaryIO : : ReadString ( file , length ) ;
2023-07-31 06:49:43 +00:00
BinaryIO : : BinaryRead ( file , sceneTrans . width ) ;
2021-12-05 17:54:36 +00:00
}
//BR<42> THER MAY I HAVE SOME L<> <4C> PS?
2023-08-10 21:35:12 +00:00
uint8_t loops = ( m_FileFormatVersion < = Zone : : FileFormatVersion : : LatePreAlpha | | m_FileFormatVersion > = Zone : : FileFormatVersion : : Launch ) ? 2 : 5 ;
2021-12-05 17:54:36 +00:00
for ( uint8_t i = 0 ; i < loops ; + + i ) {
sceneTrans . points . push_back ( LoadSceneTransitionInfo ( file ) ) ;
}
m_SceneTransitions . push_back ( sceneTrans ) ;
}
2022-11-01 18:21:26 +00:00
SceneTransitionInfo Zone : : LoadSceneTransitionInfo ( std : : istream & file ) {
2021-12-05 17:54:36 +00:00
SceneTransitionInfo info ;
BinaryIO : : BinaryRead ( file , info . sceneID ) ;
BinaryIO : : BinaryRead ( file , info . position ) ;
return info ;
}
2022-11-01 18:21:26 +00:00
void Zone : : LoadPath ( std : : istream & file ) {
2021-12-05 17:54:36 +00:00
Path path = Path ( ) ;
BinaryIO : : BinaryRead ( file , path . pathVersion ) ;
2022-11-12 14:44:03 +00:00
2021-12-05 17:54:36 +00:00
uint8_t stringLength ;
BinaryIO : : BinaryRead ( file , stringLength ) ;
for ( uint8_t i = 0 ; i < stringLength ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
path . pathName . push_back ( character ) ;
}
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , path . pathType ) ;
BinaryIO : : BinaryRead ( file , path . flags ) ;
BinaryIO : : BinaryRead ( file , path . pathBehavior ) ;
2021-12-05 17:54:36 +00:00
if ( path . pathType = = PathType : : MovingPlatform ) {
if ( path . pathVersion > = 18 ) {
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , path . movingPlatform . timeBasedMovement ) ;
2021-12-05 17:54:36 +00:00
} else if ( path . pathVersion > = 13 ) {
uint8_t count ;
BinaryIO : : BinaryRead ( file , count ) ;
for ( uint8_t i = 0 ; i < count ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
path . movingPlatform . platformTravelSound . push_back ( character ) ;
}
}
} else if ( path . pathType = = PathType : : Property ) {
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , path . property . pathType ) ;
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , path . property . price ) ;
2023-08-10 21:35:12 +00:00
BinaryIO : : BinaryRead ( file , path . property . rentalTime ) ;
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , path . property . associatedZone ) ;
2022-10-24 05:54:21 +00:00
if ( path . pathVersion > = 5 ) {
uint8_t count1 ;
BinaryIO : : BinaryRead ( file , count1 ) ;
for ( uint8_t i = 0 ; i < count1 ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
path . property . displayName . push_back ( character ) ;
}
uint32_t count2 ;
BinaryIO : : BinaryRead ( file , count2 ) ;
for ( uint8_t i = 0 ; i < count2 ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
path . property . displayDesc . push_back ( character ) ;
}
2021-12-05 17:54:36 +00:00
}
2022-10-24 05:54:21 +00:00
2022-11-12 14:44:03 +00:00
if ( path . pathVersion > = 6 ) BinaryIO : : BinaryRead ( file , path . property . type ) ;
2022-10-24 05:54:21 +00:00
if ( path . pathVersion > = 7 ) {
BinaryIO : : BinaryRead ( file , path . property . cloneLimit ) ;
BinaryIO : : BinaryRead ( file , path . property . repMultiplier ) ;
2023-08-10 21:35:12 +00:00
BinaryIO : : BinaryRead ( file , path . property . rentalPeriod ) ;
2022-10-24 05:54:21 +00:00
}
if ( path . pathVersion > = 8 ) {
BinaryIO : : BinaryRead ( file , path . property . achievementRequired ) ;
2023-08-10 21:35:12 +00:00
BinaryIO : : BinaryRead ( file , path . property . playerZoneCoords ) ;
2022-10-24 05:54:21 +00:00
BinaryIO : : BinaryRead ( file , path . property . maxBuildHeight ) ;
2021-12-05 17:54:36 +00:00
}
} else if ( path . pathType = = PathType : : Camera ) {
uint8_t count ;
BinaryIO : : BinaryRead ( file , count ) ;
for ( uint8_t i = 0 ; i < count ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
path . camera . nextPath . push_back ( character ) ;
}
if ( path . pathVersion > = 14 ) {
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , path . camera . rotatePlayer ) ;
2021-12-05 17:54:36 +00:00
}
} else if ( path . pathType = = PathType : : Spawner ) {
BinaryIO : : BinaryRead ( file , path . spawner . spawnedLOT ) ;
BinaryIO : : BinaryRead ( file , path . spawner . respawnTime ) ;
BinaryIO : : BinaryRead ( file , path . spawner . maxToSpawn ) ;
BinaryIO : : BinaryRead ( file , path . spawner . amountMaintained ) ;
BinaryIO : : BinaryRead ( file , path . spawner . spawnerObjID ) ;
BinaryIO : : BinaryRead ( file , path . spawner . spawnerNetActive ) ;
}
// Read waypoints
BinaryIO : : BinaryRead ( file , path . waypointCount ) ;
for ( uint32_t i = 0 ; i < path . waypointCount ; + + i ) {
PathWaypoint waypoint = PathWaypoint ( ) ;
BinaryIO : : BinaryRead ( file , waypoint . position . x ) ;
BinaryIO : : BinaryRead ( file , waypoint . position . y ) ;
BinaryIO : : BinaryRead ( file , waypoint . position . z ) ;
2022-07-25 02:26:51 +00:00
2022-11-12 14:44:03 +00:00
if ( path . pathType = = PathType : : Spawner | | path . pathType = = PathType : : MovingPlatform | | path . pathType = = PathType : : Race | | path . pathType = = PathType : : Camera | | path . pathType = = PathType : : Rail ) {
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , waypoint . rotation . w ) ;
BinaryIO : : BinaryRead ( file , waypoint . rotation . x ) ;
BinaryIO : : BinaryRead ( file , waypoint . rotation . y ) ;
BinaryIO : : BinaryRead ( file , waypoint . rotation . z ) ;
}
if ( path . pathType = = PathType : : MovingPlatform ) {
BinaryIO : : BinaryRead ( file , waypoint . movingPlatform . lockPlayer ) ;
2023-08-21 19:33:13 +00:00
BinaryIO : : BinaryRead ( file , waypoint . speed ) ;
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , waypoint . movingPlatform . wait ) ;
if ( path . pathVersion > = 13 ) {
uint8_t count1 ;
BinaryIO : : BinaryRead ( file , count1 ) ;
for ( uint8_t i = 0 ; i < count1 ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
waypoint . movingPlatform . departSound . push_back ( character ) ;
}
uint8_t count2 ;
BinaryIO : : BinaryRead ( file , count2 ) ;
for ( uint8_t i = 0 ; i < count2 ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
waypoint . movingPlatform . arriveSound . push_back ( character ) ;
}
}
} else if ( path . pathType = = PathType : : Camera ) {
BinaryIO : : BinaryRead ( file , waypoint . camera . time ) ;
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , waypoint . camera . fov ) ;
2021-12-05 17:54:36 +00:00
BinaryIO : : BinaryRead ( file , waypoint . camera . tension ) ;
BinaryIO : : BinaryRead ( file , waypoint . camera . continuity ) ;
BinaryIO : : BinaryRead ( file , waypoint . camera . bias ) ;
} else if ( path . pathType = = PathType : : Race ) {
2022-11-12 14:44:03 +00:00
BinaryIO : : BinaryRead ( file , waypoint . racing . isResetNode ) ;
BinaryIO : : BinaryRead ( file , waypoint . racing . isNonHorizontalCamera ) ;
BinaryIO : : BinaryRead ( file , waypoint . racing . planeWidth ) ;
BinaryIO : : BinaryRead ( file , waypoint . racing . planeHeight ) ;
BinaryIO : : BinaryRead ( file , waypoint . racing . shortestDistanceToEnd ) ;
2022-11-14 19:57:49 +00:00
} else if ( path . pathType = = PathType : : Rail ) {
2023-08-21 19:33:13 +00:00
if ( path . pathVersion > 16 ) BinaryIO : : BinaryRead ( file , waypoint . speed ) ;
2021-12-05 17:54:36 +00:00
}
// object LDF configs
if ( path . pathType = = PathType : : Movement | | path . pathType = = PathType : : Spawner | | path . pathType = = PathType : : Rail ) {
uint32_t count ;
BinaryIO : : BinaryRead ( file , count ) ;
for ( uint32_t i = 0 ; i < count ; + + i ) {
uint8_t count1 ;
std : : string parameter ;
std : : string value ;
BinaryIO : : BinaryRead ( file , count1 ) ;
for ( uint8_t i = 0 ; i < count1 ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
parameter . push_back ( character ) ;
}
uint8_t count2 ;
BinaryIO : : BinaryRead ( file , count2 ) ;
for ( uint8_t i = 0 ; i < count2 ; + + i ) {
uint16_t character ;
BinaryIO : : BinaryRead ( file , character ) ;
value . push_back ( character ) ;
}
2022-11-12 14:44:03 +00:00
LDFBaseData * ldfConfig = nullptr ;
2022-11-14 19:57:49 +00:00
if ( path . pathType = = PathType : : Movement | | path . pathType = = PathType : : Rail ) {
2023-08-16 20:53:13 +00:00
// cause NetDevil puts spaces in things that don't need spaces
2023-08-20 05:13:01 +00:00
parameter . erase ( std : : remove_if ( parameter . begin ( ) , parameter . end ( ) , : : isspace ) , parameter . end ( ) ) ;
2023-08-16 20:53:13 +00:00
auto waypointCommand = WaypointCommandType : : StringToWaypointCommandType ( parameter ) ;
2023-08-20 05:13:01 +00:00
if ( waypointCommand = = eWaypointCommandType : : DELAY ) value . erase ( std : : remove_if ( value . begin ( ) , value . end ( ) , : : isspace ) , value . end ( ) ) ;
if ( waypointCommand ! = eWaypointCommandType : : INVALID ) waypoint . commands . push_back ( WaypointCommand ( waypointCommand , value ) ) ;
2023-08-16 20:53:13 +00:00
else Game : : logger - > Log ( " Zone " , " Tried to load invalid waypoint command '%s' " , parameter . c_str ( ) ) ;
2022-11-12 14:44:03 +00:00
} else {
ldfConfig = LDFBaseData : : DataFromString ( parameter + " = " + value ) ;
2023-08-10 02:37:36 +00:00
if ( ldfConfig ) waypoint . config . push_back ( ldfConfig ) ;
2022-11-12 14:44:03 +00:00
}
2021-12-05 17:54:36 +00:00
}
}
2023-08-06 22:41:38 +00:00
// We verify the waypoint heights against the navmesh because in many movement paths,
2023-08-10 02:37:36 +00:00
// the waypoint is located near 0 height,
2023-08-06 22:41:38 +00:00
if ( path . pathType = = PathType : : Movement ) {
if ( dpWorld : : Instance ( ) . IsLoaded ( ) ) {
2023-08-06 23:06:12 +00:00
// 2000 should be large enough for every world.
waypoint . position . y = dpWorld : : Instance ( ) . GetNavMesh ( ) - > GetHeightAtPoint ( waypoint . position , 2000.0f ) ;
2023-08-06 22:41:38 +00:00
}
}
2021-12-05 17:54:36 +00:00
path . pathWaypoints . push_back ( waypoint ) ;
}
m_Paths . push_back ( path ) ;
}