diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index e7a7bd17..01c1540b 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -99,22 +99,6 @@ Entity::~Entity() { m_Character->SaveXMLToDatabase(); } - if (IsPlayer()) { - Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity(); - for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) { - script->OnPlayerExit(zoneControl, this); - } - - std::vector scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPTED_ACTIVITY); - for (Entity* scriptEntity : scriptedActs) { - if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds - for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) { - script->OnPlayerExit(scriptEntity, this); - } - } - } - } - CancelAllTimers(); CancelCallbackTimers(); diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index aacb2bc8..db60a1d1 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -217,37 +217,42 @@ void EntityManager::UpdateEntities(const float deltaTime) { m_EntitiesToKill.clear(); - for (const auto& entry : m_EntitiesToDelete) + for (const auto entry : m_EntitiesToDelete) { - auto* entity = GetEntity(entry); + // Get all this info first before we delete the player. + auto entityToDelete = GetEntity(entry); - m_Entities.erase(entry); + auto networkIdToErase = entityToDelete->GetNetworkId(); - const auto& iter = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entity); + const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete); - if (iter != m_EntitiesToGhost.end()) + if (entityToDelete) { - m_EntitiesToGhost.erase(iter); - } - - if (entity != nullptr) - { - if (entity->GetNetworkId() != 0) + // If we are a player run through the player destructor. + if (entityToDelete->IsPlayer()) { - m_LostNetworkIds.push(entity->GetNetworkId()); - } - - if (entity->IsPlayer()) - { - delete dynamic_cast(entity); + delete dynamic_cast(entityToDelete); } else { - delete entity; + delete entityToDelete; } - entity = nullptr; + entityToDelete = nullptr; + + if (networkIdToErase != 0) + { + m_LostNetworkIds.push(networkIdToErase); + } } + + if (ghostingToDelete != m_EntitiesToGhost.end()) + { + m_EntitiesToGhost.erase(ghostingToDelete); + } + + m_Entities.erase(entry); + } m_EntitiesToDelete.clear(); diff --git a/dGame/Player.cpp b/dGame/Player.cpp index 634d4a68..350ddca5 100644 --- a/dGame/Player.cpp +++ b/dGame/Player.cpp @@ -13,6 +13,7 @@ #include "dZoneManager.h" #include "CharacterComponent.h" #include "Mail.h" +#include "CppScripts.h" std::vector Player::m_Players = {}; @@ -329,5 +330,21 @@ Player::~Player() return; } + if (IsPlayer()) { + Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity(); + for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) { + script->OnPlayerExit(zoneControl, this); + } + + std::vector scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPTED_ACTIVITY); + for (Entity* scriptEntity : scriptedActs) { + if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds + for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) { + script->OnPlayerExit(scriptEntity, this); + } + } + } + } + m_Players.erase(iter); } diff --git a/dScripts/NjMonastryBossInstance.cpp b/dScripts/NjMonastryBossInstance.cpp index c6c8e324..27de7439 100644 --- a/dScripts/NjMonastryBossInstance.cpp +++ b/dScripts/NjMonastryBossInstance.cpp @@ -91,9 +91,27 @@ void NjMonastryBossInstance::OnPlayerLoaded(Entity *self, Entity *player) { void NjMonastryBossInstance::OnPlayerExit(Entity *self, Entity *player) { UpdatePlayer(self, player->GetObjectID(), true); - //TODO: Add functionality to dynamically turn off the large team variable when enough players leave. - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayerLeft", 0, 0, - player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); + // Fetch the total players loaded from the vars + auto totalPlayersLoaded = self->GetVar >(TotalPlayersLoadedVariable); + + // Find the player to remove + auto playerToRemove = std::find(totalPlayersLoaded.begin(), totalPlayersLoaded.end(), player->GetObjectID()); + + // If we found the player remove them from out list of players + if (playerToRemove != totalPlayersLoaded.end()) { + totalPlayersLoaded.erase(playerToRemove); + } else { + Game::logger->Log("NjMonastryBossInstance", "Failed to remove player at exit.\n"); + } + + // Set the players loaded var back + self->SetVar>(TotalPlayersLoadedVariable, totalPlayersLoaded); + + // Since this is an exit method, check if enough players have left. If enough have left + // resize the instance to account for such. + if (totalPlayersLoaded.size() <= 2) self->SetVar(LargeTeamVariable, false); + + GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayerLeft", 0, 0, player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); } void NjMonastryBossInstance::OnActivityTimerDone(Entity *self, const std::string &name) { diff --git a/dScripts/SGCannon.cpp b/dScripts/SGCannon.cpp index a5c2c843..3912364c 100644 --- a/dScripts/SGCannon.cpp +++ b/dScripts/SGCannon.cpp @@ -144,8 +144,9 @@ void SGCannon::OnMessageBoxResponse(Entity *self, Entity *sender, int32_t button if (player != nullptr) { if (button == 1 && identifier == u"Shooting_Gallery_Stop") { - static_cast(player)->SendToZone(1300); - + UpdatePlayer(self, player->GetObjectID(), true); + RemovePlayer(player->GetObjectID()); + StopGame(self, true); return; }