90 if (
Player* player = ref.GetSource())
97 for (
Unit* pet : player->m_Controlled)
171 if (properties->
Flags & 512)
173 switch (properties->
Title)
196 if (!summon->GetVehicle() &&
ShouldFollowOnSpawn(summon->m_Properties) && summon->CanFollowOwner())
200 summon->GetMotionMaster()->Clear();
201 summon->GetMotionMaster()->MoveFollow(owner,
PET_FOLLOW_DIST, summon->GetFollowAngle());
274 TC_LOG_ERROR(
"scripts.ai",
"CreatureAI::EngagementStart called even though creature is already engaged. Creature debug info:\n{}",
me->
GetDebugInfo());
286 TC_LOG_DEBUG(
"scripts.ai",
"CreatureAI::EngagementOver called even though creature is not currently engaged. Creature debug info:\n{}",
me->
GetDebugInfo());
328 typedef std::pair<int32, int32> coordinate;
336 std::queue<coordinate> Q;
337 std::unordered_set<coordinate> alreadyChecked;
338 std::unordered_set<coordinate> outOfBounds;
353 bool boundsWarning =
false;
357 coordinate front = Q.front();
358 bool hasOutOfBoundsNeighbor =
false;
359 for (coordinate
const& off : std::list<coordinate>{ {1, 0}, {0, 1}, {-1, 0}, {0, -1} })
361 coordinate next(front.first + off.first, front.second + off.second);
364 boundsWarning =
true;
367 if (alreadyChecked.find(next) == alreadyChecked.end())
374 outOfBounds.insert(next);
375 hasOutOfBoundsNeighbor =
true;
377 alreadyChecked.insert(next);
379 else if (outOfBounds.find(next) != outOfBounds.end())
380 hasOutOfBoundsNeighbor =
true;
382 if (fill || hasOutOfBoundsNeighbor)
388 point->SetImmuneToAll(
true);
389 if (!hasOutOfBoundsNeighbor)
413 if (!areaBoundary->IsWithinBoundary(pos))
AISpellInfoType * GetAISpellInfo(uint32 i)
static const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT
static const uint32 BOUNDARY_VISUALIZE_CREATURE
static const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT
static const int8 BOUNDARY_VISUALIZE_STEP_SIZE
static const float BOUNDARY_VISUALIZE_CREATURE_SCALE
static bool ShouldFollowOnSpawn(SummonPropertiesEntry const *properties)
std::vector< AreaBoundary const * > CreatureBoundary
std::chrono::seconds Seconds
Seconds shorthand typedef.
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
@ LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED
@ LANG_CREATURE_MOVEMENT_NOT_BOUNDED
@ LANG_CREATURE_NO_INTERIOR_POINT_FOUND
#define TC_LOG_DEBUG(filterType__,...)
#define TC_LOG_ERROR(filterType__,...)
@ TEMPSUMMON_TIMED_DESPAWN
@ UNIT_FLAG_UNINTERACTIBLE
static bool CanBeginCombat(Unit const *a, Unit const *b)
int32 VisualizeBoundary(Seconds duration, Unit *owner=nullptr, bool fill=false) const
CreatureAI(Creature *creature)
virtual void MoveInLineOfSight(Unit *)
static bool IsInBounds(CreatureBoundary const &boundary, Position const *who)
void TriggerAlert(Unit const *who) const
CreatureBoundary const * _boundary
@ EVADE_REASON_NO_HOSTILES
void OnOwnerCombatInteraction(Unit *target)
Creature * DoSummonFlyer(uint32 entry, WorldObject *obj, float flightZ, float radius=5.0f, Milliseconds despawnTime=30s, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
bool _EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
void JustEnteredCombat(Unit *) override
void DoZoneInCombat(Creature *creature=nullptr)
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
void OnCharmed(bool isNew) override
virtual void JustAppeared()
virtual bool CheckInRoom()
bool IsInBoundary(Position const *who=nullptr) const
void SetBoundary(CreatureBoundary const *boundary, bool negativeBoundaries=false)
void EngagementStart(Unit *who)
Creature * DoSummon(uint32 entry, Position const &pos, Milliseconds despawnTime=30s, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
void MoveInLineOfSight_Safe(Unit *who)
== Reactions At =================================
virtual void EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
bool LoadCreaturesAddon()
void DoImmediateBoundaryCheck()
bool _IsTargetAcceptable(Unit const *target) const
void SetLootRecipient(Unit *unit, bool withGroup=true)
void GetHomePosition(float &x, float &y, float &z, float &ori) const
void SetLastDamagedTime(time_t val)
bool HasReactState(ReactStates state) const
void DoNotReacquireSpellFocusTarget()
bool IsEngaged() const override
void ResetPlayerDamageReq()
void SetCannotReachTarget(bool cannotReach)
void SetTarget(ObjectGuid guid) override
void AtEngage(Unit *target) override
void AtDisengage() override
void SendAIReaction(AiReaction reactionType)
bool IsImmuneToPC() const
bool IsInEvadeMode() const
std::string GetDebugInfo() const override
bool CanStartAttack(Unit const *u, bool force) const
PlayerList const & GetPlayers() const
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveDistract(uint32 time, float orientation)
static ObjectGuid const Empty
std::string ToString() const
static ObjectGuid GetGUID(Object const *o)
virtual void OnCharmed(bool isNew)
static AISpellInfoType * AISpellInfo
virtual void AttackStart(Unit *)
Vehicle * GetVehicle() const
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Unit * GetVehicleBase() const
MotionMaster * GetMotionMaster()
TempSummon * ToTempSummon()
void AddUnitState(uint32 f)
void ClearComboPointHolders()
Unit * GetCharmerOrOwner() const
void EngageWithTarget(Unit *who)
virtual float GetFollowAngle() const
bool HasUnitState(const uint32 f) const
SpellHistory * GetSpellHistory()
ObjectGuid LastCharmerGUID
void CombatStop(bool includingCast=false, bool mutualPvP=true)
void RemoveAurasOnEvade()
bool IsHostileTo(WorldObject const *target) const
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Position GetRandomNearPosition(float radius)
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
float GetPositionZ() const
float GetAbsoluteAngle(float x, float y) const
float GetPositionX() const
void GetPosition(float &x, float &y) const
float GetPositionY() const