Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_herald_volazj.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/*
7 * Comment: Missing AI for Twisted Visages
8 */
9
10#include "ScriptMgr.h"
11#include "ScriptedCreature.h"
12#include "ahnkahet.h"
13#include "Player.h"
14#include "SpellInfo.h"
15
31
33{
38};
39
44
46{
47public:
48 boss_volazj() : CreatureScript("boss_volazj") { }
49
50 struct boss_volazjAI : public ScriptedAI
51 {
52 boss_volazjAI(Creature* creature) : ScriptedAI(creature), Summons(me)
53 {
54 instance = creature->GetInstanceScript();
55 }
56
58
64
65 // returns the percentage of health after taking the given damage.
67 {
68 if (damage > me->GetHealth())
69 return 0;
70 return 100*(me->GetHealth()-damage)/me->GetMaxHealth();
71 }
72
73 void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) OVERRIDE
74 {
76 damage = 0;
77
78 if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)||
79 (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33))
80 {
81 me->InterruptNonMeleeSpells(false);
82 DoCast(me, SPELL_INSANITY, false);
83 }
84 }
85
86 void SpellHitTarget(Unit* target, const SpellInfo* spell) OVERRIDE
87 {
88 if (spell->Id == SPELL_INSANITY)
89 {
90 // Not good target or too many players
91 if (target->GetTypeId() != TypeID::TYPEID_PLAYER || insanityHandled > 4)
92 return;
93 // First target - start channel visual and set self as unnattackable
94 if (!insanityHandled)
95 {
96 // Channel visual
98 // Unattackable
100 me->SetControlled(true, UNIT_STATE_STUNNED);
101 }
102 // phase mask
103 target->CastSpell(target, SPELL_INSANITY_TARGET+insanityHandled, true);
104 // summon twisted party members for this target
105 Map::PlayerList const &players = me->GetMap()->GetPlayers();
106 for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
107 {
108 Player* player = i->GetSource();
109 if (!player || !player->IsAlive())
110 continue;
111 // Summon clone
112 if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 0))
113 {
114 // clone
115 player->CastSpell(summon, SPELL_CLONE_PLAYER, true);
116 // set phase
117 summon->SetPhaseMask((1<<(4+insanityHandled)), true);
118 }
119 }
121 }
122 }
123
125 {
126 Map::PlayerList const &players = me->GetMap()->GetPlayers();
127 for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
128 {
129 Player* player = i->GetSource();
131 }
132 }
133
135 {
139
140 if (instance)
141 {
144 }
145
146 // Visible for all players in insanity
147 me->SetPhaseMask((1|16|32|64|128|256), true);
148 // Used for Insanity handling
149 insanityHandled = 0;
150
152
153 // Cleanup
154 Summons.DespawnAll();
156 me->SetControlled(false, UNIT_STATE_STUNNED);
157 }
158
159 void EnterCombat(Unit* /*who*/) OVERRIDE
160 {
162
163 if (instance)
164 {
167 }
168 }
169
171 {
172 Summons.Summon(summon);
173 }
174
176 {
177 uint32 spell = 0;
178 switch (phase)
179 {
180 case 16:
182 break;
183 case 32:
185 break;
186 case 64:
188 break;
189 case 128:
191 break;
192 case 256:
194 break;
195 }
196 return spell;
197 }
198
200 {
201 uint32 phase = summon->GetPhaseMask();
202 uint32 nextPhase = 0;
203 Summons.Despawn(summon);
204
205 // Check if all summons in this phase killed
206 for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter)
207 {
208 if (Creature* visage = Unit::GetCreature(*me, *iter))
209 {
210 // Not all are dead
211 if (phase == visage->GetPhaseMask())
212 return;
213 else
214 nextPhase = visage->GetPhaseMask();
215 }
216 }
217
218 // Roll Insanity
219 uint32 spell = GetSpellForPhaseMask(phase);
220 uint32 spell2 = GetSpellForPhaseMask(nextPhase);
221 Map* map = me->GetMap();
222 if (!map)
223 return;
224
225 Map::PlayerList const &PlayerList = map->GetPlayers();
226 if (!PlayerList.isEmpty())
227 {
228 for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
229 {
230 if (Player* player = i->GetSource())
231 {
232 if (player->HasAura(spell))
233 {
234 player->RemoveAurasDueToSpell(spell);
235 if (spell2) // if there is still some different mask cast spell for it
236 player->CastSpell(player, spell2, true);
237 }
238 }
239 }
240 }
241 }
242
244 {
245 //Return since we have no target
246 if (!UpdateVictim())
247 return;
248
249 if (insanityHandled)
250 {
251 if (!Summons.empty())
252 return;
253
254 insanityHandled = 0;
256 me->SetControlled(false, UNIT_STATE_STUNNED);
257 me->RemoveAurasDueToSpell(INSANITY_VISUAL);
258 }
259
260 if (uiMindFlayTimer <= diff)
261 {
264 } else uiMindFlayTimer -= diff;
265
266 if (uiShadowBoltVolleyTimer <= diff)
267 {
270 } else uiShadowBoltVolleyTimer -= diff;
271
272 if (uiShiverTimer <= diff)
273 {
274 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
275 DoCast(target, SPELL_SHIVER);
277 } else uiShiverTimer -= diff;
278
280 }
281
282 void JustDied(Unit* /*killer*/) OVERRIDE
283 {
285
286 if (instance)
287 instance->SetBossState(DATA_HERALD_VOLAZJ, DONE);
288
289 Summons.DespawnAll();
291 }
292
293 void KilledUnit(Unit* /*victim*/) OVERRIDE
294 {
295 Talk(SAY_SLAY);
296 }
297 };
298
300 {
301 return new boss_volazjAI(creature);
302 }
303};
304
306{
307 new boss_volazj();
308}
@ IN_MILLISECONDS
Definition Common.h:125
@ ACHIEVEMENT_TIMED_TYPE_EVENT
Definition DBCEnums.h:158
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_CORPSE_DESPAWN
Definition Object.h:72
@ UNIT_STATE_STUNNED
Definition Unit.h:515
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
@ NPC_TWISTED_VISAGE
Definition ahnkahet.h:59
@ DATA_HERALD_VOLAZJ
Definition ahnkahet.h:20
@ SAY_SLAY
#define SAY_DEATH
#define SAY_AGGRO
@ SPELL_MIND_FLAY
void AddSC_boss_volazj()
@ SPELL_INSANITY_PHASING_1
@ SPELL_SHADOW_BOLT_VOLLEY
@ SPELL_INSANITY
@ INSANITY_VISUAL
@ SPELL_INSANITY_PHASING_5
@ SPELL_CLONE_PLAYER
@ SPELL_INSANITY_PHASING_4
@ SPELL_MIND_FLAY
@ SPELL_INSANITY_TARGET
@ SPELL_SHIVER
@ SPELL_INSANITY_PHASING_2
@ SPELL_INSANITY_PHASING_3
@ ACHIEV_QUICK_DEMISE_START_EVENT
@ SPELL_SHADOW_BOLT_VOLLEY
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
bool isEmpty() const
Definition LinkedList.h:86
Definition Map.h:238
MapRefManager PlayerList
Definition Map.h:406
PlayerList const & GetPlayers() const
Definition Map.h:407
iterator end()
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
StorageType::const_iterator const_iterator
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
bool IsAlive() const
Definition Unit.h:2032
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
uint32 GetPhaseMask() const
Definition Object.h:643
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ SAY_PHASE
Creature * me
ScriptedAI(Creature *creature)
uint32 GetHealthPct(uint32 damage)
void SummonedCreatureDespawn(Creature *summon) OVERRIDE
void JustSummoned(Creature *summon) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void KilledUnit(Unit *) OVERRIDE
uint32 GetSpellForPhaseMask(uint32 phase)
void SpellHitTarget(Unit *target, const SpellInfo *spell) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
boss_volazjAI(Creature *creature)
void DamageTaken(Unit *, uint32 &damage) OVERRIDE