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 "SpellScript.h"
26
34
58
59#define SPELL_LIGHTNING_RING_1 DUNGEON_MODE<uint32>(50840,59848)
60#define SPELL_LIGHTNING_RING_2 DUNGEON_MODE<uint32>(51849,59861)
61#define SPELL_STATIC_CHARGE DUNGEON_MODE<uint32>(50834,59861)
62#define SPELL_CHAIN_LIGHTNING DUNGEON_MODE<uint32>(50830,59844)
63#define SPELL_LIGHTNING_SHIELD DUNGEON_MODE<uint32>(50831,59845)
64#define SPELL_SUMMON_IRON_TROGG_PERIODIC DUNGEON_MODE<uint32>(50792,59859)
65#define SPELL_SUMMON_MALFORMED_OOZE_PERIODIC DUNGEON_MODE<uint32>(50801,59858)
66#define SPELL_TOXIC_VOLLEY DUNGEON_MODE<uint32>(50838,59853)
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;
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 }
252
253private:
259};
260
261// 27981 - Malformed Ooze
263{
264 npc_malformed_ooze(Creature* creature) : ScriptedAI(creature) { }
265
266 void InitializeAI() override
267 {
268 me->SetCorpseDelay(5, true);
270 }
271
272 void JustAppeared() override
273 {
275 }
276
277 void MovementInform(uint32 type, uint32 id) override
278 {
279 if (type == POINT_MOTION_TYPE && id == POINT_CENTER)
280 {
283 }
284 }
285
286 /* This is far from correct implementation. Once ooze reaches center point, it casts periodic aura. When spell hits another ooze, both
287 caster and target removes periodic aura and caster starts moving to target. Target does not stop random movement. Once caster is close
288 enough to target, caster casts a spell to combine with target. Target despawns instantly, caster despawns after 1sec.
289
290 Since target does not stop random movement, that causes problems because combine spell is used when oozes are close enough to each other
291 but with current implementation it takes too much time to reach target, as result there may be too much oozes trying to combine at
292 the same time.
293 Increasing radius at which combine spell can be used or trying to change the way oozes chases target only creates more problems because
294 combine spell may target not required target but just ooze which was closer to caster. That leaves multiple spawns which can't combine
295 anymore since combining process was started(auras were removed) but wasn't finished sucessfully
296
297 Currently target is forced to stop random movement and caster just casts spell when is close enough to target. Spells has additional
298 conditions in DB. That makes oozes combine every time sucessfully but not too fast and give players more time too kill sludges
299 Ideally both spells should be scripted, filtering targets(if possible) and casting spell on target which was stored previously may look
300 overcomplicated but saves from casting spell on wrong target. Or maybe solving the problem with moving to stored target will be enough */
301 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
302 {
303 Creature* creatureTarget = target->ToCreature();
304 if (!creatureTarget)
305 return;
306
307 switch (spellInfo->Id)
308 {
310 _combineTarget = creatureTarget->GetGUID();
313 creatureTarget->GetMotionMaster()->MoveIdle();
315 me->GetMotionMaster()->MovePoint(POINT_COMBINE, creatureTarget->GetPosition());
316
317 _scheduler.Schedule(1s, [this](TaskContext& task)
318 {
320 // Completely unclear what should happen in this case or in case when caster dies
321 if (!combineTarget || !combineTarget->IsAlive())
322 {
324 return;
325 }
326
327 if (me->GetExactDist2d(combineTarget) <= 0.1f)
328 DoCast(combineTarget, SPELL_SUMMON_IRON_SLUDGE);
329 else
330 {
332 task.Repeat();
333 }
334 });
335 break;
337 creatureTarget->DespawnOrUnsummon();
339 break;
340 }
341 }
342
343 void UpdateAI(uint32 diff) override
344 {
345 _scheduler.Update(diff);
346 }
347
348private:
351};
352
353// 28165 - Iron Sludge
355{
356 npc_iron_sludge(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
357
358 void JustAppeared() override
359 {
360 me->SetCorpseDelay(4, true);
362
364 if (CreatureAI* ai = sjonnir->AI())
365 ai->JustSummoned(me);
366 }
367
368 void JustEngagedWith(Unit* /*who*/) override
369 {
370 _scheduler.Schedule(3s, 6s, [this](TaskContext& task)
371 {
373 task.Repeat(3s, 6s);
374 });
375 }
376
377 void JustDied(Unit* /*killer*/) override
378 {
380 if (CreatureAI* ai = sjonnir->AI())
381 ai->DoAction(ACTION_SLUDGE_DEAD);
382 }
383
384 void UpdateAI(uint32 diff) override
385 {
386 if (!UpdateVictim())
387 return;
388
389 _scheduler.Update(diff);
390 }
391
392private:
395};
396
397/* 50789 - Summon Iron Dwarf
398 50792 - Summon Iron Trogg
399 59859 - Summon Iron Trogg
400 50801 - Summon Malformed Ooze
401 59858 - Summon Malformed Ooze
402 50824 - Summon Earthen Dwarf */
434
435// 50777 - Iron Sludge Spawn Visual
437{
438 void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
439 {
440 // They're indeed passive but I'm not sure enough if it's handled by this aura or directly in script
441 if (Creature* creature = GetTarget()->ToCreature())
442 creature->SetReactState(REACT_PASSIVE);
443 }
444
445 void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
446 {
447 if (Creature* creature = GetTarget()->ToCreature())
448 {
449 creature->SetReactState(REACT_AGGRESSIVE);
450 if (creature->IsAIEnabled() && creature->IsAlive())
451 creature->AI()->DoZoneInCombat();
452 }
453 }
454
460};
461
463{
464 public:
466 {
467 }
468
469 bool OnCheck(Player* /*player*/, Unit* target) override
470 {
471 if (!target)
472 return false;
473
474 if (Creature* Sjonnir = target->ToCreature())
475 if (Sjonnir->AI()->GetData(DATA_ABUSE_THE_OOZE) >= 5)
476 return true;
477
478 return false;
479 }
480};
481
First const & RAND(First const &first, Second const &second, Rest const &... rest)
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ POINT_MOTION_TYPE
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
#define RegisterSpellScriptWithArgs(spell_script, script_name,...)
Definition ScriptMgr.h:1382
@ EFFECT_0
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_DUMMY
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
EvadeReason
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
DamageEffectType
@ UNIT_STATE_CASTING
Definition Unit.h:290
SjonnirMisc
@ POINT_CENTER
@ ACTION_SLUDGE_DEAD
@ DATA_ABUSE_THE_OOZE
@ POINT_COMBINE
#define SPELL_LIGHTNING_RING_2
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
#define SPELL_SUMMON_IRON_TROGG_PERIODIC
#define SPELL_CHAIN_LIGHTNING
SjonnirTexts
@ SAY_DEATH
@ SAY_AGGRO
@ EMOTE_FRENZY
@ SAY_SLAY
#define SPELL_LIGHTNING_RING_1
SjonnirSpells
@ SPELL_OOZE_COMBINE_EFFECT
@ SPELL_SUMMON_IRON_DWARF_2
@ SPELL_IRON_SLUDGE_SPAWN_VISUAL
@ 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_SUMMON_IRON_DWARF_1
#define SPELL_LIGHTNING_SHIELD
#define SPELL_TOXIC_VOLLEY
#define SPELL_SUMMON_MALFORMED_OOZE_PERIODIC
SjonnirCreatures
@ NPC_FORGED_IRON_DWARF
@ NPC_FORGED_IRON_TROGG
@ NPC_EARTHEN_DWARF
#define SPELL_STATIC_CHARGE
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
bool UpdateVictim()
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Creature *const me
Definition CreatureAI.h:63
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetCorpseDelay(uint32 delay, bool ignoreCorpseDecayRatio=false)
Definition Creature.h:118
CreatureAI * AI() const
Definition Creature.h:235
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
EventId ExecuteEvent()
Definition EventMap.cpp:77
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
Creature * GetCreature(uint32 type)
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
void MoveRandom(float wanderDistance=0.0f, Optional< Milliseconds > duration={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::ForceWalk, MovementSlot slot=MOTION_SLOT_DEFAULT, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={}, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
uint32 const Id
Definition SpellInfo.h:328
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
void Summon(Creature const *summon)
TaskContext & Repeat(TaskScheduler::duration_t duration)
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & Update()
Update the scheduler to the current time.
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool IsAlive() const
Definition Unit.h:1205
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:805
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
bool OnCheck(Player *, Unit *target) override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
spell_sjonnir_periodic_summon(uint32 leftPipeSpell, uint32 rightPipeSpell)
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:117
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
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