From 1e9b18fa9d86ab2593cd1700b65503bf18656da9 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 11 Jun 2026 07:12:43 -0700 Subject: [PATCH] chore: cleanup usage of pointers in the activity component (#1989) * chore: cleanup usage of pointers in the activity component * feedback --- dGame/dComponents/ActivityComponent.cpp | 313 ++++++++---------- dGame/dComponents/ActivityComponent.h | 62 ++-- .../02_server/Map/AG/NpcAgCourseStarter.cpp | 20 +- dScripts/ActivityManager.cpp | 2 +- 4 files changed, 167 insertions(+), 230 deletions(-) diff --git a/dGame/dComponents/ActivityComponent.cpp b/dGame/dComponents/ActivityComponent.cpp index 2dfd5e95..7fa73f01 100644 --- a/dGame/dComponents/ActivityComponent.cpp +++ b/dGame/dComponents/ActivityComponent.cpp @@ -22,6 +22,7 @@ #include "eMatchUpdate.h" #include "ServiceType.h" #include "MessageType/Chat.h" +#include "ObjectIDManager.h" #include "CDCurrencyTableTable.h" #include "CDActivityRewardsTable.h" @@ -29,6 +30,11 @@ #include "LeaderboardManager.h" #include "CharacterComponent.h" #include "Amf3.h" +#include + +namespace { + const ActivityInstance g_EmptyInstance{ nullptr, CDActivities{} }; +} ActivityComponent::ActivityComponent(Entity* parent, int32_t componentID) : Component(parent, componentID) { RegisterMsg(&ActivityComponent::OnGetObjectReportInfo); @@ -71,9 +77,9 @@ void ActivityComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIniti if (m_DirtyActivityInfo) { outBitStream.Write(m_ActivityPlayers.size()); if (!m_ActivityPlayers.empty()) { - for (const auto& activityPlayer : m_ActivityPlayers) { - outBitStream.Write(activityPlayer->playerID); - for (const auto& activityValue : activityPlayer->values) { + for (const auto& [playerID, values] : m_ActivityPlayers) { + outBitStream.Write(playerID); + for (const auto& activityValue : values) { outBitStream.Write(activityValue); } } @@ -111,78 +117,81 @@ void ActivityComponent::PlayerJoin(Entity* player) { if (HasLobby()) { PlayerJoinLobby(player); } else if (!IsPlayedBy(player)) { - auto* instance = NewInstance(); - instance->AddParticipant(player); + NewInstance().AddParticipant(player); } } void ActivityComponent::PlayerJoinLobby(Entity* player) { if (!m_Parent->HasComponent(eReplicaComponentType::QUICK_BUILD)) GameMessages::SendMatchResponse(player, player->GetSystemAddress(), 0); // tell the client they joined a lobby - LobbyPlayer* newLobbyPlayer = new LobbyPlayer(); - newLobbyPlayer->entityID = player->GetObjectID(); - Lobby* playerLobby = nullptr; + LobbyPlayer newLobbyPlayer{}; + newLobbyPlayer.entityID = player->GetObjectID(); + LWOOBJID playerLobbyID = LWOOBJID_EMPTY; auto* character = player->GetCharacter(); if (character != nullptr) character->SetLastNonInstanceZoneID(Game::zoneManager->GetZone()->GetWorldID()); - for (Lobby* lobby : m_Queue) { - if (lobby->players.size() < m_ActivityInfo.maxTeamSize || m_ActivityInfo.maxTeamSize == 1 && lobby->players.size() < m_ActivityInfo.maxTeams) { + for (auto& [lobbyID, lobby] : m_Queue) { + if (lobby.players.size() < m_ActivityInfo.maxTeamSize || m_ActivityInfo.maxTeamSize == 1 && lobby.players.size() < m_ActivityInfo.maxTeams) { // If an empty slot in an existing lobby is found - lobby->players.push_back(newLobbyPlayer); - playerLobby = lobby; + lobby.players.push_back(newLobbyPlayer); + playerLobbyID = lobbyID; // Update the joining player on players already in the lobby, and update players already in the lobby on the joining player - std::string matchUpdateJoined = "player=9:" + std::to_string(player->GetObjectID()) + "\nplayerName=0:" + player->GetCharacter()->GetName(); - for (LobbyPlayer* joinedPlayer : lobby->players) { - auto* entity = joinedPlayer->GetEntity(); + LDFData playerLDF("player", player->GetObjectID()); + LDFData playerName("playerName", player->GetCharacter()->GetName()); + std::string matchUpdateJoined = playerLDF.GetString() + "\n" + playerName.GetString(); + for (const auto& joinedPlayer : lobby.players) { + auto* const entity = joinedPlayer.GetEntity(); if (entity == nullptr) { continue; } - std::string matchUpdate = "player=9:" + std::to_string(entity->GetObjectID()) + "\nplayerName=0:" + entity->GetCharacter()->GetName(); + LDFData entityLDF("player", entity->GetObjectID()); + LDFData entityName("playerName", entity->GetCharacter()->GetName()); + std::string matchUpdate = entityLDF.GetString() + "\n" + entityName.GetString(); GameMessages::SendMatchUpdate(player, player->GetSystemAddress(), matchUpdate, eMatchUpdate::PLAYER_ADDED); - PlayerReady(entity, joinedPlayer->ready); + PlayerReady(entity, joinedPlayer.ready); GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchUpdateJoined, eMatchUpdate::PLAYER_ADDED); } + break; } } - if (!playerLobby) { + if (playerLobbyID == LWOOBJID_EMPTY) { // If all lobbies are full - playerLobby = new Lobby(); - playerLobby->players.push_back(newLobbyPlayer); - playerLobby->timer = m_ActivityInfo.waitTime / 1000; - m_Queue.push_back(playerLobby); + playerLobbyID = ObjectIDManager::GenerateObjectID(); + auto& newLobby = m_Queue[playerLobbyID]; + newLobby.players.push_back(newLobbyPlayer); + newLobby.timer = m_ActivityInfo.waitTime / 1000; } + const auto& lobby = m_Queue[playerLobbyID]; - if (m_ActivityInfo.maxTeamSize != 1 && playerLobby->players.size() >= m_ActivityInfo.minTeamSize || m_ActivityInfo.maxTeamSize == 1 && playerLobby->players.size() >= m_ActivityInfo.minTeams) { + if (m_ActivityInfo.maxTeamSize != 1 && lobby.players.size() >= m_ActivityInfo.minTeamSize || m_ActivityInfo.maxTeamSize == 1 && lobby.players.size() >= m_ActivityInfo.minTeams) { // Update the joining player on the match timer - std::string matchTimerUpdate = "time=3:" + std::to_string(playerLobby->timer); - GameMessages::SendMatchUpdate(player, player->GetSystemAddress(), matchTimerUpdate, eMatchUpdate::PHASE_WAIT_READY); + LDFData matchTimer("time", lobby.timer); + GameMessages::SendMatchUpdate(player, player->GetSystemAddress(), matchTimer.GetString(), eMatchUpdate::PHASE_WAIT_READY); } } void ActivityComponent::PlayerLeave(LWOOBJID playerID) { - // Removes the player from a lobby and notifies the others, not applicable for non-lobby instances - for (Lobby* lobby : m_Queue) { - for (int i = 0; i < lobby->players.size(); ++i) { - if (lobby->players[i]->entityID == playerID) { - std::string matchUpdateLeft = "player=9:" + std::to_string(playerID); - for (LobbyPlayer* lobbyPlayer : lobby->players) { - auto* entity = lobbyPlayer->GetEntity(); + for (auto& lobby : m_Queue | std::views::values) { + for (int i = 0; i < lobby.players.size(); i++) { + const auto& player = lobby.players[i]; + if (player.entityID == playerID) { + LDFData matchUpdateLeft("player", playerID); + for (const auto& lobbyPlayer : lobby.players) { + auto* const entity = lobbyPlayer.GetEntity(); if (entity == nullptr) continue; - GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchUpdateLeft, eMatchUpdate::PLAYER_REMOVED); + GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchUpdateLeft.GetString(), eMatchUpdate::PLAYER_REMOVED); } - delete lobby->players[i]; - lobby->players[i] = nullptr; - lobby->players.erase(lobby->players.begin() + i); + lobby.players.erase(lobby.players.begin() + i); return; } @@ -191,85 +200,79 @@ void ActivityComponent::PlayerLeave(LWOOBJID playerID) { } void ActivityComponent::Update(float deltaTime) { - std::vector lobbiesToRemove{}; + std::vector lobbiesToRemove{}; // Ticks all the lobbies, not applicable for non-instance activities - for (Lobby* lobby : m_Queue) { - for (LobbyPlayer* player : lobby->players) { - auto* entity = player->GetEntity(); + for (auto& [lobbyID, lobby] : m_Queue) { + for (const auto& player : lobby.players) { + const auto* const entity = player.GetEntity(); if (entity == nullptr) { - PlayerLeave(player->entityID); + PlayerLeave(player.entityID); return; } } - if (lobby->players.empty()) { - lobbiesToRemove.push_back(lobby); + if (lobby.players.empty()) { + lobbiesToRemove.push_back(lobbyID); continue; } // Update the match time for all players - if (m_ActivityInfo.maxTeamSize != 1 && lobby->players.size() >= m_ActivityInfo.minTeamSize - || m_ActivityInfo.maxTeamSize == 1 && lobby->players.size() >= m_ActivityInfo.minTeams) { - if (lobby->timer == m_ActivityInfo.waitTime / 1000) { - for (LobbyPlayer* joinedPlayer : lobby->players) { - auto* entity = joinedPlayer->GetEntity(); + if (m_ActivityInfo.maxTeamSize != 1 && lobby.players.size() >= m_ActivityInfo.minTeamSize + || m_ActivityInfo.maxTeamSize == 1 && lobby.players.size() >= m_ActivityInfo.minTeams) { + if (lobby.timer == m_ActivityInfo.waitTime / 1000) { + for (const auto& joinedPlayer : lobby.players) { + auto* const entity = joinedPlayer.GetEntity(); if (entity == nullptr) continue; - std::string matchTimerUpdate = "time=3:" + std::to_string(lobby->timer); - GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchTimerUpdate, eMatchUpdate::PHASE_WAIT_READY); + LDFData matchTimerUpdate("time", lobby.timer); + GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchTimerUpdate.GetString(), eMatchUpdate::PHASE_WAIT_READY); } } - lobby->timer -= deltaTime; + lobby.timer -= deltaTime; } bool lobbyReady = true; - for (LobbyPlayer* player : lobby->players) { - if (player->ready) continue; + for (const auto& player : lobby.players) { + if (player.ready) continue; lobbyReady = false; } // If everyone's ready, jump the timer - if (lobbyReady && lobby->timer > m_ActivityInfo.startDelay / 1000) { - lobby->timer = m_ActivityInfo.startDelay / 1000; + if (lobbyReady && lobby.timer > m_ActivityInfo.startDelay / 1000) { + lobby.timer = m_ActivityInfo.startDelay / 1000; // Update players in lobby on switch to start delay - std::string matchTimerUpdate = "time=3:" + std::to_string(lobby->timer); - for (LobbyPlayer* player : lobby->players) { - auto* entity = player->GetEntity(); + LDFData matchTimerUpdate("time", lobby.timer); + for (const auto& player : lobby.players) { + auto* const entity = player.GetEntity(); if (entity == nullptr) continue; - GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchTimerUpdate, eMatchUpdate::PHASE_WAIT_START); + GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchTimerUpdate.GetString(), eMatchUpdate::PHASE_WAIT_START); } } // The timer has elapsed, start the instance - if (lobby->timer <= 0.0f) { + if (lobby.timer <= 0.0f) { LOG("Setting up instance."); - ActivityInstance* instance = NewInstance(); - LoadPlayersIntoInstance(instance, lobby->players); - instance->StartZone(); - lobbiesToRemove.push_back(lobby); + auto& instance = NewInstance(); + LoadPlayersIntoInstance(instance, lobby.players); + instance.StartZone(); + lobbiesToRemove.push_back(lobbyID); } } - while (!lobbiesToRemove.empty()) { - RemoveLobby(lobbiesToRemove.front()); - lobbiesToRemove.erase(lobbiesToRemove.begin()); + for (const auto id : lobbiesToRemove) { + RemoveLobby(id); } } -void ActivityComponent::RemoveLobby(Lobby* lobby) { - for (int i = 0; i < m_Queue.size(); ++i) { - if (m_Queue[i] == lobby) { - m_Queue.erase(m_Queue.begin() + i); - return; - } - } +void ActivityComponent::RemoveLobby(const LWOOBJID lobbyID) { + if (m_Queue.contains(lobbyID)) m_Queue.erase(lobbyID); } bool ActivityComponent::HasLobby() const { @@ -278,9 +281,9 @@ bool ActivityComponent::HasLobby() const { } bool ActivityComponent::PlayerIsInQueue(Entity* player) { - for (Lobby* lobby : m_Queue) { - for (LobbyPlayer* lobbyPlayer : lobby->players) { - if (player->GetObjectID() == lobbyPlayer->entityID) return true; + for (const auto& lobby : m_Queue | std::views::values) { + for (const auto& lobbyPlayer : lobby.players) { + if (player->GetObjectID() == lobbyPlayer.entityID) return true; } } @@ -288,8 +291,8 @@ bool ActivityComponent::PlayerIsInQueue(Entity* player) { } bool ActivityComponent::IsPlayedBy(Entity* player) const { - for (const auto* instance : this->m_Instances) { - for (const auto* instancePlayer : instance->GetParticipants()) { + for (const auto& instance : m_Instances) { + for (const auto* instancePlayer : instance.GetParticipants()) { if (instancePlayer != nullptr && instancePlayer->GetObjectID() == player->GetObjectID()) return true; } @@ -299,8 +302,8 @@ bool ActivityComponent::IsPlayedBy(Entity* player) const { } bool ActivityComponent::IsPlayedBy(LWOOBJID playerID) const { - for (const auto* instance : this->m_Instances) { - for (const auto* instancePlayer : instance->GetParticipants()) { + for (const auto& instance : m_Instances) { + for (const auto* instancePlayer : instance.GetParticipants()) { if (instancePlayer != nullptr && instancePlayer->GetObjectID() == playerID) return true; } @@ -329,136 +332,95 @@ bool ActivityComponent::TakeCost(Entity* player) const { } void ActivityComponent::PlayerReady(Entity* player, bool bReady) { - for (Lobby* lobby : m_Queue) { - for (LobbyPlayer* lobbyPlayer : lobby->players) { - if (lobbyPlayer->entityID == player->GetObjectID()) { + for (auto& lobby : m_Queue | std::views::values) { + for (auto& lobbyPlayer : lobby.players) { + if (lobbyPlayer.entityID == player->GetObjectID()) { - lobbyPlayer->ready = bReady; + lobbyPlayer.ready = bReady; // Update players in lobby on player being ready - std::string matchReadyUpdate = "player=9:" + std::to_string(player->GetObjectID()); + LDFData matchReadyUpdate("player", player->GetObjectID()); eMatchUpdate readyStatus = eMatchUpdate::PLAYER_READY; if (!bReady) readyStatus = eMatchUpdate::PLAYER_NOT_READY; - for (LobbyPlayer* otherPlayer : lobby->players) { - auto* entity = otherPlayer->GetEntity(); + for (const auto& otherPlayer : lobby.players) { + auto* const entity = otherPlayer.GetEntity(); if (entity == nullptr) continue; - GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchReadyUpdate, readyStatus); + GameMessages::SendMatchUpdate(entity, entity->GetSystemAddress(), matchReadyUpdate.GetString(), readyStatus); } } } } } -ActivityInstance* ActivityComponent::NewInstance() { - auto* instance = new ActivityInstance(m_Parent, m_ActivityInfo); - m_Instances.push_back(instance); - return instance; +ActivityInstance& ActivityComponent::NewInstance() { + m_Instances.push_back(ActivityInstance(m_Parent, m_ActivityInfo)); + return m_Instances.back(); } -void ActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector& lobby) const { - for (LobbyPlayer* player : lobby) { - auto* entity = player->GetEntity(); +void ActivityComponent::LoadPlayersIntoInstance(ActivityInstance& instance, const std::vector& lobby) const { + for (const auto& player : lobby) { + auto* const entity = player.GetEntity(); if (entity == nullptr || !CheckCost(entity)) { continue; } - instance->AddParticipant(entity); + instance.AddParticipant(entity); } } -const std::vector& ActivityComponent::GetInstances() const { - return m_Instances; -} - -ActivityInstance* ActivityComponent::GetInstance(const LWOOBJID playerID) { - for (const auto* instance : GetInstances()) { - for (const auto* participant : instance->GetParticipants()) { +const ActivityInstance& ActivityComponent::GetInstance(const LWOOBJID playerID) const { + for (const auto& instance : m_Instances) { + for (const auto* participant : instance.GetParticipants()) { if (participant->GetObjectID() == playerID) - return const_cast(instance); + return instance; } } - return nullptr; + return g_EmptyInstance; } -void ActivityComponent::ClearInstances() { - for (ActivityInstance* instance : m_Instances) { - delete instance; - } - m_Instances.clear(); -} - -ActivityPlayer* ActivityComponent::GetActivityPlayerData(LWOOBJID playerID) { - for (auto* activityData : m_ActivityPlayers) { - if (activityData->playerID == playerID) { - return activityData; - } - } - - return nullptr; +bool ActivityComponent::PlayerHasActivityData(LWOOBJID playerID) const { + return m_ActivityPlayers.contains(playerID); } void ActivityComponent::RemoveActivityPlayerData(LWOOBJID playerID) { - for (size_t i = 0; i < m_ActivityPlayers.size(); i++) { - if (m_ActivityPlayers[i]->playerID == playerID) { - delete m_ActivityPlayers[i]; - m_ActivityPlayers[i] = nullptr; - - m_ActivityPlayers.erase(m_ActivityPlayers.begin() + i); - m_DirtyActivityInfo = true; - Game::entityManager->SerializeEntity(m_Parent); - - return; - } - } -} - -ActivityPlayer* ActivityComponent::AddActivityPlayerData(LWOOBJID playerID) { - auto* data = GetActivityPlayerData(playerID); - if (data != nullptr) - return data; - - m_ActivityPlayers.push_back(new ActivityPlayer{ playerID, {} }); + m_ActivityPlayers.erase(playerID); m_DirtyActivityInfo = true; - Game::entityManager->SerializeEntity(m_Parent); - - return GetActivityPlayerData(playerID); } -float_t ActivityComponent::GetActivityValue(LWOOBJID playerID, uint32_t index) { - auto value = -1.0f; +float_t ActivityComponent::GetActivityValue(LWOOBJID playerID, uint32_t index) const { + float value = -1.0f; - auto* data = GetActivityPlayerData(playerID); - if (data != nullptr) { - value = data->values[std::min(index, static_cast(9))]; + const auto& data = m_ActivityPlayers.find(playerID); + if (data != m_ActivityPlayers.cend()) { + value = data->second[std::min(index, static_cast(9))]; } - + LOG_DEBUG("Player %llu has score %f at index %i", playerID, value, index); return value; } void ActivityComponent::SetActivityValue(LWOOBJID playerID, uint32_t index, float_t value) { - auto* data = AddActivityPlayerData(playerID); - if (data != nullptr) { - data->values[std::min(index, static_cast(9))] = value; - } + auto& data = m_ActivityPlayers[playerID]; + data[std::min(index, static_cast(9))] = value; + LOG_DEBUG("%llu index %i has score of %f", playerID, index, value); m_DirtyActivityInfo = true; Game::entityManager->SerializeEntity(m_Parent); } void ActivityComponent::PlayerRemove(LWOOBJID playerID) { - for (auto* instance : GetInstances()) { - auto participants = instance->GetParticipants(); + for (int i = 0; i < m_Instances.size(); i++) { + auto& instance = m_Instances[i]; + auto participants = instance.GetParticipants(); for (const auto* participant : participants) { if (participant != nullptr && participant->GetObjectID() == playerID) { - instance->RemoveParticipant(participant); + instance.RemoveParticipant(participant); RemoveActivityPlayerData(playerID); // If the instance is empty after the delete of the participant, delete the instance too - if (instance->GetParticipants().empty()) { - m_Instances.erase(std::find(m_Instances.begin(), m_Instances.end(), instance)); - delete instance; + if (instance.GetParticipants().empty()) { + m_Instances.erase(m_Instances.begin() + i); } return; } @@ -595,14 +557,13 @@ bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& auto& instances = activityInfo.PushDebug("Instances: " + std::to_string(m_Instances.size())); size_t i = 0; for (const auto& activityInstance : m_Instances) { - if (!activityInstance) continue; auto& instance = instances.PushDebug("Instance " + std::to_string(i++)); - instance.PushDebug("Score") = activityInstance->GetScore(); - instance.PushDebug("Next Zone Clone ID") = activityInstance->GetNextZoneCloneID(); + instance.PushDebug("Score") = activityInstance.GetScore(); + instance.PushDebug("Next Zone Clone ID") = activityInstance.GetNextZoneCloneID(); { auto& activityInfo = instance.PushDebug("Activity Info"); - const auto& instanceActInfo = activityInstance->GetActivityInfo(); + const auto& instanceActInfo = activityInstance.GetActivityInfo(); activityInfo.PushDebug("ActivityID") = instanceActInfo.ActivityID; activityInfo.PushDebug("locStatus") = instanceActInfo.locStatus; activityInfo.PushDebug("instanceMapID") = instanceActInfo.instanceMapID; @@ -625,7 +586,7 @@ bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& } auto& participants = instance.PushDebug("Participants"); - for (const auto* participant : activityInstance->GetParticipants()) { + for (const auto* participant : activityInstance.GetParticipants()) { if (!participant) continue; auto* character = participant->GetCharacter(); if (!character) continue; @@ -635,38 +596,36 @@ bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& auto& queue = activityInfo.PushDebug("Queue"); i = 0; - for (const auto& lobbyQueue : m_Queue) { + for (const auto& lobbyQueue : m_Queue | std::views::values) { auto& lobby = queue.PushDebug("Lobby " + std::to_string(i++)); - lobby.PushDebug("Timer") = lobbyQueue->timer; + lobby.PushDebug("Timer") = lobbyQueue.timer; auto& players = lobby.PushDebug("Players"); - for (const auto* player : lobbyQueue->players) { - if (!player) continue; - auto* playerEntity = player->GetEntity(); + for (const auto& player : lobbyQueue.players) { + const auto* const playerEntity = player.GetEntity(); if (!playerEntity) continue; auto* character = playerEntity->GetCharacter(); if (!character) continue; - players.PushDebug(std::to_string(playerEntity->GetObjectID()) + ": " + character->GetName()) = player->ready ? "Ready" : "Not Ready"; + players.PushDebug(std::to_string(playerEntity->GetObjectID()) + ": " + character->GetName()) = player.ready ? "Ready" : "Not Ready"; } } auto& activityPlayers = activityInfo.PushDebug("Activity Players"); - for (const auto* activityPlayer : m_ActivityPlayers) { - if (!activityPlayer) continue; - auto* const activityPlayerEntity = Game::entityManager->GetEntity(activityPlayer->playerID); + for (const auto& [playerID, playerScores] : m_ActivityPlayers) { + auto* const activityPlayerEntity = Game::entityManager->GetEntity(playerID); if (!activityPlayerEntity) continue; auto* character = activityPlayerEntity->GetCharacter(); if (!character) continue; - auto& playerData = activityPlayers.PushDebug(std::to_string(activityPlayer->playerID) + " " + character->GetName()); + auto& playerData = activityPlayers.PushDebug(std::to_string(playerID) + " " + character->GetName()); auto& scores = playerData.PushDebug("Scores"); for (size_t i = 0; i < 10; ++i) { - scores.PushDebug(std::to_string(i)) = activityPlayer->values[i]; + scores.PushDebug(std::to_string(i)) = playerScores[i]; } } - + activityInfo.PushDebug("ActivityID") = m_ActivityID; return true; } diff --git a/dGame/dComponents/ActivityComponent.h b/dGame/dComponents/ActivityComponent.h index 4f423d8e..856ca70f 100644 --- a/dGame/dComponents/ActivityComponent.h +++ b/dGame/dComponents/ActivityComponent.h @@ -8,14 +8,15 @@ #include "eReplicaComponentType.h" #include "CDActivitiesTable.h" +#include namespace GameMessages { class GameMsg; }; - /** - * Represents an instance of an activity, having participants and score - */ +/** + * Represents an instance of an activity, having participants and score + */ class ActivityInstance { public: ActivityInstance(Entity* parent, CDActivities activityInfo) { m_Parent = parent; m_ActivityInfo = activityInfo; }; @@ -104,7 +105,7 @@ struct LobbyPlayer { /** * The ID of the entity that is in the lobby */ - LWOOBJID entityID; + LWOOBJID entityID = LWOOBJID_EMPTY; /** * Whether or not the entity is ready @@ -126,12 +127,12 @@ struct Lobby { /** * The lobby of players */ - std::vector players; + std::vector players; /** * The timer that determines when the activity should start */ - float timer; + float timer{}; }; /** @@ -142,12 +143,12 @@ struct ActivityPlayer { /** * The entity that the score is tracked for */ - LWOOBJID playerID; + LWOOBJID playerID{}; /** * The list of score for this entity */ - float values[10]; + float values[10]{}; }; /** @@ -194,13 +195,13 @@ public: * @param instance the instance to load the players into * @param lobby the players to load into the instance */ - void LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector& lobby) const; + void LoadPlayersIntoInstance(ActivityInstance& instance, const std::vector& lobby) const; /** * Removes a lobby from the activity manager * @param lobby the lobby to remove */ - void RemoveLobby(Lobby* lobby); + void RemoveLobby(const LWOOBJID lobbyID); /** * Marks a player as (un)ready in a lobby @@ -246,7 +247,7 @@ public: */ bool IsPlayedBy(LWOOBJID playerID) const; - /** + /** * Checks if the entity has enough cost to play this activity * @param player the entity to check * @return true if the entity has enough cost to play this activity, false otherwise @@ -271,20 +272,14 @@ public: * Creates a new instance for this activity * @return a new instance for this activity */ - ActivityInstance* NewInstance(); - - /** - * Returns all the currently active instances of this activity - * @return all the currently active instances of this activity - */ - const std::vector& GetInstances() const; + ActivityInstance& NewInstance(); /** * Returns the instance that some entity is currently playing in * @param playerID the entity to check for * @return if any, the instance that the entity is currently in */ - ActivityInstance* GetInstance(const LWOOBJID playerID); + const ActivityInstance& GetInstance(const LWOOBJID playerID) const; /** * @brief Reloads the config settings for this component @@ -292,23 +287,12 @@ public: */ void ReloadConfig(); - /** - * Removes all the instances - */ - void ClearInstances(); - - /** - * Returns all the score for the players that are currently playing this activity - * @return - */ - std::vector GetActivityPlayers() { return m_ActivityPlayers; }; - /** * Returns activity data for a specific entity (e.g. score and such). * @param playerID the entity to get data for * @return the activity data (score) for the passed player in this activity, if it exists */ - ActivityPlayer* GetActivityPlayerData(LWOOBJID playerID); + bool PlayerHasActivityData(LWOOBJID playerID) const; /** * Sets some score value for an entity @@ -324,7 +308,7 @@ public: * @param index the index to get score for * @return activity score for the passed parameters */ - float_t GetActivityValue(LWOOBJID playerID, uint32_t index); + float_t GetActivityValue(LWOOBJID playerID, uint32_t index) const; /** * Removes activity score tracking for some entity @@ -332,13 +316,6 @@ public: */ void RemoveActivityPlayerData(LWOOBJID playerID); - /** - * Adds activity score tracking for some entity - * @param playerID the entity to add the activity score for - * @return the created entry - */ - ActivityPlayer* AddActivityPlayerData(LWOOBJID playerID); - /** * Sets the mapID that this activity points to * @param mapID the map ID to set @@ -346,7 +323,6 @@ public: void SetInstanceMapID(uint32_t mapID) { m_ActivityInfo.instanceMapID = mapID; }; private: - bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& msg); /** * The database information for this activity @@ -356,17 +332,17 @@ private: /** * All the active instances of this activity */ - std::vector m_Instances; + std::vector m_Instances; /** * The current lobbies for this activity */ - std::vector m_Queue; + std::map m_Queue; /** * All the activity score for the players in this activity */ - std::vector m_ActivityPlayers; + std::map> m_ActivityPlayers; /** * The activity id diff --git a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp index fc724fb9..7e8ca7e8 100644 --- a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp +++ b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp @@ -19,7 +19,7 @@ void NpcAgCourseStarter::OnUse(Entity* self, Entity* user) { const auto userId = user->GetObjectID(); const auto& userSysAddr = user->GetSystemAddress(); - if (scriptedActivityComponent->GetActivityPlayerData(userId) != nullptr) { + if (scriptedActivityComponent->PlayerHasActivityData(userId)) { GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", userSysAddr); } else { GameMessages::SendNotifyClientObject(selfId, u"start", 0, 0, LWOOBJID_EMPTY, "", userSysAddr); @@ -45,18 +45,18 @@ void NpcAgCourseStarter::OnMessageBoxResponse(Entity* self, Entity* sender, int3 GameMessages::SendNotifyClientObject(selfId, u"start_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); GameMessages::SendActivityStart(selfId, senderSysAddr); - auto* const data = scriptedActivityComponent->AddActivityPlayerData(senderId); - if (data->values[1] != 0) return; + const auto score = scriptedActivityComponent->GetActivityValue(senderId, 1); + if (score != 0 && score != -1.0f) return; const auto raceStartTime = Game::server->GetUptime() + std::chrono::seconds(4); // Offset for starting timer const auto fRaceStartTime = std::chrono::duration>(raceStartTime).count(); - data->values[1] = fRaceStartTime; + scriptedActivityComponent->SetActivityValue(senderId, 1, fRaceStartTime); Game::entityManager->SerializeEntity(self); } else if (identifier == u"FootRaceCancel") { GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); - if (scriptedActivityComponent->GetActivityPlayerData(senderId) != nullptr) { + if (scriptedActivityComponent->PlayerHasActivityData(senderId)) { GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); } else { GameMessages::SendNotifyClientObject(selfId, u"start", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); @@ -74,8 +74,7 @@ void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std const auto senderId = sender->GetObjectID(); const auto& senderSysAddr = sender->GetSystemAddress(); - auto* const data = scriptedActivityComponent->GetActivityPlayerData(senderId); - if (!data) return; + if (!scriptedActivityComponent->PlayerHasActivityData(senderId)) return; if (args == "course_cancel") { GameMessages::SendNotifyClientObject(selfId, u"cancel_timer", 0, 0, @@ -84,8 +83,11 @@ void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std } else if (args == "course_finish") { const auto raceEndTime = Game::server->GetUptime(); const auto fRaceEndTime = std::chrono::duration>(raceEndTime).count(); - const auto raceTimeElapsed = fRaceEndTime - data->values[1]; - data->values[2] = raceTimeElapsed; + const float startTime = scriptedActivityComponent->GetActivityValue(senderId, 1); + if (startTime == 0 || startTime == -1.0f) return; + + const auto raceTimeElapsed = fRaceEndTime - startTime; + scriptedActivityComponent->SetActivityValue(senderId, 2, raceTimeElapsed); auto* const missionComponent = sender->GetComponent(); if (missionComponent != nullptr) { diff --git a/dScripts/ActivityManager.cpp b/dScripts/ActivityManager.cpp index 047eb76f..35459538 100644 --- a/dScripts/ActivityManager.cpp +++ b/dScripts/ActivityManager.cpp @@ -114,7 +114,7 @@ uint32_t ActivityManager::CalculateActivityRating(Entity* self, const LWOOBJID p if (sac == nullptr) return 0; - return sac->GetInstance(playerID)->GetParticipants().size(); + return sac->GetInstance(playerID).GetParticipants().size(); } uint32_t ActivityManager::GetActivityID(const Entity* self) {