#ifndef PETCOMPONENT_H #define PETCOMPONENT_H #include "Entity.h" #include "MovementAIComponent.h" #include "Component.h" #include "Preconditions.h" #include "eReplicaComponentType.h" #include "ePetAbilityType.h" /* * The current state of the pet AI */ enum class PetAiState : uint8_t { idle = 0, // Doing nothing spawn, // Spawning into the world follow, // Begin following goToObj, // Go to object interact, // Interact with an object despawn // Despawning from world }; /* * The type of object the pet is interacting with */ enum PetInteractType : uint8_t { none, // Not interacting treasure, // Treasure dig bouncer // Bouncer switch }; /** * The flags governing the status of the pet: Governs the icon above their head and the interactions available */ enum PetFlag : uint32_t { NONE, BEING_TAMED = 4, NOT_WAITING = 5, PLAY_SPAWN_ANIM = 7, TAMEABLE = 8 }; /* * DEPRECATED The status of the pet: Governs the icon above their head and the interactions available */ /*enum PetStatus : uint32_t { NONE, BEING_TAMED = 1 << 4, //PetFlag::BEING_TAMED, //0x10, IS_NOT_WAITING = 1 << 5, //PetFlag::NOT_WAITING, //0x20, PLAY_SPAWN_ANIM = 1 << 7, //PetFlag::PLAY_SPAWN_ANIM, //0x80, TAMEABLE = 1 << 8 // PetFlag::TAMEABLE //0x4000000 };*/ 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. */ class PetComponent : public Component { public: inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PET; PetComponent(Entity* parentEntity, uint32_t componentId); ~PetComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * 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; }; /** * Template function for setting pet flags */ template void SetFlag(T... flag) { //m_Flags |= (uint32_t)flag; m_Flags |= ((uint32_t)flag | ...);//(static_cast(flag) | ...); //T::operator|(m_Flags, flag...); } /** * Template function for getting pet flags */ template const bool HasFlag(T... flag) { //return (m_Flags & (u_int32_t)flag) == (u_int32_t)flag; //return T::operator&(m_Flags, flag...) == T::operator&(flag...); return true; } void Update(float deltaTime) override; /** * Handles updates for unowned pets * @param deltaTime time since last update */ void UpdateUnowned(float deltaTime); /** * 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(); /** * 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 */ void OnFollow(); /** * 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); /** * Stop a pet interaction with an object */ void StopInteract(); /** * 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; }; /** * 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(NiPoint3 position, LWOOBJID source, int32_t commandType, int32_t typeId, bool overrideObey); /** * 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; /** * Sets the ability of the pet, currently unused * @param value the ability to set */ void SetAbility(ePetAbilityType value); /** * 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); /** * Sets if the pet is ready to interact with an object * @param isReady whether the pet is ready to interact (true) or not (false) */ void SetIsReadyToInteract(bool isReady) { m_ReadyToInteract = isReady; }; /** * @return is pet ready to interact with an object */ 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; }; /** * Set up the pet bouncer interaction */ void SetupInteractBouncer(); /** * Set up the treasure dig interaction */ void SetupInteractTreasureDig(); /** * Starts the pet treasure dig interaction */ void StartInteractTreasureDig(); /** * Handles the pet treasure dig interaction */ void HandleInteractTreasureDig(); /** * 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: /** * 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; }; /** * Cache of all the pets that are currently spawned, indexed by tamer */ static std::unordered_map activePets; /** * Cache of all the pets that are currently being tamed, indexed by tamer */ static std::unordered_map currentActivities; /** * Cache of all the minigames and their information from the database */ static std::unordered_map buildCache; /** * Flags that indicate that a player has tamed a pet, indexed by the LOT of the pet */ static std::map petFlags; /** * The halting radius of the pet while following a player */ static float m_FollowRadius; /** * 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; /** * The type of object that the pet is currently interacting with (e.g. a treasure chest or switch) */ PetInteractType m_InteractType; /** * 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; /** * The current flags of the pet (e.g. tamable, tamed, etc). */ uint32_t m_Flags; /** * The current state of the pet AI */ PetAiState m_State; /** * A currently active ability, mostly unused */ ePetAbilityType m_Ability; /** * 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; /** * A timer that tracks how long until a tamed pet will bounce again when standing over a treasure dig site */ float m_TimerBounce; /** * Boolean that sets if a pet is ready to interact with an object */ bool m_ReadyToInteract; /** * Boolean that sets if a pet is currently handling an interaction with an object */ bool m_IsHandlingInteraction; /** * 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; /** * The rate at which imagination is drained from the user for having the pet out. */ float imaginationDrainRate; /** * The walk speed of the pet */ float m_WalkSpeed; /** * The run speed of the pet */ float m_RunSpeed; /** * The sprint speed of the pet */ float m_SprintSpeed; }; #endif // PETCOMPONENT_H