/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 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 Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef AZEROTHCORE_CREATURE_H #define AZEROTHCORE_CREATURE_H #include "Cell.h" #include "CharmInfo.h" #include "Common.h" #include "CreatureData.h" #include "LootMgr.h" #include "Unit.h" #include class SpellInfo; class CreatureAI; class Quest; class Player; class WorldSession; class CreatureGroup; // max different by z coordinate for creature aggro reaction #define CREATURE_Z_ATTACK_RANGE 3 #define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY class Creature : public Unit, public GridObject, public MovableMapObject, public UpdatableMapObject { public: explicit Creature(bool isWorldObject = false); ~Creature() override; void AddToWorld() override; void RemoveFromWorld() override; float GetNativeObjectScale() const override; void SetObjectScale(float scale) override; void SetDisplayId(uint32 displayId, float displayScale = 1.f) override; void SetDisplayFromModel(uint32 modelIdx); void DisappearAndDie(); [[nodiscard]] bool isVendorWithIconSpeak() const; bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 vehId, float x, float y, float z, float ang, const CreatureData* data = nullptr); bool LoadCreaturesAddon(bool reload = false); void SelectLevel(bool changelevel = true); void LoadEquipment(int8 id = 1, bool force = false); [[nodiscard]] ObjectGuid::LowType GetSpawnId() const { return m_spawnId; } void Update(uint32 time) override; // overwrited Unit::Update void GetRespawnPosition(float& x, float& y, float& z, float* ori = nullptr, float* dist = nullptr) const; void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } void SetCorpseRemoveTime(uint32 delay); [[nodiscard]] uint32 GetCorpseDelay() const { return m_corpseDelay; } [[nodiscard]] bool HasFlagsExtra(uint32 flag) const { return GetCreatureTemplate()->HasFlagsExtra(flag); } [[nodiscard]] bool IsRacialLeader() const { return GetCreatureTemplate()->RacialLeader; } [[nodiscard]] bool IsCivilian() const { return HasFlagsExtra(CREATURE_FLAG_EXTRA_CIVILIAN); } [[nodiscard]] bool IsTrigger() const { return HasFlagsExtra(CREATURE_FLAG_EXTRA_TRIGGER); } [[nodiscard]] bool IsGuard() const { return HasFlagsExtra(CREATURE_FLAG_EXTRA_GUARD); } CreatureMovementData const& GetMovementTemplate() const; [[nodiscard]] bool CanWalk() const { return GetMovementTemplate().IsGroundAllowed(); } [[nodiscard]] bool CanSwim() const override; [[nodiscard]] bool CanEnterWater() const override; [[nodiscard]] bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); } [[nodiscard]] bool CanHover() const { return GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || IsHovering(); } [[nodiscard]] bool IsRooted() const { return GetMovementTemplate().IsRooted(); } MovementGeneratorType GetDefaultMovementType() const override { return m_defaultMovementType; } void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; } /** * @brief A creature can have 3 ReactStates : Agressive, Passive, Neutral * - Agressive : The creature will attack any non friend units in sight * - Passive : The creature will not attack anyone * - Neutral : The creature will attack only if attacked */ void SetReactState(ReactStates state) { m_reactState = state; } [[nodiscard]] ReactStates GetReactState() const { return m_reactState; } [[nodiscard]] bool HasReactState(ReactStates state) const { return (m_reactState == state); } /// @brief Check if the creature has the specified ReactState void InitializeReactState(); ///// @todo RENAME THIS!!!!! bool isCanInteractWithBattleMaster(Player* player, bool msg) const; bool isCanTrainingAndResetTalentsOf(Player* player) const; [[nodiscard]] bool IsValidTrainerForPlayer(Player* player, uint32* npcFlags = nullptr) const; bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const; void LoadSpellTemplateImmunity(); bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr) override; [[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const; // redefine Unit::IsImmunedToSpell bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const override; // redefine Unit::IsImmunedToSpellEffect [[nodiscard]] bool isElite() const { if (IsPet()) return false; uint32 rank = GetCreatureTemplate()->rank; return rank != CREATURE_ELITE_NORMAL && rank != CREATURE_ELITE_RARE; } [[nodiscard]] bool isWorldBoss() const { if (IsPet()) return false; return GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_BOSS_MOB; } [[nodiscard]] bool IsDungeonBoss() const; [[nodiscard]] bool IsImmuneToKnockback() const; [[nodiscard]] bool IsAvoidingAOE() const { return HasFlagsExtra(CREATURE_FLAG_EXTRA_AVOID_AOE); } uint8 getLevelForTarget(WorldObject const* target) const override; // overwrite Unit::getLevelForTarget for boss level support [[nodiscard]] bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); } [[nodiscard]] bool IsEvadingAttacks() const { return IsInEvadeMode() || CanNotReachTarget(); } bool AIM_Initialize(CreatureAI* ai = nullptr); void Motion_Initialize(); [[nodiscard]] CreatureAI* AI() const { return (CreatureAI*)i_AI; } bool SetWalk(bool enable) override; bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override; bool SetSwim(bool enable) override; bool SetCanFly(bool enable, bool packetOnly = false) override; bool SetWaterWalking(bool enable, bool packetOnly = false) override; bool SetFeatherFall(bool enable, bool packetOnly = false) override; bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true) override; bool HasSpellFocus(Spell const* focusSpell = nullptr) const; struct { ::Spell const* Spell = nullptr; uint32 Delay = 0; // ms until the creature's target should snap back (0 = no snapback scheduled) ObjectGuid Target; // the creature's "real" target while casting float Orientation = 0.0f; // the creature's "real" orientation while casting } _spellFocusInfo; [[nodiscard]] uint32 GetShieldBlockValue() const override { return (GetLevel() / 2 + uint32(GetStat(STAT_STRENGTH) / 20)); } [[nodiscard]] SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType /*attackType*/ = BASE_ATTACK, uint8 /*damageIndex*/ = 0) const override { return m_meleeDamageSchoolMask; } void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); } void _AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time); void AddSpellCooldown(uint32 spell_id, uint32 /*itemid*/, uint32 end_time, bool needSendToClient = false, bool forceSendToSpectator = false) override; [[nodiscard]] bool HasSpellCooldown(uint32 spell_id) const override; [[nodiscard]] uint32 GetSpellCooldown(uint32 spell_id) const; void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override; [[nodiscard]] bool IsSpellProhibited(SpellSchoolMask idSchoolMask) const; void ClearProhibitedSpellTimers(); [[nodiscard]] bool HasSpell(uint32 spellID) const override; void UpdateMovementFlags(); uint32 GetRandomId(uint32 id1, uint32 id2, uint32 id3); bool UpdateEntry(uint32 entry, const CreatureData* data = nullptr, bool changelevel = true, bool updateAI = false); bool UpdateEntry(uint32 entry, bool updateAI) { return UpdateEntry(entry, nullptr, true, updateAI); } 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 CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override; void LoadSparringPct(); [[nodiscard]] float GetSparringPct() const { return _sparringPct; } bool HasWeapon(WeaponAttackType type) const override; bool HasWeaponForAttack(WeaponAttackType type) const override { return (Unit::HasWeaponForAttack(type) && HasWeapon(type)); } void SetCanDualWield(bool value) override; [[nodiscard]] int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; } uint8 GetCurrentEquipmentId() { return m_equipmentId; } void SetCurrentEquipmentId(uint8 id) { m_equipmentId = id; } float GetSpellDamageMod(int32 Rank); [[nodiscard]] VendorItemData const* GetVendorItems() const; uint32 GetVendorItemCurrentCount(VendorItem const* vItem); uint32 UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count); [[nodiscard]] TrainerSpellData const* GetTrainerSpells() const; [[nodiscard]] CreatureTemplate const* GetCreatureTemplate() const { return m_creatureInfo; } [[nodiscard]] CreatureData const* GetCreatureData() const { return m_creatureData; } void SetDetectionDistance(float dist){ m_detectionDistance = dist; } [[nodiscard]] CreatureAddon const* GetCreatureAddon() const; [[nodiscard]] std::string const& GetAIName() const; [[nodiscard]] std::string GetScriptName() const; [[nodiscard]] uint32 GetScriptId() const; // override WorldObject function for proper name localization [[nodiscard]] std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override; void setDeathState(DeathState s, bool despawn = false) override; // override virtual Unit::setDeathState bool LoadFromDB(ObjectGuid::LowType guid, Map* map, bool allowDuplicate = false) { return LoadCreatureFromDB(guid, map, false, allowDuplicate); } bool LoadCreatureFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true, bool allowDuplicate = false); void SaveToDB(); virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); // overriden in Pet virtual void DeleteFromDB(); // overriden in Pet Loot loot; [[nodiscard]] ObjectGuid GetLootRecipientGUID() const { return m_lootRecipient; } [[nodiscard]] Player* GetLootRecipient() const; [[nodiscard]] ObjectGuid::LowType GetLootRecipientGroupGUID() const { return m_lootRecipientGroup; } [[nodiscard]] Group* GetLootRecipientGroup() const; [[nodiscard]] bool hasLootRecipient() const { return m_lootRecipient || m_lootRecipientGroup; } bool isTappedBy(Player const* player) const; // return true if the creature is tapped by the player or a member of his party. [[nodiscard]] bool CanGeneratePickPocketLoot() const; void SetPickPocketLootTime(); void ResetPickPocketLootTime() { lootPickPocketRestoreTime = 0; } void SetLootRecipient (Unit* unit, bool withGroup = true); void AllLootRemovedFromCorpse(); [[nodiscard]] uint16 GetLootMode() const { return m_LootMode; } [[nodiscard]] bool HasLootMode(uint16 lootMode) const { return m_LootMode & lootMode; } void SetLootMode(uint16 lootMode) { m_LootMode = lootMode; } void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; } void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; } void ResetLootMode() { m_LootMode = LOOT_MODE_DEFAULT; } SpellInfo const* reachWithSpellAttack(Unit* victim); SpellInfo const* reachWithSpellCure(Unit* victim); uint32 m_spells[MAX_CREATURE_SPELLS]; CreatureSpellCooldowns m_CreatureSpellCooldowns; uint32 m_ProhibitSchoolTime[7]; bool CanStartAttack(Unit const* u) const; float GetAggroRange(Unit const* target) const; float GetAttackDistance(Unit const* player) const; [[nodiscard]] float GetDetectionRange() const { return m_detectionDistance; } void SendAIReaction(AiReaction reactionType); [[nodiscard]] Unit* SelectNearestTarget(float dist = 0, bool playerOnly = false) const; [[nodiscard]] Unit* SelectNearestTargetInAttackDistance(float dist) const; void DoFleeToGetAssistance(); void CallForHelp(float fRadius, Unit* target = nullptr); void CallAssistance(Unit* target = nullptr); void SetNoCallAssistance(bool val) { m_AlreadyCallAssistance = val; } void SetNoSearchAssistance(bool val) { m_AlreadySearchedAssistance = val; } bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; } bool CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction = true) const; bool _IsTargetAcceptable(Unit const* target) const; [[nodiscard]] bool CanIgnoreFeignDeath() const { return HasFlagsExtra(CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH); } // pussywizard: Updated at faction change, disable move in line of sight if actual faction is not hostile to anyone void UpdateMoveInLineOfSightState(); bool IsMoveInLineOfSightDisabled() { return m_moveInLineOfSightDisabled; } bool IsMoveInLineOfSightStrictlyDisabled() { return m_moveInLineOfSightStrictlyDisabled; } void RemoveCorpse(bool setSpawnTime = true, bool skipVisibility = false); void DespawnOrUnsummon(Milliseconds msTimeToDespawn, Seconds forcedRespawnTimer); void DespawnOrUnsummon(uint32 msTimeToDespawn = 0) { DespawnOrUnsummon(Milliseconds(msTimeToDespawn), 0s); }; void DespawnOnEvade(Seconds respawnDelay = 20s); [[nodiscard]] time_t const& GetRespawnTime() const { return m_respawnTime; } [[nodiscard]] time_t GetRespawnTimeEx() const; void SetRespawnTime(uint32 respawn); void Respawn(bool force = false); void SaveRespawnTime() override; [[nodiscard]] uint32 GetRespawnDelay() const { return m_respawnDelay; } void SetRespawnDelay(uint32 delay) { m_respawnDelay = delay; } uint32 GetCombatPulseDelay() const { return m_combatPulseDelay; } void SetCombatPulseDelay(uint32 delay) // (secs) interval at which the creature pulses the entire zone into combat (only works in dungeons) { m_combatPulseDelay = delay; if (m_combatPulseTime == 0 || m_combatPulseTime > delay) m_combatPulseTime = delay; } [[nodiscard]] float GetWanderDistance() const { return m_wanderDistance; } void SetWanderDistance(float dist) { m_wanderDistance = dist; } void DoImmediateBoundaryCheck() { m_boundaryCheckTime = 0; } uint32 m_groupLootTimer; // (msecs)timer used for group loot uint32 lootingGroupLowGUID; // used to find group which is looting corpse void SendZoneUnderAttackMessage(Player* attacker); void SetInCombatWithZone(); [[nodiscard]] bool hasQuest(uint32 quest_id) const override; [[nodiscard]] bool hasInvolvedQuest(uint32 quest_id) const override; bool isRegeneratingHealth() { return m_regenHealth; } void SetRegeneratingHealth(bool enable) { m_regenHealth = enable; } void SetRegeneratingPower(bool enable) { m_regenPower = enable; } [[nodiscard]] virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; } [[nodiscard]] virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const { if (pos >= MAX_SPELL_CHARM || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED) return 0; else return m_charmInfo->GetCharmSpell(pos)->GetAction(); } void SetCannotReachTarget(ObjectGuid const& target = ObjectGuid::Empty); [[nodiscard]] bool CanNotReachTarget() const; [[nodiscard]] bool IsNotReachableAndNeedRegen() const; void SetPosition(float x, float y, float z, float o); void SetPosition(const Position& pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); } void SetHomePosition(float x, float y, float z, float o) { m_homePosition.Relocate(x, y, z, o); } void SetHomePosition(const Position& pos) { m_homePosition.Relocate(pos); } void GetHomePosition(float& x, float& y, float& z, float& ori) const { m_homePosition.GetPosition(x, y, z, ori); } [[nodiscard]] Position const& GetHomePosition() const { return m_homePosition; } void SetTransportHomePosition(float x, float y, float z, float o) { m_transportHomePosition.Relocate(x, y, z, o); } void SetTransportHomePosition(const Position& pos) { m_transportHomePosition.Relocate(pos); } void GetTransportHomePosition(float& x, float& y, float& z, float& ori) const { m_transportHomePosition.GetPosition(x, y, z, ori); } [[nodiscard]] Position const& GetTransportHomePosition() const { return m_transportHomePosition; } [[nodiscard]] uint32 GetWaypointPath() const { return m_path_id; } void LoadPath(uint32 pathid) { m_path_id = pathid; } [[nodiscard]] uint32 GetCurrentWaypointID() const { return m_waypointID; } void UpdateWaypointID(uint32 wpID) { m_waypointID = wpID; } void SearchFormation(); [[nodiscard]] CreatureGroup const* GetFormation() const { return m_formation; } [[nodiscard]] CreatureGroup* GetFormation() { return m_formation; } void SetFormation(CreatureGroup* formation) { m_formation = formation; } Unit* SelectVictim(); void SetReputationRewardDisabled(bool disable) { DisableReputationReward = disable; } [[nodiscard]] bool IsReputationRewardDisabled() const { return DisableReputationReward; } void SetLootRewardDisabled(bool disable) { DisableLootReward = disable; } [[nodiscard]] bool IsLootRewardDisabled() const { return DisableLootReward; } [[nodiscard]] bool IsDamageEnoughForLootingAndReward() const; void LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer = true); void ResetPlayerDamageReq(); [[nodiscard]] uint32 GetPlayerDamageReq() const; [[nodiscard]] uint32 GetOriginalEntry() const { return m_originalEntry; } void SetOriginalEntry(uint32 entry) { m_originalEntry = entry; } static float _GetDamageMod(int32 Rank); float m_SightDistance, m_CombatDistance; bool m_isTempWorldObject; //true when possessed // Handling caster facing during spellcast void SetTarget(ObjectGuid guid = ObjectGuid::Empty) override; void ClearTarget() { SetTarget(); }; void FocusTarget(Spell const* focusSpell, WorldObject const* target); void ReleaseFocus(Spell const* focusSpell); [[nodiscard]] bool IsMovementPreventedByCasting() const override; // Part of Evade mechanics std::shared_ptr const& GetLastLeashExtensionTimePtr() const; void SetLastLeashExtensionTimePtr(std::shared_ptr const& timer); void ClearLastLeashExtensionTimePtr(); time_t GetLastLeashExtensionTime() const; void UpdateLeashExtensionTime(); uint8 GetLeashTimer() const; bool IsFreeToMove(); static constexpr uint32 MOVE_CIRCLE_CHECK_INTERVAL = 3000; static constexpr uint32 MOVE_BACKWARDS_CHECK_INTERVAL = 2000; static constexpr uint32 EXTEND_LEASH_CHECK_INTERVAL = 3000; uint32 m_moveCircleMovementTime = MOVE_CIRCLE_CHECK_INTERVAL; uint32 m_moveBackwardsMovementTime = MOVE_BACKWARDS_CHECK_INTERVAL; uint32 m_extendLeashTime = EXTEND_LEASH_CHECK_INTERVAL; [[nodiscard]] bool HasSwimmingFlagOutOfCombat() const { return !_isMissingSwimmingFlagOutOfCombat; } void RefreshSwimmingFlag(bool recheck = false); void SetAssistanceTimer(uint32 value) { m_assistanceTimer = value; } void ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds duration); /** * @brief Helper to resume chasing current victim. */ void ResumeChasingVictim() { GetMotionMaster()->MoveChase(GetVictim()); }; /** * @brief Returns true if the creature is able to cast the spell. */ bool CanCastSpell(uint32 spellID) const; /** * @brief Helper to get the creature's summoner GUID, if it is a summon */ [[nodiscard]] ObjectGuid GetSummonerGUID() const; // Used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims // NOTE: If you use SetCombatMovement while the creature is in combat, it will do NOTHING - This only affects AttackStart // You should make the necessary to make it happen so. // Remember that if you modified _isCombatMovementAllowed (e.g: using SetCombatMovement) it will not be reset at Reset(). // It will keep the last value you set. void SetCombatMovement(bool allowMovement); bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; } std::string GetDebugInfo() const override; bool IsUpdateNeeded() override; protected: bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr); bool InitEntry(uint32 entry, const CreatureData* data = nullptr); // vendor items VendorItemCounts m_vendorItemCounts; static float _GetHealthMod(int32 Rank); ObjectGuid m_lootRecipient; ObjectGuid::LowType m_lootRecipientGroup; /// Timers time_t m_corpseRemoveTime; // (secs) timer for death or corpse disappearance time_t m_respawnTime; // (secs) time of next respawn time_t m_respawnedTime; // (secs) time when creature respawned uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance float m_wanderDistance; uint32 m_boundaryCheckTime; // (msecs) remaining time for next evade boundary check uint16 m_transportCheckTimer; uint32 lootPickPocketRestoreTime; uint32 m_combatPulseTime; // (msecs) remaining time for next zone-in-combat pulse uint32 m_combatPulseDelay; ReactStates m_reactState; // for AI, not charmInfo void RegenerateHealth(); void Regenerate(Powers power); MovementGeneratorType m_defaultMovementType; ObjectGuid::LowType m_spawnId; ///< For new or temporary creatures is 0 for saved it is lowguid uint8 m_equipmentId; int8 m_originalEquipmentId; // can be -1 bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; bool m_regenHealth; bool m_regenPower; bool m_AI_locked; SpellSchoolMask m_meleeDamageSchoolMask; uint32 m_originalEntry; bool m_moveInLineOfSightDisabled; bool m_moveInLineOfSightStrictlyDisabled; Position m_homePosition; Position m_transportHomePosition; bool DisableReputationReward; bool DisableLootReward; CreatureTemplate const* m_creatureInfo; // in difficulty mode > 0 can different from sObjectMgr->GetCreatureTemplate(GetEntry()) CreatureData const* m_creatureData; float m_detectionDistance; uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable float _sparringPct; [[nodiscard]] bool IsInvisibleDueToDespawn() const override; bool CanAlwaysSee(WorldObject const* obj) const override; bool IsAlwaysDetectableFor(WorldObject const* seer) const override; private: void ForcedDespawn(uint32 timeMSToDespawn = 0, Seconds forcedRespawnTimer = 0s); [[nodiscard]] bool CanPeriodicallyCallForAssistance() const; // WaypointMovementGenerator variable uint32 m_waypointID; uint32 m_path_id; // Formation variable CreatureGroup* m_formation; bool TriggerJustRespawned; // Shared timer between mobs who assist another. // Damaging one extends leash range on all of them. mutable std::shared_ptr m_lastLeashExtensionTime; ObjectGuid m_cannotReachTarget; uint32 m_cannotReachTimer; Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing bool _isMissingSwimmingFlagOutOfCombat; uint32 m_assistanceTimer; uint32 _playerDamageReq; bool _damagedByPlayer; bool _isCombatMovementAllowed; }; class AssistDelayEvent : public BasicEvent { public: AssistDelayEvent(ObjectGuid victim, Creature* owner) : BasicEvent(), m_victim(victim), m_owner(owner) { } bool Execute(uint64 e_time, uint32 p_time) override; void AddAssistant(ObjectGuid guid) { m_assistants.push_back(guid); } private: AssistDelayEvent(); ObjectGuid m_victim; GuidList m_assistants; Creature* m_owner; }; class ForcedDespawnDelayEvent : public BasicEvent { public: ForcedDespawnDelayEvent(Creature& owner, Seconds respawnTimer) : BasicEvent(), m_owner(owner), m_respawnTimer(respawnTimer) { } bool Execute(uint64 e_time, uint32 p_time) override; private: Creature& m_owner; Seconds const m_respawnTimer; }; class TemporaryThreatModifierEvent : public BasicEvent { public: TemporaryThreatModifierEvent(Creature& owner, ObjectGuid threatVictimGUID, float threatValue) : BasicEvent(), m_owner(owner), m_threatVictimGUID(threatVictimGUID), m_threatValue(threatValue) { } bool Execute(uint64 e_time, uint32 p_time) override; private: Creature& m_owner; ObjectGuid m_threatVictimGUID; float m_threatValue; }; #endif