DarkflameServer/dGame/dComponents/PetComponent.h

584 lines
15 KiB
C
Raw Normal View History

2023-12-15 05:43:08 +00:00
#ifndef PETCOMPONENT_H
#define PETCOMPONENT_H
#include "Entity.h"
#include "MovementAIComponent.h"
#include "Component.h"
#include "Preconditions.h"
#include "eReplicaComponentType.h"
#include "ePetAbilityType.h"
2023-12-16 00:38:52 +00:00
#include "CDPetComponentTable.h"
2023-12-11 01:55:36 +00:00
/*
* The current state of the pet AI
*/
2023-12-12 03:10:29 +00:00
enum class PetAiState : uint8_t {
2023-12-11 01:55:36 +00:00
idle = 0, // Doing nothing
spawn, // Spawning into the world
2023-12-12 03:10:29 +00:00
follow, // Begin following
2023-12-11 01:55:36 +00:00
goToObj, // Go to object
2023-12-12 03:10:29 +00:00
interact, // Interact with an object
2023-12-11 01:55:36 +00:00
despawn // Despawning from world
};
2023-12-12 03:10:29 +00:00
/*
* The type of object the pet is interacting with
*/
2023-12-15 05:43:08 +00:00
enum PetInteractType : uint8_t {
2023-12-12 03:10:29 +00:00
none, // Not interacting
treasure, // Treasure dig
bouncer // Bouncer switch
};
2023-12-15 05:43:08 +00:00
/**
* The flags governing the status of the pet: Governs the icon above their head and the interactions available
2023-12-11 01:55:36 +00:00
*/
2023-12-15 05:43:08 +00:00
enum PetFlag : uint32_t {
2023-11-19 22:46:27 +00:00
NONE,
IDLE = 1 << 0, //0x01 - Seems to be "idle," which the game doesn't differentiate from "follow"
2023-12-17 01:55:43 +00:00
UNKNOWN4 = 1 << 2, //0x04 - FOLLOWING(?)
BEING_TAMED = 1 << 4, //0x10,
NOT_WAITING = 1 << 5, //0x20,
2023-12-28 01:39:07 +00:00
IMMOBILE = 1 << 6, //0x40 - Seems to be the "stop moving" flag - called when taming begins and stays active until a name is submitted
SPAWNING = 1 << 7, //0x80
2023-12-28 01:39:07 +00:00
ON_SWITCH = 1 << 8, //0x100
2023-12-17 01:55:43 +00:00
UNKNOWN1024 = 1 << 10, //0x400
TAMEABLE = 1 << 26 //0x4000000
2023-11-19 22:46:27 +00:00
};
2023-12-17 01:55:43 +00:00
/*
132 = 128 + 4
*/
/**
* The pet emote animation ids that can used in PetComponent::Command()
2023-12-15 05:43:08 +00:00
*/
2023-11-19 22:46:27 +00:00
enum PetEmote : int32_t {
ActivateSwitch = 201,
DigTreasure,
Bounce
};
/**
* Represents an entity that is a pet. This pet can be tamed and consequently follows the tamer around, allowing it
* to dig for treasure and activate pet bouncers.
*/
2023-12-15 05:43:08 +00:00
class PetComponent : public Component {
public:
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-23 01:08:49 +00:00
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PET;
2022-07-28 13:39:57 +00:00
2023-12-15 05:43:08 +00:00
PetComponent(Entity* parentEntity, uint32_t componentId);
2022-07-28 13:39:57 +00:00
~PetComponent() override;
2023-12-16 00:38:52 +00:00
2023-12-15 11:34:38 +00:00
/**
* Serializes the pet
* @param outBitStream The output bitstream
* @param bIsInitialUpdate Boolean value of whether this is the initial update
*/
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
2023-12-11 01:55:36 +00:00
/**
* Sets the AI state of the pet
* @param newState New pet AI state
*/
void SetPetAiState(PetAiState newState);
/**
* Gets the AI state of the pet
*/
PetAiState GetPetAiState() { return m_State; };
2023-12-15 05:43:08 +00:00
/**
2023-12-15 11:34:38 +00:00
* Sets one or more pet flags
* @param flag PetFlag(s) to set
*/
template <typename... varArg>
2024-01-01 18:21:49 +00:00
void SetFlag(varArg... flag) { m_Flags |= (static_cast<uint32_t>(flag) | ...); };
/**
* Sets the pet to ONLY have the specified flag(s), clearing all others
* @param flag PetFlag(s) to set exclusively
2023-12-15 05:43:08 +00:00
*/
2023-12-15 11:34:38 +00:00
template <typename... varArg>
2024-01-01 18:21:49 +00:00
void SetOnlyFlag(varArg... flag) { m_Flags = (static_cast<uint32_t>(flag) | ...); };
2023-12-15 05:43:08 +00:00
/**
2023-12-15 11:34:38 +00:00
* Unsets one or more pet flags
* @param flag PetFlag(s) to unset
2023-12-15 11:34:38 +00:00
*/
template <typename... varArg>
2024-01-01 18:21:49 +00:00
void UnsetFlag(varArg... flag) { m_Flags &= ~(static_cast<uint32_t>(flag) | ...); };
2023-12-15 11:34:38 +00:00
/**
* Returns true if the pet has all the specified flag(s)
* @param flag PetFlag(s) to check
2023-12-15 05:43:08 +00:00
*/
2023-12-15 11:34:38 +00:00
template <typename... varArg>
2024-01-01 18:21:49 +00:00
const bool HasFlag(varArg... flag) { return (m_Flags & (static_cast<uint32_t>(flag) | ...)) == (static_cast<uint32_t>(flag) | ...); };
2023-12-15 05:43:08 +00:00
/**
* Returns true if the pet has ONLY the specified flag(s)
* @param flag PetFlag(s) to check if the pet has exclusively
*/
template <typename... varArg>
2024-01-01 18:21:49 +00:00
const bool HasOnlyFlag(varArg... flag) { return m_Flags == (static_cast<uint32_t>(flag) | ...); };
/**
* Governs the pet update loop
* @param deltaTime Time elapsed since last update
*/
2022-07-28 13:39:57 +00:00
void Update(float deltaTime) override;
2023-11-22 03:19:30 +00:00
/**
* Handles updates for unowned pets
* @param deltaTime time since last update
*/
void UpdateUnowned(float deltaTime);
2022-07-28 13:39:57 +00:00
/**
* Handles an OnUse event from another entity, initializing the pet taming minigame if this pet is untamed.
* @param originator the entity that triggered the event
*/
void OnUse(Entity* originator) override;
/**
* Attempts to complete the pet minigame by passing a list of bricks to build the minigame model.
* @param bricks the bricks to try to complete the minigame with
* @param clientFailed unused
*/
void TryBuild(uint32_t numBricks, bool clientFailed);
/**
* Handles a notification from the client regarding the completion of the pet minigame, adding the pet to their
* inventory.
* @param position the position to spawn the completed model at
*/
void NotifyTamingBuildSuccess(NiPoint3 position);
/**
* Handles the notification of the client to set the name of the pet (indicating that minigame was completed
* successfully).
* @param name the name of the pet to set
*/
void RequestSetPetName(std::u16string name);
/**
* Handles a notification of the client that the taming entity is leaving the minigame, either voluntary or because
* time ran out.
* @param voluntaryExit whether the client voluntarily exited the minigame
*/
void ClientExitTamingMinigame(bool voluntaryExit);
/**
* Starts the internal timer for the build limit for building the minigame model
*/
void StartTimer();
/**
* Notifies the client that they failed the minigame because time ran out
*/
void ClientFailTamingMinigame();
/**
* Makes the pet wander around
*/
void Wander();
2023-12-12 03:10:29 +00:00
/**
* Called when the pet is first spawned
*/
void OnSpawn();
/**
* Continues a step in the follow state, making sure that the entity is around its start position
*/
2024-01-01 18:21:49 +00:00
void OnFollow(const float deltaTime);
2023-12-12 03:10:29 +00:00
/**
* Continues a step in the interact state, handling the pet's interaction with an entity
*/
void OnInteract();
/**
* Start a pet interaction with an object at a given position
*/
void StartInteract(const NiPoint3& position, const PetInteractType interactType, const LWOOBJID& interactID);
2023-12-12 03:10:29 +00:00
/**
* Stop a pet interaction with an object
* @param bDontSerialize optional parameter, set to true to not serialize afterwards
2023-12-12 03:10:29 +00:00
*/
void StopInteract(bool bDontSerialize = false);
2023-12-12 03:10:29 +00:00
/**
* Set the type of interaction the pet is executing
*/
void SetInteractType(PetInteractType interactType) { m_InteractType = interactType; };
/**
* Get the type of interaction the pet is executing
*/
PetInteractType GetInteractType() { return m_InteractType; };
2022-07-28 13:39:57 +00:00
/**
* Spawns a pet from an item in the inventory of an owner
* @param item the item to create the pet from
* @param registerPet notifies the client that the pet was spawned, not necessary if this pet is being tamed
*/
void Activate(Item* item, bool registerPet = true, bool fromTaming = false);
/**
* Despawns the pet
*/
void Deactivate();
/**
* Removes the pet from the inventory
*/
void Release();
/**
* Commands the pet to do an action, actions are still a relative mystery, next to playing emotes
* @param position a position to execute the command at, currently unused
* @param source the source object that triggered the command
* @param commandType the type of the command (see function body for types)
* @param typeId extra information about the command, e.g. the emote to play
* @param overrideObey unused
*/
void Command(const NiPoint3& position, const LWOOBJID& source, int32_t commandType, int32_t typeId, bool overrideObey);
2022-07-28 13:39:57 +00:00
/**
* Returns the ID of the owner of this pet (if any)
* @return the ID of the owner of this pet
*/
LWOOBJID GetOwnerId() const;
/**
* Returns the entity that owns this pet (if any)
* @return the entity that owns this pet
*/
Entity* GetOwner() const;
/**
* Returns the ID that is stored in the database with regards to this pet, only set for pets that are tamed
* @return the ID that is stored in the database with regards to this pet
*/
LWOOBJID GetDatabaseId() const;
/**
* Returns the ID of the object that the pet is currently interacting with, could be a treasure chest or a switch
* @return the ID of the object that the pet is currently interacting with
*/
LWOOBJID GetInteraction() const;
/**
* Sets the ID that the pet is interacting with
* @param value the ID that the pet is interacting with
*/
void SetInteraction(LWOOBJID value);
/**
* Returns the ID that this pet was spawned from, only set for tamed pets
* @return the ID that this pet was spawned from
*/
LWOOBJID GetItemId() const;
/**
* Returns the status of this pet, e.g. tamable or tamed. The values here are still a bit of mystery and likely a
* bit map
* @return the status of this pet
*/
uint32_t GetStatus() const;
/**
* Sets the current status of the pet
* @param value the current status of the pet to set
*/
void SetStatus(uint32_t value);
/**
* Returns an ability the pet may perform, currently unused
* @return an ability the pet may perform
*/
ePetAbilityType GetAbility() const;
2022-07-28 13:39:57 +00:00
/**
* Sets the ability of the pet, currently unused
* @param value the ability to set
*/
void SetAbility(ePetAbilityType value);
2022-07-28 13:39:57 +00:00
/**
* Sets preconditions for the pet that need to be met before it can be tamed
* @param conditions the preconditions to set
*/
void SetPreconditions(std::string& conditions);
/**
2023-12-13 06:14:53 +00:00
* Sets if the pet is ready to interact with an object
* @param isReady whether the pet is ready to interact (true) or not (false)
*/
2023-12-13 06:14:53 +00:00
void SetIsReadyToInteract(bool isReady) { m_ReadyToInteract = isReady; };
/**
2023-12-13 06:14:53 +00:00
* @return is pet ready to interact with an object
*/
2023-12-13 07:06:58 +00:00
bool IsReadyToInteract() { return m_ReadyToInteract; };
/**
* Sets if the pet is currently handling an interaction with an object
* @param isHandlingInteraction whether the pet is currently handling an interaction with an object
*/
void SetIsHandlingInteraction(bool isHandlingInteraction) { m_IsHandlingInteraction = isHandlingInteraction; };
/**
* @return is pet currently handling an interaction with an object
*/
bool IsHandlingInteraction() { return m_IsHandlingInteraction; };
2023-11-19 22:46:27 +00:00
/**
2023-12-13 06:14:53 +00:00
* Set up the pet bouncer interaction
2023-12-12 03:10:29 +00:00
*/
2023-12-13 06:14:53 +00:00
void SetupInteractBouncer();
2023-11-19 22:46:27 +00:00
2023-12-28 01:39:07 +00:00
/**
* Starts the pet bouncer interaction
*/
void StartInteractBouncer();
/**
* Handles the pet bouncer interaction
*/
void HandleInteractBouncer();
2023-11-19 22:46:27 +00:00
/**
2023-12-13 06:14:53 +00:00
* Set up the treasure dig interaction
2023-11-19 22:46:27 +00:00
*/
2023-12-13 06:14:53 +00:00
void SetupInteractTreasureDig();
2023-11-19 22:46:27 +00:00
/**
2023-12-13 06:14:53 +00:00
* Starts the pet treasure dig interaction
*/
void StartInteractTreasureDig();
2023-11-19 22:46:27 +00:00
/**
2023-12-13 06:14:53 +00:00
* Handles the pet treasure dig interaction
*/
void HandleInteractTreasureDig();
2022-07-28 13:39:57 +00:00
/**
* Returns the entity that this component belongs to
* @return the entity that this component belongs to
*/
Entity* GetParentEntity() const;
/**
* Sets the name of the pet to be moderated
* @param petName the name of the pet to set
*/
void SetPetNameForModeration(const std::string& petName);
/**
* Loads the pet name up for moderation along with the moderation status from the database and sets them for this
* pet.
*/
void LoadPetNameFromModeration();
/**
* Returns the component of the pet some entity is currently taming (if any)
* @param tamer the entity that's currently taming
* @return the pet component of the entity that's being tamed
*/
static PetComponent* GetTamingPet(LWOOBJID tamer);
/**
* Returns the pet that's currently spawned for some entity (if any)
* @param owner the owner of the pet that's spawned
* @return the pet component of the entity that was spawned by the owner
*/
static PetComponent* GetActivePet(LWOOBJID owner);
/**
* Adds the timer to the owner of this pet to drain imagination at the rate
* specified by the parameter imaginationDrainRate
*
* @param item The item that represents this pet in the inventory.
*/
void AddDrainImaginationTimer(Item* item, bool fromTaming = false);
private:
2022-07-28 13:39:57 +00:00
/**
* Information for the minigame to be completed
*/
struct PetPuzzleData
{
/**
* The LOT of the object that is to be created
*/
LOT puzzleModelLot;
/**
* That file that contains the bricks required to build the model
*/
std::string buildFile;
/**
* The time limit to complete the build
*/
int32_t timeLimit;
/**
* The imagination cost for the tamer to start the minigame
*/
int32_t imaginationCost;
/**
* The number of pieces required to complete the minigame
*/
int32_t numValidPieces;
};
2023-12-16 00:38:52 +00:00
/**
2023-12-16 03:47:16 +00:00
* Pet information loaded from the CDClientDatabase
2023-12-16 00:38:52 +00:00
*/
2023-12-28 01:39:07 +00:00
CDPetComponent* m_PetInfo;
2023-12-16 00:38:52 +00:00
2022-07-28 13:39:57 +00:00
/**
* Cache of all the pets that are currently spawned, indexed by tamer
*/
static std::unordered_map<LWOOBJID, LWOOBJID> activePets;
/**
* Cache of all the pets that are currently being tamed, indexed by tamer
*/
static std::unordered_map<LWOOBJID, LWOOBJID> currentActivities;
/**
* Cache of all the minigames and their information from the database
*/
static std::unordered_map<LOT, PetComponent::PetPuzzleData> buildCache;
/**
* Flags that indicate that a player has tamed a pet, indexed by the LOT of the pet
*/
static std::map<LOT, int32_t> petFlags;
2022-07-28 13:39:57 +00:00
/**
2023-12-16 00:38:52 +00:00
* The halting radius of the pet while following a player TODO: Move into struct?
*/
2023-12-16 00:38:52 +00:00
float m_FollowRadius;
2022-07-28 13:39:57 +00:00
/**
* The ID of the component in the pet component table
*/
uint32_t m_ComponentId;
/**
* The ID of the model that was built to complete the taming minigame for this pet
*/
LWOOBJID m_ModelId;
/**
* The ID of the object that the pet is currently interacting with (e.g. a treasure chest or switch)
*/
LWOOBJID m_Interaction;
2023-12-12 03:10:29 +00:00
/**
* The type of object that the pet is currently interacting with (e.g. a treasure chest or switch)
*/
PetInteractType m_InteractType;
2022-07-28 13:39:57 +00:00
/**
* The ID of the entity that owns this pet
*/
LWOOBJID m_Owner;
/**
* The ID of the entity that is currently taming this pet
*/
LWOOBJID m_Tamer;
/**
* The ID under which this pet is stored in the database (if it's tamed)
*/
LWOOBJID m_DatabaseId;
/**
* The ID of the item from which this pet was created
*/
LWOOBJID m_ItemId;
/**
* The moderation status for the name of this pet
*/
uint32_t m_ModerationStatus;
/**
* The name of this pet
*/
std::string m_Name;
/**
* The name of the owner of this pet
*/
std::string m_OwnerName;
/**
2023-12-15 05:43:08 +00:00
* The current flags of the pet (e.g. tamable, tamed, etc).
2022-07-28 13:39:57 +00:00
*/
2023-12-15 05:43:08 +00:00
uint32_t m_Flags;
2022-07-28 13:39:57 +00:00
2023-12-11 01:55:36 +00:00
/**
* The current state of the pet AI
*/
PetAiState m_State;
2022-07-28 13:39:57 +00:00
/**
* A currently active ability, mostly unused
*/
ePetAbilityType m_Ability;
2022-07-28 13:39:57 +00:00
/**
* The time an entity has left to complete the minigame
*/
float m_Timer;
/**
* A timer that tracks how long a tamed pet has been to far away from its owner, triggering a teleport after timeout
*/
float m_TimerAway;
/**
2023-12-13 06:14:53 +00:00
* A timer that tracks how long until a tamed pet will bounce again when standing over a treasure dig site
*/
float m_TimerBounce;
2022-07-28 13:39:57 +00:00
/**
2023-12-13 06:14:53 +00:00
* Boolean that sets if a pet is ready to interact with an object
*/
2023-12-13 06:14:53 +00:00
bool m_ReadyToInteract;
/**
* Boolean that sets if a pet is currently handling an interaction with an object
*/
bool m_IsHandlingInteraction;
2022-07-28 13:39:57 +00:00
/**
* The position that this pet was spawned at
*/
NiPoint3 m_StartPosition;
/**
* The movement AI component that is related to this pet, required to move it around
*/
MovementAIComponent* m_MovementAI;
/**
* Preconditions that need to be met before an entity can tame this pet
*/
PreconditionExpression* m_Preconditions;
};
2023-12-15 05:43:08 +00:00
#endif // PETCOMPONENT_H