TrinityCore
Loading...
Searching...
No Matches
boss_sjonnir.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#include "ScriptMgr.h"
19#include "halls_of_stone.h"
20#include "InstanceScript.h"
21#include "MotionMaster.h"
22#include "ObjectAccessor.h"
23#include "ScriptedCreature.h"
24#include "SpellInfo.h"
25#include "SpellMgr.h"
26#include "SpellScript.h"
27
35
67
77
84
93
94Position const CenterPoint = { 1293.8799f, 666.942f, 189.60754f, 0.0f };
95
96// 27978 - Sjonnir The Ironshaper
97struct boss_sjonnir : public BossAI
98{
101
120
121 void JustSummoned(Creature* summoned) override
122 {
123 switch (summoned->GetEntry())
124 {
127 // AttackStart(me->GetVictim()) does not work in case of very first spawn
129 summoned->AI()->AttackStart(target);
130 break;
132 summoned->AI()->AttackStart(me);
133 break;
134 }
135 summons.Summon(summoned);
136 }
137
138 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
139 {
140 if (me->HealthBelowPctDamaged(75, damage) && !_summonsTroggs)
141 {
142 _summonsTroggs = true;
145 }
146
147 if (me->HealthBelowPctDamaged(50, damage) && !_summonsOozes)
148 {
149 _summonsOozes = true;
152 }
153
154 if (me->HealthBelowPctDamaged(25, damage) && !_summonsDwarfs)
155 {
156 _summonsDwarfs = true;
159 }
160
161 if (me->HealthBelowPctDamaged(20, damage) && !_frenzied)
162 {
163 _frenzied = true;
164 // Old removed, more powerful added
168 }
169 }
170
171 void EnterEvadeMode(EvadeReason /*why*/) override
172 {
176 }
177
178 void JustDied(Unit* /*killer*/) override
179 {
180 _JustDied();
182 }
183
184 void KilledUnit(Unit* who) override
185 {
186 if (who->GetTypeId() == TYPEID_PLAYER)
187 Talk(SAY_SLAY);
188 }
189
190 void DoAction(int32 action) override
191 {
192 if (action == ACTION_SLUDGE_DEAD)
194 }
195
196 uint32 GetData(uint32 type) const override
197 {
198 if (type == DATA_ABUSE_THE_OOZE)
199 return _sludgesKilled;
200
201 return 0;
202 }
203
204 void UpdateAI(uint32 diff) override
205 {
206 if (!UpdateVictim())
207 return;
208
209 events.Update(diff);
210
212 return;
213
214 while (uint32 eventId = events.ExecuteEvent())
215 {
216 switch (eventId)
217 {
220 events.Repeat(10s, 15s);
221 break;
223 if (!me->HasAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_LIGHTNING_SHIELD, me)))
225 events.Repeat(5s, 15s);
226 break;
228 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true, true))
230 events.Repeat(20s, 27s);
231 break;
234 events.Repeat(50s);
235 break;
238 events.Repeat(15s);
239 break;
240 case EVENT_FRENZY:
243 break;
244 default:
245 break;
246 }
247
249 return;
250 }
251
253 }
254
255private:
261};
262
263// 27981 - Malformed Ooze
265{
266 npc_malformed_ooze(Creature* creature) : ScriptedAI(creature) { }
267
268 void InitializeAI() override
269 {
270 me->SetCorpseDelay(5, true);
272 }
273
274 void JustAppeared() override
275 {
277 }
278
279 void MovementInform(uint32 type, uint32 id) override
280 {
281 if (type == POINT_MOTION_TYPE && id == POINT_CENTER)
282 {
285 }
286 }
287
288 /* This is far from correct implementation. Once ooze reaches center point, it casts periodic aura. When spell hits another ooze, both
289 caster and target removes periodic aura and caster starts moving to target. Target does not stop random movement. Once caster is close
290 enough to target, caster casts a spell to combine with target. Target despawns instantly, caster despawns after 1sec.
291
292 Since target does not stop random movement, that causes problems because combine spell is used when oozes are close enough to each other
293 but with current implementation it takes too much time to reach target, as result there may be too much oozes trying to combine at
294 the same time.
295 Increasing radius at which combine spell can be used or trying to change the way oozes chases target only creates more problems because
296 combine spell may target not required target but just ooze which was closer to caster. That leaves multiple spawns which can't combine
297 anymore since combining process was started(auras were removed) but wasn't finished sucessfully
298
299 Currently target is forced to stop random movement and caster just casts spell when is close enough to target. Spells has additional
300 conditions in DB. That makes oozes combine every time sucessfully but not too fast and give players more time too kill sludges
301 Ideally both spells should be scripted, filtering targets(if possible) and casting spell on target which was stored previously may look
302 overcomplicated but saves from casting spell on wrong target. Or maybe solving the problem with moving to stored target will be enough */
303 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
304 {
305 Creature* creatureTarget = target->ToCreature();
306 if (!creatureTarget)
307 return;
308
309 switch (spellInfo->Id)
310 {
312 _combineTarget = creatureTarget->GetGUID();
315 creatureTarget->GetMotionMaster()->MoveIdle();
317 me->GetMotionMaster()->MovePoint(POINT_COMBINE, creatureTarget->GetPosition());
318
319 _scheduler.Schedule(1s, [this](TaskContext task)
320 {
322 // Completely unclear what should happen in this case or in case when caster dies
323 if (!combineTarget || !combineTarget->IsAlive())
324 {
326 return;
327 }
328
329 if (me->GetExactDist2d(combineTarget) <= 0.1f)
330 DoCast(combineTarget, SPELL_SUMMON_IRON_SLUDGE);
331 else
332 {
334 task.Repeat();
335 }
336 });
337 break;
339 creatureTarget->DespawnOrUnsummon();
341 break;
342 }
343 }
344
345 void UpdateAI(uint32 diff) override
346 {
347 _scheduler.Update(diff);
348 }
349
350private:
353};
354
355// 28165 - Iron Sludge
357{
358 npc_iron_sludge(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
359
360 void JustAppeared() override
361 {
362 me->SetCorpseDelay(4, true);
364
366 if (CreatureAI* ai = sjonnir->AI())
367 ai->JustSummoned(me);
368 }
369
370 void JustEngagedWith(Unit* /*who*/) override
371 {
372 _scheduler.Schedule(3s, 6s, [this](TaskContext task)
373 {
375 task.Repeat(3s, 6s);
376 });
377 }
378
379 void JustDied(Unit* /*killer*/) override
380 {
382 if (CreatureAI* ai = sjonnir->AI())
383 ai->DoAction(ACTION_SLUDGE_DEAD);
384 }
385
386 void UpdateAI(uint32 diff) override
387 {
388 if (!UpdateVictim())
389 return;
390
391 _scheduler.Update(diff, [this]
392 {
394 });
395 }
396
397private:
400};
401
402/* 50789 - Summon Iron Dwarf
403 50792 - Summon Iron Trogg
404 59859 - Summon Iron Trogg
405 50801 - Summon Malformed Ooze
406 59858 - Summon Malformed Ooze
407 50824 - Summon Earthen Dwarf */
441
442// 50777 - Iron Sludge Spawn Visual
444{
446
447 void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
448 {
449 // They're indeed passive but I'm not sure enough if it's handled by this aura or directly in script
450 if (Creature* creature = GetTarget()->ToCreature())
451 creature->SetReactState(REACT_PASSIVE);
452 }
453
454 void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
455 {
456 if (Creature* creature = GetTarget()->ToCreature())
457 {
458 creature->SetReactState(REACT_AGGRESSIVE);
459 if (creature->IsAIEnabled() && creature->IsAlive())
460 creature->AI()->DoZoneInCombat();
461 }
462 }
463
469};
470
472{
473 public:
475 {
476 }
477
478 bool OnCheck(Player* /*player*/, Unit* target) override
479 {
480 if (!target)
481 return false;
482
483 if (Creature* Sjonnir = target->ToCreature())
484 if (Sjonnir->AI()->GetData(DATA_ABUSE_THE_OOZE) >= 5)
485 return true;
486
487 return false;
488 }
489};
490
First const & RAND(First const &first, Second const &second, Rest const &... rest)
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
@ POINT_MOTION_TYPE
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
#define RegisterSpellScriptWithArgs(spell_script, script_name,...)
Definition ScriptMgr.h:1127
@ EFFECT_0
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_DUMMY
#define sSpellMgr
Definition SpellMgr.h:738
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
SjonnirMisc
@ POINT_CENTER
@ ACTION_SLUDGE_DEAD
@ DATA_ABUSE_THE_OOZE
@ POINT_COMBINE
void AddSC_boss_sjonnir()
Position const CenterPoint
SjonnirEvents
@ EVENT_CHAIN_LIGHTNING
@ EVENT_STATIC_CHARGE
@ EVENT_LIGHTNING_SHIELD
@ EVENT_LIGHTNING_RING_2
@ EVENT_FRENZY
@ EVENT_LIGHTNING_RING_1
SjonnirTexts
@ SAY_DEATH
@ SAY_AGGRO
@ EMOTE_FRENZY
@ SAY_SLAY
SjonnirSpells
@ SPELL_OOZE_COMBINE_EFFECT
@ SPELL_SUMMON_IRON_TROGG_PERIODIC
@ SPELL_SUMMON_IRON_DWARF_2
@ SPELL_IRON_SLUDGE_SPAWN_VISUAL
@ SPELL_LIGHTNING_RING_2
@ SPELL_SUMMON_IRON_TROGG_2
@ SPELL_SUMMON_EARTHEN_DWARF_2
@ SPELL_SUMMON_IRON_DWARF_PERIODIC
@ SPELL_SUMMON_MALFORMED_OOZE_1
@ SPELL_OOZE_COMBINE_PERIODIC
@ SPELL_SUMMON_MALFORMED_OOZE_2
@ SPELL_SUMMON_IRON_TROGG_1
@ SPELL_SUMMON_EARTHEN_DWARF_1
@ SPELL_SUMMON_IRON_SLUDGE
@ SPELL_SUMMON_EARTHEN_DWARF_PERIODIC
@ SPELL_FRENZY
@ SPELL_CHAIN_LIGHTNING
@ SPELL_SUMMON_MALFORMED_OOZE_PERIODIC
@ SPELL_LIGHTNING_SHIELD
@ SPELL_LIGHTNING_RING_1
@ SPELL_STATIC_CHARGE
@ SPELL_TOXIC_VOLLEY
@ SPELL_SUMMON_IRON_DWARF_1
SjonnirCreatures
@ NPC_FORGED_IRON_DWARF
@ NPC_FORGED_IRON_TROGG
@ NPC_EARTHEN_DWARF
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
@ EVADE_REASON_SEQUENCE_BREAK
Definition CreatureAI.h:97
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void SetReactState(ReactStates st)
Definition Creature.h:119
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetCorpseDelay(uint32 delay, bool ignoreCorpseDecayRatio=false)
Definition Creature.h:89
CreatureAI * AI() const
Definition Creature.h:154
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
void CancelEvent(EventId eventId)
Definition EventMap.cpp:151
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
Creature * GetCreature(uint32 type)
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveRandom(float wanderDistance=0.0f)
static Creature * ToCreature(Object *o)
Definition Object.h:186
TypeID GetTypeId() const
Definition Object.h:93
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
uint32 Id
Definition SpellInfo.h:289
void Summon(Creature const *summon)
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)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:30
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsAlive() const
Definition Unit.h:1234
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition Unit.h:918
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnCheck(Player *, Unit *target) override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
PrepareAuraScript(spell_sjonnir_iron_sludge_spawn_visual)
bool Validate(SpellInfo const *) override
spell_sjonnir_periodic_summon(uint32 leftPipeSpell, uint32 rightPipeSpell)
PrepareAuraScript(spell_sjonnir_periodic_summon)
void OnPeriodic(AuraEffect const *)
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
@ DATA_SJONNIR_THE_IRONSHAPER
#define RegisterHallsOfStoneCreatureAI(ai_name)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
float GetExactDist2d(const float x, const float y) const
Definition Position.h:109
void GetPosition(float &x, float &y) const
Definition Position.h:84
void JustSummoned(Creature *summoned) override
void JustEngagedWith(Unit *who) override
void UpdateAI(uint32 diff) override
void KilledUnit(Unit *who) override
void JustDied(Unit *) override
boss_sjonnir(Creature *creature)
void DoAction(int32 action) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
uint32 GetData(uint32 type) const override
void EnterEvadeMode(EvadeReason) override
npc_iron_sludge(Creature *creature)
TaskScheduler _scheduler
void JustDied(Unit *) override
void JustEngagedWith(Unit *) override
InstanceScript * _instance
void JustAppeared() override
void UpdateAI(uint32 diff) override
TaskScheduler _scheduler
void JustAppeared() override
void SpellHitTarget(WorldObject *target, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
ObjectGuid _combineTarget
npc_malformed_ooze(Creature *creature)
void InitializeAI() override
void MovementInform(uint32 type, uint32 id) override