2021-12-05 17:54:36 +00:00
|
|
|
#include "Game.h"
|
|
|
|
#include "dCommonVars.h"
|
|
|
|
#include "dZoneManager.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "dLogger.h"
|
|
|
|
#include "dConfig.h"
|
|
|
|
#include "InventoryComponent.h"
|
|
|
|
#include "DestroyableComponent.h"
|
|
|
|
#include "GameMessages.h"
|
|
|
|
#include "VanityUtilities.h"
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
#include "../dWorldServer/ObjectIDManager.h"
|
|
|
|
|
|
|
|
dZoneManager* dZoneManager::m_Address = nullptr;
|
|
|
|
|
|
|
|
void dZoneManager::Initialize(const LWOZONEID& zoneID) {
|
|
|
|
Game::logger->Log("dZoneManager", "Preparing zone: %i/%i/%i\n", zoneID.GetMapID(), zoneID.GetInstanceID(), zoneID.GetCloneID());
|
|
|
|
|
|
|
|
int64_t startTime = 0;
|
|
|
|
int64_t endTime = 0;
|
|
|
|
|
|
|
|
startTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
|
|
|
|
|
|
|
LoadZone(zoneID);
|
|
|
|
|
|
|
|
LOT zoneControlTemplate = 2365;
|
|
|
|
|
2022-02-05 12:27:24 +00:00
|
|
|
CDZoneTableTable* zoneTable = CDClientManager::Instance()->GetTable<CDZoneTableTable>("ZoneTable");
|
|
|
|
if (zoneTable != nullptr){
|
|
|
|
const CDZoneTable* zone = zoneTable->Query(zoneID.GetMapID());
|
|
|
|
|
|
|
|
if (zone != nullptr) {
|
|
|
|
zoneControlTemplate = zone->zoneControlTemplate != -1 ? zone->zoneControlTemplate : 2365;
|
|
|
|
const auto min = zone->ghostdistance_min != -1.0f ? zone->ghostdistance_min : 100;
|
|
|
|
const auto max = zone->ghostdistance != -1.0f ? zone->ghostdistance : 100;
|
|
|
|
EntityManager::Instance()->SetGhostDistanceMax(max + min);
|
|
|
|
EntityManager::Instance()->SetGhostDistanceMin(min);
|
|
|
|
m_PlayerLoseCoinsOnDeath = zone->PlayerLoseCoinsOnDeath;
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Game::logger->Log("dZoneManager", "Creating zone control object %i\n", zoneControlTemplate);
|
|
|
|
|
|
|
|
// Create ZoneControl object
|
|
|
|
EntityInfo info;
|
|
|
|
info.lot = zoneControlTemplate;
|
|
|
|
info.id = 70368744177662;
|
|
|
|
Entity* zoneControl = EntityManager::Instance()->CreateEntity(info, nullptr, nullptr, true);
|
|
|
|
m_ZoneControlObject = zoneControl;
|
|
|
|
|
|
|
|
m_pZone->Initalize();
|
|
|
|
|
|
|
|
endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
|
|
|
|
|
|
|
Game::logger->Log("dZoneManager", "Zone prepared in: %llu ms\n", (endTime - startTime));
|
|
|
|
|
|
|
|
VanityUtilities::SpawnVanity();
|
|
|
|
}
|
|
|
|
|
|
|
|
dZoneManager::~dZoneManager() {
|
|
|
|
if (m_pZone) delete m_pZone;
|
|
|
|
|
|
|
|
for (std::pair<LWOOBJID, Spawner*> p : m_Spawners) {
|
|
|
|
if (p.second) {
|
|
|
|
delete p.second;
|
|
|
|
p.second = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Spawners.erase(p.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Zone * dZoneManager::GetZone() {
|
|
|
|
return m_pZone;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dZoneManager::LoadZone(const LWOZONEID& zoneID) {
|
|
|
|
if (m_pZone) delete m_pZone;
|
|
|
|
|
|
|
|
m_ZoneID = zoneID;
|
|
|
|
m_pZone = new Zone(zoneID.GetMapID(), zoneID.GetInstanceID(), zoneID.GetCloneID());
|
|
|
|
}
|
|
|
|
|
|
|
|
void dZoneManager::NotifyZone(const dZoneNotifier & notifier, const LWOOBJID& objectID) {
|
|
|
|
switch (notifier) {
|
|
|
|
case dZoneNotifier::SpawnedObjectDestroyed:
|
|
|
|
break;
|
|
|
|
case dZoneNotifier::SpawnedChildObjectDestroyed:
|
|
|
|
break;
|
|
|
|
case dZoneNotifier::ReloadZone:
|
|
|
|
Game::logger->Log("dZoneManager", "Forcing reload of zone %i\n", m_ZoneID.GetMapID());
|
|
|
|
LoadZone(m_ZoneID);
|
|
|
|
|
|
|
|
m_pZone->Initalize();
|
|
|
|
break;
|
|
|
|
case dZoneNotifier::UserJoined:
|
|
|
|
break;
|
|
|
|
case dZoneNotifier::UserMoved:
|
|
|
|
break;
|
|
|
|
case dZoneNotifier::PrintAllGameObjects:
|
|
|
|
m_pZone->PrintAllGameObjects();
|
|
|
|
break;
|
|
|
|
case dZoneNotifier::InvalidNotifier:
|
|
|
|
Game::logger->Log("dZoneManager", "Got an invalid zone notifier.\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Game::logger->Log("dZoneManager", "Unknown zone notifier: %i\n", int(notifier));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void dZoneManager::AddSpawner(LWOOBJID id, Spawner* spawner)
|
|
|
|
{
|
|
|
|
m_Spawners.insert_or_assign(id, spawner);
|
|
|
|
}
|
|
|
|
|
|
|
|
LWOZONEID dZoneManager::GetZoneID() const
|
|
|
|
{
|
|
|
|
return m_ZoneID;
|
|
|
|
}
|
|
|
|
|
2022-02-03 06:50:02 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
void dZoneManager::Update(float deltaTime) {
|
|
|
|
for (auto spawner : m_Spawners) {
|
|
|
|
spawner.second->Update(deltaTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LWOOBJID dZoneManager::MakeSpawner(SpawnerInfo info)
|
|
|
|
{
|
|
|
|
auto objectId = info.spawnerID;
|
|
|
|
|
|
|
|
if (objectId == LWOOBJID_EMPTY)
|
|
|
|
{
|
|
|
|
objectId = ObjectIDManager::Instance()->GenerateObjectID();
|
|
|
|
|
|
|
|
objectId = GeneralUtils::SetBit(objectId, OBJECT_BIT_CLIENT);
|
|
|
|
|
|
|
|
info.spawnerID = objectId;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* spawner = new Spawner(info);
|
|
|
|
|
|
|
|
EntityInfo entityInfo{};
|
|
|
|
|
|
|
|
entityInfo.id = objectId;
|
|
|
|
entityInfo.lot = 176;
|
|
|
|
|
|
|
|
auto* entity = EntityManager::Instance()->CreateEntity(entityInfo, nullptr, nullptr, false, objectId);
|
|
|
|
|
|
|
|
EntityManager::Instance()->ConstructEntity(entity);
|
|
|
|
|
|
|
|
AddSpawner(objectId, spawner);
|
|
|
|
|
|
|
|
return objectId;
|
|
|
|
}
|
|
|
|
|
|
|
|
Spawner* dZoneManager::GetSpawner(const LWOOBJID id)
|
|
|
|
{
|
|
|
|
const auto& index = m_Spawners.find(id);
|
|
|
|
|
|
|
|
if (index == m_Spawners.end()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return index->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dZoneManager::RemoveSpawner(const LWOOBJID id)
|
|
|
|
{
|
|
|
|
auto* spawner = GetSpawner(id);
|
|
|
|
|
|
|
|
if (spawner == nullptr) {
|
|
|
|
Game::logger->Log("dZoneManager", "Failed to find spawner (%llu)\n", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* entity = EntityManager::Instance()->GetEntity(id);
|
|
|
|
|
|
|
|
if (entity != nullptr) {
|
|
|
|
entity->Kill();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
Game::logger->Log("dZoneManager", "Failed to find spawner entity (%llu)\n", 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->Deactivate();
|
|
|
|
|
|
|
|
Game::logger->Log("dZoneManager", "Destroying spawner (%llu)\n", id);
|
|
|
|
|
|
|
|
m_Spawners.erase(id);
|
|
|
|
|
|
|
|
delete spawner;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<Spawner*> dZoneManager::GetSpawnersByName(std::string spawnerName) {
|
|
|
|
std::vector<Spawner*> spawners;
|
|
|
|
for (const auto& spawner : m_Spawners) {
|
|
|
|
if (spawner.second->GetName() == spawnerName) {
|
|
|
|
spawners.push_back(spawner.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return spawners;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<Spawner*> dZoneManager::GetSpawnersInGroup(std::string group) {
|
|
|
|
std::vector<Spawner*> spawnersInGroup;
|
|
|
|
for (auto spawner : m_Spawners) {
|
|
|
|
for (std::string entityGroup : spawner.second->m_Info.groups) {
|
|
|
|
if (entityGroup == group) {
|
|
|
|
spawnersInGroup.push_back(spawner.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return spawnersInGroup;
|
|
|
|
}
|