TrinityCore
Loading...
Searching...
No Matches
pet_dk.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Ordered alphabetically using scriptname.
20 * Scriptnames of files in this file should be prefixed with "npc_pet_dk_".
21 */
22
23#include "ScriptMgr.h"
24#include "CombatAI.h"
25#include "CellImpl.h"
26#include "GridNotifiersImpl.h"
27#include "MotionMaster.h"
28#include "ObjectAccessor.h"
29#include "ScriptedCreature.h"
30#include "SpellScript.h"
31
50
52{
53 npc_pet_dk_ebon_gargoyle(Creature* creature) : CasterAI(creature) { }
54
55 void InitializeAI() override
56 {
58 ObjectGuid ownerGuid = me->GetOwnerGUID();
59 if (!ownerGuid)
60 return;
61
62 // Find victim of Summon Gargoyle spell
63 std::list<Unit*> targets;
66 Cell::VisitAllObjects(me, searcher, 30.0f);
67 for (Unit* target : targets)
68 {
69 if (target->HasAura(SPELL_DK_SUMMON_GARGOYLE_1, ownerGuid))
70 {
71 me->Attack(target, false);
72 break;
73 }
74 }
75 }
76
77 void JustDied(Unit* /*killer*/) override
78 {
79 // Stop Feeding Gargoyle when it dies
80 if (Unit* owner = me->GetOwner())
81 owner->RemoveAurasDueToSpell(SPELL_DK_SUMMON_GARGOYLE_2);
82 }
83
84 // Fly away when dismissed
85 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
86 {
87 if (spellInfo->Id != SPELL_DK_DISMISS_GARGOYLE || !me->IsAlive())
88 return;
89
90 Unit* owner = me->GetOwner();
91 if (!owner || owner != caster)
92 return;
93
94 // Stop Fighting
96
97 // Sanctuary
100
102 // Fly Away
103 me->SetCanFly(true);
104 me->SetSpeedRate(MOVE_FLIGHT, 0.75f);
105 me->SetSpeedRate(MOVE_RUN, 0.75f);
106 float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation());
107 float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation());
108 float z = me->GetPositionZ() + 40;
110 me->GetMotionMaster()->MovePoint(0, x, y, z);
111
112 // Despawn as soon as possible
114 }
115};
116
118{
119 npc_pet_dk_guardian(Creature* creature) : AggressorAI(creature) { }
120
121 bool CanAIAttack(Unit const* target) const override
122 {
123 if (!target)
124 return false;
125 Unit* owner = me->GetOwner();
126 if (owner && !target->IsInCombatWith(owner))
127 return false;
128 return AggressorAI::CanAIAttack(target);
129 }
130};
131
137
139{
140 npc_pet_dk_rune_weapon(Creature* creature) : ScriptedAI(creature) { }
141
142 void IsSummonedBy(WorldObject* summoner) override
143 {
145
146 if (summoner->GetTypeId() != TYPEID_UNIT)
147 return;
148
149 Unit* unitSummoner = summoner->ToUnit();
150
151 DoCast(unitSummoner, SPELL_COPY_WEAPON, true);
152 DoCast(unitSummoner, SPELL_DK_RUNE_WEAPON_MARK, true);
159
160 _scheduler.Schedule(500ms, [this](TaskContext /*activate*/)
161 {
163 if (!_targetGUID.IsEmpty())
164 {
165 if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
166 me->EngageWithTarget(target);
167 }
168 }).Schedule(6s, [this](TaskContext visual)
169 {
170 // Cast every 6 seconds
172 visual.Repeat();
173 });
174 }
175
176 void SetGUID(ObjectGuid const& guid, int32 id) override
177 {
178 if (id == DATA_INITIAL_TARGET_GUID)
179 _targetGUID = guid;
180 }
181
182 void JustEnteredCombat(Unit* who) override
183 {
185
186 // Investigate further if these casts are done by any owned aura, eitherway SMSG_SPELL_GO is sent every X seconds.
188 {
189 // Cast every second
190 if (Unit* victim = me->GetVictim())
191 DoCast(victim, SPELL_AGGRO_8_YD_PBAE, true);
192 aggro8YD.Repeat();
193 });
194 }
195
196 void UpdateAI(uint32 diff) override
197 {
198 Unit* owner = me->GetOwner();
199 if (!owner)
200 {
202 return;
203 }
204
205 _scheduler.Update(diff);
206
208 return;
209
211 }
212
213 bool CanAIAttack(Unit const* who) const override
214 {
215 Unit* owner = me->GetOwner();
216 return owner && who->IsAlive() && me->IsValidAttackTarget(who) && !who->HasBreakableByDamageCrowdControlAura() && who->IsInCombatWith(owner) && ScriptedAI::CanAIAttack(who);
217 }
218
219 // Do not reload Creature templates on evade mode enter - prevent visual lost
220 void EnterEvadeMode(EvadeReason /*why*/) override
221 {
223
224 if (!me->IsAlive())
225 {
227 return;
228 }
229
230 Unit* owner = me->GetCharmerOrOwner();
231
232 me->CombatStop(true);
233 me->SetLootRecipient(nullptr);
236 me->SetCannotReachTarget(false);
240
241 if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
242 {
245 }
246 }
247
248private:
249 // custom UpdateVictim implementation to handle special target selection
250 // we prioritize between things that are in combat with owner based on the owner's threat to them
252 {
253 Unit* owner = me->GetOwner();
254 if (!owner)
255 return false;
256
257 if (!me->IsEngaged() && !owner->IsInCombat())
258 return false;
259
260 Unit* currentTarget = me->GetVictim();
261 if (currentTarget && !CanAIAttack(currentTarget))
262 {
263 me->InterruptNonMeleeSpells(true); // do not finish casting on invalid targets
264 me->AttackStop();
265 currentTarget = nullptr;
266 }
267
268 Unit* selectedTarget = nullptr;
269
270 // first, try to get the initial target
271 if (Unit* initialTarget = ObjectAccessor::GetUnit(*me, _targetGUID))
272 {
273 if (CanAIAttack(initialTarget))
274 selectedTarget = initialTarget;
275 }
276 else if (!_targetGUID.IsEmpty())
278
279 CombatManager const& mgr = owner->GetCombatManager();
280 if (!selectedTarget)
281 {
282 if (mgr.HasPvPCombat())
283 {
284 // select pvp target
285 float minDistance = 0.f;
286 for (auto const& pair : mgr.GetPvPCombatRefs())
287 {
288 Unit* target = pair.second->GetOther(owner);
289 if (target->GetTypeId() != TYPEID_PLAYER)
290 continue;
291 if (!CanAIAttack(target))
292 continue;
293
294 float dist = owner->GetDistance(target);
295 if (!selectedTarget || dist < minDistance)
296 {
297 selectedTarget = target;
298 minDistance = dist;
299 }
300 }
301 }
302 }
303
304 if (!selectedTarget)
305 {
306 // select pve target
307 float maxThreat = 0.f;
308 for (auto const& pair : mgr.GetPvECombatRefs())
309 {
310 Unit* target = pair.second->GetOther(owner);
311 if (!CanAIAttack(target))
312 continue;
313
314 float threat = target->GetThreatManager().GetThreat(owner);
315 if (threat >= maxThreat)
316 {
317 selectedTarget = target;
318 maxThreat = threat;
319 }
320 }
321 }
322
323 if (!selectedTarget)
324 {
326 return false;
327 }
328
329 if (selectedTarget != me->GetVictim())
330 AttackStart(selectedTarget);
331 return true;
332 }
333
336};
337
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
#define PET_FOLLOW_DIST
Definition PetDefines.h:85
#define RegisterCreatureAI(ai_name)
Definition ScriptMgr.h:1139
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ MOVE_FLIGHT
@ MOVE_RUN
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_STATE_FOLLOW
Definition Unit.h:229
void InitializeAI() override
Definition CombatAI.cpp:117
std::unordered_map< ObjectGuid, PvPCombatReference * > const & GetPvPCombatRefs() const
std::unordered_map< ObjectGuid, CombatReference * > const & GetPvECombatRefs() const
bool HasPvPCombat() const
@ EVADE_REASON_NO_HOSTILES
Definition CreatureAI.h:94
Creature *const me
Definition CreatureAI.h:82
void EngagementOver()
void SetLootRecipient(Unit *unit, bool withGroup=true)
void SetLastDamagedTime(time_t val)
Definition Creature.h:350
void DoNotReacquireSpellFocusTarget()
bool IsEngaged() const override
void SetReactState(ReactStates st)
Definition Creature.h:119
void ResetPlayerDamageReq()
Definition Creature.h:323
void SetCannotReachTarget(bool cannotReach)
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetTarget(ObjectGuid guid) override
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
void Clear()
Definition ObjectGuid.h:150
static Unit * ToUnit(Object *o)
Definition Object.h:192
TypeID GetTypeId() const
Definition Object.h:93
uint32 Id
Definition SpellInfo.h:289
TaskContext & Repeat(std::chrono::duration< _Rep, _Period > const &duration)
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
TaskScheduler & CancelGroup(group_t const group)
float GetThreat(Unit const *who, bool includeOffline=false) const
virtual void JustEnteredCombat(Unit *)
Definition UnitAI.h:212
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
virtual bool CanAIAttack(Unit const *) const
Definition UnitAI.h:139
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
ThreatManager & GetThreatManager()
Definition Unit.h:1155
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition Unit.cpp:693
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1241
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsAlive() const
Definition Unit.h:1234
bool IsInCombatWith(Unit const *who) const
Definition Unit.h:1145
Unit * GetCharmerOrOwner() const
Definition Unit.h:1265
bool SetCanFly(bool enable, bool packetOnly=false)
Definition Unit.cpp:13374
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5535
virtual float GetFollowAngle() const
Definition Unit.h:1782
Unit * GetVictim() const
Definition Unit.h:859
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8678
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void CombatStop(bool includingCast=false, bool mutualPvP=true)
Definition Unit.cpp:5691
CombatManager & GetCombatManager()
Definition Unit.h:1130
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
bool AttackStop()
Definition Unit.cpp:5645
bool IsInCombat() const
Definition Unit.h:1144
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2856
Unit * GetOwner() const
Definition Object.cpp:2180
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1123
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
DeathKnightSpells
Definition pet_dk.cpp:33
@ SPELL_FAKE_AGGRO_RADIUS_8_YARD
Definition pet_dk.cpp:42
@ SPELL_COPY_WEAPON
Definition pet_dk.cpp:39
@ SPELL_DK_DANCING_RUNE_WEAPON
Definition pet_dk.cpp:38
@ SPELL_DK_SUMMON_GARGOYLE_2
Definition pet_dk.cpp:35
@ SPELL_DK_RUNE_WEAPON_SCALING_01
Definition pet_dk.cpp:43
@ SPELL_DISMISS_RUNEBLADE
Definition pet_dk.cpp:48
@ SPELL_DK_PET_SCALING_03
Definition pet_dk.cpp:46
@ SPELL_DK_DANCING_RUNE_WEAPON_VISUAL
Definition pet_dk.cpp:41
@ SPELL_DK_RUNE_WEAPON_SCALING
Definition pet_dk.cpp:44
@ SPELL_AGGRO_8_YD_PBAE
Definition pet_dk.cpp:47
@ SPELL_PET_SCALING__MASTER_SPELL_06__SPELL_HIT_EXPERTISE_SPELL_PENETRATION
Definition pet_dk.cpp:45
@ SPELL_DK_SUMMON_GARGOYLE_1
Definition pet_dk.cpp:34
@ SPELL_DK_SANCTUARY
Definition pet_dk.cpp:37
@ SPELL_DK_RUNE_WEAPON_MARK
Definition pet_dk.cpp:40
@ SPELL_DK_DISMISS_GARGOYLE
Definition pet_dk.cpp:36
DancingRuneWeaponMisc
Definition pet_dk.cpp:133
@ DATA_INITIAL_TARGET_GUID
Definition pet_dk.cpp:135
@ TASK_GROUP_COMBAT
Definition pet_dk.cpp:134
void AddSC_deathknight_pet_scripts()
Definition pet_dk.cpp:338
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:192
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
void AttackStart(Unit *) override
void InitializeAI() override
Definition pet_dk.cpp:55
void JustDied(Unit *) override
Definition pet_dk.cpp:77
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
Definition pet_dk.cpp:85
npc_pet_dk_ebon_gargoyle(Creature *creature)
Definition pet_dk.cpp:53
bool CanAIAttack(Unit const *target) const override
Definition pet_dk.cpp:121
npc_pet_dk_guardian(Creature *creature)
Definition pet_dk.cpp:119
void JustEnteredCombat(Unit *who) override
Definition pet_dk.cpp:182
void UpdateAI(uint32 diff) override
Definition pet_dk.cpp:196
void EnterEvadeMode(EvadeReason) override
Definition pet_dk.cpp:220
void IsSummonedBy(WorldObject *summoner) override
Definition pet_dk.cpp:142
npc_pet_dk_rune_weapon(Creature *creature)
Definition pet_dk.cpp:140
bool UpdateRuneWeaponVictim()
Definition pet_dk.cpp:251
TaskScheduler _scheduler
Definition pet_dk.cpp:334
void SetGUID(ObjectGuid const &guid, int32 id) override
Definition pet_dk.cpp:176
bool CanAIAttack(Unit const *who) const override
Definition pet_dk.cpp:213
ObjectGuid _targetGUID
Definition pet_dk.cpp:335