TrinityCore
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
31{
32 // Volkhan
39 SAY_SLAY = 6
40};
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
60 SPELL_INSTAKILL_SELF = 29878, // Serverside spell
62};
63
64#define SPELL_SHATTER DUNGEON_MODE<uint32>(52429,59527)
65
67{
68 // Volkhan
74
75 // Molten Golem
77};
78
80{
81 // Volkhan
84
85 // Molten Golem
87};
88
90{
91 // Volkhan
94};
95
97{
98 // Volkhan
101
103{
104 ENTRY_BRITTLE_GOLEM = 28681
106
108{
111
112static Position const AnvilPosition = { 1333.5901f, -103.67797f, 56.7177f };
113
114struct boss_volkhan : public BossAI
115{
116 boss_volkhan(Creature* creature) : BossAI(creature, DATA_VOLKHAN),
118
119 void JustAppeared() override
120 {
123 }
124
125 void JustEngagedWith(Unit* who) override
126 {
128 Talk(SAY_AGGRO, who);
130 }
131
132 void EnterEvadeMode(EvadeReason /*why*/) override
133 {
136 }
137
138 void JustDied(Unit* killer) override
139 {
140 BossAI::JustDied(killer);
141 Talk(SAY_DEATH, killer);
142 }
143
144 void KilledUnit(Unit* who) override
145 {
146 if (who->IsPlayer())
147 Talk(SAY_SLAY, who);
148 }
149
150 void MovementInform(uint32 motionType, uint32 id) override
151 {
152 if (motionType != POINT_MOTION_TYPE)
153 return;
154
155 switch (id)
156 {
157 case POINT_ID_ANVIL:
159 break;
160 default:
161 break;
162 }
163 }
164
165 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo*/) override
166 {
167 if (damage >= me->GetHealth() || _shatteredGolems)
168 return;
169
171 {
174 _shatteredGolems = true;
175 return;
176 }
177
178 if (_temperCycles < 3 && me->HealthBelowPctDamaged(100.f - (20.f + 20.f * _temperCycles), damage))
179 {
180 if (!_temperingGolems)
181 {
183 _temperingGolems = true;
184 }
186 }
187
188 }
189
190 void DoAction(int32 action) override
191 {
192 switch (action)
193 {
196 for (ObjectGuid const& guid : summons)
197 {
198 if (Creature* golem = ObjectAccessor::GetCreature(*me, guid))
199 {
200 if (golem->HasAura(SPELL_COSMETIC_STUN_IMMUNE_FREEZE_AMNIM))
201 {
202 if (CreatureAI* ai = golem->AI())
203 {
204 ai->DoAction(ACTION_SHATTER);
206 }
207 }
208 }
209 }
210 break;
212 _temperingGolems = false;
213 break;
214 default:
215 break;
216 }
217 }
218
219 uint32 GetData(uint32 type) const override
220 {
221 switch (type)
222 {
225 default:
226 return 0;
227 }
228
229 return 0;
230 }
231
232 void UpdateAI(uint32 diff) override
233 {
235 return;
236
237 events.Update(diff);
238
240 return;
241
242 while (uint32 eventId = events.ExecuteEvent())
243 {
244 switch (eventId)
245 {
249 events.Repeat(13s);
250 break;
252 me->AttackStop();
258 break;
259 case EVENT_TEMPER:
261 {
262 me->SetFacingToObject(anvil);
267 }
268 break;
269 case EVENT_HEAT:
271 events.Repeat(10s);
272 break;
278 break;
279 default:
280 break;
281 }
282
284 return;
285 }
286 }
287
288private:
293};
294
296{
298
299 void JustAppeared() override
300 {
302 //DoCastSelf(SPELL_STUN_SELF);
303 }
304
305 void JustEngagedWith(Unit* /*who*/) override
306 {
308 }
309
310 void EnterEvadeMode(EvadeReason why) override
311 {
313 _events.Reset();
314 }
315
316 void JustDied(Unit* /*killer*/) override
317 {
319 }
320
321 void DoAction(int32 action) override
322 {
323 switch (action)
324 {
325 case ACTION_SHATTER:
329 break;
330 default:
331 break;
332 }
333 }
334
335 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo*/) override
336 {
337 // Molten Golems cannot die from foreign damage. They will kill themselves via suicide spell when getting shattered
338 if (damage >= me->GetHealth() && attacker != me)
339 damage = me->GetHealth() - 1;
340 }
341
342 void UpdateAI(uint32 diff) override
343 {
344 if (!UpdateVictim())
345 return;
346
347 _events.Update(diff);
348
350 return;
351
352 while (uint32 eventId = _events.ExecuteEvent())
353 {
354 switch (eventId)
355 {
358 _events.Repeat(5s);
359 break;
360 default:
361 break;
362 }
363
365 return;
366 }
367 }
368
369private:
371};
372
373// 52654, 52238 - Temper
375{
376 bool Validate(SpellInfo const* /*spellInfo*/) override
377 {
379 }
380
382 {
383 Unit* target = GetHitUnit();
384 if (InstanceScript* instance = target->GetInstanceScript())
385 if (GameObject* temperVisual = instance->GetGameObject(DATA_VOLKHAN_TEMPER_VISUAL))
386 temperVisual->SendCustomAnim(0);
387
389 {
390 for (uint8 i = 0; i < 2; ++i)
392
393 if (Unit* caster = GetCaster())
394 if (Creature* creatureCaster = caster->ToCreature())
395 if (CreatureAI* ai = creatureCaster->AI())
396 ai->DoAction(ACTION_GOLEMS_TEMPERED);
397 }
398 }
399
400 void Register() override
401 {
403 }
404};
405
406// 52441 - Cool Down
408{
409 bool Validate(SpellInfo const* /*spellInfo*/) override
410 {
412 }
413
414 void HandlePeriodicDummyEffect(AuraEffect const* /*aurEff*/)
415 {
416 Unit* target = GetTarget();
417 if (target->GetHealthPct() > 1.f)
418 {
419 // This damage part feels weird but there is no trace of spells in sniffs that could do such thing otherwise.
420 Unit::DealDamage(target, target, CalculatePct(target->GetMaxHealth(), target->GetMap()->IsHeroic() ? 1 : 2));
421 int32 bp = 0 - static_cast<int32>(100.f - target->GetHealthPct());
423 }
424 else
425 {
428 GetAura()->Remove();
429 }
430 }
431
432 void Register() override
433 {
435 }
436};
437
438// 59123 Cosmetic - Stun + Immune Permanent (Freeze Anim)
440{
441 void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
442 {
443 if (Creature* target = GetTarget()->ToCreature())
444 target->UpdateEntry(ENTRY_BRITTLE_GOLEM, nullptr, false);
445 }
446
447 void Register() override
448 {
450 }
451};
452
453// 52237, 59529 - Shattering Stomp
455{
457 {
458 if (Creature* caster = GetCaster()->ToCreature())
459 if (CreatureAI* ai = caster->AI())
460 ai->DoAction(ACTION_SHATTER_GOLEMS);
461 }
462
463 void Register() override
464 {
466 }
467};
468
470{
471 public:
472 achievement_shatter_resistant() : AchievementCriteriaScript("achievement_shatter_resistant") { }
473
474 bool OnCheck(Player* /*source*/, Unit* target) override
475 {
476 if (!target || !target->IsCreature())
477 return false;
478
479 if (Creature* creature = target->ToCreature())
480 if (CreatureAI* ai = creature->AI())
481 return ai->GetData(DATA_SHATTER_RESISTANT) < 5;
482
483 return false;
484 }
485};
486
488{
496}
Texts
Actions
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
@ POINT_MOTION_TYPE
Spells
Definition: PlayerAI.cpp:32
#define RegisterSpellScript(spell_script)
Definition: ScriptMgr.h:1369
SpellEffIndex
Definition: SharedDefines.h:29
@ EFFECT_0
Definition: SharedDefines.h:30
@ SPELL_EFFECT_DUMMY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_MOD_STUN
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
#define AuraEffectPeriodicFn(F, I, N)
Definition: SpellScript.h:2046
#define SpellCastFn(F)
Definition: SpellScript.h:825
#define AuraEffectApplyFn(F, I, N, M)
Definition: SpellScript.h:2029
EvadeReason
Definition: UnitAICommon.h:30
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_STATE_CASTING
Definition: Unit.h:270
T CalculatePct(T base, U pct)
Definition: Util.h:72
MovePoints
@ ACTION_SHATTER
@ ACTION_GOLEMS_TEMPERED
@ ACTION_SHATTER_GOLEMS
@ ENTRY_BRITTLE_GOLEM
#define SPELL_SHATTER
@ 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_IMMOLATION_STRIKE
@ SPELL_SHATTERING_STOMP
@ SPELL_STUN_SELF
@ PHASE_INTRO
@ PHASE_COMBAT
@ POINT_ID_ANVIL
void AddSC_boss_volkhan()
@ SAY_DEATH
@ SAY_ANNOUNCE_RUN_TO_ANVIL
@ SAY_SHATTERING_STOMP
@ SAY_AGGRO
@ SAY_SLAY
@ SAY_ANNOUNCE_SHATTERING_STOMP
@ SAY_RUN_TO_ANVIL
static Position const AnvilPosition
@ DATA_SHATTER_RESISTANT
@ EVENT_RUN_TO_ANVIL
@ EVENT_IMMOLATION_STRIKE
@ EVENT_HEAT
@ EVENT_SHATTERING_STOMP
@ EVENT_TEMPER_INTRO
@ EVENT_TEMPER
HookList< EffectPeriodicHandler > OnEffectPeriodic
Definition: SpellScript.h:2045
HookList< EffectApplyHandler > AfterEffectApply
Definition: SpellScript.h:2028
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
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:219
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
void SetReactState(ReactStates st)
Definition: Creature.h:160
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void Repeat(Milliseconds time)
Definition: EventMap.cpp:63
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
bool IsInPhase(uint8 phase) const
Definition: EventMap.h:217
void CancelEvent(uint32 eventId)
Definition: EventMap.cpp:131
void SetPhase(uint8 phase)
Definition: EventMap.cpp:28
void Reset()
Definition: EventMap.cpp:21
Creature * GetCreature(uint32 type)
bool IsHeroic() const
Definition: Map.cpp:3282
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={})
static Creature * ToCreature(Object *o)
Definition: Object.h:219
bool IsPlayer() const
Definition: Object.h:212
bool IsCreature() const
Definition: Object.h:218
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
HookList< CastHandler > AfterCast
Definition: SpellScript.h:824
Unit * GetCaster() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
Definition: SpellScript.h:840
SpellInfo const * GetSpellInfo() const
void RemoveNotExisting()
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:161
Definition: Unit.h:627
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:769
float GetHealthPct() const
Definition: Unit.h:784
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition: Unit.cpp:12671
uint64 GetMaxHealth() const
Definition: Unit.h:777
uint64 GetHealth() const
Definition: Unit.h:776
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:781
bool AttackStop()
Definition: Unit.cpp:5781
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
Map * GetMap() const
Definition: Object.h:624
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
bool OnCheck(Player *, Unit *target) override
void Register() override
void HandlePeriodicDummyEffect(AuraEffect const *)
bool Validate(SpellInfo const *) override
void HandleApply(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void HandleDummyEffect(SpellEffIndex)
#define RegisterHallsOfLightningCreatureAI(ai_name)
@ DATA_VOLKHANS_ANVIL
@ DATA_VOLKHAN
@ DATA_VOLKHAN_TEMPER_VISUAL
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
CastSpellExtraArgs & AddSpellBP0(int32 val)
Definition: SpellDefines.h:475
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