DarkflameServer/dZoneManager/dZoneManager.cpp
cooltrain7 579cf590b4
Implement CDZoneTable PlayerLoseCoinsOnDeath (#251)
* Implement ZoneTable PlayerLoseCoinsOnDeath

- Adds a check on death if the character should drop coins in the current zone

* Refactored PlayerLoseCoinOnDeath into dZoneManager

* Coin death drops use LootGenerator

* Refactored again with use of CDZoneTableTable

* Remove duplicate CDZone call during initialization
2022-02-05 13:27:24 +01:00

252 lines
6.4 KiB
C++

#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;
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;
}
}
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;
}
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);
}
}
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;
}