mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
455f9470a5
* Move EntityManager to Game namespace * move initialization to later Need to wait for dZoneManager to be initialized. * Fix bugs - Cannot delete from a RandomAccessIterator while in a range based for loop. Touchup zone manager initialize replace magic numbers with better named constants replace magic zonecontrol id with a more readable hex alternative condense stack variables move initializers closer to their use initialize entity manager with zone control change initialize timings If zone is not zero we expect to initialize the entity manager during zone manager initialization Add constexpr for zone control LOT * Add proper error handling * revert vanity changes * Update WorldServer.cpp * Update dZoneManager.cpp
575 lines
20 KiB
C++
575 lines
20 KiB
C++
#include "BaseSurvivalServer.h"
|
|
#include "GameMessages.h"
|
|
#include "DestroyableComponent.h"
|
|
#include "EntityManager.h"
|
|
#include "dZoneManager.h"
|
|
#include "Player.h"
|
|
#include "eMissionTaskType.h"
|
|
#include "eMissionState.h"
|
|
#include "MissionComponent.h"
|
|
#include "Character.h"
|
|
|
|
void BaseSurvivalServer::SetGameVariables(Entity* self) {
|
|
this->constants = std::move(GetConstants());
|
|
this->mobSets = std::move(GetMobSets());
|
|
this->spawnerNetworks = std::move(GetSpawnerNetworks());
|
|
this->missionsToUpdate = std::move(GetMissionsToUpdate());
|
|
}
|
|
|
|
void BaseSurvivalServer::BasePlayerLoaded(Entity* self, Entity* player) {
|
|
const auto& waitingIter = std::find(state.waitingPlayers.begin(), state.waitingPlayers.end(), player->GetObjectID());
|
|
const auto& playersIter = std::find(state.players.begin(), state.players.end(), player->GetObjectID());
|
|
|
|
if (waitingIter != state.waitingPlayers.end() || playersIter != state.players.end()) {
|
|
static_cast<Player*>(player)->SendToZone(player->GetCharacter()->GetLastNonInstanceZoneID());
|
|
|
|
return;
|
|
}
|
|
|
|
state.waitingPlayers.push_back(player->GetObjectID());
|
|
state.players.push_back(player->GetObjectID());
|
|
|
|
self->SetNetworkVar<uint32_t>(NumberOfPlayersVariable, self->GetNetworkVar<uint32_t>(NumberOfPlayersVariable) + 1);
|
|
self->SetNetworkVar<std::string>(DefinePlayerToUIVariable, std::to_string(player->GetObjectID()), player->GetSystemAddress());
|
|
|
|
// Notify the players of all other players
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
auto counter = 1;
|
|
for (const auto& playerID : state.players) {
|
|
self->SetNetworkVar<std::string>(UpdateScoreboardPlayersVariable + GeneralUtils::to_u16string(counter), std::to_string(playerID));
|
|
counter++;
|
|
}
|
|
|
|
self->SetNetworkVar<bool>(ShowScoreboardVariable, true);
|
|
}
|
|
|
|
SetPlayerSpawnPoints();
|
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
PlayerConfirmed(self);
|
|
} else {
|
|
UpdatePlayer(self, player->GetObjectID());
|
|
GetLeaderboardData(self, player->GetObjectID(), GetActivityID(self), 50);
|
|
ResetStats(player->GetObjectID());
|
|
}
|
|
|
|
player->AddCallbackTimer(5.0f, [this, self, player]() {
|
|
self->SetNetworkVar<uint32_t>(NumberOfPlayersVariable, self->GetNetworkVar<uint32_t>(NumberOfPlayersVariable));
|
|
self->SetNetworkVar<std::string>(DefinePlayerToUIVariable, std::to_string(player->GetObjectID()), player->GetSystemAddress());
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
auto counter = 1;
|
|
for (const auto& playerID : state.players) {
|
|
self->SetNetworkVar<std::string>(UpdateScoreboardPlayersVariable + GeneralUtils::to_u16string(counter), std::to_string(playerID));
|
|
counter++;
|
|
}
|
|
|
|
self->SetNetworkVar<bool>(ShowScoreboardVariable, true);
|
|
}
|
|
});
|
|
}
|
|
|
|
void BaseSurvivalServer::BaseStartup(Entity* self) {
|
|
self->SetVar<uint32_t>(PlayersAcceptedVariable, 0);
|
|
self->SetVar<bool>(PlayersReadyVariable, false);
|
|
}
|
|
|
|
void BaseSurvivalServer::BasePlayerExit(Entity* self, Entity* player) {
|
|
const auto& waitingIter = std::find(state.waitingPlayers.begin(), state.waitingPlayers.end(), player->GetObjectID());
|
|
const auto& playersIter = std::find(state.players.begin(), state.players.end(), player->GetObjectID());
|
|
|
|
if (waitingIter != state.waitingPlayers.end()) {
|
|
state.waitingPlayers.erase(waitingIter);
|
|
}
|
|
|
|
if (playersIter != state.players.end()) {
|
|
state.players.erase(playersIter);
|
|
}
|
|
|
|
if (waitingIter == state.waitingPlayers.end() && playersIter == state.players.end()) {
|
|
return;
|
|
}
|
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
PlayerConfirmed(self);
|
|
|
|
if (state.players.empty())
|
|
return;
|
|
|
|
if (state.waitingPlayers.empty()) {
|
|
ActivityTimerStopAllTimers(self);
|
|
ActivityTimerStart(self, AllAcceptedDelayTimer, 1.0f, constants.startDelay);
|
|
} else if (state.players.size() > state.waitingPlayers.size()) {
|
|
if (!self->GetVar<bool>(AcceptedDelayStartedVariable)) {
|
|
self->SetVar<bool>(AcceptedDelayStartedVariable, true);
|
|
ActivityTimerStart(self, AcceptedDelayTimer, 1.0f, constants.acceptedDelay);
|
|
}
|
|
}
|
|
} else {
|
|
UpdatePlayer(self, player->GetObjectID(), true);
|
|
if (CheckAllPlayersDead()) {
|
|
GameOver(self);
|
|
}
|
|
}
|
|
|
|
SetActivityValue(self, player->GetObjectID(), 1, 0);
|
|
self->SetNetworkVar<uint32_t>(NumberOfPlayersVariable,
|
|
std::min((uint32_t)0, self->GetNetworkVar<uint32_t>(NumberOfPlayersVariable) - 1));
|
|
}
|
|
|
|
void BaseSurvivalServer::BaseFireEvent(Entity* self, Entity* sender, const std::string& args, int32_t param1, int32_t param2,
|
|
int32_t param3) {
|
|
if (args == "start") {
|
|
StartWaves(self);
|
|
} else if (args == "DeactivateRewards") {
|
|
SpawnerReset(spawnerNetworks.rewardNetworks);
|
|
} else if (sender != nullptr && IsPlayerInActivity(self, sender->GetObjectID())) {
|
|
auto currentScore = GetActivityValue(self, sender->GetObjectID(), 0);
|
|
SetActivityValue(self, sender->GetObjectID(), 0, currentScore + param1);
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::BasePlayerDied(Entity* self, Entity* player) {
|
|
if (self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
const auto finalTime = ActivityTimerGetCurrentTime(self, ClockTickTimer);
|
|
SetActivityValue(self, player->GetObjectID(), 1, finalTime);
|
|
|
|
auto paramString = CheckAllPlayersDead() ? "true" : "false";
|
|
GameMessages::SendNotifyClientZoneObject(self->GetObjectID(), u"Player_Died", finalTime, 0,
|
|
player->GetObjectID(), paramString, player->GetSystemAddress());
|
|
GameOver(self);
|
|
} else {
|
|
player->Resurrect();
|
|
SetPlayerSpawnPoints();
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::BasePlayerResurrected(Entity* self, Entity* player) {
|
|
self->SetNetworkVar<bool>(ShowScoreboardVariable, true);
|
|
}
|
|
|
|
void BaseSurvivalServer::BaseMessageBoxResponse(Entity* self, Entity* sender, int32_t button,
|
|
const std::u16string& identifier, const std::u16string& userData) {
|
|
if (identifier == u"RePlay") {
|
|
PlayerAccepted(self, sender->GetObjectID());
|
|
PlayerConfirmed(self);
|
|
} else if (identifier == u"Exit_Question" && button == 1) {
|
|
ResetStats(sender->GetObjectID());
|
|
self->SetNetworkVar<std::string>(ExitWavesVariable, std::to_string(sender->GetObjectID()));
|
|
|
|
if (sender->IsPlayer()) {
|
|
auto* character = sender->GetCharacter();
|
|
if (character != nullptr) {
|
|
auto* player = dynamic_cast<Player*>(sender);
|
|
player->SendToZone(character->GetLastNonInstanceZoneID());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::OnActivityTimerUpdate(Entity* self, const std::string& name, float_t remainingTime, float_t elapsedTime) {
|
|
if (name == AcceptedDelayTimer) {
|
|
self->SetNetworkVar<uint64_t>(UpdateDefaultStartTimerVariable, remainingTime);
|
|
} else if (name == ClockTickTimer) {
|
|
self->SetNetworkVar<float_t>(UpdateTimerVariable, elapsedTime);
|
|
} else if (name == SpawnTickTimer && !self->GetVar<bool>(IsCooldownVariable)) {
|
|
SpawnMobs(self);
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::OnActivityTimerDone(Entity* self, const std::string& name) {
|
|
auto cooldownTime = constants.rewardInterval * constants.waveTime;
|
|
|
|
if (name == AcceptedDelayTimer) {
|
|
self->SetNetworkVar<uint64_t>(UpdateDefaultStartTimerVariable, 0);
|
|
ActivityTimerStart(self, AllAcceptedDelayTimer, 1, 1);
|
|
} else if (name == AllAcceptedDelayTimer) {
|
|
self->SetNetworkVar<bool>(ClearScoreboardVariable, true);
|
|
ActivityTimerStart(self, StartDelayTimer, 3, 3);
|
|
|
|
StartWaves(self);
|
|
} else if (name == StartDelayTimer) {
|
|
ActivityTimerStart(self, ClockTickTimer, 1);
|
|
ActivityTimerStart(self, SpawnTickTimer, constants.waveTime);
|
|
SpawnMobs(self);
|
|
ActivityTimerStart(self, PlaySpawnSoundTimer, 3, 3);
|
|
ActivityTimerStart(self, CoolDownStartTimer, cooldownTime, cooldownTime);
|
|
} else if (name == CoolDownStartTimer) {
|
|
self->SetVar<bool>(IsCooldownVariable, true);
|
|
|
|
ActivityTimerStop(self, SpawnTickTimer);
|
|
ActivityTimerStart(self, CoolDownStopTimer, 1, constants.coolDownTime);
|
|
|
|
ActivateSpawnerNetwork(spawnerNetworks.rewardNetworks);
|
|
SpawnerReset(spawnerNetworks.baseNetworks, false);
|
|
SpawnerReset(spawnerNetworks.randomNetworks, false);
|
|
} else if (name == CoolDownStopTimer) {
|
|
self->SetVar<bool>(IsCooldownVariable, false);
|
|
|
|
ActivityTimerStart(self, SpawnTickTimer, constants.waveTime);
|
|
ActivityTimerStart(self, CoolDownStartTimer, cooldownTime, cooldownTime);
|
|
|
|
SpawnMobs(self);
|
|
ActivityTimerStart(self, PlaySpawnSoundTimer, 3, 3);
|
|
} else if (name == PlaySpawnSoundTimer) {
|
|
for (const auto& playerID : state.players) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
if (player != nullptr) {
|
|
GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), spawnSoundGUID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::ResetStats(LWOOBJID playerID) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
if (player != nullptr) {
|
|
|
|
// Boost all the player stats when loading in
|
|
auto* destroyableComponent = player->GetComponent<DestroyableComponent>();
|
|
if (destroyableComponent != nullptr) {
|
|
destroyableComponent->SetHealth(destroyableComponent->GetMaxHealth());
|
|
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor());
|
|
destroyableComponent->SetImagination(destroyableComponent->GetMaxImagination());
|
|
}
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::PlayerConfirmed(Entity* self) {
|
|
std::vector<LWOOBJID> confirmedPlayers{};
|
|
|
|
for (const auto& playerID : state.players) {
|
|
auto pass = false;
|
|
for (const auto& waitingPlayerID : state.waitingPlayers) {
|
|
if (waitingPlayerID == playerID)
|
|
pass = true;
|
|
}
|
|
|
|
if (!pass)
|
|
confirmedPlayers.push_back(playerID);
|
|
}
|
|
|
|
auto playerIndex = 1;
|
|
for (const auto& playerID : confirmedPlayers) {
|
|
self->SetNetworkVar<std::string>(PlayerConfirmVariable + GeneralUtils::to_u16string(playerIndex), std::to_string(playerID));
|
|
playerIndex++;
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::PlayerAccepted(Entity* self, LWOOBJID playerID) {
|
|
const auto& iter = std::find(state.waitingPlayers.begin(), state.waitingPlayers.end(), playerID);
|
|
|
|
if (iter == state.waitingPlayers.end()) {
|
|
return;
|
|
}
|
|
|
|
state.waitingPlayers.erase(iter);
|
|
|
|
if (state.waitingPlayers.empty() && state.players.size() >= self->GetNetworkVar<uint32_t>(NumberOfPlayersVariable)) {
|
|
ActivityTimerStopAllTimers(self);
|
|
ActivityTimerStart(self, AllAcceptedDelayTimer, 1, constants.startDelay);
|
|
} else if (!self->GetVar<bool>(AcceptedDelayStartedVariable)) {
|
|
self->SetVar<bool>(AcceptedDelayStartedVariable, true);
|
|
ActivityTimerStart(self, AcceptedDelayTimer, 1, constants.acceptedDelay);
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::StartWaves(Entity* self) {
|
|
GameMessages::SendActivityStart(self->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
|
|
|
|
self->SetVar<bool>(PlayersReadyVariable, true);
|
|
self->SetVar<uint32_t>(BaseMobSetIndexVariable, 0);
|
|
self->SetVar<uint32_t>(RandMobSetIndexVariable, 0);
|
|
self->SetVar<bool>(AcceptedDelayStartedVariable, false);
|
|
|
|
state.waitingPlayers.clear();
|
|
|
|
for (const auto& playerID : state.players) {
|
|
const auto player = Game::entityManager->GetEntity(playerID);
|
|
if (player != nullptr) {
|
|
state.waitingPlayers.push_back(playerID);
|
|
UpdatePlayer(self, playerID);
|
|
GetLeaderboardData(self, playerID, GetActivityID(self), 50);
|
|
ResetStats(playerID);
|
|
|
|
if (!self->GetVar<bool>(FirstTimeDoneVariable)) {
|
|
TakeActivityCost(self, playerID);
|
|
}
|
|
|
|
GameMessages::SendPlayerSetCameraCyclingMode(playerID, player->GetSystemAddress());
|
|
}
|
|
}
|
|
|
|
self->SetVar<bool>(FirstTimeDoneVariable, true);
|
|
self->SetVar<std::string>(MissionTypeVariable, state.players.size() == 1 ? "survival_time_solo" : "survival_time_team");
|
|
|
|
ActivateSpawnerNetwork(spawnerNetworks.smashNetworks);
|
|
self->SetNetworkVar<bool>(WavesStartedVariable, true);
|
|
self->SetNetworkVar<std::string>(StartWaveMessageVariable, "Start!");
|
|
}
|
|
|
|
bool BaseSurvivalServer::CheckAllPlayersDead() {
|
|
auto deadPlayers = 0;
|
|
|
|
for (const auto& playerID : state.players) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
if (player == nullptr || player->GetIsDead()) {
|
|
deadPlayers++;
|
|
}
|
|
}
|
|
|
|
return deadPlayers >= state.players.size();
|
|
}
|
|
|
|
void BaseSurvivalServer::SetPlayerSpawnPoints() {
|
|
auto spawnerIndex = 1;
|
|
for (const auto& playerID : state.players) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
if (player != nullptr) {
|
|
auto possibleSpawners = Game::entityManager->GetEntitiesInGroup("P" + std::to_string(spawnerIndex) + "_Spawn");
|
|
if (!possibleSpawners.empty()) {
|
|
auto* spawner = possibleSpawners.at(0);
|
|
GameMessages::SendTeleport(playerID, spawner->GetPosition(), spawner->GetRotation(), player->GetSystemAddress(), true);
|
|
}
|
|
}
|
|
|
|
spawnerIndex++;
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::GameOver(Entity* self) {
|
|
if (!CheckAllPlayersDead())
|
|
return;
|
|
|
|
ActivityTimerStopAllTimers(self);
|
|
|
|
// Reset all the spawners
|
|
SpawnerReset(spawnerNetworks.baseNetworks);
|
|
SpawnerReset(spawnerNetworks.randomNetworks);
|
|
SpawnerReset(spawnerNetworks.rewardNetworks);
|
|
|
|
for (const auto& playerID : state.players) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
if (player == nullptr)
|
|
continue;
|
|
|
|
const auto score = GetActivityValue(self, playerID, 0);
|
|
const auto time = GetActivityValue(self, playerID, 1);
|
|
|
|
GameMessages::SendNotifyClientZoneObject(self->GetObjectID(), u"Update_ScoreBoard", time, 0,
|
|
playerID, std::to_string(score), UNASSIGNED_SYSTEM_ADDRESS);
|
|
player->Resurrect();
|
|
|
|
// Update all mission progression
|
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
|
if (missionComponent != nullptr) {
|
|
missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, time, self->GetObjectID(),
|
|
self->GetVar<std::string>(MissionTypeVariable));
|
|
|
|
for (const auto& survivalMission : missionsToUpdate) {
|
|
auto* mission = missionComponent->GetMission(survivalMission.first);
|
|
if (mission != nullptr && (uint32_t)time >= survivalMission.second
|
|
&& (mission->GetMissionState() == eMissionState::ACTIVE
|
|
|| mission->GetMissionState() == eMissionState::COMPLETE_ACTIVE)) {
|
|
|
|
mission->Progress(eMissionTaskType::SCRIPT, self->GetLOT());
|
|
}
|
|
}
|
|
}
|
|
|
|
StopActivity(self, playerID, score, time);
|
|
}
|
|
|
|
state.waveNumber = 1;
|
|
state.rewardTick = 1;
|
|
state.totalSpawned = 0;
|
|
|
|
self->SetNetworkVar<bool>(WavesStartedVariable, false);
|
|
|
|
if (constants.useMobLots) {
|
|
constants.lotPhase = 0;
|
|
UpdateMobLots(spawnerNetworks.baseNetworks);
|
|
UpdateMobLots(spawnerNetworks.randomNetworks);
|
|
}
|
|
|
|
SetPlayerSpawnPoints();
|
|
}
|
|
|
|
void BaseSurvivalServer::SpawnerReset(SpawnerNetworkCollection& spawnerNetworkCollection, bool hardReset) {
|
|
auto totalSpawned = 0;
|
|
|
|
for (auto& spawner : spawnerNetworkCollection.networks) {
|
|
for (auto& spawnerName : spawner.names) {
|
|
auto spawners = dZoneManager::Instance()->GetSpawnersByName(spawnerName + spawner.number);
|
|
if (!spawners.empty()) {
|
|
auto* spawnerObject = spawners.at(0);
|
|
|
|
auto amountSpawned = spawnerObject->GetAmountSpawned();
|
|
totalSpawned += amountSpawned;
|
|
|
|
spawner.isActive = false;
|
|
if (hardReset) {
|
|
spawnerObject->Reset();
|
|
} else {
|
|
spawnerObject->SoftReset();
|
|
}
|
|
|
|
spawnerObject->Deactivate();
|
|
}
|
|
}
|
|
}
|
|
|
|
state.totalSpawned = std::max((uint32_t)totalSpawned, state.totalSpawned);
|
|
}
|
|
|
|
void BaseSurvivalServer::SpawnerUpdate(Entity* self, SpawnerNetworkCollection& spawnerNetworkCollection, uint32_t amount) {
|
|
if (spawnerNetworkCollection.networks.empty())
|
|
return;
|
|
|
|
// If we want to spawn something specific now
|
|
if (amount != 0) {
|
|
auto spawnerNetwork = spawnerNetworkCollection.networks.at(0);
|
|
auto possibleSpawners = dZoneManager::Instance()->GetSpawnersByName(spawnerNetwork.names.at(0) + spawnerNetwork.number);
|
|
if (!possibleSpawners.empty()) {
|
|
SpawnNow(possibleSpawners.at(0), amount);
|
|
return;
|
|
}
|
|
}
|
|
|
|
auto setNumber = self->GetVar<uint32_t>(GeneralUtils::ASCIIToUTF16(spawnerNetworkCollection.mobSetName + "Num"));
|
|
auto newSet = GetRandomMobSet(spawnerNetworkCollection, setNumber);
|
|
|
|
if (!newSet.empty()) {
|
|
auto spawnerNetwork = GetRandomSpawner(spawnerNetworkCollection);
|
|
for (auto i = 0; i < spawnerNetwork.names.size(); i++) {
|
|
const auto& name = spawnerNetwork.names.at(i);
|
|
const auto& toSpawn = newSet.at(i);
|
|
|
|
auto possibleSpawners = dZoneManager::Instance()->GetSpawnersByName(name + spawnerNetwork.number);
|
|
if (!possibleSpawners.empty()) {
|
|
SpawnNow(possibleSpawners.front(), toSpawn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::SpawnNow(Spawner* spawner, uint32_t amount) {
|
|
if (spawner != nullptr) {
|
|
if (!spawner->m_Active) {
|
|
spawner->m_Info.amountMaintained = amount;
|
|
spawner->Activate();
|
|
} else {
|
|
spawner->m_Info.amountMaintained = amount;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<uint32_t> BaseSurvivalServer::GetRandomMobSet(SpawnerNetworkCollection& spawnerNetworkCollection,
|
|
uint32_t setNumber) {
|
|
|
|
if (mobSets.sets.find(spawnerNetworkCollection.mobSetName) != mobSets.sets.end()) {
|
|
auto mobSet = mobSets.sets.at(spawnerNetworkCollection.mobSetName);
|
|
if (setNumber < mobSet.size()) {
|
|
return mobSet.at(setNumber).at(rand() % mobSet.at(setNumber).size());
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
SpawnerNetwork BaseSurvivalServer::GetRandomSpawner(SpawnerNetworkCollection& spawnerNetworkCollection) {
|
|
std::vector<SpawnerNetwork> validSpawners{};
|
|
for (const auto& spawner : spawnerNetworkCollection.networks) {
|
|
if (!spawner.isLocked)
|
|
validSpawners.push_back(spawner);
|
|
}
|
|
|
|
if (!validSpawners.empty()) {
|
|
auto spawner = validSpawners.at(rand() % validSpawners.size());
|
|
spawner.isActive = true;
|
|
return spawner;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
void BaseSurvivalServer::ActivateSpawnerNetwork(SpawnerNetworkCollection& spawnerNetworkCollection) {
|
|
for (auto& spawner : spawnerNetworkCollection.networks) {
|
|
for (const auto& spawnerName : spawner.names) {
|
|
auto possibleSpawners = dZoneManager::Instance()->GetSpawnersByName(spawnerName + spawner.number);
|
|
if (!possibleSpawners.empty()) {
|
|
auto* spawnerObject = possibleSpawners.at(0);
|
|
spawnerObject->Activate();
|
|
spawnerObject->Reset();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::UpdateMobLots(SpawnerNetworkCollection& spawnerNetworkCollection) {
|
|
for (auto& spawner : spawnerNetworkCollection.networks) {
|
|
for (auto& spawnerName : spawner.names) {
|
|
if (!spawnerName.empty()) {
|
|
auto spawnerObjects = dZoneManager::Instance()->GetSpawnersByName(spawnerName + spawner.number);
|
|
if (!spawnerObjects.empty()) {
|
|
auto splitName = GeneralUtils::SplitString(spawnerName, '_');
|
|
auto cleanName = splitName.size() > 1 ? splitName.at(1) : splitName.at(0);
|
|
|
|
if (!cleanName.empty()) {
|
|
auto spawnerObject = spawnerObjects.at(0);
|
|
spawnerObject->SetSpawnLot(mobSets.mobLots.at(cleanName).at(constants.lotPhase));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BaseSurvivalServer::SpawnMobs(Entity* self) {
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable))
|
|
return;
|
|
|
|
state.waveNumber++;
|
|
auto spawnNumber = state.waveNumber > constants.rewardInterval ? state.waveNumber - state.rewardTick - 1 : state.waveNumber;
|
|
|
|
for (const auto& tier : constants.baseMobsStartTier) {
|
|
if (tier == spawnNumber)
|
|
self->SetVar<uint32_t>(BaseMobSetIndexVariable, (self->GetVar<uint32_t>(BaseMobSetIndexVariable) + 1)
|
|
% (constants.baseMobsStartTier.size() - 1));
|
|
}
|
|
|
|
for (const auto& tier : constants.randMobsStartTier) {
|
|
if (tier == spawnNumber)
|
|
self->SetVar<uint32_t>(RandMobSetIndexVariable, (self->GetVar<uint32_t>(RandMobSetIndexVariable) + 1)
|
|
% (constants.randMobsStartTier.size() - 1));
|
|
}
|
|
|
|
if (state.waveNumber == constants.unlockNetwork3)
|
|
spawnerNetworks.randomNetworks.networks.at(2).isLocked = false;
|
|
|
|
SpawnerReset(spawnerNetworks.baseNetworks, false);
|
|
SpawnerReset(spawnerNetworks.randomNetworks, false);
|
|
SpawnerUpdate(self, spawnerNetworks.baseNetworks);
|
|
|
|
if (spawnNumber >= constants.mobSet2Wave) {
|
|
if (spawnNumber == constants.mobSet2Wave)
|
|
self->SetNetworkVar<std::string>(SpawnMobVariable, "2");
|
|
SpawnerUpdate(self, spawnerNetworks.randomNetworks);
|
|
}
|
|
|
|
if (spawnNumber >= constants.mobSet3Wave) {
|
|
if (spawnNumber == constants.mobSet3Wave)
|
|
self->SetNetworkVar<std::string>(SpawnMobVariable, "3");
|
|
SpawnerUpdate(self, spawnerNetworks.randomNetworks);
|
|
}
|
|
|
|
// If we reached the end of the spawn phase we increase the lost to make it more difficult
|
|
if (constants.useMobLots && constants.lotPhase < (mobSets.mobLots.begin()->second.size() - 1)
|
|
&& spawnNumber >= constants.baseMobsStartTier.back()) {
|
|
state.waveNumber = 1;
|
|
constants.lotPhase++;
|
|
|
|
UpdateMobLots(spawnerNetworks.baseNetworks);
|
|
UpdateMobLots(spawnerNetworks.randomNetworks);
|
|
}
|
|
}
|