Merge branch 'main' into npc-pathing

This commit is contained in:
Aaron Kimbre
2023-04-10 22:19:41 -05:00
612 changed files with 12044 additions and 7169 deletions

33
dZoneManager/LUTriggers.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef __LUTRIGGERS__H__
#define __LUTRIGGERS__H__
#include <string>
#include <vector>
class Command;
class Event;
enum class eTriggerCommandType;
enum class eTriggerEventType;
namespace LUTriggers {
struct Command {
eTriggerCommandType id;
std::string target;
std::string targetName;
std::string args;
};
struct Event {
eTriggerEventType id;
std::vector<Command*> commands;
};
struct Trigger {
uint32_t id;
bool enabled;
std::vector<Event*> events;
};
};
#endif //!__LUTRIGGERS__H__

View File

@@ -162,7 +162,7 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
uint32_t objectsCount = 0;
BinaryIO::BinaryRead(file, objectsCount);
CDFeatureGatingTable* featureGatingTable = CDClientManager::Instance()->GetTable<CDFeatureGatingTable>("FeatureGating");
CDFeatureGatingTable* featureGatingTable = CDClientManager::Instance().GetTable<CDFeatureGatingTable>();
for (uint32_t i = 0; i < objectsCount; ++i) {
SceneObject obj;

View File

@@ -134,24 +134,23 @@ void Spawner::AddEntitySpawnedCallback(std::function<void(Entity*)> callback) {
void Spawner::Reset() {
m_Start = true;
for (auto* node : m_Info.nodes) {
for (const auto& spawned : node->entities) {
auto* entity = EntityManager::Instance()->GetEntity(spawned);
if (entity == nullptr) continue;
entity->Kill();
}
node->entities.clear();
}
DestroyAllEntities();
m_Entities.clear();
m_AmountSpawned = 0;
m_NeedsUpdate = true;
}
void Spawner::DestroyAllEntities(){
for (auto* node : m_Info.nodes) {
for (const auto& element : node->entities) {
auto* entity = EntityManager::Instance()->GetEntity(element);
if (entity == nullptr) continue;
entity->Kill();
}
node->entities.clear();
}
}
void Spawner::SoftReset() {
m_Start = true;
m_AmountSpawned = 0;

View File

@@ -9,6 +9,7 @@
#include <string>
#include <functional>
#include "LDFFormat.h"
#include "EntityInfo.h"
struct SpawnerNode {
NiPoint3 position = NiPoint3::ZERO;
@@ -60,6 +61,7 @@ public:
void AddEntitySpawnedCallback(std::function<void(Entity*)> callback);
void SetSpawnLot(LOT lot);
void Reset();
void DestroyAllEntities();
void SoftReset();
void SetRespawnTime(float time);
void SetNumToMaintain(int32_t value);

View File

@@ -0,0 +1,67 @@
#ifndef __WORLDCONFIG__H__
#define __WORLDCONFIG__H__
#include <cstdint>
#include <string>
struct WorldConfig {
int32_t worldConfigID{}; //! Primary key for WorlcConfig table
float peGravityValue{}; //! Unknown
float peBroadphaseWorldSize{}; //! Unknown
float peGameObjScaleFactor{}; //! Unknown
float characterRotationSpeed{}; //! The players' rotation speed
float characterWalkForwardSpeed{}; //! The players' walk forward speed
float characterWalkBackwardSpeed{}; //! The players' walk backwards speed
float characterWalkStrafeSpeed{}; //! The players' strafe speed
float characterWalkStrafeForwardSpeed{}; //! The players' walk strafe forward speed
float characterWalkStrafeBackwardSpeed{}; //! The players' walk strage backwards speed
float characterRunBackwardSpeed{}; //! The players' run backwards speed
float characterRunStrafeSpeed{}; //! The players' run strafe speed
float characterRunStrafeForwardSpeed{}; //! The players' run strafe forward speed
float characterRunStrafeBackwardSpeed{}; //! The players' run strage backwards speed
float globalCooldown{}; //! The global ability cooldown
float characterGroundedTime{}; //! Unknown
float characterGroundedSpeed{}; //! Unknown
float globalImmunityTime{}; //! Unknown
float characterMaxSlope{}; //! Unknown
float defaultRespawnTime{}; //! Unknown
float missionTooltipTimeout{};
float vendorBuyMultiplier{}; //! The buy scalar for buying from vendors
float petFollowRadius{}; //! The players' pet follow radius
float characterEyeHeight{}; //! The players' eye height
float flightVerticalVelocity{}; //! Unknown
float flightAirspeed{}; //! Unknown
float flightFuelRatio{}; //! Unknown
float flightMaxAirspeed{}; //! Unknown
float fReputationPerVote{}; //! Unknown
int32_t propertyCloneLimit{}; //! Unknown
int32_t defaultHomespaceTemplate{}; //! Unknown
float coinsLostOnDeathPercent{}; //! The percentage of coins to lose on a player death
int32_t coinsLostOnDeathMin{}; //! The minimum number of coins to lose on a player death
int32_t coinsLostOnDeathMax{}; //! The maximum number of coins to lose on a player death
int32_t characterVotesPerDay{}; //! Unknown
int32_t propertyModerationRequestApprovalCost{};//! Unknown
int32_t propertyModerationRequestReviewCost{}; //! Unknown
int32_t propertyModRequestsAllowedSpike{}; //! Unknown
int32_t propertyModRequestsAllowedInterval{}; //! Unknown
int32_t propertyModRequestsAllowedTotal{}; //! Unknown
int32_t propertyModRequestsSpikeDuration{}; //! Unknown
int32_t propertyModRequestsIntervalDuration{}; //! Unknown
bool modelModerateOnCreate{}; //! Unknown
float defaultPropertyMaxHeight{}; //! Unknown
float reputationPerVoteCast{}; //! Unknown
float reputationPerVoteReceived{}; //! Unknown
int32_t showcaseTopModelConsiderationBattles{}; //! Unknown
float reputationPerBattlePromotion{}; //! Unknown
float coinsLostOnDeathMinTimeout{}; //! Unknown
float coinsLostOnDeathMaxTimeout{}; //! Unknown
int32_t mailBaseFee{}; //! The base fee to take when a player sends mail
float mailPercentAttachmentFee{}; //! The scalar multiplied by an items base cost to determine how much that item costs to be mailed
int32_t propertyReputationDelay{}; //! Unknown
int32_t levelCap{}; //! The maximum player level
std::string levelUpBehaviorEffect{}; //! Unknown
int32_t characterVersion{}; //! Unknown
int32_t levelCapCurrencyConversion{}; //! The ratio of UScore (LEGO Score) to coins
};
#endif //! __WORLDCONFIG__H__

View File

@@ -6,6 +6,7 @@
#include "dLogger.h"
#include "GeneralUtils.h"
#include "BinaryIO.h"
#include "LUTriggers.h"
#include "AssetManager.h"
#include "CDClientManager.h"
@@ -13,6 +14,9 @@
#include "Spawner.h"
#include "dZoneManager.h"
#include "eTriggerCommandType.h"
#include "eTriggerEventType.h"
Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) :
m_ZoneID(mapID, instanceID, cloneID) {
m_NumberOfScenesLoaded = 0;
@@ -42,6 +46,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 +102,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) {
@@ -157,7 +164,7 @@ void Zone::LoadZoneIntoMemory() {
std::string Zone::GetFilePathForZoneID() {
//We're gonna go ahead and presume we've got the db loaded already:
CDZoneTableTable* zoneTable = CDClientManager::Instance()->GetTable<CDZoneTableTable>("ZoneTable");
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
const CDZoneTable* zone = zoneTable->Query(this->GetZoneID().GetMapID());
if (zone != nullptr) {
std::string toReturn = "maps/" + zone->zoneName;
@@ -230,7 +237,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<LUTriggers::Trigger*> triggers = LoadLUTriggers(luTriggersPath, scene.id);
std::vector<LUTriggers::Trigger*> triggers;
if(Game::assetManager->HasFile((m_ZonePath + luTriggersPath).c_str())) triggers = LoadLUTriggers(luTriggersPath, scene.id);
for (LUTriggers::Trigger* trigger : triggers) {
scene.triggers.insert({ trigger->id, trigger });
@@ -245,15 +253,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 +264,10 @@ std::vector<LUTriggers::Trigger*> 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;
@@ -297,11 +299,11 @@ std::vector<LUTriggers::Trigger*> Zone::LoadLUTriggers(std::string triggerFile,
auto currentEvent = currentTrigger->FirstChildElement("event");
while (currentEvent) {
LUTriggers::Event* newEvent = new LUTriggers::Event();
newEvent->eventID = currentEvent->Attribute("id");
newEvent->id = TriggerEventType::StringToTriggerEventType(currentEvent->Attribute("id"));
auto currentCommand = currentEvent->FirstChildElement("command");
while (currentCommand) {
LUTriggers::Command* newCommand = new LUTriggers::Command();
newCommand->id = currentCommand->Attribute("id");
newCommand->id = TriggerCommandType::StringToTriggerCommandType(currentCommand->Attribute("id"));
newCommand->target = currentCommand->Attribute("target");
if (currentCommand->Attribute("targetName") != NULL) {
newCommand->targetName = currentCommand->Attribute("targetName");
@@ -368,14 +370,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 +381,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 +399,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 +421,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 +445,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<SpawnerPath*>(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 +469,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 +497,19 @@ 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);
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);
} 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);
}
if (path.pathVersion > 16) BinaryIO::BinaryRead(file, waypoint.rail.speed);
}
// object LDF configs
@@ -557,7 +534,7 @@ void Zone::LoadPath(std::istream& file) {
value.push_back(character);
}
LDFBaseData* ldfConfig = nullptr;
if (path.pathType == PathType::Movement) {
if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) {
ldfConfig = LDFBaseData::DataFromString(parameter + "=0:" + value);
} else {
ldfConfig = LDFBaseData::DataFromString(parameter + "=" + value);

View File

@@ -1,35 +1,18 @@
#pragma once
#include "dZMCommon.h"
#include "LDFFormat.h"
#include "../thirdparty/tinyxml2/tinyxml2.h"
#include "tinyxml2.h"
#include <string>
#include <vector>
#include <map>
class Level;
class LUTriggers {
public:
struct Command {
std::string id;
std::string target;
std::string targetName;
std::string args;
};
struct Event {
std::string eventID;
std::vector<Command*> commands;
};
struct Trigger {
uint32_t id;
bool enabled;
std::vector<Event*> events;
};
namespace LUTriggers {
struct Trigger;
};
class Level;
struct SceneRef {
std::string filename;
uint32_t id;
@@ -59,16 +42,31 @@ 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;
};
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<LDFBaseData*> config;
};
@@ -89,6 +87,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 +127,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 +147,7 @@ struct PropertyPath {
struct CameraPath {
std::string nextPath;
uint8_t rotatePlayer;
};
struct SpawnerPath {
@@ -150,6 +164,7 @@ struct Path {
uint32_t pathVersion;
PathType pathType;
std::string pathName;
uint32_t flags;
PathBehavior pathBehavior;
uint32_t waypointCount;
std::vector<PathWaypoint> pathWaypoints;
@@ -190,7 +205,7 @@ public:
uint32_t GetWorldID() const { return m_WorldID; }
[[nodiscard]] std::string GetZoneName() const { return m_ZoneName; }
std::string GetZoneRawPath() const { return m_ZoneRawPath;}
std::string GetZoneRawPath() const { return m_ZoneRawPath; }
std::string GetZonePath() const { return m_ZonePath; }
const NiPoint3& GetSpawnPos() const { return m_Spawnpoint; }
@@ -219,9 +234,11 @@ private:
std::map<LWOSCENEID, SceneRef, mapCompareLwoSceneIDs> m_Scenes;
std::vector<SceneTransition> m_SceneTransitions;
uint32_t m_PathDataLength;
//std::vector<char> m_PathData; //Binary path data
uint32_t m_PathChunkVersion;
std::vector<Path> m_Paths;
std::map<LWOSCENEID, uint32_t, mapCompareLwoSceneIDs> m_MapRevisions; //rhs is the revision!
//private ("helper") functions:

View File

@@ -8,6 +8,8 @@
#include "DestroyableComponent.h"
#include "GameMessages.h"
#include "VanityUtilities.h"
#include "WorldConfig.h"
#include "CDZoneTableTable.h"
#include <chrono>
#include "../dWorldServer/ObjectIDManager.h"
@@ -26,7 +28,7 @@ void dZoneManager::Initialize(const LWOZONEID& zoneID) {
LOT zoneControlTemplate = 2365;
CDZoneTableTable* zoneTable = CDClientManager::Instance()->GetTable<CDZoneTableTable>("ZoneTable");
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
if (zoneTable != nullptr) {
const CDZoneTable* zone = zoneTable->Query(zoneID.GetMapID());
@@ -53,6 +55,8 @@ void dZoneManager::Initialize(const LWOZONEID& zoneID) {
endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
LoadWorldConfig();
Game::logger->Log("dZoneManager", "Zone prepared in: %llu ms", (endTime - startTime));
VanityUtilities::SpawnVanity();
@@ -69,6 +73,7 @@ dZoneManager::~dZoneManager() {
m_Spawners.erase(p.first);
}
if (m_WorldConfig) delete m_WorldConfig;
}
Zone* dZoneManager::GetZone() {
@@ -117,24 +122,6 @@ LWOZONEID dZoneManager::GetZoneID() const {
return m_ZoneID;
}
uint32_t dZoneManager::GetMaxLevel() {
if (m_MaxLevel == 0) {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT LevelCap FROM WorldConfig WHERE WorldConfigID = 1 LIMIT 1;");
m_MaxLevel = tableData.getIntField(0, -1);
tableData.finalize();
}
return m_MaxLevel;
}
int32_t dZoneManager::GetLevelCapCurrencyConversion() {
if (m_CurrencyConversionRate == 0) {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT LevelCapCurrencyConversion FROM WorldConfig WHERE WorldConfigID = 1 LIMIT 1;");
m_CurrencyConversionRate = tableData.getIntField(0, -1);
tableData.finalize();
}
return m_CurrencyConversionRate;
}
void dZoneManager::Update(float deltaTime) {
for (auto spawner : m_Spawners) {
spawner.second->Update(deltaTime);
@@ -195,17 +182,7 @@ void dZoneManager::RemoveSpawner(const LWOOBJID id) {
Game::logger->Log("dZoneManager", "Failed to find spawner entity (%llu)", id);
}
for (auto* node : spawner->m_Info.nodes) {
for (const auto& element : node->entities) {
auto* nodeEntity = EntityManager::Instance()->GetEntity(element);
if (nodeEntity == nullptr) continue;
nodeEntity->Kill();
}
node->entities.clear();
}
spawner->DestroyAllEntities();
spawner->Deactivate();
@@ -249,3 +226,77 @@ uint32_t dZoneManager::GetUniqueMissionIdStartingValue() {
}
return m_UniqueMissionIdStart;
}
void dZoneManager::LoadWorldConfig() {
Game::logger->Log("dZoneManager", "Loading WorldConfig into memory");
auto worldConfig = CDClientDatabase::ExecuteQuery("SELECT * FROM WorldConfig;");
if (!m_WorldConfig) m_WorldConfig = new WorldConfig();
if (worldConfig.eof()) {
Game::logger->Log("dZoneManager", "WorldConfig table is empty. Is this intended?");
return;
}
// Now read in the giant table
m_WorldConfig->worldConfigID = worldConfig.getIntField("WorldConfigID");
m_WorldConfig->peGravityValue = worldConfig.getFloatField("pegravityvalue");
m_WorldConfig->peBroadphaseWorldSize = worldConfig.getFloatField("pebroadphaseworldsize");
m_WorldConfig->peGameObjScaleFactor = worldConfig.getFloatField("pegameobjscalefactor");
m_WorldConfig->characterRotationSpeed = worldConfig.getFloatField("character_rotation_speed");
m_WorldConfig->characterWalkForwardSpeed = worldConfig.getFloatField("character_walk_forward_speed");
m_WorldConfig->characterWalkBackwardSpeed = worldConfig.getFloatField("character_walk_backward_speed");
m_WorldConfig->characterWalkStrafeSpeed = worldConfig.getFloatField("character_walk_strafe_speed");
m_WorldConfig->characterWalkStrafeForwardSpeed = worldConfig.getFloatField("character_walk_strafe_forward_speed");
m_WorldConfig->characterWalkStrafeBackwardSpeed = worldConfig.getFloatField("character_walk_strafe_backward_speed");
m_WorldConfig->characterRunBackwardSpeed = worldConfig.getFloatField("character_run_backward_speed");
m_WorldConfig->characterRunStrafeSpeed = worldConfig.getFloatField("character_run_strafe_speed");
m_WorldConfig->characterRunStrafeForwardSpeed = worldConfig.getFloatField("character_run_strafe_forward_speed");
m_WorldConfig->characterRunStrafeBackwardSpeed = worldConfig.getFloatField("character_run_strafe_backward_speed");
m_WorldConfig->globalCooldown = worldConfig.getFloatField("global_cooldown");
m_WorldConfig->characterGroundedTime = worldConfig.getFloatField("characterGroundedTime");
m_WorldConfig->characterGroundedSpeed = worldConfig.getFloatField("characterGroundedSpeed");
m_WorldConfig->globalImmunityTime = worldConfig.getFloatField("globalImmunityTime");
m_WorldConfig->characterMaxSlope = worldConfig.getFloatField("character_max_slope");
m_WorldConfig->defaultRespawnTime = worldConfig.getFloatField("defaultrespawntime");
m_WorldConfig->missionTooltipTimeout = worldConfig.getFloatField("mission_tooltip_timeout");
m_WorldConfig->vendorBuyMultiplier = worldConfig.getFloatField("vendor_buy_multiplier");
m_WorldConfig->petFollowRadius = worldConfig.getFloatField("pet_follow_radius");
m_WorldConfig->characterEyeHeight = worldConfig.getFloatField("character_eye_height");
m_WorldConfig->flightVerticalVelocity = worldConfig.getFloatField("flight_vertical_velocity");
m_WorldConfig->flightAirspeed = worldConfig.getFloatField("flight_airspeed");
m_WorldConfig->flightFuelRatio = worldConfig.getFloatField("flight_fuel_ratio");
m_WorldConfig->flightMaxAirspeed = worldConfig.getFloatField("flight_max_airspeed");
m_WorldConfig->fReputationPerVote = worldConfig.getFloatField("fReputationPerVote");
m_WorldConfig->propertyCloneLimit = worldConfig.getIntField("nPropertyCloneLimit");
m_WorldConfig->defaultHomespaceTemplate = worldConfig.getIntField("defaultHomespaceTemplate");
m_WorldConfig->coinsLostOnDeathPercent = worldConfig.getFloatField("coins_lost_on_death_percent");
m_WorldConfig->coinsLostOnDeathMin = worldConfig.getIntField("coins_lost_on_death_min");
m_WorldConfig->coinsLostOnDeathMax = worldConfig.getIntField("coins_lost_on_death_max");
m_WorldConfig->characterVotesPerDay = worldConfig.getIntField("character_votes_per_day");
m_WorldConfig->propertyModerationRequestApprovalCost = worldConfig.getIntField("property_moderation_request_approval_cost");
m_WorldConfig->propertyModerationRequestReviewCost = worldConfig.getIntField("property_moderation_request_review_cost");
m_WorldConfig->propertyModRequestsAllowedSpike = worldConfig.getIntField("propertyModRequestsAllowedSpike");
m_WorldConfig->propertyModRequestsAllowedInterval = worldConfig.getIntField("propertyModRequestsAllowedInterval");
m_WorldConfig->propertyModRequestsAllowedTotal = worldConfig.getIntField("propertyModRequestsAllowedTotal");
m_WorldConfig->propertyModRequestsSpikeDuration = worldConfig.getIntField("propertyModRequestsSpikeDuration");
m_WorldConfig->propertyModRequestsIntervalDuration = worldConfig.getIntField("propertyModRequestsIntervalDuration");
m_WorldConfig->modelModerateOnCreate = worldConfig.getIntField("modelModerateOnCreate") != 0;
m_WorldConfig->defaultPropertyMaxHeight = worldConfig.getFloatField("defaultPropertyMaxHeight");
m_WorldConfig->reputationPerVoteCast = worldConfig.getFloatField("reputationPerVoteCast");
m_WorldConfig->reputationPerVoteReceived = worldConfig.getFloatField("reputationPerVoteReceived");
m_WorldConfig->showcaseTopModelConsiderationBattles = worldConfig.getIntField("showcaseTopModelConsiderationBattles");
m_WorldConfig->reputationPerBattlePromotion = worldConfig.getFloatField("reputationPerBattlePromotion");
m_WorldConfig->coinsLostOnDeathMinTimeout = worldConfig.getFloatField("coins_lost_on_death_min_timeout");
m_WorldConfig->coinsLostOnDeathMaxTimeout = worldConfig.getFloatField("coins_lost_on_death_max_timeout");
m_WorldConfig->mailBaseFee = worldConfig.getIntField("mail_base_fee");
m_WorldConfig->mailPercentAttachmentFee = worldConfig.getFloatField("mail_percent_attachment_fee");
m_WorldConfig->propertyReputationDelay = worldConfig.getIntField("propertyReputationDelay");
m_WorldConfig->levelCap = worldConfig.getIntField("LevelCap");
m_WorldConfig->levelUpBehaviorEffect = worldConfig.getStringField("LevelUpBehaviorEffect");
m_WorldConfig->characterVersion = worldConfig.getIntField("CharacterVersion");
m_WorldConfig->levelCapCurrencyConversion = worldConfig.getIntField("LevelCapCurrencyConversion");
worldConfig.finalize();
Game::logger->Log("dZoneManager", "Loaded WorldConfig into memory");
}

View File

@@ -4,6 +4,8 @@
#include "Spawner.h"
#include <map>
class WorldConfig;
class dZoneManager {
public:
enum class dZoneNotifier {
@@ -16,6 +18,12 @@ public:
InvalidNotifier
};
private:
/**
* Reads the WorldConfig from the CDClientDatabase into memory
*/
void LoadWorldConfig();
public:
static dZoneManager* Instance() {
if (!m_Address) {
@@ -33,8 +41,6 @@ public:
void NotifyZone(const dZoneNotifier& notifier, const LWOOBJID& objectID); //Notifies the zone of a certain event or command.
void AddSpawner(LWOOBJID id, Spawner* spawner);
LWOZONEID GetZoneID() const;
uint32_t GetMaxLevel();
int32_t GetLevelCapCurrencyConversion();
LWOOBJID MakeSpawner(SpawnerInfo info);
Spawner* GetSpawner(LWOOBJID id);
void RemoveSpawner(LWOOBJID id);
@@ -45,27 +51,24 @@ public:
bool GetPlayerLoseCoinOnDeath() { return m_PlayerLoseCoinsOnDeath; }
uint32_t GetUniqueMissionIdStartingValue();
// The world config should not be modified by a caller.
const WorldConfig* GetWorldConfig() {
if (!m_WorldConfig) LoadWorldConfig();
return m_WorldConfig;
};
private:
/**
* The maximum level of the world.
*/
uint32_t m_MaxLevel = 0;
/**
* The ratio of LEGO Score to currency when the character has hit the max level.
*/
int32_t m_CurrencyConversionRate = 0;
/**
* The starting unique mission ID.
*/
uint32_t m_UniqueMissionIdStart = 0;
static dZoneManager* m_Address; //Singleton
Zone* m_pZone;
Zone* m_pZone = nullptr;
LWOZONEID m_ZoneID;
bool m_PlayerLoseCoinsOnDeath; //Do players drop coins in this zone when smashed
std::map<LWOOBJID, Spawner*> m_Spawners;
WorldConfig* m_WorldConfig = nullptr;
Entity* m_ZoneControlObject;
Entity* m_ZoneControlObject = nullptr;
};