diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 0caeada8..6f8f65e9 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -605,8 +605,8 @@ void Entity::Initialize() { } // Scripted activity component - int scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY); - if ((scriptedActivityID > 0)) { + int scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY, -1); + if ((scriptedActivityID != -1)) { AddComponent(scriptedActivityID); } diff --git a/dGame/dComponents/ScriptedActivityComponent.cpp b/dGame/dComponents/ActivityComponent.cpp similarity index 81% rename from dGame/dComponents/ScriptedActivityComponent.cpp rename to dGame/dComponents/ActivityComponent.cpp index 8bcddd05..59637d59 100644 --- a/dGame/dComponents/ScriptedActivityComponent.cpp +++ b/dGame/dComponents/ActivityComponent.cpp @@ -1,4 +1,4 @@ -#include "ScriptedActivityComponent.h" +#include "ActivityComponent.h" #include "GameMessages.h" #include "CDClientManager.h" #include "MissionComponent.h" @@ -29,8 +29,9 @@ #include "CDActivitiesTable.h" #include "LeaderboardManager.h" -ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activityID) : Component(parent) { - m_ActivityID = activityID; +ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) { + if (activityID > 0) m_ActivityID = activityID; + else m_ActivityID = parent->GetVar(u"activityID"); CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable(); std::vector activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); }); @@ -40,15 +41,10 @@ ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activit m_ActivityInfo.minTeamSize = 1; m_ActivityInfo.minTeams = 1; } - - const auto& transferOverride = parent->GetVar(u"transferZoneID"); - if (!transferOverride.empty()) { - m_ActivityInfo.instanceMapID = std::stoi(GeneralUtils::UTF16ToWTF8(transferOverride)); - - // TODO: LU devs made me do it (for some reason cannon cove instancer is marked to go to GF survival) - // NOTE: 1301 is GF survival - if (m_ActivityInfo.instanceMapID == 1301) { - m_ActivityInfo.instanceMapID = 1302; + if (m_ActivityInfo.instanceMapID == -1) { + const auto& transferOverride = parent->GetVarAsString(u"transferZoneID"); + if (!transferOverride.empty()) { + GeneralUtils::TryParse(transferOverride, m_ActivityInfo.instanceMapID); } } } @@ -79,30 +75,28 @@ ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activit } } -ScriptedActivityComponent::~ScriptedActivityComponent() -= default; - -void ScriptedActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { - outBitStream->Write(true); - 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) { - outBitStream->Write(activityValue); +void ActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { + outBitStream->Write(m_DirtyActivityInfo); + 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) { + outBitStream->Write(activityValue); + } } } + if (!bIsInitialUpdate) m_DirtyActivityInfo = false; } } -void ScriptedActivityComponent::ReloadConfig() { +void ActivityComponent::ReloadConfig() { CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable(); std::vector activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); }); for (auto activity : activities) { auto mapID = m_ActivityInfo.instanceMapID; - if ((mapID == 1203 || mapID == 1261 || mapID == 1303 || mapID == 1403) && Game::config->GetValue("solo_racing") == "1") { + if (static_cast(activity.leaderboardType) == Leaderboard::Type::Racing && Game::config->GetValue("solo_racing") == "1") { m_ActivityInfo.minTeamSize = 1; m_ActivityInfo.minTeams = 1; } else { @@ -112,11 +106,7 @@ void ScriptedActivityComponent::ReloadConfig() { } } -void ScriptedActivityComponent::HandleMessageBoxResponse(Entity* player, const std::string& id) { - if (m_ActivityInfo.ActivityID == 103) { - return; - } - +void ActivityComponent::HandleMessageBoxResponse(Entity* player, const std::string& id) { if (id == "LobbyExit") { PlayerLeave(player->GetObjectID()); } else if (id == "PlayButton") { @@ -124,11 +114,7 @@ void ScriptedActivityComponent::HandleMessageBoxResponse(Entity* player, const s } } -void ScriptedActivityComponent::PlayerJoin(Entity* player) { - if (m_ActivityInfo.ActivityID == 103 || PlayerIsInQueue(player) || !IsValidActivity(player)) { - return; - } - +void ActivityComponent::PlayerJoin(Entity* player) { // If we have a lobby, queue the player and allow others to join, otherwise spin up an instance on the spot if (HasLobby()) { PlayerJoinLobby(player); @@ -136,11 +122,9 @@ void ScriptedActivityComponent::PlayerJoin(Entity* player) { auto* instance = NewInstance(); instance->AddParticipant(player); } - - Game::entityManager->SerializeEntity(m_Parent); } -void ScriptedActivityComponent::PlayerJoinLobby(Entity* 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(); @@ -189,7 +173,7 @@ void ScriptedActivityComponent::PlayerJoinLobby(Entity* player) { } } -void ScriptedActivityComponent::PlayerLeave(LWOOBJID playerID) { +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) { @@ -214,7 +198,7 @@ void ScriptedActivityComponent::PlayerLeave(LWOOBJID playerID) { } } -void ScriptedActivityComponent::Update(float deltaTime) { +void ActivityComponent::Update(float deltaTime) { std::vector lobbiesToRemove{}; // Ticks all the lobbies, not applicable for non-instance activities for (Lobby* lobby : m_Queue) { @@ -287,7 +271,7 @@ void ScriptedActivityComponent::Update(float deltaTime) { } } -void ScriptedActivityComponent::RemoveLobby(Lobby* lobby) { +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); @@ -296,29 +280,12 @@ void ScriptedActivityComponent::RemoveLobby(Lobby* lobby) { } } -bool ScriptedActivityComponent::HasLobby() const { +bool ActivityComponent::HasLobby() const { // If the player is not in the world he has to be, create a lobby for the transfer return m_ActivityInfo.instanceMapID != UINT_MAX && m_ActivityInfo.instanceMapID != Game::server->GetZoneID(); } -bool ScriptedActivityComponent::IsValidActivity(Entity* player) { - // Makes it so that scripted activities with an unimplemented map cannot be joined - /*if (player->GetGMLevel() < eGameMasterLevel::DEVELOPER && (m_ActivityInfo.instanceMapID == 1302 || m_ActivityInfo.instanceMapID == 1301)) { - if (m_Parent->GetLOT() == 4860) { - auto* missionComponent = player->GetComponent(); - missionComponent->CompleteMission(229); - } - - ChatPackets::SendSystemMessage(player->GetSystemAddress(), u"Sorry, this activity is not ready."); - static_cast(player)->SendToZone(Game::zoneManager->GetZone()->GetWorldID()); // Gets them out of this stuck state - - return false; - }*/ - - return true; -} - -bool ScriptedActivityComponent::PlayerIsInQueue(Entity* player) { +bool ActivityComponent::PlayerIsInQueue(Entity* player) { for (Lobby* lobby : m_Queue) { for (LobbyPlayer* lobbyPlayer : lobby->players) { if (player->GetObjectID() == lobbyPlayer->entityID) return true; @@ -328,7 +295,7 @@ bool ScriptedActivityComponent::PlayerIsInQueue(Entity* player) { return false; } -bool ScriptedActivityComponent::IsPlayedBy(Entity* player) const { +bool ActivityComponent::IsPlayedBy(Entity* player) const { for (const auto* instance : this->m_Instances) { for (const auto* instancePlayer : instance->GetParticipants()) { if (instancePlayer != nullptr && instancePlayer->GetObjectID() == player->GetObjectID()) @@ -339,7 +306,7 @@ bool ScriptedActivityComponent::IsPlayedBy(Entity* player) const { return false; } -bool ScriptedActivityComponent::IsPlayedBy(LWOOBJID playerID) const { +bool ActivityComponent::IsPlayedBy(LWOOBJID playerID) const { for (const auto* instance : this->m_Instances) { for (const auto* instancePlayer : instance->GetParticipants()) { if (instancePlayer != nullptr && instancePlayer->GetObjectID() == playerID) @@ -350,7 +317,7 @@ bool ScriptedActivityComponent::IsPlayedBy(LWOOBJID playerID) const { return false; } -bool ScriptedActivityComponent::TakeCost(Entity* player) const { +bool ActivityComponent::TakeCost(Entity* player) const { if (m_ActivityInfo.optionalCostLOT <= 0 || m_ActivityInfo.optionalCostCount <= 0) return true; @@ -366,7 +333,7 @@ bool ScriptedActivityComponent::TakeCost(Entity* player) const { return true; } -void ScriptedActivityComponent::PlayerReady(Entity* player, bool bReady) { +void ActivityComponent::PlayerReady(Entity* player, bool bReady) { for (Lobby* lobby : m_Queue) { for (LobbyPlayer* lobbyPlayer : lobby->players) { if (lobbyPlayer->entityID == player->GetObjectID()) { @@ -389,13 +356,13 @@ void ScriptedActivityComponent::PlayerReady(Entity* player, bool bReady) { } } -ActivityInstance* ScriptedActivityComponent::NewInstance() { +ActivityInstance* ActivityComponent::NewInstance() { auto* instance = new ActivityInstance(m_Parent, m_ActivityInfo); m_Instances.push_back(instance); return instance; } -void ScriptedActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector& lobby) const { +void ActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector& lobby) const { for (LobbyPlayer* player : lobby) { auto* entity = player->GetEntity(); if (entity == nullptr || !TakeCost(entity)) { @@ -406,11 +373,11 @@ void ScriptedActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instan } } -const std::vector& ScriptedActivityComponent::GetInstances() const { +const std::vector& ActivityComponent::GetInstances() const { return m_Instances; } -ActivityInstance* ScriptedActivityComponent::GetInstance(const LWOOBJID playerID) { +ActivityInstance* ActivityComponent::GetInstance(const LWOOBJID playerID) { for (const auto* instance : GetInstances()) { for (const auto* participant : instance->GetParticipants()) { if (participant->GetObjectID() == playerID) @@ -421,14 +388,14 @@ ActivityInstance* ScriptedActivityComponent::GetInstance(const LWOOBJID playerID return nullptr; } -void ScriptedActivityComponent::ClearInstances() { +void ActivityComponent::ClearInstances() { for (ActivityInstance* instance : m_Instances) { delete instance; } m_Instances.clear(); } -ActivityPlayer* ScriptedActivityComponent::GetActivityPlayerData(LWOOBJID playerID) { +ActivityPlayer* ActivityComponent::GetActivityPlayerData(LWOOBJID playerID) { for (auto* activityData : m_ActivityPlayers) { if (activityData->playerID == playerID) { return activityData; @@ -438,13 +405,14 @@ ActivityPlayer* ScriptedActivityComponent::GetActivityPlayerData(LWOOBJID player return nullptr; } -void ScriptedActivityComponent::RemoveActivityPlayerData(LWOOBJID 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; @@ -452,18 +420,19 @@ void ScriptedActivityComponent::RemoveActivityPlayerData(LWOOBJID playerID) { } } -ActivityPlayer* ScriptedActivityComponent::AddActivityPlayerData(LWOOBJID playerID) { +ActivityPlayer* ActivityComponent::AddActivityPlayerData(LWOOBJID playerID) { auto* data = GetActivityPlayerData(playerID); if (data != nullptr) return data; m_ActivityPlayers.push_back(new ActivityPlayer{ playerID, {} }); + m_DirtyActivityInfo = true; Game::entityManager->SerializeEntity(m_Parent); return GetActivityPlayerData(playerID); } -float_t ScriptedActivityComponent::GetActivityValue(LWOOBJID playerID, uint32_t index) { +float_t ActivityComponent::GetActivityValue(LWOOBJID playerID, uint32_t index) { auto value = -1.0f; auto* data = GetActivityPlayerData(playerID); @@ -474,16 +443,16 @@ float_t ScriptedActivityComponent::GetActivityValue(LWOOBJID playerID, uint32_t return value; } -void ScriptedActivityComponent::SetActivityValue(LWOOBJID playerID, uint32_t index, float_t 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; } - + m_DirtyActivityInfo = true; Game::entityManager->SerializeEntity(m_Parent); } -void ScriptedActivityComponent::PlayerRemove(LWOOBJID playerID) { +void ActivityComponent::PlayerRemove(LWOOBJID playerID) { for (auto* instance : GetInstances()) { auto participants = instance->GetParticipants(); for (const auto* participant : participants) { diff --git a/dGame/dComponents/ActivityComponent.h b/dGame/dComponents/ActivityComponent.h new file mode 100644 index 00000000..96dbd5fb --- /dev/null +++ b/dGame/dComponents/ActivityComponent.h @@ -0,0 +1,371 @@ +#ifndef ACTIVITYCOMPONENT_H +#define ACTIVITYCOMPONENT_H + +#include "CDClientManager.h" +#include "BitStream.h" +#include "Entity.h" +#include "Component.h" +#include "eReplicaComponentType.h" + +#include "CDActivitiesTable.h" + + /** + * Represents an instance of an activity, having participants and score + */ +class ActivityInstance { +public: + ActivityInstance(Entity* parent, CDActivities activityInfo) { m_Parent = parent; m_ActivityInfo = activityInfo; }; + //~ActivityInstance(); + + /** + * Adds an entity to this activity + * @param participant the entity to add + */ + void AddParticipant(Entity* participant); + + /** + * Removes all the participants from this activity + */ + void ClearParticipants() { m_Participants.clear(); }; + + /** + * Starts the instance world for this activity and sends all participants there + */ + void StartZone(); + + /** + * Gives the rewards for completing this activity to some participant + * @param participant the participant to give rewards to + */ + void RewardParticipant(Entity* participant); + + /** + * Removes a participant from this activity + * @param participant the participant to remove + */ + void RemoveParticipant(const Entity* participant); + + /** + * Returns all the participants of this activity + * @return all the participants of this activity + */ + std::vector GetParticipants() const; + + /** + * Currently unused + */ + uint32_t GetScore() const; + + /** + * Currently unused + */ + void SetScore(uint32_t score); +private: + + /** + * Currently unused + */ + uint32_t score = 0; + + /** + * The instance ID of this activity + */ + uint32_t m_NextZoneCloneID = 0; + + /** + * The database information for this activity + */ + CDActivities m_ActivityInfo; + + /** + * The entity that owns this activity (the entity that has the ScriptedActivityComponent) + */ + Entity* m_Parent; + + /** + * All the participants of this activity + */ + std::vector m_Participants; +}; + +/** + * Represents an entity in a lobby + */ +struct LobbyPlayer { + + /** + * The ID of the entity that is in the lobby + */ + LWOOBJID entityID; + + /** + * Whether or not the entity is ready + */ + bool ready = false; + + /** + * Returns the entity that is in the lobby + * @return the entity that is in the lobby + */ + Entity* GetEntity() const; +}; + +/** + * Represents a lobby of players with a timer until it should start the activity + */ +struct Lobby { + + /** + * The lobby of players + */ + std::vector players; + + /** + * The timer that determines when the activity should start + */ + float timer; +}; + +/** + * Represents the score for the player in an activity, one index might represent score, another one time, etc. + */ +struct ActivityPlayer { + + /** + * The entity that the score is tracked for + */ + LWOOBJID playerID; + + /** + * The list of score for this entity + */ + float values[10]; +}; + +/** + * Welcome to the absolute behemoth that is the scripted activity component. I have now clue how this was managed in + * live but I figure somewhat similarly and it's terrible. In a nutshell, this components handles any activity that + * can be done in the game from quick builds to boss fights to races. On top of that, this component handles instancing + * and lobbying. + */ +class ActivityComponent : public Component { +public: + ActivityComponent(Entity* parent, int32_t activityID); + + void Update(float deltaTime) override; + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; + + /** + * Makes some entity join the minigame, if it's a lobbied one, the entity will be placed in the lobby + * @param player the entity to join the game + */ + void PlayerJoin(Entity* player); + + /** + * Makes an entity join the lobby for this minigame, if it exists + * @param player the entity to join + */ + void PlayerJoinLobby(Entity* player); + + /** + * Makes the player leave the lobby + * @param playerID the entity to leave the lobby + */ + void PlayerLeave(LWOOBJID playerID); + + /** + * Removes the entity from the minigame (and its score) + * @param playerID the entity to remove from the minigame + */ + void PlayerRemove(LWOOBJID playerID); + + /** + * Adds all the players to an instance of some activity + * @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; + + /** + * Removes a lobby from the activity manager + * @param lobby the lobby to remove + */ + void RemoveLobby(Lobby* lobby); + + /** + * Marks a player as (un)ready in a lobby + * @param player the entity to mark + * @param bReady true if the entity is ready, false otherwise + */ + void PlayerReady(Entity* player, bool bReady); + + /** + * Returns the ID of this activity + * @return the ID of this activity + */ + int GetActivityID() { return m_ActivityInfo.ActivityID; } + + /** + * Returns if this activity has a lobby, e.g. if it needs to instance players to some other map + * @return true if this activity has a lobby, false otherwise + */ + bool HasLobby() const; + + /** + * Checks if a player is currently waiting in a lobby + * @param player the entity to check for + * @return true if the entity is waiting in a lobby, false otherwise + */ + bool PlayerIsInQueue(Entity* player); + + /** + * Checks if an entity is currently playing this activity + * @param player the entity to check + * @return true if the entity is playing this lobby, false otherwise + */ + bool IsPlayedBy(Entity* player) const; + + /** + * Checks if an entity is currently playing this activity + * @param playerID the entity to check + * @return true if the entity is playing this lobby, false otherwise + */ + bool IsPlayedBy(LWOOBJID playerID) const; + + /** + * Removes the cost of the activity (e.g. green imaginate) for the entity that plays this activity + * @param player the entity to take cost for + * @return true if the cost was successfully deducted, false otherwise + */ + bool TakeCost(Entity* player) const; + + /** + * Handles any response from a player clicking on a lobby / instance menu + * @param player the entity that clicked + * @param id the message that was passed + */ + void HandleMessageBoxResponse(Entity* player, const std::string& id); + + /** + * 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; + + /** + * 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); + + /** + * @brief Reloads the config settings for this component + * + */ + 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); + + /** + * Sets some score value for an entity + * @param playerID the entity to set score for + * @param index the score index to set + * @param value the value to set in for that index + */ + void SetActivityValue(LWOOBJID playerID, uint32_t index, float_t value); + + /** + * Returns activity score for the passed parameters + * @param playerID the entity to get score for + * @param index the index to get score for + * @return activity score for the passed parameters + */ + float_t GetActivityValue(LWOOBJID playerID, uint32_t index); + + /** + * Removes activity score tracking for some entity + * @param playerID the entity to remove score for + */ + 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 + */ + void SetInstanceMapID(uint32_t mapID) { m_ActivityInfo.instanceMapID = mapID; }; + + /** + * Returns the LMI that this activity points to for a team size + * @param teamSize the team size to get the LMI for + * @return the LMI that this activity points to for a team size + */ + uint32_t GetLootMatrixForTeamSize(uint32_t teamSize) { return m_ActivityLootMatrices[teamSize]; } +private: + + /** + * The database information for this activity + */ + CDActivities m_ActivityInfo; + + /** + * All the active instances of this activity + */ + std::vector m_Instances; + + /** + * The current lobbies for this activity + */ + std::vector m_Queue; + + /** + * All the activity score for the players in this activity + */ + std::vector m_ActivityPlayers; + + /** + * LMIs for team sizes + */ + std::unordered_map m_ActivityLootMatrices; + + /** + * The activity id + */ + int32_t m_ActivityID; + + /** + * If the Activity info is dirty + */ + bool m_DirtyActivityInfo = true; +}; + +#endif // ACTIVITYCOMPONENT_H diff --git a/dGame/dComponents/CMakeLists.txt b/dGame/dComponents/CMakeLists.txt index fa0aea35..04358cbe 100644 --- a/dGame/dComponents/CMakeLists.txt +++ b/dGame/dComponents/CMakeLists.txt @@ -1,4 +1,5 @@ -set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp" +set(DGAME_DCOMPONENTS_SOURCES "ActivityComponent.cpp" + "BaseCombatAIComponent.cpp" "BouncerComponent.cpp" "BuffComponent.cpp" "BuildBorderComponent.cpp" @@ -36,7 +37,6 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp" "RigidbodyPhantomPhysicsComponent.cpp" "MultiZoneEntranceComponent.cpp" "RocketLaunchpadControlComponent.cpp" - "ScriptedActivityComponent.cpp" "ShootingGalleryComponent.cpp" "SimplePhysicsComponent.cpp" "SkillComponent.cpp" diff --git a/dGame/dComponents/ScriptedActivityComponent.h b/dGame/dComponents/ScriptedActivityComponent.h index 3bc8114f..79a9593d 100644 --- a/dGame/dComponents/ScriptedActivityComponent.h +++ b/dGame/dComponents/ScriptedActivityComponent.h @@ -1,381 +1,15 @@ -/* - * Darkflame Universe - * Copyright 2018 - */ +#ifndef __SCRIPTEDACTIVITYCOMPONENT__H__ +#define __SCRIPTEDACTIVITYCOMPONENT__H__ -#include "CDClientManager.h" - -#ifndef SCRIPTEDACTIVITYCOMPONENT_H -#define SCRIPTEDACTIVITYCOMPONENT_H - -#include "BitStream.h" -#include "Entity.h" -#include "Component.h" +#include "ActivityComponent.h" #include "eReplicaComponentType.h" -#include "CDActivitiesTable.h" +class Entity; - /** - * Represents an instance of an activity, having participants and score - */ -class ActivityInstance { -public: - ActivityInstance(Entity* parent, CDActivities activityInfo) { m_Parent = parent; m_ActivityInfo = activityInfo; }; - //~ActivityInstance(); - - /** - * Adds an entity to this activity - * @param participant the entity to add - */ - void AddParticipant(Entity* participant); - - /** - * Removes all the participants from this activity - */ - void ClearParticipants() { m_Participants.clear(); }; - - /** - * Starts the instance world for this activity and sends all participants there - */ - void StartZone(); - - /** - * Gives the rewards for completing this activity to some participant - * @param participant the participant to give rewards to - */ - void RewardParticipant(Entity* participant); - - /** - * Removes a participant from this activity - * @param participant the participant to remove - */ - void RemoveParticipant(const Entity* participant); - - /** - * Returns all the participants of this activity - * @return all the participants of this activity - */ - std::vector GetParticipants() const; - - /** - * Currently unused - */ - uint32_t GetScore() const; - - /** - * Currently unused - */ - void SetScore(uint32_t score); -private: - - /** - * Currently unused - */ - uint32_t score = 0; - - /** - * The instance ID of this activity - */ - uint32_t m_NextZoneCloneID = 0; - - /** - * The database information for this activity - */ - CDActivities m_ActivityInfo; - - /** - * The entity that owns this activity (the entity that has the ScriptedActivityComponent) - */ - Entity* m_Parent; - - /** - * All the participants of this activity - */ - std::vector m_Participants; -}; - -/** - * Represents an entity in a lobby - */ -struct LobbyPlayer { - - /** - * The ID of the entity that is in the lobby - */ - LWOOBJID entityID; - - /** - * Whether or not the entity is ready - */ - bool ready = false; - - /** - * Returns the entity that is in the lobby - * @return the entity that is in the lobby - */ - Entity* GetEntity() const; -}; - -/** - * Represents a lobby of players with a timer until it should start the activity - */ -struct Lobby { - - /** - * The lobby of players - */ - std::vector players; - - /** - * The timer that determines when the activity should start - */ - float timer; -}; - -/** - * Represents the score for the player in an activity, one index might represent score, another one time, etc. - */ -struct ActivityPlayer { - - /** - * The entity that the score is tracked for - */ - LWOOBJID playerID; - - /** - * The list of score for this entity - */ - float values[10]; -}; - -/** - * Welcome to the absolute behemoth that is the scripted activity component. I have now clue how this was managed in - * live but I figure somewhat similarly and it's terrible. In a nutshell, this components handles any activity that - * can be done in the game from quick builds to boss fights to races. On top of that, this component handles instancing - * and lobbying. - */ -class ScriptedActivityComponent : public Component { +class ScriptedActivityComponent : public ActivityComponent { public: inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY; - - ScriptedActivityComponent(Entity* parent, int activityID); - ~ScriptedActivityComponent() override; - - void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; - - /** - * Makes some entity join the minigame, if it's a lobbied one, the entity will be placed in the lobby - * @param player the entity to join the game - */ - void PlayerJoin(Entity* player); - - /** - * Makes an entity join the lobby for this minigame, if it exists - * @param player the entity to join - */ - void PlayerJoinLobby(Entity* player); - - /** - * Makes the player leave the lobby - * @param playerID the entity to leave the lobby - */ - void PlayerLeave(LWOOBJID playerID); - - /** - * Removes the entity from the minigame (and its score) - * @param playerID the entity to remove from the minigame - */ - void PlayerRemove(LWOOBJID playerID); - - /** - * Adds all the players to an instance of some activity - * @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; - - /** - * Removes a lobby from the activity manager - * @param lobby the lobby to remove - */ - void RemoveLobby(Lobby* lobby); - - /** - * Marks a player as (un)ready in a lobby - * @param player the entity to mark - * @param bReady true if the entity is ready, false otherwise - */ - void PlayerReady(Entity* player, bool bReady); - - /** - * Returns the ID of this activity - * @return the ID of this activity - */ - int GetActivityID() { return m_ActivityInfo.ActivityID; } - - /** - * Returns if this activity has a lobby, e.g. if it needs to instance players to some other map - * @return true if this activity has a lobby, false otherwise - */ - bool HasLobby() const; - - /** - * Checks if a player is currently waiting in a lobby - * @param player the entity to check for - * @return true if the entity is waiting in a lobby, false otherwise - */ - bool PlayerIsInQueue(Entity* player); - - /** - * Checks if an entity is currently playing this activity - * @param player the entity to check - * @return true if the entity is playing this lobby, false otherwise - */ - bool IsPlayedBy(Entity* player) const; - - /** - * Checks if an entity is currently playing this activity - * @param playerID the entity to check - * @return true if the entity is playing this lobby, false otherwise - */ - bool IsPlayedBy(LWOOBJID playerID) const; - - /** - * Legacy: used to check for unimplemented maps, gladly, this now just returns true :) - */ - bool IsValidActivity(Entity* player); - - /** - * Removes the cost of the activity (e.g. green imaginate) for the entity that plays this activity - * @param player the entity to take cost for - * @return true if the cost was successfully deducted, false otherwise - */ - bool TakeCost(Entity* player) const; - - /** - * Handles any response from a player clicking on a lobby / instance menu - * @param player the entity that clicked - * @param id the message that was passed - */ - void HandleMessageBoxResponse(Entity* player, const std::string& id); - - /** - * 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; - - /** - * 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); - - /** - * @brief Reloads the config settings for this component - * - */ - 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); - - /** - * Sets some score value for an entity - * @param playerID the entity to set score for - * @param index the score index to set - * @param value the value to set in for that index - */ - void SetActivityValue(LWOOBJID playerID, uint32_t index, float_t value); - - /** - * Returns activity score for the passed parameters - * @param playerID the entity to get score for - * @param index the index to get score for - * @return activity score for the passed parameters - */ - float_t GetActivityValue(LWOOBJID playerID, uint32_t index); - - /** - * Removes activity score tracking for some entity - * @param playerID the entity to remove score for - */ - 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 - */ - void SetInstanceMapID(uint32_t mapID) { m_ActivityInfo.instanceMapID = mapID; }; - - /** - * Returns the LMI that this activity points to for a team size - * @param teamSize the team size to get the LMI for - * @return the LMI that this activity points to for a team size - */ - uint32_t GetLootMatrixForTeamSize(uint32_t teamSize) { return m_ActivityLootMatrices[teamSize]; } -private: - - /** - * The database information for this activity - */ - CDActivities m_ActivityInfo; - - /** - * All the active instances of this activity - */ - std::vector m_Instances; - - /** - * The current lobbies for this activity - */ - std::vector m_Queue; - - /** - * All the activity score for the players in this activity - */ - std::vector m_ActivityPlayers; - - /** - * LMIs for team sizes - */ - std::unordered_map m_ActivityLootMatrices; - - /** - * The activity id - * - */ - int32_t m_ActivityID; + ScriptedActivityComponent(Entity* parent, int activityID) : ActivityComponent(parent, activityID){}; }; -#endif // SCRIPTEDACTIVITYCOMPONENT_H +#endif //!__SCRIPTEDACTIVITYCOMPONENT__H__