/** * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * * Copyright (C) 2005-2015 MaNGOS project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * World of Warcraft, and all World of Warcraft or Warcraft art, images, * and lore are copyrighted by Blizzard Entertainment, Inc. */ #ifndef MANGOSSERVER_CREATURE_H #define MANGOSSERVER_CREATURE_H #include "Common.h" #include "Unit.h" #include "UpdateMask.h" #include "ItemPrototype.h" #include "SharedDefines.h" #include "LootMgr.h" #include "DBCEnums.h" #include "Database/DatabaseEnv.h" #include "Cell.h" #include struct SpellEntry; class CreatureAI; class Group; class Quest; class Player; class WorldSession; struct GameEventCreatureData; enum CreatureFlagsExtra { CREATURE_EXTRA_FLAG_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group CREATURE_EXTRA_FLAG_NO_AGGRO = 0x00000002, // not aggro (ignore faction/reputation hostility) CREATURE_EXTRA_FLAG_NO_PARRY = 0x00000004, // creature can't parry CREATURE_EXTRA_FLAG_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry CREATURE_EXTRA_FLAG_NO_BLOCK = 0x00000010, // creature can't block CREATURE_EXTRA_FLAG_NO_CRUSH = 0x00000020, // creature can't do crush attacks CREATURE_EXTRA_FLAG_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP CREATURE_EXTRA_FLAG_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures) CREATURE_EXTRA_FLAG_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me CREATURE_EXTRA_FLAG_AGGRO_ZONE = 0x00000200, // creature sets itself in combat with zone on aggro CREATURE_EXTRA_FLAG_GUARD = 0x00000400, // creature is a guard CREATURE_EXTRA_FLAG_NO_CALL_ASSIST = 0x00000800, // creature shouldn't call for assistance on aggro CREATURE_EXTRA_FLAG_ACTIVE = 0x00001000, // creature is active object. Grid of this creature will be loaded and creature set as active CREATURE_EXTRA_FLAG_MMAP_FORCE_ENABLE = 0x00002000, // creature is forced to use MMaps CREATURE_EXTRA_FLAG_MMAP_FORCE_DISABLE = 0x00004000, // creature is forced to NOT use MMaps }; // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform #if defined( __GNUC__ ) #pragma pack(1) #else #pragma pack(push,1) #endif #define MAX_KILL_CREDIT 2 #define MAX_CREATURE_MODEL 2 // only single send to client in static data // from `creature_template` table struct CreatureInfo { uint32 Entry; char* Name; char* SubName; uint32 MinLevel; uint32 MaxLevel; uint32 ModelId[MAX_CREATURE_MODEL]; uint32 FactionAlliance; uint32 FactionHorde; float Scale; uint32 Family; // enum CreatureFamily values (optional) uint32 CreatureType; // enum CreatureType values uint32 InhabitType; uint32 RegenerateStats; bool RacialLeader; uint32 NpcFlags; uint32 UnitFlags; // enum UnitFlags mask values uint32 DynamicFlags; uint32 ExtraFlags; uint32 CreatureTypeFlags; // enum CreatureTypeFlags mask values float SpeedWalk; float SpeedRun; uint32 UnitClass; // enum Classes. Note only 4 classes are known for creatures. uint32 Rank; float HealthMultiplier; float PowerMultiplier; float DamageMultiplier; float DamageVariance; float ArmorMultiplier; float ExperienceMultiplier; uint32 MinLevelHealth; uint32 MaxLevelHealth; uint32 MinLevelMana; uint32 MaxLevelMana; float MinMeleeDmg; float MaxMeleeDmg; float MinRangedDmg; float MaxRangedDmg; uint32 Armor; uint32 MeleeAttackPower; uint32 RangedAttackPower; uint32 MeleeBaseAttackTime; uint32 RangedBaseAttackTime; uint32 DamageSchool; uint32 MinLootGold; uint32 MaxLootGold; uint32 LootId; uint32 PickpocketLootId; uint32 SkinningLootId; uint32 KillCredit[MAX_KILL_CREDIT]; uint32 MechanicImmuneMask; int32 ResistanceHoly; int32 ResistanceFire; int32 ResistanceNature; int32 ResistanceFrost; int32 ResistanceShadow; int32 ResistanceArcane; uint32 PetSpellDataId; uint32 MovementType; uint32 TrainerType; uint32 TrainerSpell; uint32 TrainerClass; uint32 TrainerRace; uint32 TrainerTemplateId; uint32 VendorTemplateId; uint32 GossipMenuId; uint32 EquipmentTemplateId; uint32 civilian; char const* AIName; //uint32 ScriptID; // helpers static HighGuid GetHighGuid() { return HIGHGUID_UNIT; // in pre-3.x always HIGHGUID_UNIT } ObjectGuid GetObjectGuid(uint32 lowguid) const { return ObjectGuid(GetHighGuid(), Entry, lowguid); } SkillType GetRequiredLootSkill() const { if (CreatureTypeFlags & CREATURE_TYPEFLAGS_HERBLOOT) { return SKILL_HERBALISM; } else if (CreatureTypeFlags & CREATURE_TYPEFLAGS_MININGLOOT) { return SKILL_MINING; } else { return SKILL_SKINNING; } // normal case } bool isTameable() const { return CreatureType == CREATURE_TYPE_BEAST && Family != 0 && (CreatureTypeFlags & CREATURE_TYPEFLAGS_TAMEABLE); } }; struct CreatureTemplateSpells { uint32 entry; uint32 spells[CREATURE_MAX_SPELLS]; }; struct EquipmentInfo { uint32 entry; uint32 equipentry[3]; }; struct EquipmentInfoItem { uint32 entry; uint32 Class; uint32 SubClass; uint32 Material; uint32 DisplayID; uint32 InventoryType; uint32 Sheath; }; // depricated old way struct EquipmentInfoRaw { uint32 entry; uint32 equipmodel[3]; uint32 equipinfo[3]; uint32 equipslot[3]; }; // from `creature` table struct CreatureData { uint32 id; // entry in creature_template uint16 mapid; uint32 modelid_override; // overrides any model defined in creature_template int32 equipmentId; float posX; float posY; float posZ; float orientation; uint32 spawntimesecs; float spawndist; uint32 currentwaypoint; uint32 curhealth; uint32 curmana; bool is_dead; uint8 movementType; // helper function ObjectGuid GetObjectGuid(uint32 lowguid) const { return ObjectGuid(CreatureInfo::GetHighGuid(), id, lowguid); } }; enum SplineFlags { SPLINEFLAG_WALKMODE = 0x0000100, SPLINEFLAG_FLYING = 0x0000200, }; // from `creature_addon` and `creature_template_addon`tables struct CreatureDataAddon { uint32 guidOrEntry; uint32 mount; uint32 bytes1; uint8 sheath_state; // SheathState uint8 flags; // UnitBytes2_Flags uint32 emote; uint32 move_flags; uint32 const* auras; // loaded as char* "spell1 spell2 ... " }; // Bases values for given Level and UnitClass struct CreatureClassLvlStats { uint32 BaseHealth; uint32 BaseMana; float BaseDamage; float BaseMeleeAttackPower; float BaseRangedAttackPower; uint32 BaseArmor; }; struct CreatureModelInfo { uint32 modelid; float bounding_radius; float combat_reach; uint8 gender; uint32 modelid_other_gender; // The oposite gender for this modelid (male/female) uint32 modelid_other_team; // The oposite team. Generally for alliance totem }; // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform #if defined( __GNUC__ ) #pragma pack() #else #pragma pack(pop) #endif struct CreatureLocale { std::vector Name; std::vector SubName; }; struct GossipMenuItemsLocale { std::vector OptionText; std::vector BoxText; }; struct PointOfInterestLocale { std::vector IconName; }; enum InhabitTypeValues { INHABIT_GROUND = 1, INHABIT_WATER = 2, INHABIT_AIR = 4, INHABIT_ANYWHERE = INHABIT_GROUND | INHABIT_WATER | INHABIT_AIR }; // Enums used by StringTextData::Type (CreatureEventAI) enum ChatType { CHAT_TYPE_SAY = 0, CHAT_TYPE_YELL = 1, CHAT_TYPE_TEXT_EMOTE = 2, CHAT_TYPE_BOSS_EMOTE = 3, CHAT_TYPE_WHISPER = 4, CHAT_TYPE_BOSS_WHISPER = 5, CHAT_TYPE_ZONE_YELL = 6 }; // Selection method used by SelectAttackingTarget enum AttackingTarget { ATTACKING_TARGET_RANDOM = 0, // Just selects a random target ATTACKING_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom ATTACKING_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top }; enum SelectFlags { SELECT_FLAG_IN_LOS = 0x001, // Default Selection Requirement for Spell-targets SELECT_FLAG_PLAYER = 0x002, SELECT_FLAG_POWER_MANA = 0x004, // For Energy based spells, like manaburn SELECT_FLAG_POWER_RAGE = 0x008, SELECT_FLAG_POWER_ENERGY = 0x010, SELECT_FLAG_IN_MELEE_RANGE = 0x040, SELECT_FLAG_NOT_IN_MELEE_RANGE = 0x080, }; enum RegenStatsFlags { REGEN_FLAG_HEALTH = 0x001, REGEN_FLAG_POWER = 0x002, }; // Vendors struct VendorItem { VendorItem(uint32 _item, uint32 _maxcount, uint32 _incrtime, uint16 _conditionId) : item(_item), maxcount(_maxcount), incrtime(_incrtime), conditionId(_conditionId) {} uint32 item; uint32 maxcount; // 0 for infinity item amount uint32 incrtime; // time for restore items amount if maxcount != 0 uint16 conditionId; // condition to check for this item }; typedef std::vector VendorItemList; struct VendorItemData { VendorItemList m_items; VendorItem* GetItem(uint32 slot) const { if (slot >= m_items.size()) { return NULL; } return m_items[slot]; } bool Empty() const { return m_items.empty(); } uint8 GetItemCount() const { return m_items.size(); } void AddItem(uint32 item, uint32 maxcount, uint32 ptime, uint16 conditonId) { m_items.push_back(new VendorItem(item, maxcount, ptime, conditonId)); } bool RemoveItem(uint32 item_id); VendorItem const* FindItem(uint32 item_id) const; size_t FindItemSlot(uint32 item_id) const; void Clear() { for (VendorItemList::const_iterator itr = m_items.begin(); itr != m_items.end(); ++itr) { delete(*itr); } m_items.clear(); } }; struct VendorItemCount { explicit VendorItemCount(uint32 _item, uint32 _count) : itemId(_item), count(_count), lastIncrementTime(time(NULL)) {} uint32 itemId; uint32 count; time_t lastIncrementTime; }; typedef std::list VendorItemCounts; struct TrainerSpell { TrainerSpell() : spell(0), spellCost(0), reqSkill(0), reqSkillValue(0), reqLevel(0), isProvidedReqLevel(false) {} TrainerSpell(uint32 _spell, uint32 _spellCost, uint32 _reqSkill, uint32 _reqSkillValue, uint32 _reqLevel, bool _isProvidedReqLevel) : spell(_spell), spellCost(_spellCost), reqSkill(_reqSkill), reqSkillValue(_reqSkillValue), reqLevel(_reqLevel), isProvidedReqLevel(_isProvidedReqLevel) {} uint32 spell; uint32 spellCost; uint32 reqSkill; uint32 reqSkillValue; uint32 reqLevel; bool isProvidedReqLevel; }; typedef UNORDERED_MAP < uint32 /*spellid*/, TrainerSpell > TrainerSpellMap; struct TrainerSpellData { TrainerSpellData() : trainerType(0) {} TrainerSpellMap spellList; uint32 trainerType; // trainer type based at trainer spells, can be different from creature_template value. // req. for correct show non-prof. trainers like weaponmaster, allowed values 0 and 2. TrainerSpell const* Find(uint32 spell_id) const; void Clear() { spellList.clear(); } }; typedef std::map CreatureSpellCooldowns; // max different by z coordinate for creature aggro reaction #define CREATURE_Z_ATTACK_RANGE 3 #define MAX_VENDOR_ITEMS 255 // Limitation in item count field size in SMSG_LIST_INVENTORY enum VirtualItemSlot { VIRTUAL_ITEM_SLOT_0 = 0, VIRTUAL_ITEM_SLOT_1 = 1, VIRTUAL_ITEM_SLOT_2 = 2, }; #define MAX_VIRTUAL_ITEM_SLOT 3 enum VirtualItemInfoByteOffset { VIRTUAL_ITEM_INFO_0_OFFSET_CLASS = 0, VIRTUAL_ITEM_INFO_0_OFFSET_SUBCLASS = 1, VIRTUAL_ITEM_INFO_0_OFFSET_MATERIAL = 2, VIRTUAL_ITEM_INFO_0_OFFSET_INVENTORYTYPE = 3, VIRTUAL_ITEM_INFO_1_OFFSET_SHEATH = 0, }; struct CreatureCreatePos { public: // exactly coordinates used CreatureCreatePos(Map* map, float x, float y, float z, float o) : m_map(map), m_closeObject(NULL), m_angle(0.0f), m_dist(0.0f) { m_pos.x = x; m_pos.y = y; m_pos.z = z; m_pos.o = o; } // if dist == 0.0f -> exactly object coordinates used, in other case close point to object (CONTACT_DIST can be used as minimal distances) CreatureCreatePos(WorldObject* closeObject, float ori, float dist = 0.0f, float angle = 0.0f) : m_map(closeObject->GetMap()), m_closeObject(closeObject), m_angle(angle), m_dist(dist) { m_pos.o = ori; } public: Map* GetMap() const { return m_map; } void SelectFinalPoint(Creature* cr); bool Relocate(Creature* cr) const; // read only after SelectFinalPoint Position m_pos; private: Map* m_map; WorldObject* m_closeObject; float m_angle; float m_dist; }; enum CreatureSubtype { CREATURE_SUBTYPE_GENERIC, // new Creature CREATURE_SUBTYPE_PET, // new Pet CREATURE_SUBTYPE_TOTEM, // new Totem CREATURE_SUBTYPE_TEMPORARY_SUMMON, // new TemporarySummon }; enum TemporaryFactionFlags // Used at real faction changes { TEMPFACTION_NONE = 0x00, // When no flag is used in temporary faction change, faction will be persistent. It will then require manual change back to default/another faction when changed once TEMPFACTION_RESTORE_RESPAWN = 0x01, // Default faction will be restored at respawn TEMPFACTION_RESTORE_COMBAT_STOP = 0x02, // ... at CombatStop() (happens at creature death, at evade or custom scripte among others) TEMPFACTION_RESTORE_REACH_HOME = 0x04, // ... at reaching home in home movement (evade), if not already done at CombatStop() TEMPFACTION_TOGGLE_NON_ATTACKABLE = 0x08, // Remove UNIT_FLAG_NON_ATTACKABLE(0x02) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_TOGGLE_OOC_NOT_ATTACK = 0x10, // Remove UNIT_FLAG_OOC_NOT_ATTACKABLE(0x100) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_TOGGLE_PASSIVE = 0x20, // Remove UNIT_FLAG_PASSIVE(0x200) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_TOGGLE_PACIFIED = 0x40, // Remove UNIT_FLAG_PACIFIED(0x20000) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_TOGGLE_NOT_SELECTABLE = 0x80, // Remove UNIT_FLAG_NOT_SELECTABLE(0x2000000) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_ALL, }; class Creature : public Unit { CreatureAI* i_AI; public: /* Loot Variables */ bool hasBeenLootedOnce; uint32 assignedLooter; explicit Creature(CreatureSubtype subtype = CREATURE_SUBTYPE_GENERIC); virtual ~Creature(); void AddToWorld() override; void RemoveFromWorld() override; bool Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo const* cinfo, Team team = TEAM_NONE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL); bool LoadCreatureAddon(bool reload); void SelectLevel(const CreatureInfo* cinfo, float percentHealth = 100.0f); void LoadEquipment(uint32 equip_entry, bool force = false); bool HasStaticDBSpawnData() const; // listed in `creature` table and have fixed in DB guid char const* GetSubName() const { return GetCreatureInfo()->SubName; } void Update(uint32 update_diff, uint32 time) override; // overwrite Unit::Update virtual void RegenerateAll(uint32 update_diff); uint32 GetEquipmentId() const { return m_equipmentId; } CreatureSubtype GetSubtype() const { return m_subtype; } bool IsPet() const { return m_subtype == CREATURE_SUBTYPE_PET; } bool IsTotem() const { return m_subtype == CREATURE_SUBTYPE_TOTEM; } bool IsTemporarySummon() const { return m_subtype == CREATURE_SUBTYPE_TEMPORARY_SUMMON; } bool IsCorpse() const { return GetDeathState() == CORPSE; } bool IsDespawned() const { return GetDeathState() == DEAD; } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } uint32 GetCorpseDelay() const { return m_corpseDelay; } bool IsRacialLeader() const { return GetCreatureInfo()->RacialLeader; } bool IsCivilian() const { return GetCreatureInfo()->civilian; } bool IsGuard() const { return GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_GUARD; } bool CanWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; } bool CanSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; } bool IsSwimming() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_SWIMMING))); } bool CanFly() const { return (GetCreatureInfo()->InhabitType & INHABIT_AIR) || m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_LEVITATING | MOVEFLAG_CAN_FLY)); } bool IsFlying() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING|MOVEFLAG_LEVITATING))); } bool IsTrainerOf(Player* player, bool msg) const; bool CanInteractWithBattleMaster(Player* player, bool msg) const; bool CanTrainAndResetTalentsOf(Player* pPlayer) const; bool IsOutOfThreatArea(Unit* pVictim) const; void FillGuidsListFromThreatList(GuidVector& guids, uint32 maxamount = 0); bool IsImmuneToSpell(SpellEntry const* spellInfo, bool castOnSelf) override; bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index, bool castOnSelf) const override; bool IsElite() const { if (IsPet()) { return false; } uint32 rank = GetCreatureInfo()->Rank; return rank != CREATURE_ELITE_NORMAL && rank != CREATURE_ELITE_RARE; } bool IsWorldBoss() const { if (IsPet()) { return false; } return GetCreatureInfo()->Rank == CREATURE_ELITE_WORLDBOSS; } uint32 GetLevelForTarget(Unit const* target) const override; // overwrite Unit::GetLevelForTarget for boss level support bool IsInEvadeMode() const; bool AIM_Initialize(); CreatureAI* AI() { return i_AI; } void SetWalk(bool enable, bool asDefault = true); void SetLevitate(bool enable) override; void SetSwim(bool enable) override; void SetCanFly(bool enable) override; void SetFeatherFall(bool enable) override; void SetHover(bool enable) override; void SetRoot(bool enable) override; void SetWaterWalk(bool enable) override; uint32 GetShieldBlockValue() const override // dunno mob block value { return (getLevel() / 2 + uint32(GetStat(STAT_STRENGTH) / 20)); } SpellSchoolMask GetMeleeDamageSchoolMask() const override { return m_meleeDamageSchoolMask; } void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = GetSchoolMask(school); } void _AddCreatureSpellCooldown(uint32 spell_id, time_t end_time); void _AddCreatureCategoryCooldown(uint32 category, time_t apply_time); void AddCreatureSpellCooldown(uint32 spellid); bool HasSpellCooldown(uint32 spell_id) const; bool HasCategoryCooldown(uint32 spell_id) const; uint32 GetCreatureSpellCooldownDelay(uint32 spellId) const; bool HasSpell(uint32 spellID) const override; bool UpdateEntry(uint32 entry, Team team = ALLIANCE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL, bool preserveHPAndPower = true); void ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated); bool UpdateStats(Stats stat) override; bool UpdateAllStats() override; void UpdateResistances(uint32 school) override; void UpdateArmor() override; void UpdateMaxHealth() override; void UpdateMaxPower(Powers power) override; void UpdateAttackPowerAndDamage(bool ranged = false) override; void UpdateDamagePhysical(WeaponAttackType attType) override; uint32 GetCurrentEquipmentId() const { return m_equipmentId; } static float _GetHealthMod(int32 Rank); ///< Get custom factor to scale health (default 1, CONFIG_FLOAT_RATE_CREATURE_*_HP) static float _GetDamageMod(int32 Rank); ///< Get custom factor to scale damage (default 1, CONFIG_FLOAT_RATE_*_DAMAGE) static float _GetSpellDamageMod(int32 Rank); ///< Get custom factor to scale spell damage (default 1, CONFIG_FLOAT_RATE_*_SPELLDAMAGE) VendorItemData const* GetVendorItems() const; VendorItemData const* GetVendorTemplateItems() const; uint32 GetVendorItemCurrentCount(VendorItem const* vItem); uint32 UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count); TrainerSpellData const* GetTrainerTemplateSpells() const; TrainerSpellData const* GetTrainerSpells() const; CreatureInfo const* GetCreatureInfo() const { return m_creatureInfo; } CreatureDataAddon const* GetCreatureAddon() const; static uint32 ChooseDisplayId(const CreatureInfo* cinfo, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL); std::string GetAIName() const; std::string GetScriptName() const; uint32 GetScriptId() const; // overwrite WorldObject function for proper name localization const char* GetNameForLocaleIdx(int32 locale_idx) const override; void SetDeathState(DeathState s) override; // overwrite virtual Unit::SetDeathState bool LoadFromDB(uint32 guid, Map* map); void SaveToDB(); // overwrited in Pet virtual void SaveToDB(uint32 mapid); virtual void DeleteFromDB(); // overwrited in Pet static void DeleteFromDB(uint32 lowguid, CreatureData const* data); /// Represent the loots available on the creature. Loot loot; /// Indicates whether the creature has has been pickpocked. bool lootForPickPocketed; /// Indicates whether the creature has been checked. bool lootForBody; /// Indicates whether the creature has been skinned. bool lootForSkin; /** * Method preparing the creature for the loot state. Based on the previous loot state, the loot ID provided in the database and the creature's type, * this method updates the state of the creature for loots. * * At the end of this method, the creature loot state may be: * Lootable: UNIT_DYNFLAG_LOOTABLE * Skinnable: UNIT_FLAG_SKINNABLE * Not lootable: No flag */ void PrepareBodyLootState(); /** * function returning the GUID of the loot recipient (a player GUID). * * \return ObjectGuid Player GUID. */ ObjectGuid GetLootRecipientGuid() const { return m_lootRecipientGuid; } /** * function returning the group recipient ID. * * \return uint32 Group ID. */ uint32 GetLootGroupRecipientId() const { return m_lootGroupRecipientId; } Player* GetLootRecipient() const; // use group cases as prefered Group* GetGroupLootRecipient() const; bool IsTappedBy(Player const* player) const; /** * function indicating whether the whether the creature has a looter recipient defined (either a group ID, either a player GUID). * * \return boolean true if the creature has a recipient defined, false otherwise. */ bool HasLootRecipient() const { return m_lootGroupRecipientId || m_lootRecipientGuid; } /** * function indicating whether the recipient is a group. * * \return boolean true if the creature's recipient is a group, false otherwise. */ bool IsGroupLootRecipient() const { return m_lootGroupRecipientId; } void SetLootRecipient(Unit* unit); void AllLootRemovedFromCorpse(); Player* GetOriginalLootRecipient() const; // ignore group changes/etc, not for looting SpellEntry const* ReachWithSpellAttack(Unit* pVictim); SpellEntry const* ReachWithSpellCure(Unit* pVictim); uint32 m_spells[CREATURE_MAX_SPELLS]; CreatureSpellCooldowns m_CreatureSpellCooldowns; CreatureSpellCooldowns m_CreatureCategoryCooldowns; float GetAttackDistance(Unit const* pl) const; void SendAIReaction(AiReaction reactionType); void DoFleeToGetAssistance(); void CallForHelp(float fRadius); void CallAssistance(); void SetNoCallAssistance(bool val) { m_AlreadyCallAssistance = val; } void SetNoSearchAssistance(bool val) { m_AlreadySearchedAssistance = val; } bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; } bool CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction = true) const; bool CanInitiateAttack(); MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; } void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; } // for use only in LoadHelper, Map::Add Map::CreatureCellRelocation Cell const& GetCurrentCell() const { return m_currentCell; } void SetCurrentCell(Cell const& cell) { m_currentCell = cell; } bool IsVisibleInGridForPlayer(Player* pl) const override; void RemoveCorpse(); bool IsDeadByDefault() const { return m_IsDeadByDefault; }; void ForcedDespawn(uint32 timeMSToDespawn = 0); time_t const& GetRespawnTime() const { return m_respawnTime; } time_t GetRespawnTimeEx() const; void SetRespawnTime(uint32 respawn) { m_respawnTime = respawn ? time(NULL) + respawn : 0; } void Respawn(); void SaveRespawnTime() override; uint32 GetRespawnDelay() const { return m_respawnDelay; } void SetRespawnDelay(uint32 delay) { m_respawnDelay = delay; } /** * Returns the time when the creature has been killed. */ time_t GetKilledTime() const { return m_killedTime; } /** * Set the time when the creature has been killed. */ void SetKilledTime(time_t time) { m_killedTime = time; } float GetRespawnRadius() const { return m_respawnradius; } void SetRespawnRadius(float dist) { m_respawnradius = dist; } // Functions spawn/remove creature with DB guid in all loaded map copies (if point grid loaded in map) static void AddToRemoveListInMaps(uint32 db_guid, CreatureData const* data); static void SpawnInMaps(uint32 db_guid, CreatureData const* data); void StartGroupLoot(Group* group, uint32 timer) override; void SendZoneUnderAttackMessage(Player* attacker); void SetInCombatWithZone(); Unit* SelectAttackingTarget(AttackingTarget target, uint32 position, uint32 uiSpellEntry, uint32 selectFlags = 0) const; Unit* SelectAttackingTarget(AttackingTarget target, uint32 position, SpellEntry const* pSpellInfo = NULL, uint32 selectFlags = 0) const; bool HasQuest(uint32 quest_id) const override; bool HasInvolvedQuest(uint32 quest_id) const override; GridReference& GetGridRef() { return m_gridRef; } bool IsRegeneratingHealth() { return GetCreatureInfo()->RegenerateStats & REGEN_FLAG_HEALTH; } bool IsRegeneratingPower() { return GetCreatureInfo()->RegenerateStats & REGEN_FLAG_POWER; } virtual uint8 GetPetAutoSpellSize() const { return CREATURE_MAX_SPELLS; } virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const { if (pos >= CREATURE_MAX_SPELLS || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED) { return 0; } else { return m_charmInfo->GetCharmSpell(pos)->GetAction(); } } void SetCombatStartPosition(float x, float y, float z) { m_combatStartX = x; m_combatStartY = y; m_combatStartZ = z; } void GetCombatStartPosition(float& x, float& y, float& z) { x = m_combatStartX; y = m_combatStartY; z = m_combatStartZ; } void SetRespawnCoord(CreatureCreatePos const& pos) { m_respawnPos = pos.m_pos; } void SetRespawnCoord(float x, float y, float z, float ori) { m_respawnPos.x = x; m_respawnPos.y = y; m_respawnPos.z = z; m_respawnPos.o = ori; } void GetRespawnCoord(float& x, float& y, float& z, float* ori = NULL, float* dist = NULL) const; void ResetRespawnCoord(); void SetDeadByDefault(bool death_state) { m_IsDeadByDefault = death_state; } void SetFactionTemporary(uint32 factionId, uint32 tempFactionFlags = TEMPFACTION_ALL); void ClearTemporaryFaction(); uint32 GetTemporaryFactionFlags() { return m_temporaryFactionFlags; } void SendAreaSpiritHealerQueryOpcode(Player* pl); void SetVirtualItem(VirtualItemSlot slot, uint32 item_id); void SetVirtualItemRaw(VirtualItemSlot slot, uint32 display_id, uint32 info0, uint32 info1); void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; } bool IsReputationGainDisabled() { return DisableReputationGain; } protected: bool MeetsSelectAttackingRequirement(Unit* pTarget, SpellEntry const* pSpellInfo, uint32 selectFlags) const; bool CreateFromProto(uint32 guidlow, CreatureInfo const* cinfo, Team team, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL); bool InitEntry(uint32 entry, Team team = ALLIANCE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL); uint32 m_groupLootTimer; // (msecs)timer used for group loot uint32 m_groupLootId; // used to find group which is looting corpse void StopGroupLoot() override; // vendor items VendorItemCounts m_vendorItemCounts; void _RealtimeSetCreatureInfo(); uint32 m_lootMoney; ObjectGuid m_lootRecipientGuid; // player who will have rights for looting if m_lootGroupRecipient==0 or group disbanded uint32 m_lootGroupRecipientId; // group who will have rights for looting if set and exist /// Timers time_t m_corpseRemoveTime; // (secs) time for death or corpse disappearance time_t m_respawnTime; // (secs) time of next respawn uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance uint32 m_aggroDelay; // (msecs)delay between respawn and aggro due to movement float m_respawnradius; time_t m_killedTime; // Exact time of the death. CreatureSubtype m_subtype; // set in Creatures subclasses for fast it detect without dynamic_cast use void RegeneratePower(); void RegenerateHealth(); MovementGeneratorType m_defaultMovementType; Cell m_currentCell; // store current cell where creature listed uint32 m_equipmentId; // below fields has potential for optimization bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; bool m_AI_locked; bool m_IsDeadByDefault; uint32 m_temporaryFactionFlags; // used for real faction changes (not auras etc) SpellSchoolMask m_meleeDamageSchoolMask; uint32 m_originalEntry; float m_combatStartX; float m_combatStartY; float m_combatStartZ; Position m_respawnPos; bool DisableReputationGain; private: GridReference m_gridRef; CreatureInfo const* m_creatureInfo; }; class ForcedDespawnDelayEvent : public BasicEvent { public: ForcedDespawnDelayEvent(Creature& owner) : BasicEvent(), m_owner(owner) { } bool Execute(uint64 e_time, uint32 p_time) override; private: Creature& m_owner; }; #endif