DarkflameServer/dGame/dComponents/InventoryComponent.h

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

483 lines
15 KiB
C
Raw Permalink Normal View History

#pragma once
#ifndef INVENTORYCOMPONENT_H
#define INVENTORYCOMPONENT_H
#include <map>
#include <stack>
#include "BehaviorSlot.h"
#include "tinyxml2.h"
#include "dCommonVars.h"
#include "EquippedItem.h"
#include "Inventory.h"
#include "LDFFormat.h"
#include "DatabasePet.h"
#include "Component.h"
#include "ItemSetPassiveAbility.h"
#include "eItemSetPassiveAbilityID.h"
2022-02-10 05:21:10 +00:00
#include "PossessorComponent.h"
#include "eInventoryType.h"
#include "eReplicaComponentType.h"
#include "eLootSourceType.h"
class Entity;
class ItemSet;
typedef std::map<std::string, EquippedItem> EquipmentMap;
enum class eItemType : int32_t;
/**
* Handles the inventory of entity, including the items they possess and have equipped. An entity can have inventories
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
* inventories.
*/
class InventoryComponent : 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::INVENTORY;
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
void LoadXml(tinyxml2::XMLDocument* document);
void UpdateXml(tinyxml2::XMLDocument* document) override;
2022-07-28 13:39:57 +00:00
/**
* Returns an inventory of the specified type, if it exists
* @param type the inventory type to find an inventory for
* @return the inventory of the specified type
*/
Inventory* GetInventory(eInventoryType type);
/**
* Returns all the inventories this entity has, indexed by type
* @return all the inventories this entity has, indexed by type
*/
const std::map<eInventoryType, Inventory*>& GetInventories() const;
/**
* Returns the amount of items this entity possesses of a certain LOT
* @param lot the lot to search for
* @return the amount of items this entity possesses the specified LOT
*/
uint32_t GetLotCount(LOT lot) const;
/**
* Returns the amount of items this entity possesses of a LOT, given that they're not in a temporary inventory
* (vendor buyback, vault, etc).
* @param lot the lot to search for
* @return the amount of items this entity possesses of the specified lot
*/
uint32_t GetLotCountNonTransfer(LOT lot) const;
/**
* Returns the items that are currently equipped by this entity
* @return the items that are currently equipped by this entity
*/
const EquipmentMap& GetEquippedItems() const;
/**
* Adds an item to the inventory of the entity
* @param lot the lot to add
* @param count the amount of items to add
* @param inventoryType the inventory to add the item to
* @param config optional config for this item, used for example for rockets
* @param parent optional parent of this item, used for proxy items
* @param showFlyingLoot show a client animation if the item is added
* @param isModMoveAndEquip equips the item
* @param subKey optional sub ID of a related object, used by pets
* @param inventorySourceType if the inventory was moved, the source inventory
* @param sourceType the source of the item, used to determine if the item is dropped or mailed if the inventory is full
* @param bound whether this item is bound
* @param preferredSlot the preferred slot to store this item
* @param lootSourceType The source of the loot. Defaults to none.
*/
void AddItem(
LOT lot,
uint32_t count,
eLootSourceType lootSourceType = eLootSourceType::NONE,
eInventoryType inventoryType = INVALID,
const std::vector<LDFBaseData*>& config = {},
LWOOBJID parent = LWOOBJID_EMPTY,
bool showFlyingLoot = true,
bool isModMoveAndEquip = false,
LWOOBJID subKey = LWOOBJID_EMPTY,
eInventoryType inventorySourceType = INVALID,
int32_t sourceType = 0,
bool bound = false,
int32_t preferredSlot = -1
);
/**
* Removes a LOT from the inventory
* @param lot the lot to remove
* @param count the number of items to remove
* @param inventoryType optional inventory type to remove the item from
* @param ignoreBound ignores bound items
*/
void RemoveItem(LOT lot, uint32_t count, eInventoryType inventoryType = INVALID, bool ignoreBound = false);
/**
* Moves an existing item to an inventory of the entity
* @param item the item to add
* @param inventory the inventory to add the item to
* @param count the number of items to add
* @param showFlyingLot displays UI animation to the user
* @param isModMoveAndEquip equips the item
* @param ignoreEquipped does not stack on equipped items
* @param preferredSlot the preferred slot to store the item in
*/
void MoveItemToInventory(Item* item, eInventoryType inventory, uint32_t count, bool showFlyingLot = true, bool isModMoveAndEquip = false, bool ignoreEquipped = false, int32_t preferredSlot = -1);
/**
* Moves a stack of items to an inventory
* @param item the item to move
* @param inventory the inventory to move the item to
* @param slot the slot in the inventory to move the item to
*/
void MoveStack(Item* item, eInventoryType inventory, uint32_t slot = 0);
/**
* Returns an item in the inventory by object ID
* @param id the id of the item to find
* @return item in the inventory by object ID
*/
Item* FindItemById(LWOOBJID id) const;
/**
* Returns an item in the inventory that matches the specified LOT
* @param lot the lot of the item to find
* @param inventoryType optional inventory to search in
* @param ignoreEquipped ignores items that are equipped
* @param ignoreBound ignores items that are bound
* @return item in the inventory that matches the specified LOT
*/
Item* FindItemByLot(LOT lot, eInventoryType inventoryType = INVALID, bool ignoreEquipped = false, bool ignoreBound = false);
/**
* Finds an item in the inventory that has the specified subkey, useful for pets
* @param id the subkey to look for
* @param inventoryType optional inventory type to search in
* @return item in the inventory that has the specified subkey
*/
Item* FindItemBySubKey(LWOOBJID id, eInventoryType inventoryType = INVALID);
/**
* Checks if the entity has enough space for a batch of loot
* @param loot a map of items to add and how many to add
* @return whether the entity has enough space for all the items
*/
bool HasSpaceForLoot(const std::unordered_map<LOT, int32_t>& loot);
/**
* Equips an item in the specified slot
* @param location the location to store the item (e.g. chest, left hand, etc.)
* @param item the item to place
* @param keepCurrent stores the item in an additional temp slot if there's already an item equipped
*/
void UpdateSlot(const std::string& location, EquippedItem item, bool keepCurrent = false);
/**
* Removes a slot from the inventory
* @param location the slot to remove
*/
void RemoveSlot(const std::string& location);
/**
* Equips the given item, guesses the slot to equip it in
* @param item the item to equip
* @param skipChecks skips checks for equipping cars and rockets (e.g. no special behavior follows)
*/
void EquipItem(Item* item, bool skipChecks = false);
/**
* Unequips an item from the inventory
* @param item the item to unequip
*/
void UnEquipItem(Item* item);
/**
* Unequips an Item from the inventory
* @param item the Item to unequip
* @return if we were successful
*/
void HandlePossession(Item* item);
/**
* Adds a buff related to equipping a lot to the entity
2022-03-27 22:28:21 +00:00
* @param item the item to find buffs for
*/
2022-03-27 22:24:06 +00:00
void ApplyBuff(Item* item) const;
/**
* Removes buffs related to equipping a lot from the entity
2022-03-27 22:28:21 +00:00
* @param item the item to find buffs for
*/
2022-03-27 22:24:06 +00:00
void RemoveBuff(Item* item) const;
/**
* Saves the equipped items into a temp state
*/
void PushEquippedItems();
/**
* Unequips all the temporary items and equips the previous item state
*/
void PopEquippedItems();
/**
* Returns if the entity has an item equipped of the given lot
* @param lot to lot to search for
* @return if the entity has an item equipped of the given lot
*/
bool IsEquipped(LOT lot) const;
/**
* Checks and ensures that we have loaded the item set that might be related to this item
* @param lot the lot to check the item set for
*/
void CheckItemSet(LOT lot);
/**
* Sets the current consumable lot
* @param lot the lot to set as consumable
*/
void SetConsumable(LOT lot);
/**
* Returns the current consumable lot
* @return the current consumable lot
*/
LOT GetConsumable() const;
/**
* Finds all the buffs related to a lot
2022-03-27 22:37:05 +00:00
* @param item the item to get the buffs for
* @param castOnEquip if true, the skill missions for these buffs will be progressed
* @return the buffs related to the specified lot
*/
2022-03-27 22:24:06 +00:00
std::vector<uint32_t> FindBuffs(Item* item, bool castOnEquip) const;
/**
* Initializes the equipped items with a list of items
* @param items the items to equip
*/
void SetNPCItems(const std::vector<LOT>& items);
/**
* Adds a skill related to a passed item to the currently equipped skills
* @param lot the lot to add a skill for
*/
void AddItemSkills(LOT lot);
/**
* Removes the skills related to the passed LOT from the currently equipped skills
* @param lot the lot to remove
*/
void RemoveItemSkills(LOT lot);
/**
* Triggers one of the passive abilities from the equipped item set
* @param trigger the trigger to fire
*/
void TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target = nullptr);
/**
* Returns if the entity has any of the passed passive abilities equipped
* @param passiveIDs the IDs to check for
* @param equipmentRequirement the number of equipment required to be allowed to have the ability
* @return if the entity has any of the passed passive abilities equipped
*/
bool HasAnyPassive(const std::vector<eItemSetPassiveAbilityID>& passiveIDs, int32_t equipmentRequirement) const;
/**
* Despawns the currently active pet, if any
*/
void DespawnPet();
/**
* Spawns the item as a pet (if it is one)
* @param item the pet to spawn
*/
void SpawnPet(Item* item);
/**
* Updates the database pet data for an item (e.g. moderation status)
* @param id the id of the pet to find
* @param data the data to store on the pet
*/
void SetDatabasePet(LWOOBJID id, const DatabasePet& data);
/**
* Returns the database pet information for an object
* @param id the object ID to search for
* @return the database pet information for the object that belongs to the passed id
*/
const DatabasePet& GetDatabasePet(LWOOBJID id) const;
/**
* Checks if the provided object ID is in this inventory and is a pet
* @param id the id of the object to check for
* @return if the provided object ID is in this inventory and is a pet
*/
bool IsPet(LWOOBJID id) const;
/**
* Removes pet database information from the item with the specified object id
* @param id the object id to remove pet info for
*/
void RemoveDatabasePet(LWOOBJID id);
/**
* Returns the current behavior slot active for the passed item type
* @param type the item type to find the behavior slot for
* @return the current behavior slot active for the passed item type
*/
static BehaviorSlot FindBehaviorSlot(eItemType type);
/**
* Checks if the inventory type is a temp inventory
* @param type the inventory type to check
* @return if the inventory type is a temp inventory
*/
static bool IsTransferInventory(eInventoryType type);
/**
* Finds the skill related to the passed LOT from the ObjectSkills table
* @param lot the lot to find
* @return the skill related to the passed LOT
*/
static uint32_t FindSkill(LOT lot);
2022-07-28 13:39:57 +00:00
/**
* Call this when you equip an item. This calls OnFactionTriggerItemEquipped for any scripts found on the items.
*
* @param equippedItem The item script to lookup and call equip on
*/
void EquipScripts(Item* equippedItem);
/**
* Call this when you unequip an item. This calls OnFactionTriggerItemUnequipped for any scripts found on the items.
*
* @param unequippedItem The item script to lookup and call unequip on
*/
void UnequipScripts(Item* unequippedItem);
std::map<BehaviorSlot, uint32_t> GetSkills(){ return m_Skills; };
bool SetSkill(int slot, uint32_t skillId);
bool SetSkill(BehaviorSlot slot, uint32_t skillId);
~InventoryComponent() override;
2022-07-28 13:39:57 +00:00
private:
/**
* All the inventory this entity possesses
*/
std::map<eInventoryType, Inventory*> m_Inventories;
/**
* The skills that this entity currently has active
*/
std::map<BehaviorSlot, uint32_t> m_Skills;
/**
* The pets this entity has, mapped by object ID and pet info
*/
std::unordered_map<LWOOBJID, DatabasePet> m_Pets;
/**
* Cache of item sets this entity has encountered
*/
std::vector<ItemSet*> m_Itemsets;
/**
* The LOTs we've checked all the item sets for (for cache reasons)
*/
std::vector<LOT> m_ItemSetsChecked;
/**
* all the equipped items
*/
EquipmentMap m_Equipped;
/**
* Clone of the equipped items before unequipping all of them
*/
EquipmentMap m_Pushed;
/**
* If the inventory has changed
*/
bool m_Dirty;
/**
* The currently active consumable
*/
LOT m_Consumable;
2022-02-10 05:21:10 +00:00
/**
* Currently has a car equipped
*/
bool hasCarEquipped = false;
Entity* equippedCarEntity = nullptr;
2022-02-10 09:03:51 +00:00
LWOOBJID previousPossessableID = LWOOBJID_EMPTY;
LWOOBJID previousPossessorID = LWOOBJID_EMPTY;
/**
* Creates all the proxy items (subitems) for a parent item
* @param parent the parent item to generate all the subitems for
* @return the proxy items (subitems) for a parent item
*/
std::vector<Item*> GenerateProxies(Item* parent);
/**
* Finds all the proxy items in this inventory for a given parent item
* @param parent the parent to find proxy items for
* @return the proxy items for the parent
*/
std::vector<Item*> FindProxies(LWOOBJID parent);
/**
2022-02-07 04:33:07 +00:00
* Returns true if the provided LWOOBJID is the parent of this Item.
* @param parent the parent item to check for proxies
* @return if the provided ID is a valid proxy item
*/
bool IsValidProxy(LWOOBJID parent);
/**
* Returns if the provided ID is a valid proxy item (e.g. we have children for it)
* @param parent the parent item to check for
* @return if the provided ID is a valid proxy item
*/
bool IsParentValid(Item* root);
/**
* Removes all the proxy items that have a dangling parent
*/
void CheckProxyIntegrity();
/**
* Removes all the proxy items for a given parent from the inventory
* @param item the item to remove proxy items for
*/
void PurgeProxies(Item* item);
/**
* Saves all the pet information stored in inventory items to the database
* @param document the xml doc to save to
*/
void LoadPetXml(tinyxml2::XMLDocument* document);
/**
* Loads all the pet information from an xml doc into items
* @param document the xml doc to load from
*/
void UpdatePetXml(tinyxml2::XMLDocument* document);
};
#endif