diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 1e90e8db..d196e935 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -200,6 +200,16 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) { // If we are not on our clone do not allow us to claim the property if (propertyCloneId != playerCloneId) return false; + std::string name = zone->GetZoneName(); + std::string description = ""; + + auto prop_path = zone->GetPath(m_Parent->GetVarAsString(u"propertyName")); + + if (prop_path){ + if (!prop_path->property.displayName.empty()) name = prop_path->property.displayName; + description = prop_path->property.displayDesc; + } + SetOwnerId(playerId); propertyId = ObjectIDManager::GenerateRandomObjectID(); @@ -207,14 +217,15 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) { auto* insertion = Database::CreatePreppedStmt( "INSERT INTO properties" "(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id, performance_cost)" - "VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)" + "VALUES (?, ?, ?, ?, ?, ?, 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)" ); insertion->setUInt64(1, propertyId); insertion->setUInt64(2, (uint32_t)playerId); insertion->setUInt(3, templateId); insertion->setUInt64(4, playerCloneId); - insertion->setString(5, zone->GetZoneName().c_str()); - insertion->setInt(6, propertyZoneId); + insertion->setString(5, name.c_str()); + insertion->setString(6, description.c_str()); + insertion->setInt(7, propertyZoneId); // Try and execute the query, print an error if it fails. try { diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 655af84e..c05c0672 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -344,6 +344,11 @@ void Item::DisassembleModel() { std::string lxfmlPath = "BrickModels/" + GeneralUtils::SplitString(renderAssetSplit.back(), '.').at(0) + ".lxfml"; auto buffer = Game::assetManager->GetFileAsBuffer(lxfmlPath.c_str()); + if (!buffer.m_Success) { + Game::logger->Log("Item", "Failed to load %s to disassemble model into bricks, check that this file exists", lxfmlPath.c_str()); + return; + } + std::istream file(&buffer); result.finalize(); diff --git a/dGame/dUtilities/BrickDatabase.cpp b/dGame/dUtilities/BrickDatabase.cpp index c36a1097..6d1e380c 100644 --- a/dGame/dUtilities/BrickDatabase.cpp +++ b/dGame/dUtilities/BrickDatabase.cpp @@ -19,6 +19,11 @@ std::vector& BrickDatabase::GetBricks(const std::string& lxfmlPath) { } AssetMemoryBuffer buffer = Game::assetManager->GetFileAsBuffer((lxfmlPath).c_str()); + + if (!buffer.m_Success) { + return emptyCache; + } + std::istream file(&buffer); if (!file.good()) { return emptyCache; diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index e8f1659e..8f4ac1a8 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -584,6 +584,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (args[0].find("\\") != std::string::npos) return; auto buf = Game::assetManager->GetFileAsBuffer(("macros/" + args[0] + ".scm").c_str()); + + if (!buf.m_Success){ + ChatPackets::SendSystemMessage(sysAddr, u"Unknown macro! Is the filename right?"); + return; + } + std::istream infile(&buf); if (infile.good()) { diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 1fe47454..3a1127a4 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -42,6 +42,12 @@ void Zone::LoadZoneIntoMemory() { if (m_ZoneFilePath == "ERR") return; AssetMemoryBuffer buffer = Game::assetManager->GetFileAsBuffer(m_ZoneFilePath.c_str()); + + 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."); + } + std::istream file(&buffer); if (file) { BinaryIO::BinaryRead(file, m_ZoneFileFormatVersion); @@ -92,15 +98,12 @@ void Zone::LoadZoneIntoMemory() { if (m_ZoneFileFormatVersion >= Zone::ZoneFileFormatVersion::EarlyAlpha) { BinaryIO::BinaryRead(file, m_PathDataLength); - uint32_t unknown; - uint32_t pathCount; + BinaryIO::BinaryRead(file, m_PathChunkVersion); // always should be 1 - BinaryIO::BinaryRead(file, unknown); + uint32_t pathCount; BinaryIO::BinaryRead(file, pathCount); - for (uint32_t i = 0; i < pathCount; ++i) { - LoadPath(file); - } + for (uint32_t i = 0; i < pathCount; ++i) LoadPath(file); for (Path path : m_Paths) { if (path.pathType == PathType::Spawner) { @@ -230,7 +233,8 @@ void Zone::LoadScene(std::istream& file) { scene.filename = BinaryIO::ReadString(file, sceneFilenameLength); std::string luTriggersPath = scene.filename.substr(0, scene.filename.size() - 4) + ".lutriggers"; - std::vector triggers = LoadLUTriggers(luTriggersPath, scene.id); + std::vector triggers; + if(Game::assetManager->HasFile(luTriggersPath.c_str())) triggers = LoadLUTriggers(luTriggersPath, scene.id); for (LUTriggers::Trigger* trigger : triggers) { scene.triggers.insert({ trigger->id, trigger }); @@ -245,15 +249,6 @@ void Zone::LoadScene(std::istream& file) { scene.name = BinaryIO::ReadString(file, sceneNameLength); file.ignore(3); - /* - if (m_Scenes.find(scene.id) != m_Scenes.end()) { - //Extract the layer id from the filename (bad I know, but it's reliable at least): - std::string layer = scene.filename.substr(scene.filename.rfind('x') + 1); - layer = layer.substr(0, layer.find('_')); - lwoSceneID.SetLayerID(std::atoi(layer.c_str())); - } - */ - lwoSceneID.SetLayerID(scene.sceneType); m_Scenes.insert(std::make_pair(lwoSceneID, scene)); @@ -265,7 +260,10 @@ std::vector Zone::LoadLUTriggers(std::string triggerFile, auto buffer = Game::assetManager->GetFileAsBuffer((m_ZonePath + triggerFile).c_str()); - if (!buffer.m_Success) return lvlTriggers; + if (!buffer.m_Success) { + Game::logger->Log("Zone", "Failed to load %s from disk. Skipping loading triggers", (m_ZonePath + triggerFile).c_str()); + return lvlTriggers; + } std::istream file(&buffer); std::stringstream data; @@ -368,14 +366,10 @@ SceneTransitionInfo Zone::LoadSceneTransitionInfo(std::istream& file) { } void Zone::LoadPath(std::istream& file) { - // Currently only spawner (type 4) paths are supported Path path = Path(); - uint32_t unknown1; - uint32_t pathType; - uint32_t pathBehavior; - BinaryIO::BinaryRead(file, path.pathVersion); + uint8_t stringLength; BinaryIO::BinaryRead(file, stringLength); for (uint8_t i = 0; i < stringLength; ++i) { @@ -383,16 +377,14 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, character); path.pathName.push_back(character); } - BinaryIO::BinaryRead(file, pathType); - path.pathType = PathType(pathType); - BinaryIO::BinaryRead(file, unknown1); - BinaryIO::BinaryRead(file, pathBehavior); - path.pathType = PathType(pathType); + + BinaryIO::BinaryRead(file, path.pathType); + BinaryIO::BinaryRead(file, path.flags); + BinaryIO::BinaryRead(file, path.pathBehavior); if (path.pathType == PathType::MovingPlatform) { if (path.pathVersion >= 18) { - uint8_t unknown; - BinaryIO::BinaryRead(file, unknown); + BinaryIO::BinaryRead(file, path.movingPlatform.timeBasedMovement); } else if (path.pathVersion >= 13) { uint8_t count; BinaryIO::BinaryRead(file, count); @@ -403,10 +395,9 @@ void Zone::LoadPath(std::istream& file) { } } } else if (path.pathType == PathType::Property) { - int32_t unknown; - BinaryIO::BinaryRead(file, unknown); + BinaryIO::BinaryRead(file, path.property.pathType); BinaryIO::BinaryRead(file, path.property.price); - BinaryIO::BinaryRead(file, path.property.rentalTime); + BinaryIO::BinaryRead(file, path.property.rentalTimeUnit); BinaryIO::BinaryRead(file, path.property.associatedZone); if (path.pathVersion >= 5) { @@ -426,10 +417,7 @@ void Zone::LoadPath(std::istream& file) { } } - if (path.pathVersion >= 6) { - int32_t unknown1; - BinaryIO::BinaryRead(file, unknown1); - } + if (path.pathVersion >= 6) BinaryIO::BinaryRead(file, path.property.type); if (path.pathVersion >= 7) { BinaryIO::BinaryRead(file, path.property.cloneLimit); @@ -453,11 +441,10 @@ void Zone::LoadPath(std::istream& file) { path.camera.nextPath.push_back(character); } if (path.pathVersion >= 14) { - uint8_t unknown; - BinaryIO::BinaryRead(file, unknown); + BinaryIO::BinaryRead(file, path.camera.rotatePlayer); + } } else if (path.pathType == PathType::Spawner) { - //SpawnerPath* path = static_cast(path); // Convert to a spawner path BinaryIO::BinaryRead(file, path.spawner.spawnedLOT); BinaryIO::BinaryRead(file, path.spawner.respawnTime); BinaryIO::BinaryRead(file, path.spawner.maxToSpawn); @@ -478,7 +465,7 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, waypoint.position.z); - if (path.pathType == PathType::Spawner || path.pathType == PathType::MovingPlatform || path.pathType == PathType::Race) { + if (path.pathType == PathType::Spawner || path.pathType == PathType::MovingPlatform || path.pathType == PathType::Race || path.pathType == PathType::Camera || path.pathType == PathType::Rail) { BinaryIO::BinaryRead(file, waypoint.rotation.w); BinaryIO::BinaryRead(file, waypoint.rotation.x); BinaryIO::BinaryRead(file, waypoint.rotation.y); @@ -506,33 +493,17 @@ void Zone::LoadPath(std::istream& file) { } } } else if (path.pathType == PathType::Camera) { - float unknown; - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); BinaryIO::BinaryRead(file, waypoint.camera.time); - BinaryIO::BinaryRead(file, unknown); + BinaryIO::BinaryRead(file, waypoint.camera.fov); BinaryIO::BinaryRead(file, waypoint.camera.tension); BinaryIO::BinaryRead(file, waypoint.camera.continuity); BinaryIO::BinaryRead(file, waypoint.camera.bias); } else if (path.pathType == PathType::Race) { - uint8_t unknown; - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); - float unknown1; - BinaryIO::BinaryRead(file, unknown1); - BinaryIO::BinaryRead(file, unknown1); - BinaryIO::BinaryRead(file, unknown1); - } else if (path.pathType == PathType::Rail) { - float unknown; - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); - BinaryIO::BinaryRead(file, unknown); - if (path.pathVersion >= 17) { - BinaryIO::BinaryRead(file, unknown); - } + 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); } // object LDF configs @@ -556,8 +527,14 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, character); value.push_back(character); } - LDFBaseData* ldfConfig = LDFBaseData::DataFromString(parameter + "=" + value); - waypoint.config.push_back(ldfConfig); + + LDFBaseData* ldfConfig = nullptr; + if (path.pathType == PathType::Movement) { + ldfConfig = LDFBaseData::DataFromString(parameter + "=0:" + value); + } else { + ldfConfig = LDFBaseData::DataFromString(parameter + "=" + value); + } + if (ldfConfig) waypoint.config.push_back(ldfConfig); } } diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index f041b616..0e7ae5eb 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -59,16 +59,32 @@ struct MovingPlatformPathWaypoint { 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; + std::vector config; +}; + 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; }; @@ -89,6 +105,19 @@ enum class PathBehavior : uint32_t { 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 PropertyRentalTimeUnit : int32_t { Forever = 0, Seconds = 1, @@ -116,17 +145,19 @@ enum class PropertyAchievmentRequired : int32_t { struct MovingPlatformPath { std::string platformTravelSound; + uint8_t timeBasedMovement; }; struct PropertyPath { + PropertyPathType pathType; int32_t price; - int32_t rentalTime; + PropertyRentalTimeUnit rentalTimeUnit; uint64_t associatedZone; std::string displayName; std::string displayDesc; + PropertyType type; int32_t cloneLimit; float repMultiplier; - PropertyRentalTimeUnit rentalTimeUnit; PropertyAchievmentRequired achievementRequired; NiPoint3 playerZoneCoords; float maxBuildHeight; @@ -134,6 +165,7 @@ struct PropertyPath { struct CameraPath { std::string nextPath; + uint8_t rotatePlayer; }; struct SpawnerPath { @@ -150,6 +182,7 @@ struct Path { uint32_t pathVersion; PathType pathType; std::string pathName; + uint32_t flags; PathBehavior pathBehavior; uint32_t waypointCount; std::vector pathWaypoints; @@ -219,9 +252,11 @@ private: std::map m_Scenes; std::vector m_SceneTransitions; + uint32_t m_PathDataLength; - //std::vector m_PathData; //Binary path data - std::vector m_Paths; + uint32_t m_PathChunkVersion; + std::vector m_Paths; + std::map m_MapRevisions; //rhs is the revision! //private ("helper") functions: