Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
CreatureAI.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Creature.h"
7#include "CreatureAI.h"
8#include "CreatureAIImpl.h"
9#include "CreatureTextMgr.h"
10#include "Log.h"
11#include "MapReference.h"
12#include "Player.h"
13#include "SpellMgr.h"
14#include "Vehicle.h"
15#include "World.h"
16
17//Disable CreatureAI when charmed
18void CreatureAI::OnCharmed(bool /*apply*/)
19{
20 //me->IsAIEnabled = !apply;*/
21 me->NeedChangeAI = true;
22 me->IsAIEnabled = false;
23}
24
27
28void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= NULL*/)
29{
30 sCreatureTextMgr->SendChat(me, id, whisperTarget);
31}
32
33void CreatureAI::DoZoneInCombat(Creature* creature /*= NULL*/, float maxRangeToNearestTarget /* = 50.0f*/)
34{
35 if (!creature)
36 creature = me;
37
38 if (!creature->CanHaveThreatList())
39 return;
40
41 Map* map = creature->GetMap();
42 if (!map->IsInstance()) //use IsInstance instead of Instanceable, in case battlegrounds will be instantiated
43 {
44 SF_LOG_ERROR("misc", "DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TypeID::TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
45 return;
46 }
47
48 if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
49 {
50 if (Unit* nearTarget = creature->SelectNearestTarget(maxRangeToNearestTarget))
51 creature->AI()->AttackStart(nearTarget);
52 else if (creature->IsSummon())
53 {
54 if (Unit* summoner = creature->ToTempSummon()->GetSummoner())
55 {
56 Unit* target = summoner->getAttackerForHelper();
57 if (!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty())
58 target = summoner->getThreatManager().getHostilTarget();
59 if (target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
60 creature->AI()->AttackStart(target);
61 }
62 }
63 }
64
65 // Intended duplicated check, the code above this should select a victim
66 // If it can't find a suitable attack target then we should error out.
67 if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
68 {
69 SF_LOG_ERROR("misc", "DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry());
70 return;
71 }
72
73 Map::PlayerList const& playerList = map->GetPlayers();
74
75 if (playerList.isEmpty())
76 return;
77
78 for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
79 {
80 if (Player* player = itr->GetSource())
81 {
82 if (player->IsGameMaster())
83 continue;
84
85 if (player->IsAlive())
86 {
87 creature->SetInCombatWith(player);
88 player->SetInCombatWith(creature);
89 creature->AddThreat(player, 0.0f);
90 }
91
92 /* Causes certain things to never leave the threat list (Priest Lightwell, etc):
93 for (Unit::ControlList::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr)
94 {
95 creature->SetInCombatWith(*itr);
96 (*itr)->SetInCombatWith(creature);
97 creature->AddThreat(*itr, 0.0f);
98 }*/
99 }
100 }
101}
102
103// scripts does not take care about MoveInLineOfSight loops
104// MoveInLineOfSight can be called inside another MoveInLineOfSight and cause stack overflow
113
115{
116 if (me->GetVictim())
117 return;
118
119 if (me->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) // non-combat pets should just stand there and look good;)
120 return;
121
122 if (me->CanStartAttack(who, false))
123 AttackStart(who);
124 //else if (who->GetVictim() && me->IsFriendlyTo(who)
125 // && me->IsWithinDistInMap(who, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS))
126 // && me->CanStartAttack(who->GetVictim(), true)) /// @todo if we use true, it will not attack it when it arrives
127 // me->GetMotionMaster()->MoveChase(who->GetVictim());
128}
129
131{
132 if (!_EnterEvadeMode())
133 return;
134
135 SF_LOG_DEBUG("entities.unit", "Creature %u enters evade mode.", me->GetEntry());
136
137 if (!me->GetVehicle()) // otherwise me will be in evade mode forever
138 {
139 if (Unit* owner = me->GetCharmerOrOwner())
140 {
141 me->GetMotionMaster()->Clear(false);
142 me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
143 }
144 else
145 {
146 // Required to prevent attacking creatures that are evading and cause them to reenter combat
147 // Does not apply to MoveFollow
148 me->AddUnitState(UNIT_STATE_EVADE);
149 me->GetMotionMaster()->MoveTargetedHome();
150 }
151 }
152
153 Reset();
154
155 if (me->IsVehicle()) // use the same sequence of addtoworld, aireset may remove all summons!
156 me->GetVehicleKit()->Reset(true);
157}
158
159/*void CreatureAI::AttackedBy(Unit* attacker)
160{
161 if (!me->GetVictim())
162 AttackStart(attacker);
163}*/
164
166{
167 if (me->IsValidAttackTarget(target))
168 {
169 AttackStart(target);
170 me->SetReactState(REACT_PASSIVE);
171 }
172}
173
175{
176 if (!me->IsInCombat())
177 return false;
178
179 if (me->HasReactState(REACT_PASSIVE))
180 {
181 if (me->GetVictim())
182 return true;
183 else
184 me->SetReactState(REACT_AGGRESSIVE);
185 }
186
187 if (Unit* victim = me->SelectVictim())
188 AttackStart(victim);
189 return me->GetVictim();
190}
191
193{
194 if (!me->IsInCombat())
195 return false;
196
197 if (!me->HasReactState(REACT_PASSIVE))
198 {
199 if (Unit* victim = me->SelectVictim())
200 AttackStart(victim);
201 return me->GetVictim();
202 }
203 else if (me->getThreatManager().isThreatListEmpty())
204 {
206 return false;
207 }
208
209 return true;
210}
211
213{
214 if (!me->IsAlive())
215 return false;
216
217 // don't remove vehicle auras, passengers aren't supposed to drop off the vehicle
218 // don't remove clone caster on evade (to be verified)
219 me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER);
220
221 // sometimes bosses stuck in combat?
222 me->DeleteThreatList();
223 me->CombatStop(true);
224 me->LoadCreaturesAddon(true);
225 me->SetLootRecipient(NULL);
226 me->ResetPlayerDamageReq();
227 me->SetLastDamagedTime(0);
228
229 if (me->IsInEvadeMode())
230 return false;
231
232 return true;
233}
234
235Creature* CreatureAI::DoSummon(uint32 entry, const Position& pos, uint32 despawnTime, TempSummonType summonType)
236{
237 return me->SummonCreature(entry, pos, summonType, despawnTime);
238}
239
240Creature* CreatureAI::DoSummon(uint32 entry, WorldObject* obj, float radius, uint32 despawnTime, TempSummonType summonType)
241{
242 Position pos;
243 obj->GetRandomNearPosition(pos, radius);
244 return me->SummonCreature(entry, pos, summonType, despawnTime);
245}
246
247Creature* CreatureAI::DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius, uint32 despawnTime, TempSummonType summonType)
248{
249 Position pos;
250 obj->GetRandomNearPosition(pos, radius);
251 pos.m_positionZ += flightZ;
252 return me->SummonCreature(entry, pos, summonType, despawnTime);
253}
AISpellInfoType * GetAISpellInfo(uint32 i)
#define sCreatureTextMgr
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ MOTION_SLOT_ACTIVE
@ TYPEID_UNIT
Definition Object.h:54
TempSummonType
Definition Object.h:67
#define PET_FOLLOW_DIST
Definition PetDefines.h:57
@ CREATURE_TYPE_NON_COMBAT_PET
@ SPELL_AURA_CLONE_CASTER
@ SPELL_AURA_CONTROL_VEHICLE
@ UNIT_STATE_EVADE
Definition Unit.h:533
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
virtual void MoveInLineOfSight(Unit *)
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
Creature * DoSummon(uint32 entry, Position const &pos, uint32 despawnTime=30000, TempSummonType summonType=TempSummonType::TEMPSUMMON_CORPSE_TIMED_DESPAWN)
bool _EnterEvadeMode()
bool UpdateVictimWithGaze()
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool m_MoveInLineOfSight_locked
Definition CreatureAI.h:174
Creature * DoSummonFlyer(uint32 entry, WorldObject *obj, float flightZ, float radius=5.0f, uint32 despawnTime=30000, TempSummonType summonType=TempSummonType::TEMPSUMMON_CORPSE_TIMED_DESPAWN)
bool UpdateVictim()
void SetGazeOn(Unit *target)
Creature *const me
Definition CreatureAI.h:56
void MoveInLineOfSight_Safe(Unit *who)
== Reactions At =================================
void OnCharmed(bool apply)
virtual void EnterEvadeMode()
bool HasReactState(ReactStates state) const
Definition Creature.h:462
Unit * SelectNearestTarget(float dist=0, bool playerOnly=false) const
CreatureAI * AI() const
Definition Creature.h:483
bool isEmpty() const
Definition LinkedList.h:86
Definition Map.h:238
MapRefManager PlayerList
Definition Map.h:406
PlayerList const & GetPlayers() const
Definition Map.h:407
bool IsInstance() const
Definition Map.h:368
iterator end()
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
TypeID GetTypeId() const
Definition Object.h:131
uint32 GetEntry() const
Definition Object.h:125
Creature * ToCreature()
Definition Object.h:207
Unit * GetSummoner() const
Unit * getHostilTarget()
virtual void Reset()
Definition UnitAI.h:120
static AISpellInfoType * AISpellInfo
Definition UnitAI.h:242
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
Definition Unit.h:1367
bool CanHaveThreatList() const
Definition Unit.cpp:4424
void AddThreat(Unit *victim, float fThreat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *threatSpell=NULL)
Definition Unit.cpp:4463
Unit * getAttackerForHelper() const
TempSummon * ToTempSummon()
Definition Unit.h:2821
bool IsSummon() const
Definition Unit.h:1503
Unit * GetVictim() const
Definition Unit.h:1468
bool IsFriendlyTo(Unit const *unit) const
Definition Unit.cpp:2283
ThreatManager & getThreatManager()
Definition Unit.h:2455
bool IsHostileTo(Unit const *unit) const
Definition Unit.cpp:2278
void SetInCombatWith(Unit *enemy)
Map * GetMap() const
Definition Object.h:740
void GetRandomNearPosition(Position &pos, float radius)
Definition Object.cpp:3088
float m_positionZ
Definition Object.h:289