TrinityCore
boss_magus_telestra.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 Achievement implementation requires additional research.
20 Telestra's clones are unkillable and only executes set of actions when damaged to full health. Those actions includes cast of
21 'Telestra Clone Dies' aura which lands on boss(3 auras for 3 clones). Comments claims 'frost' clone can fail achievement due to
22 her Blizzard spell. Thing is action sets on retail cannot be started when creature casts spell(general mechanic or supported by flag or by
23 special action-check which can be used directly in action set as first action, preventing execution of next events until current cast is
24 finished. You can notice that everywhere - bosses don't enter in another phase while casting spells, for example).
25
26 But while actions clones executes surely has something related to achievement, Telestra Clone Dies auras probably aren't. The problem is those
27 auras are missiles and it may take seconds to hit boss, leaving a small chance to complete achievement. Speed of missiles is just 5 and unique
28 missile motion makes it slower. On top of that when clone dies, it can be not close enough to the boss.
29
30 That achievement is more trickier, some people claim it can be enough to kill clones only once, or it requires to kill clones twice. Or that
31 it is possible to get achievement even if she didn't summoned clones.
32 At least we can be sure auras are scripted to inform AI that all 3 clones are dead because once 3 auras are applied on boss, she casts a spell
33 which we can use later in SpellHit hook to perform merge sequence.
34
35 Currently we force clones to use SetData (in DB) to inform boss that clone is dead. And auras are used only to inform boss that
36 all clones are dead.
37 World Trigger spawned in front of boss may be related to something.
38 */
39
40#include "GameEventMgr.h"
41#include "GameTime.h"
42#include "ScriptedCreature.h"
43#include "ScriptMgr.h"
44#include "SpellInfo.h"
45#include "SpellScript.h"
46#include "nexus.h"
47
49{
54 SAY_SPLIT = 4
55};
56
58{
62
67
72
75
77};
78
80{
84
88
91};
92
93enum Misc
94{
97
99};
100
102{
104 _split1(false), _split2(false), _unkillable(false), _splitted(false)
105 {
106 Initialize();
107 }
108
110 {
111 for (uint8 n = 0; n < 3; ++n)
112 time[n] = 0;
113
115 }
116
117 void Reset() override
118 {
119 _Reset();
120 _split1 = false;
121 _split2 = false;
122 _unkillable = false;
123 _splitted = false;
124 Initialize();
125
127 me->SetUninteractible(false);
128
131 }
132
133 void JustEngagedWith(Unit* who) override
134 {
137
141 }
142
143 void AttackStart(Unit* who) override
144 {
146 }
147
148 void KilledUnit(Unit* who) override
149 {
150 if (who->GetTypeId() == TYPEID_PLAYER)
151 Talk(SAY_KILL);
152 }
153
154 void DamageTaken(Unit* /*killer*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
155 {
156 if (damage >= me->GetHealth() && _unkillable)
157 damage = me->GetHealth() - 1;
158
159 // Boss can receive damage while being already splitted, prevent performing second split if already splitted
160 if (_splitted)
161 return;
162
163 // Once in normal
164 if (!_split1 && me->HealthBelowPctDamaged(50, damage) && !IsHeroic())
165 {
166 _split1 = true;
168 }
169
170 // Twice in heroic
171 if (!_split1 && me->HealthBelowPctDamaged(65, damage) && IsHeroic())
172 {
173 _split1 = true;
175 }
176
177 if (!_split2 && me->HealthBelowPctDamaged(35, damage) && IsHeroic())
178 {
179 _split2 = true;
181 }
182 }
183
184 void OnSpellCast(SpellInfo const* spell) override
185 {
186 if (spell->Id == SPELL_SUMMON_CLONES)
188 }
189
190 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
191 {
192 if (spellInfo->Id == SPELL_TRIGGER_000)
194 }
195
196 void JustDied(Unit* /*killer*/) override
197 {
198 _JustDied();
200 }
201
202 void SetData(uint32 type, uint32 data) override
203 {
204 if (type == 0 && data == 1)
206 }
207
208 void DoAction(int32 action) override
209 {
210 if (action == ACTION_MAGUS_DEAD)
211 {
212 uint8 i = 0;
213 while (time[i] != 0)
214 ++i;
215
217 if (i == 2)
218 {
219 if ((time[2] - time[1] < 5) && (time[1] - time[0] < 5))
221
222 // Reset time
223 for (uint8 n = 0; n < 3; ++n)
224 time[n] = 0;
225 }
226 }
227 }
228
229 uint32 GetData(uint32 type) const override
230 {
231 if (type == DATA_SPLIT_PERSONALITY)
232 return splitPersonality;
233
234 return 0;
235 }
236
237 void UpdateAI(uint32 diff) override
238 {
239 if (!UpdateVictim())
240 return;
241
242 events.Update(diff);
243
245 return;
246
247 while (uint32 eventId = events.ExecuteEvent())
248 {
249 switch (eventId)
250 {
251 // Combat spells
252 case EVENT_ICE_NOVA:
254 events.Repeat(20s, 25s);
255 break;
256 case EVENT_FIREBOMB:
258 events.Repeat(1600ms, 2400ms);
259 break;
262 events.Repeat(20s, 25s);
263 break;
264
265 // Split sequence, continues in OnSpellCast
266 case EVENT_SPLIT:
267 _splitted = true;
268 // Cancel combat spells
269 events.Reset();
273 break;
274 case EVENT_SPLIT_2:
275 _unkillable = true;
276 // Hack, transform creature (from aura) has visible and invisible models and probability is NYI
277 me->SetDisplayId(15435);
278 me->SetUninteractible(true);
279 // Not restored later, maybe after wipe
282 break;
283 case EVENT_SPLIT_3:
285 break;
286
287 // Merge sequence
288 case EVENT_MERGE:
295 me->SetUninteractible(false);
296 _unkillable = false;
298 break;
299 case EVENT_MERGE_2:
304 _splitted = false;
305 break;
306 default:
307 break;
308 }
309
311 return;
312 }
313 }
314
315private:
320 time_t time[3];
322};
323
324// 47710 - Summon Telestra Clones
326{
327 bool Validate(SpellInfo const* /*spellInfo*/) override
328 {
329 return ValidateSpellInfo(
330 {
334 });
335 }
336
337 void HandleScript(SpellEffIndex /*effIndex*/)
338 {
339 Unit* caster = GetCaster();
340 caster->CastSpell(caster, SPELL_SUMMON_CLONE_FIRE);
341 caster->CastSpell(caster, SPELL_SUMMON_CLONE_ARCANE);
342 caster->CastSpell(caster, SPELL_SUMMON_CLONE_FROST);
343 }
344
345 void Register() override
346 {
348 }
349};
350
351// 47711 - Telestra Clone Dies (Fire)
352// 47712 - Telestra Clone Dies (Frost)
353// 47713 - Telestra Clone Dies (Arcane)
355{
356 bool Validate(SpellInfo const* /*spellInfo*/) override
357 {
359 }
360
361 void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
362 {
363 Unit* target = GetTarget();
365 target->CastSpell(target, SPELL_TRIGGER_000);
366 }
367
368 void Register() override
369 {
371 }
372};
373
375{
376 public:
377 achievement_split_personality() : AchievementCriteriaScript("achievement_split_personality")
378 {
379 }
380
381 bool OnCheck(Player* /*player*/, Unit* target) override
382 {
383 if (!target)
384 return false;
385
386 if (Creature* Telestra = target->ToCreature())
387 if (Telestra->AI()->GetData(DATA_SPLIT_PERSONALITY) == 2)
388 return true;
389
390 return false;
391 }
392};
393
395{
400}
Texts
@ EQUIP_UNEQUIP
Definition: CreatureAI.h:55
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define sGameEventMgr
Definition: GameEventMgr.h:177
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
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_SCRIPT_EFFECT
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
#define AuraEffectApplyFn(F, I, N, M)
Definition: SpellScript.h:2029
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_STATE_CASTING
Definition: Unit.h:270
@ DATA_SPLIT_PERSONALITY
@ GAME_EVENT_WINTER_VEIL
@ ACTION_MAGUS_DEAD
@ SPELL_SUMMON_CLONE_FROST
@ SPELL_CLONE_DIES_FIRE
@ SPELL_CLONE_DIES_FROST
@ SPELL_TELEPORT
@ SPELL_SUMMON_CLONE_FIRE
@ SPELL_CLONE_DIES_ARCANE
@ SPELL_ICE_NOVA
@ SPELL_FIREBOMB
@ SPELL_SUMMON_CLONES
@ SPELL_TRIGGER_000
@ SPELL_SUMMON_CLONE_ARCANE
@ SPELL_GRAVITY_WELL
@ SPELL_WEAR_CHRISTMAS_HAT
@ SPELL_SPAWN_BACK_IN
void AddSC_boss_magus_telestra()
@ EVENT_MERGE
@ EVENT_MERGE_2
@ EVENT_SPLIT_2
@ EVENT_GRAVITY_WELL
@ EVENT_FIREBOMB
@ EVENT_ICE_NOVA
@ EVENT_SPLIT_3
@ EVENT_SPLIT
HookList< EffectApplyHandler > AfterEffectApply
Definition: SpellScript.h:2028
Unit * GetTarget() const
void JustEngagedWith(Unit *who) override
EventMap events
void _JustDied()
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 SetDisplayId(uint32 displayId, bool setNative=false) override
Definition: Creature.cpp:3402
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
void Reset()
Definition: EventMap.cpp:21
static Creature * ToCreature(Object *o)
Definition: Object.h:219
TypeID GetTypeId() const
Definition: Object.h:173
uint32 const Id
Definition: SpellInfo.h:325
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Definition: SpellScript.h:839
void AttackStartCaster(Unit *victim, float dist)
Definition: UnitAI.cpp:55
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Definition: Unit.h:627
Aura * AddAura(uint32 spellId, Unit *target)
Definition: Unit.cpp:11618
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
uint64 GetHealth() const
Definition: Unit.h:776
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:781
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
bool OnCheck(Player *, Unit *target) override
bool Validate(SpellInfo const *) override
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
time_t GetGameTime()
Definition: GameTime.cpp:44
@ DATA_MAGUS_TELESTRA
Definition: nexus.h:31
#define RegisterNexusCreatureAI(ai_name)
Definition: nexus.h:74
bool IsHeroic() const
void SetEquipmentSlots(bool loadDefault, int32 mainHand=EQUIP_NO_CHANGE, int32 offHand=EQUIP_NO_CHANGE, int32 ranged=EQUIP_NO_CHANGE)
uint32 GetData(uint32 type) const override
void OnSpellCast(SpellInfo const *spell) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void DoAction(int32 action) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void SetData(uint32 type, uint32 data) override
void JustEngagedWith(Unit *who) override
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void JustDied(Unit *) override
boss_magus_telestra(Creature *creature)
void UpdateAI(uint32 diff) override
void KilledUnit(Unit *who) override