DarkflameServer/dGame/dComponents/ScriptedActivityComponent.h
David Markowitz ae349d6b15
feat: Add isolated and simplified path to add components (#1204)
* Components: Make ComponentType inline

Prevents the next commits ODR violation

* Components: Add new components

* Entity: Add headers

inline script component ComponentType

* Components: Flip constructor argument order

Entity comes first always

* Entity: Add generic AddComponent

Allows for much easier adding of components and is error proof by not allowing the user to add more than 1 of a specific component type to an Entity.

* Entity: Migrate all component constructors

Move all to the new variadic templates AddComponent function to reduce clutter and ways the component map is modified.
The new function makes no assumptions.  Component is assumed to not exist and is checked for with operator[].  This will construct a null component which will then be newed if the component didnt exist, or it will just get the current component if it does already exist.  No new component will be allocated or constructed if the component already exists and the already existing pointer is returned instead.

* Entity: Add placement new

For the case where the component may already exist, use a placement new to construct the component again, it would be constructed again, but would not need to go through the allocator.

* Entity: Add comments on likely new code

* Tests: Fix tests

* Update Entity.cpp

* Update SGCannon.cpp

* Entity: call destructor when re-constructing

* Update Entity.cpp

Update Entity.cpp

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-10-22 20:08:49 -05:00

382 lines
9.5 KiB
C++

/*
* Darkflame Universe
* Copyright 2018
*/
#include "CDClientManager.h"
#ifndef SCRIPTEDACTIVITYCOMPONENT_H
#define SCRIPTEDACTIVITYCOMPONENT_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<Entity*> 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<LWOOBJID> 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<LobbyPlayer*> 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 {
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<LobbyPlayer*>& 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<ActivityInstance*>& 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<ActivityPlayer*> 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<ActivityInstance*> m_Instances;
/**
* The current lobbies for this activity
*/
std::vector<Lobby*> m_Queue;
/**
* All the activity score for the players in this activity
*/
std::vector<ActivityPlayer*> m_ActivityPlayers;
/**
* LMIs for team sizes
*/
std::unordered_map<uint32_t, uint32_t> m_ActivityLootMatrices;
/**
* The activity id
*
*/
int32_t m_ActivityID;
};
#endif // SCRIPTEDACTIVITYCOMPONENT_H