TrinityCore
Loading...
Searching...
No Matches
boss_volkhan.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 "halls_of_lightning.h"
19#include "ScriptMgr.h"
20#include "GameObject.h"
21#include "InstanceScript.h"
22#include "Map.h"
23#include "MotionMaster.h"
24#include "ObjectAccessor.h"
25#include "ScriptedCreature.h"
26#include "SpellAuraEffects.h"
27#include "SpellInfo.h"
28#include "SpellScript.h"
29
41
43{
44 // Volkhan
49 SPELL_HEAT = 52387,
51
52 // Volkhan's Anvil
54
55 // Molten Golem
58 SPELL_STUN_SELF = 47067, // Serverside spell @todo
61 SPELL_INSTAKILL_SELF = 29878, // Serverside spell
63};
64
77
79{
80 // Volkhan
83
84 // Molten Golem
86};
87
89{
90 // Volkhan
93};
94
96{
97 // Volkhan
99};
100
102{
103 ENTRY_BRITTLE_GOLEM = 28681
105
110
111static Position const AnvilPosition = { 1333.5901f, -103.67797f, 56.7177f };
112
113struct boss_volkhan : public BossAI
114{
117
123
124 void JustEngagedWith(Unit* who) override
125 {
127 Talk(SAY_AGGRO, who);
129 }
130
131 void EnterEvadeMode(EvadeReason /*why*/) override
132 {
135 }
136
137 void JustDied(Unit* killer) override
138 {
139 BossAI::JustDied(killer);
140 Talk(SAY_DEATH, killer);
141 }
142
143 void KilledUnit(Unit* who) override
144 {
145 if (who->IsPlayer())
146 Talk(SAY_SLAY, who);
147 }
148
149 void MovementInform(uint32 motionType, uint32 id) override
150 {
151 if (motionType != POINT_MOTION_TYPE)
152 return;
153
154 switch (id)
155 {
156 case POINT_ID_ANVIL:
158 break;
159 default:
160 break;
161 }
162 }
163
164 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo*/) override
165 {
166 if (damage >= me->GetHealth() || _shatteredGolems)
167 return;
168
170 {
173 _shatteredGolems = true;
174 return;
175 }
176
177 if (_temperCycles < 3 && me->HealthBelowPctDamaged(100.f - (20.f + 20.f * _temperCycles), damage))
178 {
179 if (!_temperingGolems)
180 {
182 _temperingGolems = true;
183 }
185 }
186
187 }
188
189 void DoAction(int32 action) override
190 {
191 switch (action)
192 {
195 for (ObjectGuid const& guid : summons)
196 {
197 if (Creature* golem = ObjectAccessor::GetCreature(*me, guid))
198 {
199 if (golem->HasAura(SPELL_COSMETIC_STUN_IMMUNE_FREEZE_AMNIM))
200 {
201 if (CreatureAI* ai = golem->AI())
202 {
203 ai->DoAction(ACTION_SHATTER);
205 }
206 }
207 }
208 }
209 break;
211 _temperingGolems = false;
212 break;
213 default:
214 break;
215 }
216 }
217
218 uint32 GetData(uint32 type) const override
219 {
220 switch (type)
221 {
224 default:
225 return 0;
226 }
227
228 return 0;
229 }
230
231 void UpdateAI(uint32 diff) override
232 {
234 return;
235
236 events.Update(diff);
237
239 return;
240
241 while (uint32 eventId = events.ExecuteEvent())
242 {
243 switch (eventId)
244 {
248 events.Repeat(13s);
249 break;
251 me->AttackStop();
257 break;
258 case EVENT_TEMPER:
260 {
261 me->SetFacingToObject(anvil);
266 }
267 break;
268 case EVENT_HEAT:
270 events.Repeat(10s);
271 break;
277 break;
278 default:
279 break;
280 }
281
283 return;
284 }
285
287 }
288
289private:
294};
295
297{
299
300 void JustAppeared() override
301 {
303 //DoCastSelf(SPELL_STUN_SELF);
304 }
305
306 void JustEngagedWith(Unit* /*who*/) override
307 {
309 }
310
311 void EnterEvadeMode(EvadeReason why) override
312 {
314 _events.Reset();
315 }
316
317 void JustDied(Unit* /*killer*/) override
318 {
320 }
321
322 void DoAction(int32 action) override
323 {
324 switch (action)
325 {
326 case ACTION_SHATTER:
330 break;
331 default:
332 break;
333 }
334 }
335
336 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo*/) override
337 {
338 // Molten Golems cannot die from foreign damage. They will kill themselves via suicide spell when getting shattered
339 if (damage >= me->GetHealth() && attacker != me)
340 damage = me->GetHealth() - 1;
341 }
342
343 void UpdateAI(uint32 diff) override
344 {
345 if (!UpdateVictim())
346 return;
347
348 _events.Update(diff);
349
351 return;
352
353 while (uint32 eventId = _events.ExecuteEvent())
354 {
355 switch (eventId)
356 {
359 _events.Repeat(5s);
360 break;
361 default:
362 break;
363 }
364
366 return;
367 }
368
370 }
371
372private:
374};
375
376// 52654, 52238 - Temper
378{
380
381 bool Validate(SpellInfo const* /*spellInfo*/) override
382 {
384 }
385
387 {
388 Unit* target = GetHitUnit();
389 if (InstanceScript* instance = target->GetInstanceScript())
390 if (GameObject* temperVisual = instance->GetGameObject(DATA_VOLKHAN_TEMPER_VISUAL))
391 temperVisual->SendCustomAnim(0);
392
394 {
395 for (uint8 i = 0; i < 2; ++i)
397
398 if (Unit* caster = GetCaster())
399 if (Creature* creatureCaster = caster->ToCreature())
400 if (CreatureAI* ai = creatureCaster->AI())
401 ai->DoAction(ACTION_GOLEMS_TEMPERED);
402 }
403 }
404
409};
410
411// 52441 - Cool Down
413{
415
416 bool Validate(SpellInfo const* /*spellInfo*/) override
417 {
419 }
420
421 void HandlePeriodicDummyEffect(AuraEffect const* /*aurEff*/)
422 {
423 Unit* target = GetTarget();
424 if (target->GetHealthPct() > 1.f)
425 {
426 // This damage part feels weird but there is no trace of spells in sniffs that could do such thing otherwise.
427 Unit::DealDamage(target, target, CalculatePct(target->GetMaxHealth(), target->GetMap()->IsHeroic() ? 1 : 2));
428 int32 bp = 0 - static_cast<int32>(100.f - target->GetHealthPct());
430 }
431 else
432 {
435 GetAura()->Remove();
436 }
437 }
438
443};
444
445// 59123 Cosmetic - Stun + Immune Permanent (Freeze Anim)
461
462// 52237, 59529 - Shattering Stomp
464{
466
468 {
469 if (Creature* caster = GetCaster()->ToCreature())
470 if (CreatureAI* ai = caster->AI())
471 ai->DoAction(ACTION_SHATTER_GOLEMS);
472 }
473
478};
479
481{
482 public:
483 achievement_shatter_resistant() : AchievementCriteriaScript("achievement_shatter_resistant") { }
484
485 bool OnCheck(Player* /*source*/, Unit* target) override
486 {
487 if (!target || !target->IsCreature())
488 return false;
489
490 if (Creature* creature = target->ToCreature())
491 if (CreatureAI* ai = creature->AI())
492 return ai->GetData(DATA_SHATTER_RESISTANT) < 5;
493
494 return false;
495 }
496};
497
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
@ POINT_MOTION_TYPE
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_MOD_STUN
#define SpellEffectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define SpellCastFn(F)
#define AuraEffectApplyFn(F, I, N, M)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
T CalculatePct(T base, U pct)
Definition Util.h:71
VolkhanTexts
@ SAY_DEATH
@ SAY_ANNOUNCE_RUN_TO_ANVIL
@ SAY_SHATTERING_STOMP
@ SAY_AGGRO
@ SAY_SLAY
@ SAY_ANNOUNCE_SHATTERING_STOMP
@ SAY_RUN_TO_ANVIL
VolkhanActions
@ ACTION_SHATTER
@ ACTION_GOLEMS_TEMPERED
@ ACTION_SHATTER_GOLEMS
VolkhanSpells
@ SPELL_SUMMON_MOLTEN_GOLEM
@ SPELL_TEMPER_DUMMY_INTRO
@ SPELL_DAZE_IMMUNITY_CANCEL
@ SPELL_TEMPER_DUMMY_COMBAT
@ SPELL_INSTAKILL_SELF
@ SPELL_COOL_DOWN
@ SPELL_COSMETIC_STUN_IMMUNE_FREEZE_AMNIM
@ SPELL_HEAT
@ SPELL_TEMPER_SUMMON_OBJECT
@ SPELL_COOL_DOWN_SLOW
@ SPELL_SHATTER
@ SPELL_IMMOLATION_STRIKE
@ SPELL_SHATTERING_STOMP
@ SPELL_STUN_SELF
void AddSC_boss_volkhan()
VolkhanMovePoints
@ POINT_ID_ANVIL
VolkhanPhases
@ PHASE_INTRO
@ PHASE_COMBAT
VolkhanEvents
@ EVENT_RUN_TO_ANVIL
@ EVENT_IMMOLATION_STRIKE
@ EVENT_HEAT
@ EVENT_SHATTERING_STOMP
@ EVENT_TEMPER_INTRO
@ EVENT_TEMPER
VolkhanMisc
@ ENTRY_BRITTLE_GOLEM
static Position const AnvilPosition
VolkhanData
@ DATA_SHATTER_RESISTANT
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
Aura * GetAura() const
Unit * GetTarget() const
virtual void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)=0
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void JustDied(Unit *) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
virtual void EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
void SetReactState(ReactStates st)
Definition Creature.h:119
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:236
void CancelEvent(EventId eventId)
Definition EventMap.cpp:151
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:28
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void Reset()
Definition EventMap.cpp:21
Creature * GetCreature(uint32 type)
bool IsHeroic() const
Definition Map.cpp:4256
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
static Creature * ToCreature(Object *o)
Definition Object.h:186
bool IsPlayer() const
Definition Object.h:179
bool IsCreature() const
Definition Object.h:185
HookList< CastHandler > AfterCast
Unit * GetCaster() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
SpellInfo const * GetSpellInfo() const
void RemoveNotExisting()
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
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
Definition Unit.h:769
static uint32 DealDamage(Unit *attacker, Unit *victim, uint32 damage, CleanDamage const *cleanDamage=nullptr, DamageEffectType damagetype=DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *spellProto=nullptr, bool durabilityLoss=true)
Definition Unit.cpp:716
float GetHealthPct() const
Definition Unit.h:921
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
uint32 GetMaxHealth() const
Definition Unit.h:914
void SetFacingToObject(WorldObject const *object, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13259
uint32 GetHealth() const
Definition Unit.h:913
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
bool AttackStop()
Definition Unit.cpp:5645
Map * GetMap() const
Definition Object.h:449
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
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
PrepareAuraScript(spell_volkhan_cool_down)
void HandlePeriodicDummyEffect(AuraEffect const *)
bool Validate(SpellInfo const *) override
void HandleApply(AuraEffect const *, AuraEffectHandleModes)
PrepareAuraScript(spell_volkhan_cosmetic_stun_immune_permanent)
PrepareSpellScript(spell_volkhan_shattering_stomp)
bool Validate(SpellInfo const *) override
void HandleDummyEffect(SpellEffIndex)
PrepareSpellScript(spell_volkhan_temper_dummy)
#define RegisterHallsOfLightningCreatureAI(ai_name)
@ DATA_VOLKHANS_ANVIL
@ BOSS_VOLKHAN
@ DATA_VOLKHAN_TEMPER_VISUAL
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
CastSpellExtraArgs & AddSpellBP0(int32 val)
uint8 _shatteredGolemsCount
void EnterEvadeMode(EvadeReason) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *who) override
void MovementInform(uint32 motionType, uint32 id) override
void JustDied(Unit *killer) override
void JustAppeared() override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void DoAction(int32 action) override
uint32 GetData(uint32 type) const override
void KilledUnit(Unit *who) override
boss_volkhan(Creature *creature)
void EnterEvadeMode(EvadeReason why) override
void JustAppeared() override
void JustDied(Unit *) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
npc_volkhan_molten_golem(Creature *creature)
void DoAction(int32 action) override
void DamageTaken(Unit *attacker, uint32 &damage, DamageEffectType, SpellInfo const *) override