#pragma once #include "dZMCommon.h" #include "LDFFormat.h" #include "tinyxml2.h" #include #include #include namespace LUTriggers { struct Trigger; }; class Level; struct SceneRef { std::string filename; uint32_t id; uint32_t sceneType; //0 = general, 1 = audio? std::string name; NiPoint3 unknown1; float unknown2; uint8_t color_r; uint8_t color_g; uint8_t color_b; Level* level; std::map triggers; }; struct SceneTransitionInfo { uint64_t sceneID; //id of the scene being transitioned to. NiPoint3 position; }; struct SceneTransition { std::string name; std::vector points; float width; }; struct MovingPlatformPathWaypoint { uint8_t lockPlayer; float speed; float wait; std::string departSound; std::string arriveSound; }; struct CameraPathWaypoint { float time; float fov; float tension; float continuity; float bias; }; struct RacingPathWaypoint { uint8_t isResetNode; uint8_t isNonHorizontalCamera; float planeWidth; float planeHeight; float shortestDistanceToEnd; }; struct RailPathWaypoint { float speed; }; struct PathWaypoint { NiPoint3 position; NiQuaternion rotation; // not included in all, but it's more convenient here MovingPlatformPathWaypoint movingPlatform; CameraPathWaypoint camera; RacingPathWaypoint racing; RailPathWaypoint rail; std::vector config; }; enum class PathType : uint32_t { Movement = 0, MovingPlatform = 1, Property = 2, Camera = 3, Spawner = 4, Showcase = 5, Race = 6, Rail = 7 }; enum class PathBehavior : uint32_t { Loop = 0, Bounce = 1, Once = 2 }; enum class PropertyPathType : int32_t { Path = 0, EntireZone = 1, GenetatedRectangle = 2 }; enum class PropertyType : int32_t { Premiere = 0, Prize = 1, LUP = 2, Headspace = 3 }; enum class PropertyRentalPeriod : uint32_t { Forever = 0, Seconds = 1, Minutes = 2, Hours = 3, Days = 4, Weeks = 5, Months = 6, Years = 7 }; enum class PropertyAchievmentRequired : uint32_t { None = 0, Builder = 1, Craftsman = 2, SeniorBuilder = 3, JourneyMan = 4, MasterBuilder = 5, Architect = 6, SeniorArchitect = 7, MasterArchitect = 8, Visionary = 9, Exemplar = 10 }; struct MovingPlatformPath { std::string platformTravelSound; uint8_t timeBasedMovement; }; struct PropertyPath { PropertyPathType pathType; int32_t price; uint32_t rentalTime; uint64_t associatedZone; std::string displayName; std::string displayDesc; PropertyType type; uint32_t cloneLimit; float repMultiplier; PropertyRentalPeriod rentalPeriod; PropertyAchievmentRequired achievementRequired; NiPoint3 playerZoneCoords; float maxBuildHeight; }; struct CameraPath { std::string nextPath; uint8_t rotatePlayer; }; struct SpawnerPath { LOT spawnedLOT; uint32_t respawnTime; int32_t maxToSpawn; uint32_t amountMaintained; LWOOBJID spawnerObjID; uint8_t spawnerNetActive; }; struct Path { uint32_t pathVersion; PathType pathType; std::string pathName; uint32_t flags; PathBehavior pathBehavior; uint32_t waypointCount; std::vector pathWaypoints; SpawnerPath spawner; MovingPlatformPath movingPlatform; PropertyPath property; CameraPath camera; }; class Zone { public: enum class FileFormatVersion : uint32_t { //Times are guessed. PrePreAlpha = 30, PreAlpha = 32, LatePreAlpha = 33, EarlyAlpha = 35, Alpha = 36, LateAlpha = 37, Beta = 38, Launch = 39, Auramar = 40, Latest = 41 }; public: Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID); ~Zone(); void Initalize(); void LoadZoneIntoMemory(); std::string GetFilePathForZoneID(); uint32_t CalculateChecksum(); void LoadLevelsIntoMemory(); void AddRevision(LWOSCENEID sceneID, uint32_t revision); const LWOZONEID& GetZoneID() const { return m_ZoneID; } const uint32_t GetChecksum() const { return m_CheckSum; } const void PrintAllGameObjects(); LUTriggers::Trigger* GetTrigger(uint32_t sceneID, uint32_t triggerID); const Path* GetPath(std::string name) const; uint32_t GetWorldID() const { return m_WorldID; } [[nodiscard]] std::string GetZoneName() const { return m_ZoneName; } std::string GetZoneRawPath() const { return m_ZoneRawPath; } std::string GetZonePath() const { return m_ZonePath; } const NiPoint3& GetSpawnPos() const { return m_Spawnpoint; } const NiQuaternion& GetSpawnRot() const { return m_SpawnpointRotation; } void SetSpawnPos(const NiPoint3& pos) { m_Spawnpoint = pos; } void SetSpawnRot(const NiQuaternion& rot) { m_SpawnpointRotation = rot; } private: LWOZONEID m_ZoneID; std::string m_ZoneFilePath; uint32_t m_NumberOfScenesLoaded; uint32_t m_NumberOfObjectsLoaded; uint32_t m_NumberOfSceneTransitionsLoaded; FileFormatVersion m_FileFormatVersion; uint32_t m_CheckSum; uint32_t m_WorldID; //should be equal to the MapID NiPoint3 m_Spawnpoint; NiQuaternion m_SpawnpointRotation; uint32_t m_SceneCount; std::string m_ZonePath; //Path to the .luz's folder std::string m_ZoneName; //Name given to the zone by a level designer std::string m_ZoneDesc; //Description of the zone by a level designer std::string m_ZoneRawPath; //Path to the .raw file of this zone. std::map m_Scenes; std::vector m_SceneTransitions; uint32_t m_PathDataLength; uint32_t m_PathChunkVersion; std::vector m_Paths; std::map m_MapRevisions; //rhs is the revision! //private ("helper") functions: void LoadScene(std::istream& file); std::vector LoadLUTriggers(std::string triggerFile, LWOSCENEID sceneID); void LoadSceneTransition(std::istream& file); SceneTransitionInfo LoadSceneTransitionInfo(std::istream& file); void LoadPath(std::istream& file); };