2021-12-05 17:54:36 +00:00
|
|
|
#include "BaseWavesServer.h"
|
|
|
|
#include "GameMessages.h"
|
|
|
|
#include "DestroyableComponent.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "dZoneManager.h"
|
2024-01-12 17:39:51 +00:00
|
|
|
#include "CharacterComponent.h"
|
2022-07-05 06:00:10 +00:00
|
|
|
#include "eMissionTaskType.h"
|
|
|
|
#include "eMissionState.h"
|
|
|
|
#include "MissionComponent.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "Character.h"
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::SetGameVariables(Entity* self) {
|
|
|
|
this->constants = std::move(GetConstants());
|
|
|
|
this->waves = std::move(GetWaves());
|
|
|
|
this->missions = std::move(GetWaveMissions());
|
|
|
|
this->spawners = std::move(GetSpawnerNames());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::BasePlayerLoaded(Entity* self, Entity* player) {
|
|
|
|
GameMessages::SendPlayerSetCameraCyclingMode(player->GetObjectID(), player->GetSystemAddress());
|
|
|
|
GameMessages::SendPlayerAllowedRespawn(player->GetObjectID(), true, player->GetSystemAddress());
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
state.waitingPlayers.push_back(player->GetObjectID());
|
|
|
|
state.players.push_back(player->GetObjectID());
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetNetworkVar<uint32_t>(NumberOfPlayersVariable, self->GetNetworkVar<uint32_t>(NumberOfPlayersVariable) + 1);
|
|
|
|
self->SetNetworkVar<std::string>(DefinePlayerToUIVariable, std::to_string(player->GetObjectID()), player->GetSystemAddress());
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// 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++;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!this->constants.introCelebration.empty()) {
|
|
|
|
self->SetNetworkVar<std::string>(WatchingIntroVariable, this->constants.introCelebration + "_"
|
|
|
|
+ std::to_string(player->GetObjectID()));
|
|
|
|
} else {
|
|
|
|
self->SetNetworkVar<bool>(ShowScoreboardVariable, true);
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
SetPlayerSpawnPoints();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
|
|
PlayerConfirmed(self);
|
|
|
|
} else {
|
|
|
|
UpdatePlayer(self, player->GetObjectID());
|
|
|
|
GetLeaderboardData(self, player->GetObjectID(), GetActivityID(self), 50);
|
|
|
|
ResetStats(player->GetObjectID());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::BaseStartup(Entity* self) {
|
|
|
|
self->SetVar<uint32_t>(PlayersAcceptedVariable, 0);
|
|
|
|
self->SetVar<bool>(PlayersReadyVariable, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::BasePlayerExit(Entity* self, Entity* player) {
|
2022-06-24 20:26:09 +00:00
|
|
|
auto waitingPlayerToErase = std::find(state.waitingPlayers.begin(), state.waitingPlayers.end(), player->GetObjectID());
|
|
|
|
if (waitingPlayerToErase != state.waitingPlayers.end()) state.waitingPlayers.erase(waitingPlayerToErase);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2022-06-24 20:26:09 +00:00
|
|
|
auto playerToErase = std::find(state.players.begin(), state.players.end(), player->GetObjectID());
|
|
|
|
if (playerToErase != state.players.end()) state.players.erase(playerToErase);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
|
|
PlayerConfirmed(self);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (state.players.empty())
|
|
|
|
return;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
SetActivityValue(self, player->GetObjectID(), 1, 0);
|
|
|
|
SetActivityValue(self, player->GetObjectID(), 2, 0);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetNetworkVar<uint32_t>(NumberOfPlayersVariable,
|
2023-12-28 04:18:20 +00:00
|
|
|
std::min(static_cast<uint32_t>(0), self->GetNetworkVar<uint32_t>(NumberOfPlayersVariable) - 1));
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::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 == "Survival_Update") {
|
|
|
|
const auto senderID = sender != nullptr ? sender->GetObjectID() : LWOOBJID_EMPTY;
|
|
|
|
if (UpdateSpawnedEnemies(self, senderID, param1)) {
|
|
|
|
const auto currentTime = GetActivityValue(self, senderID, 1);
|
|
|
|
const auto currentWave = GetActivityValue(self, senderID, 2);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& mission : this->missions) {
|
|
|
|
if (currentWave == mission.wave && currentTime <= mission.time) {
|
|
|
|
UpdateMissionForAllPlayers(self, mission.missionID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::BasePlayerDied(Entity* self, Entity* player) {
|
|
|
|
const auto currentTime = ActivityTimerGetCurrentTime(self, ClockTickTimer);
|
|
|
|
const auto finalTime = GetActivityValue(self, player->GetObjectID(), 1);
|
|
|
|
const auto finalWave = GetActivityValue(self, player->GetObjectID(), 2);
|
|
|
|
|
|
|
|
auto paramString = CheckAllPlayersDead() ? "true" : "false";
|
|
|
|
|
|
|
|
GameMessages::SendNotifyClientZoneObject(self->GetObjectID(), u"Player_Died", finalTime, finalWave,
|
|
|
|
player->GetObjectID(), paramString, player->GetSystemAddress());
|
|
|
|
|
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable)) {
|
|
|
|
player->Resurrect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GameOver(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::BasePlayerResurrected(Entity* self, Entity* player) {
|
|
|
|
GameMessages::SendNotifyClientZoneObject(self->GetObjectID(), u"Player_Res", 0, 0,
|
|
|
|
player->GetObjectID(), "", player->GetSystemAddress());
|
|
|
|
|
|
|
|
if (self->GetNetworkVar<bool>(WavesStartedVariable))
|
|
|
|
return;
|
|
|
|
|
|
|
|
self->SetNetworkVar<bool>(ShowScoreboardVariable, true);
|
|
|
|
SetPlayerSpawnPoints(player->GetObjectID());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::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()));
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (sender->IsPlayer()) {
|
|
|
|
auto* character = sender->GetCharacter();
|
|
|
|
if (character != nullptr) {
|
2024-01-12 17:39:51 +00:00
|
|
|
auto* characterComponent = sender->GetComponent<CharacterComponent>();
|
|
|
|
if (characterComponent) characterComponent->SendToZone(character->GetLastNonInstanceZoneID());
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::OnActivityTimerUpdate(Entity* self, const std::string& name, float_t remainingTime, float_t elapsedTime) {
|
|
|
|
if (name == AcceptedDelayTimer) {
|
|
|
|
self->SetNetworkVar<uint32_t>(UpdateDefaultStartTimerVariable, remainingTime);
|
|
|
|
} else if (name == ClockTickTimer) {
|
|
|
|
self->SetNetworkVar<float_t>(UpdateTimerVariable, elapsedTime);
|
|
|
|
} else if (name == NextWaveTickTimer || name == TimedWaveTimer || name == GameOverWinTimer) {
|
|
|
|
self->SetNetworkVar<uint32_t>(UpdateCooldownVariable, remainingTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::OnActivityTimerDone(Entity* self, const std::string& name) {
|
|
|
|
if (name == AcceptedDelayTimer) {
|
|
|
|
self->SetNetworkVar<uint32_t>(UpdateDefaultStartTimerVariable, 0);
|
|
|
|
ActivityTimerStart(self, AllAcceptedDelayTimer, 1, 1);
|
|
|
|
} else if (name == AllAcceptedDelayTimer) {
|
|
|
|
self->SetNetworkVar<bool>(ClearScoreboardVariable, true);
|
|
|
|
ActivityTimerStart(self, StartDelayTimer, 4, 4);
|
|
|
|
StartWaves(self);
|
|
|
|
} else if (name == StartDelayTimer) {
|
|
|
|
ActivityTimerStart(self, ClockTickTimer, 1);
|
|
|
|
SpawnWave(self);
|
|
|
|
ActivityTimerStart(self, PlaySpawnSoundTimer, 3, 3);
|
|
|
|
} else if (name == PlaySpawnSoundTimer) {
|
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player != nullptr) {
|
|
|
|
GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), spawnSoundGUID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (name == NextWaveTickTimer) {
|
|
|
|
self->SetNetworkVar<bool>(StartCooldownVariable, false);
|
|
|
|
SpawnWave(self);
|
|
|
|
} else if (name == WaveCompleteDelayTimer) {
|
|
|
|
self->SetNetworkVar<uint32_t>(StartCooldownVariable, constants.waveTime);
|
|
|
|
ActivityTimerStart(self, NextWaveTickTimer, 1, constants.waveTime);
|
|
|
|
} else if (name == TimedWaveTimer) {
|
|
|
|
ActivityTimerStart(self, WaveCompleteDelayTimer, constants.waveCompleteDelay, constants.waveCompleteDelay);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
const auto currentTime = ActivityTimerGetCurrentTime(self, ClockTickTimer);
|
|
|
|
const auto currentWave = state.waveNumber;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-12-28 04:18:20 +00:00
|
|
|
self->SetNetworkVar<uint32_t>(WaveCompleteVariable, { currentWave, static_cast<uint32_t>(currentTime) });
|
2021-12-05 17:54:36 +00:00
|
|
|
} else if (name == GameOverWinTimer) {
|
|
|
|
GameOver(self, true);
|
|
|
|
} else if (name == CinematicDoneTimer) {
|
2023-07-15 20:56:33 +00:00
|
|
|
for (auto* boss : Game::entityManager->GetEntitiesInGroup("boss")) {
|
2021-12-05 17:54:36 +00:00
|
|
|
boss->OnFireEventServerSide(self, "startAI");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::ResetStats(LWOOBJID playerID) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player != nullptr) {
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::PlayerConfirmed(Entity* self) {
|
|
|
|
std::vector<LWOOBJID> confirmedPlayers{};
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& playerID : state.players) {
|
|
|
|
auto pass = false;
|
|
|
|
for (const auto& waitingPlayerID : state.waitingPlayers) {
|
|
|
|
if (waitingPlayerID == playerID)
|
|
|
|
pass = true;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!pass)
|
|
|
|
confirmedPlayers.push_back(playerID);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
auto playerIndex = 1;
|
|
|
|
for (const auto& playerID : confirmedPlayers) {
|
|
|
|
self->SetNetworkVar<std::string>(PlayerConfirmVariable + GeneralUtils::to_u16string(playerIndex), std::to_string(playerID));
|
|
|
|
playerIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::PlayerAccepted(Entity* self, LWOOBJID playerID) {
|
|
|
|
state.waitingPlayers.erase(std::find(state.waitingPlayers.begin(), state.waitingPlayers.end(), playerID));
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::StartWaves(Entity* self) {
|
|
|
|
GameMessages::SendActivityStart(self->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetNetworkVar<std::string>(WatchingIntroVariable, "");
|
|
|
|
self->SetVar<bool>(PlayersReadyVariable, true);
|
|
|
|
self->SetVar<uint32_t>(BaseMobSetIndexVariable, 0);
|
|
|
|
self->SetVar<uint32_t>(RandMobSetIndexVariable, 0);
|
|
|
|
self->SetVar<bool>(AcceptedDelayStartedVariable, false);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
state.waitingPlayers.clear();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
const auto player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player != nullptr) {
|
|
|
|
state.waitingPlayers.push_back(playerID);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
UpdatePlayer(self, playerID);
|
|
|
|
GetLeaderboardData(self, playerID, GetActivityID(self), 1);
|
|
|
|
ResetStats(playerID);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!self->GetVar<bool>(FirstTimeDoneVariable)) {
|
|
|
|
TakeActivityCost(self, playerID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetVar<bool>(FirstTimeDoneVariable, true);
|
|
|
|
self->SetVar<std::string>(MissionTypeVariable, state.players.size() == 1 ? "survival_time_solo" : "survival_time_team");
|
|
|
|
self->SetNetworkVar<bool>(WavesStartedVariable, true);
|
|
|
|
self->SetNetworkVar<std::string>(StartWaveMessageVariable, "Start!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
bool BaseWavesServer::CheckAllPlayersDead() {
|
|
|
|
auto deadPlayers = 0;
|
|
|
|
|
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player == nullptr || player->GetIsDead()) {
|
|
|
|
deadPlayers++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return deadPlayers >= state.players.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::SetPlayerSpawnPoints(const LWOOBJID& specificPlayerID) {
|
|
|
|
auto spawnerIndex = 1;
|
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player != nullptr && (specificPlayerID == LWOOBJID_EMPTY || playerID == specificPlayerID)) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto possibleSpawners = Game::entityManager->GetEntitiesInGroup("P" + std::to_string(spawnerIndex) + "_Spawn");
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!possibleSpawners.empty()) {
|
|
|
|
auto* spawner = possibleSpawners.at(0);
|
|
|
|
GameMessages::SendTeleport(playerID, spawner->GetPosition(), spawner->GetRotation(), player->GetSystemAddress(), true);
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
spawnerIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::GameOver(Entity* self, bool won) {
|
|
|
|
if (!CheckAllPlayersDead() && !won)
|
|
|
|
return;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
ActivityTimerStopAllTimers(self);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Reset all the spawners
|
|
|
|
state.waveNumber = 0;
|
|
|
|
state.totalSpawned = 0;
|
|
|
|
state.currentSpawned = 0;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetNetworkVar<bool>(WavesStartedVariable, false);
|
|
|
|
self->SetNetworkVar<uint32_t>(StartCooldownVariable, 0);
|
|
|
|
SetPlayerSpawnPoints();
|
|
|
|
ClearSpawners();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player == nullptr)
|
|
|
|
continue;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
const auto score = GetActivityValue(self, playerID, 0);
|
|
|
|
const auto time = GetActivityValue(self, playerID, 1);
|
|
|
|
const auto wave = GetActivityValue(self, playerID, 2);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
GameMessages::SendNotifyClientZoneObject(self->GetObjectID(), u"Update_ScoreBoard", time, 0,
|
|
|
|
playerID, std::to_string(wave), UNASSIGNED_SYSTEM_ADDRESS);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (won) {
|
|
|
|
SetPlayerSpawnPoints();
|
|
|
|
self->SetNetworkVar<bool>(ShowScoreboardVariable, true);
|
|
|
|
} else {
|
|
|
|
player->Resurrect();
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Update all mission progression
|
|
|
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
|
|
|
if (missionComponent != nullptr) {
|
2022-01-18 05:55:01 +00:00
|
|
|
missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, time, self->GetObjectID(), self->GetVar<std::string>(MissionTypeVariable));
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2022-06-13 03:19:27 +00:00
|
|
|
StopActivity(self, playerID, wave, time, score);
|
2023-06-22 02:46:01 +00:00
|
|
|
SaveScore(self, playerID, wave, time);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::GameWon(Entity* self) {
|
|
|
|
ActivityTimerStopAllTimers(self);
|
|
|
|
|
|
|
|
const auto winDelay = waves.back().winDelay;
|
|
|
|
ActivityTimerStart(self, GameOverWinTimer, 1, winDelay);
|
|
|
|
self->SetNetworkVar<uint32_t>(StartTimedWaveVariable, { winDelay, state.waveNumber });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::SpawnNow(const std::string& spawnerName, uint32_t amount, LOT spawnLot) {
|
2023-07-17 22:55:33 +00:00
|
|
|
const auto spawners = Game::zoneManager->GetSpawnersByName(spawnerName);
|
2021-12-05 17:54:36 +00:00
|
|
|
for (auto* spawner : spawners) {
|
|
|
|
if (spawnLot != LOT_NULL) {
|
|
|
|
spawner->SetSpawnLot(spawnLot);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
spawner->m_Info.amountMaintained = amount;
|
|
|
|
spawner->m_Info.maxToSpawn = amount;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
spawner->Reset();
|
|
|
|
spawner->Activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::SpawnWave(Entity* self) {
|
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable))
|
|
|
|
return;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// If there's no wave left
|
|
|
|
if (state.waveNumber >= waves.size()) {
|
|
|
|
GameOver(self);
|
|
|
|
return;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
const auto wave = waves.at(state.waveNumber);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Handles meta info to the client about the current round
|
2023-12-28 04:18:20 +00:00
|
|
|
if (wave.winDelay != static_cast<uint32_t>(-1)) {
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetNetworkVar<bool>(WonWaveVariable, true);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Close the game if we don't expect a notification from an other entity to end it
|
|
|
|
if (!wave.notifyWin) {
|
|
|
|
GameWon(self);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2023-03-12 14:21:27 +00:00
|
|
|
if (player && player->GetIsDead()) {
|
2021-12-05 17:54:36 +00:00
|
|
|
player->Resurrect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-12-28 04:18:20 +00:00
|
|
|
if (wave.timeLimit != static_cast<uint32_t>(-1)) {
|
2021-12-05 17:54:36 +00:00
|
|
|
ActivityTimerStart(self, TimedWaveTimer, 1.0f, wave.timeLimit);
|
|
|
|
self->SetNetworkVar<uint32_t>(StartTimedWaveVariable, { wave.timeLimit, state.waveNumber + 1 });
|
|
|
|
} else {
|
|
|
|
self->SetNetworkVar<uint32_t>(NewWaveVariable, state.waveNumber + 1);
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// NOTE: The script does some stuff with events here, although BONS does not have those
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Optional cinematics to play
|
|
|
|
if (!wave.cinematic.empty()) {
|
|
|
|
ActivityTimerStart(self, CinematicDoneTimer, wave.cinematicLength, wave.cinematicLength);
|
|
|
|
self->SetNetworkVar<std::string>(StartCinematicVariable, wave.cinematic);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Spawn the enemies
|
|
|
|
state.currentSpawned = 0;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& mobDefinition : wave.waveMobs) {
|
|
|
|
SpawnNow(mobDefinition.spawnerName, mobDefinition.amountToSpawn, mobDefinition.lot);
|
|
|
|
state.currentSpawned += mobDefinition.amountToSpawn;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
state.waveNumber++;
|
|
|
|
state.totalSpawned += state.currentSpawned;
|
|
|
|
self->SetNetworkVar<uint32_t>(NumRemainingVariable, state.currentSpawned);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
bool BaseWavesServer::UpdateSpawnedEnemies(Entity* self, LWOOBJID enemyID, uint32_t score) {
|
|
|
|
if (!self->GetNetworkVar<bool>(WavesStartedVariable))
|
|
|
|
return false;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
state.currentSpawned--;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* enemy = Game::entityManager->GetEntity(enemyID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (enemy != nullptr && enemy->IsPlayer() && IsPlayerInActivity(self, enemyID)) {
|
|
|
|
SetActivityValue(self, enemyID, 0, GetActivityValue(self, enemyID, 0) + score);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (state.currentSpawned <= 0) {
|
|
|
|
const auto currentTime = ActivityTimerGetCurrentTime(self, ClockTickTimer);
|
|
|
|
const auto completedWave = state.waveNumber - 1;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// When the last enemy is smashed (e.g. in last wave - 1)
|
|
|
|
if (state.waveNumber >= waves.size() - 1) {
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// If there's no more follow up waves, (e.g in last wave), end the game. Generally called by some other script
|
|
|
|
if (state.waveNumber >= waves.size()) {
|
|
|
|
GameWon(self);
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
ActivityTimerStopAllTimers(self);
|
|
|
|
self->SetNetworkVar<float_t>(UpdateTimerVariable, currentTime);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
ActivityTimerStart(self, WaveCompleteDelayTimer, constants.waveCompleteDelay, constants.waveCompleteDelay);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
const auto waveMission = waves.at(completedWave).missions;
|
|
|
|
const auto soloWaveMissions = waves.at(completedWave).soloMissions;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player != nullptr && !player->GetIsDead()) {
|
|
|
|
SetActivityValue(self, playerID, 1, currentTime);
|
|
|
|
SetActivityValue(self, playerID, 2, state.waveNumber);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Update player missions
|
|
|
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
|
|
|
if (missionComponent != nullptr) {
|
|
|
|
for (const auto& missionID : waveMission) {
|
2022-01-18 05:55:01 +00:00
|
|
|
// Get the mission state
|
|
|
|
auto missionState = missionComponent->GetMissionState(missionID);
|
|
|
|
// For some reason these achievements are not accepted by default, so we accept them here if they arent already.
|
|
|
|
if (missionState != eMissionState::COMPLETE && missionState != eMissionState::UNKNOWN) {
|
|
|
|
missionComponent->AcceptMission(missionID);
|
|
|
|
missionState = missionComponent->GetMissionState(missionID);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2022-01-18 05:55:01 +00:00
|
|
|
if (missionState != eMissionState::COMPLETE) {
|
|
|
|
auto mission = missionComponent->GetMission(missionID);
|
|
|
|
if (mission != nullptr) {
|
|
|
|
mission->Progress(eMissionTaskType::SCRIPT, self->GetLOT());
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-18 05:55:01 +00:00
|
|
|
// Progress solo missions
|
2021-12-05 17:54:36 +00:00
|
|
|
if (state.players.size() == 1) {
|
2022-01-18 05:55:01 +00:00
|
|
|
for (const auto& missionID : soloWaveMissions) {
|
|
|
|
// Get the mission state
|
|
|
|
auto missionState = missionComponent->GetMissionState(missionID);
|
|
|
|
// For some reason these achievements are not accepted by default, so we accept them here if they arent already.
|
|
|
|
if (missionState != eMissionState::COMPLETE && missionState != eMissionState::UNKNOWN) {
|
|
|
|
missionComponent->AcceptMission(missionID);
|
|
|
|
missionState = missionComponent->GetMissionState(missionID);
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2022-01-18 05:55:01 +00:00
|
|
|
if (missionState != eMissionState::COMPLETE) {
|
|
|
|
auto mission = missionComponent->GetMission(missionID);
|
|
|
|
if (mission != nullptr) {
|
|
|
|
mission->Progress(eMissionTaskType::SCRIPT, self->GetLOT());
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Might seem odd to send the next wave but the client isn't 0-indexed so it thinks it completed the correct wave
|
2023-12-28 04:18:20 +00:00
|
|
|
self->SetNetworkVar<uint32_t>(WaveCompleteVariable, { state.waveNumber, static_cast<uint32_t>(currentTime) });
|
2021-12-05 17:54:36 +00:00
|
|
|
return true;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
self->SetNetworkVar<uint32_t>(NumRemainingVariable, state.currentSpawned);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done
|
|
|
|
void BaseWavesServer::UpdateMissionForAllPlayers(Entity* self, uint32_t missionID) {
|
|
|
|
for (const auto& playerID : state.players) {
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (player != nullptr) {
|
|
|
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
2022-01-18 05:55:01 +00:00
|
|
|
if (missionComponent == nullptr) return;
|
|
|
|
// Get the mission state
|
|
|
|
auto missionState = missionComponent->GetMissionState(missionID);
|
|
|
|
// For some reason these achievements are not accepted by default, so we accept them here if they arent already.
|
|
|
|
if (missionState != eMissionState::COMPLETE && missionState != eMissionState::UNKNOWN) {
|
|
|
|
missionComponent->AcceptMission(missionID);
|
|
|
|
missionState = missionComponent->GetMissionState(missionID);
|
|
|
|
}
|
|
|
|
if (missionState != eMissionState::COMPLETE) {
|
|
|
|
auto mission = missionComponent->GetMission(missionID);
|
|
|
|
if (mission != nullptr) {
|
|
|
|
mission->Progress(eMissionTaskType::SCRIPT, self->GetLOT());
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BaseWavesServer::ClearSpawners() {
|
|
|
|
for (const auto& spawnerName : spawners) {
|
2023-07-17 22:55:33 +00:00
|
|
|
const auto spawnerObjects = Game::zoneManager->GetSpawnersByName(spawnerName);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
for (auto* spawnerObject : spawnerObjects) {
|
|
|
|
spawnerObject->Reset();
|
|
|
|
spawnerObject->Deactivate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|