DarkflameServer/dGame/dComponents/PetComponent.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

552 lines
14 KiB
C
Raw Normal View History

2023-12-15 05:43:08 +00:00
#ifndef PETCOMPONENT_H
#define PETCOMPONENT_H
#include "Entity.h"
2024-04-20 02:53:52 +00:00
#include "Flag.h"
#include "MovementAIComponent.h"
#include "Component.h"
#include "Preconditions.h"
#include "ePetAbilityType.h"
#include "eReplicaComponentType.h"
#include "ePetAbilityType.h"
2023-12-16 00:38:52 +00:00
#include "CDPetComponentTable.h"
#include "CDClientManager.h"
2024-04-20 02:53:52 +00:00
#include <optional>
#include <gtest/gtest.h>
// Forward declarations
class PetTest;
class PetComponentFlagTest;
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
*/
2024-03-06 05:37:42 +00:00
enum class 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
*/
2024-03-06 05:37:42 +00:00
enum class PetFlag : uint32_t {
2023-11-19 22:46:27 +00:00
NONE,
2024-04-20 02:53:52 +00:00
IDLE, //0x01 - Seems to be "idle," which the game doesn't differentiate from "follow"
UNKNOWN2, //0x02,
UNKNOWN4, //0x04 - FOLLOWING(?)
BEING_TAMED, //0x10,
NOT_WAITING, //0x20,
IMMOBILE, //0x40 - Seems to be the "stop moving" flag - called when taming begins and stays active until a name is submitted
SPAWNING, //0x80
ON_SWITCH, //0x100
UNKNOWN1024 = 10, //0x400
TAMEABLE = 26 //0x4000000
2023-11-19 22:46:27 +00:00
};
/**
* The pet emote animation ids that can used in PetComponent::Command()
2023-12-15 05:43:08 +00:00
*/
2024-03-06 05:37:42 +00:00
enum class PetEmote : int32_t {
2023-11-19 22:46:27 +00:00
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.
*/
2024-04-20 02:53:52 +00:00
class PetComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PET;
2022-07-28 13:39:57 +00:00
/**
* PetComponent constructor
* @param parentEntity The parent entity
* @param componentId The component id
*/
explicit PetComponent(Entity* parentEntity, uint32_t componentId);
2024-04-20 02:53:52 +00:00
~PetComponent() override = default;
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
*/
2024-04-20 02:53:52 +00:00
void SetPetAiState(const PetAiState newState) noexcept {
m_State = newState;
};
2023-12-11 01:55:36 +00:00
/**
* Gets the AI state of the pet
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
PetAiState GetPetAiState() const noexcept {
return m_State;
2024-03-06 05:37:42 +00:00
}
/**
* Governs the pet update loop
* @param deltaTime Time elapsed since last update
*/
void Update(float deltaTime) override;
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;
2022-07-28 13:39:57 +00:00
/**
* 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
*/
2022-04-07 05:21:29 +00:00
void TryBuild(uint32_t numBricks, bool clientFailed);
2022-07-28 13:39:57 +00:00
/**
* 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);
2022-07-28 13:39:57 +00:00
/**
* 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
*/
2024-03-09 00:43:40 +00:00
void RequestSetPetName(const std::u16string& name);
2022-07-28 13:39:57 +00:00
/**
* 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);
2022-07-28 13:39:57 +00:00
/**
* Starts the internal timer for the build limit for building the minigame model
*/
void StartTimer();
2022-07-28 13:39:57 +00:00
/**
* Notifies the client that they failed the minigame because time ran out
*/
void ClientFailTamingMinigame();
2022-07-28 13:39:57 +00:00
/**
* Makes the pet wander around
*/
void Wander();
2022-07-28 13:39:57 +00:00
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
*/
2024-04-20 02:53:52 +00:00
void StartInteract(const NiPoint3& position, const PetInteractType interactionType, 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
/**
* 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
*/
2022-06-18 07:14:24 +00:00
void Activate(Item* item, bool registerPet = true, bool fromTaming = false);
2022-07-28 13:39:57 +00:00
/**
* Despawns the pet
*/
2024-03-09 00:43:40 +00:00
void Deactivate(eHelpType msg = eHelpType::NONE);
2022-07-28 13:39:57 +00:00
/**
* Removes the pet from the inventory
*/
void Release();
2022-07-28 13:39:57 +00:00
/**
* 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, const int32_t commandType, const int32_t typeId, const 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
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
LWOOBJID GetOwnerId() const noexcept {
return m_Owner;
};
2022-07-28 13:39:57 +00:00
/**
* Returns the entity that owns this pet (if any)
* @return the entity that owns this pet
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
Entity* GetOwner() const;
2022-07-28 13:39:57 +00:00
/**
* 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
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
LWOOBJID GetDatabaseId() const noexcept {
return m_DatabaseId;
}
2022-07-28 13:39:57 +00:00
/**
* Returns the ID that this pet was spawned from, only set for tamed pets
* @return the ID that this pet was spawned from
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
LWOOBJID GetItemId() const noexcept {
return m_ItemId;
}
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
*/
2024-04-20 02:53:52 +00:00
void SetPreconditions(const std::string& preconditions) {
m_Preconditions = PreconditionExpression(preconditions);
}
2022-07-28 13:39:57 +00:00
/**
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)
*/
2024-04-20 02:53:52 +00:00
void SetIsReadyToInteract(const bool isReady) {
m_ReadyToInteract = isReady;
};
/**
2023-12-13 06:14:53 +00:00
* @return is pet ready to interact with an object
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
bool IsReadyToInteract() const noexcept {
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
*/
2024-04-20 02:53:52 +00:00
void SetIsHandlingInteraction(const bool isHandlingInteraction) {
m_IsHandlingInteraction = isHandlingInteraction;
}
/**
* @return is pet currently handling an interaction with an object
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
bool IsHandlingInteraction() const noexcept {
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();
/**
* Returns the entity that this component belongs to
* @return the entity that this component belongs to
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
Entity* GetParentEntity() const noexcept {
return m_Parent;
}
2022-07-28 13:39:57 +00:00
/**
* Sets the name of the pet to be moderated
* @param petName the name of the pet to set
*/
void SetPetNameForModeration(const std::string& petName);
2022-07-28 13:39:57 +00:00
/**
* Loads the pet name up for moderation along with the moderation status from the database and sets them for this
* pet.
*/
void LoadPetNameFromModeration();
2022-07-28 13:39:57 +00:00
/**
* 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
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
static PetComponent* GetTamingPet(LWOOBJID tamer);
2022-07-28 13:39:57 +00:00
/**
* 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
*/
2024-04-20 02:53:52 +00:00
[[nodiscard]]
static PetComponent* GetActivePet(LWOOBJID owner);
2022-07-28 13:39:57 +00:00
/**
* 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.
*/
2022-06-18 07:14:24 +00:00
void AddDrainImaginationTimer(Item* item, bool fromTaming = false);
private:
2024-04-20 02:53:52 +00:00
// Needed so these can access flags
friend class DamagingPets;
friend class PetTest;
FRIEND_TEST(PetTest, PetComponentFlagTest);
/**
* Information for the minigame to be completed
*/
2024-04-20 02:53:52 +00:00
struct PuzzleData
{
/**
* The LOT of the object that is to be created
*/
LOT puzzleModelLot;
2022-07-28 13:39:57 +00:00
/**
* That file that contains the bricks required to build the model
*/
std::string buildFile;
2022-07-28 13:39:57 +00:00
/**
* The time limit to complete the build
*/
int32_t timeLimit;
2022-07-28 13:39:57 +00:00
/**
* The imagination cost for the tamer to start the minigame
*/
int32_t imaginationCost;
2022-07-28 13:39:57 +00:00
/**
* The number of pieces required to complete the minigame
*/
int32_t numValidPieces;
};
2022-07-28 13:39:57 +00:00
2024-04-20 02:53:52 +00:00
struct Interaction {
/**
* The type of object that the pet is currently interacting with (e.g. a treasure chest or switch)
*/
PetInteractType type = PetInteractType::none;
/**
* The interaction ability
*/
ePetAbilityType ability = ePetAbilityType::Invalid;
/**
* The ID of the object that the pet is currently interacting with (e.g. a treasure chest or switch)
*/
LWOOBJID obj = LWOOBJID_EMPTY;
};
/**
* Pet interaction info
*/
Interaction m_Interaction{};
/**
* Cache of all the pets that are currently spawned, indexed by tamer
*/
static std::unordered_map<LWOOBJID, LWOOBJID> activePets;
2022-07-28 13:39:57 +00:00
/**
* Cache of all the pets that are currently being tamed, indexed by tamer
*/
static std::unordered_map<LWOOBJID, LWOOBJID> currentActivities;
2022-07-28 13:39:57 +00:00
/**
* Cache of all the minigames and their information from the database
*/
2024-04-20 02:53:52 +00:00
static std::unordered_map<LOT, PetComponent::PuzzleData> buildCache;
2022-07-28 13:39:57 +00:00
/**
* 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;
/**
* The ID of the component in the pet component table
*/
uint32_t m_ComponentId;
2022-07-28 13:39:57 +00:00
/**
* The ID of the model that was built to complete the taming minigame for this pet
*/
2024-04-20 02:53:52 +00:00
LWOOBJID m_ModelId = LWOOBJID_EMPTY;
2023-12-12 03:10:29 +00:00
/**
* The ID of the entity that owns this pet
*/
2024-04-20 02:53:52 +00:00
LWOOBJID m_Owner = LWOOBJID_EMPTY;
2022-07-28 13:39:57 +00:00
/**
* The ID of the entity that is currently taming this pet
*/
2024-04-20 02:53:52 +00:00
LWOOBJID m_Tamer = LWOOBJID_EMPTY;
2022-07-28 13:39:57 +00:00
/**
* The ID under which this pet is stored in the database (if it's tamed)
*/
2024-04-20 02:53:52 +00:00
LWOOBJID m_DatabaseId = LWOOBJID_EMPTY;
2022-07-28 13:39:57 +00:00
/**
* The ID of the item from which this pet was created
*/
LWOOBJID m_ItemId;
2022-07-28 13:39:57 +00:00
/**
* The moderation status for the name of this pet
*/
2024-04-20 02:53:52 +00:00
uint32_t m_ModerationStatus = 0;
2022-07-28 13:39:57 +00:00
/**
* The name of this pet
*/
std::string m_Name;
2022-07-28 13:39:57 +00:00
/**
* The name of the owner of this pet
*/
std::string m_OwnerName;
2022-07-28 13:39:57 +00:00
/**
2023-12-15 05:43:08 +00:00
* The current flags of the pet (e.g. tamable, tamed, etc).
*/
2024-04-20 02:53:52 +00:00
Flag<PetFlag> 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;
/**
* The time an entity has left to complete the minigame
*/
2024-04-20 02:53:52 +00:00
float m_Timer = 0;
2022-07-28 13:39:57 +00:00
/**
* A timer that tracks how long a tamed pet has been to far away from its owner, triggering a teleport after timeout
*/
2024-04-20 02:53:52 +00:00
float m_TimerAway = 0;
2022-07-28 13:39:57 +00:00
/**
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
*/
2024-04-20 02:53:52 +00:00
float m_TimerBounce = 0;
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;
/**
* The position that this pet was spawned at
*/
NiPoint3 m_StartPosition;
2022-07-28 13:39:57 +00:00
/**
* The movement AI component that is related to this pet, required to move it around
*/
MovementAIComponent* m_MovementAI;
2022-07-28 13:39:57 +00:00
/**
* Preconditions that need to be met before an entity can tame this pet
*/
2024-04-20 02:53:52 +00:00
std::optional<PreconditionExpression> m_Preconditions;
/**
* Pet information loaded from the CDClientDatabase
*/
CDPetComponent m_PetInfo;
};
2023-12-15 05:43:08 +00:00
#endif // !PETCOMPONENT_H