text: /**
   * 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-2017  MaNGOS project <https://getmangos.eu>
   *
   * 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 "SharedDefines.h"
  #include "LootMgr.h"
  #include "DBCEnums.h"
  #include "Cell.h"
  
  #include <list>
  
  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
      CREATURE_EXTRA_FLAG_WALK_IN_WATER          = 0x00008000,       // creature is forced to walk in water even it can swim
      CREATURE_EXTRA_FLAG_HAVE_NO_SWIM_ANIMATION = 0x00010000,       // we have to not set "swim" animation or creature will have "no animation"
  };
  
  // 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 4                                // only single send to client in static data
  #define USE_DEFAULT_DATABASE_LEVEL  0                       // just used to show we don't want to force the new creature level and use the level stored in db
  
  // 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;
      uint32  SchoolImmuneMask;
      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<std::string> Name;
      std::vector<std::string> SubName;
  };
  
  struct GossipMenuItemsLocale
  {
      std::vector<std::string> OptionText;
      std::vector<std::string> BoxText;
  };
  
  struct PointOfInterestLocale
  {
      std::vector<std::string> 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<VendorItem*> 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<VendorItemCount> 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<uint32, time_t> 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(uint32 forcedLevel = USE_DEFAULT_DATABASE_LEVEL);
          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; }
          virtual bool CanSwim() const override { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
          bool IsSwimming() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_SWIMMING))); } 
          virtual bool CanFly() const override { 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 IsImmuneToDamage(SpellSchoolMask meleeSchoolMask) 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);
          virtual 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;
          bool IsDamageEnoughForLootingAndReward() const { return m_PlayerDamageReq == 0; }
          void LowerPlayerDamageReq(uint32 unDamage);
          void ResetPlayerDamageReq() { m_PlayerDamageReq = GetHealth() / 2; }
  
          /**
          * 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 inPlace = false);
          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<Creature>& 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;
  
          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;
          uint32 m_PlayerDamageReq;
  
          // 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<Creature> 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
  