Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_bloodboil.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/* ScriptData
7SDName: Boss_Bloodboil
8SD%Complete: 80
9SDComment: Bloodboil not working correctly, missing enrage
10SDCategory: Black Temple
11EndScriptData */
12
13#include "ScriptMgr.h"
14#include "ScriptedCreature.h"
15#include "black_temple.h"
16
18{
19 //Speech'n'Sound
25
26 //Spells
30 SPELL_BLOODBOIL = 42005, // This spell is AoE whereas it shouldn't be
37 SPELL_EJECT1 = 40486, // 1000 Physical damage + knockback + script effect (should handle threat reduction I think)
38 SPELL_EJECT2 = 40597, // 1000 Physical damage + Stun (used in phase 2?)
42};
43
44
45//This is used to sort the players by distance in preparation for the Bloodboil cast.
46
48{
49public:
50 boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { }
51
53 {
54 return new boss_gurtogg_bloodboilAI(creature);
55 }
56
58 {
60 {
61 instance = creature->GetInstanceScript();
62 }
63
65
67
69
80
81 bool Phase1;
82
84 {
85 if (instance)
87
88 TargetGUID = 0;
89
90 TargetThreat = 0;
91
92 BloodboilTimer = 10000;
94 AcidGeyserTimer = 1000;
95 AcidicWoundTimer = 6000;
96 ArcingSmashTimer = 19000;
97 EnrageTimer = 600000;
98 FelAcidTimer = 25000;
99 EjectTimer = 10000;
101 PhaseChangeTimer = 60000;
102
103 Phase1 = true;
104
105 me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
106 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
107 }
108
109 void EnterCombat(Unit* /*who*/) OVERRIDE
110 {
113 if (instance)
115 }
116
117 void KilledUnit(Unit* /*victim*/) OVERRIDE
118 {
119 Talk(SAY_SLAY);
120 }
121
122 void JustDied(Unit* /*killer*/) OVERRIDE
123 {
124 if (instance)
125 instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE);
126
128 }
129
130 // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited.
132 {
133 // Get the Threat List
134 std::list<HostileReference*> m_threatlist = me->getThreatManager().getThreatList();
135
136 if (m_threatlist.empty()) // He doesn't have anyone in his threatlist, useless to continue
137 return;
138
139 std::list<Unit*> targets;
140 std::list<HostileReference*>::const_iterator itr = m_threatlist.begin();
141 for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container
142 {
143 Unit* target = Unit::GetUnit(*me, (*itr)->getUnitGuid());
144 //only on alive players
145 if (target && target->IsAlive() && target->GetTypeId() == TypeID::TYPEID_PLAYER)
146 targets.push_back(target);
147 }
148
149 //Sort the list of players
150 targets.sort(Skyfire::ObjectDistanceOrderPred(me, false));
151 //Resize so we only get top 5
152 targets.resize(5);
153
154 //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp
155 /*SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_BLOODBOIL);
156 if (spellInfo)
157 {
158 for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
159 {
160 Unit* target = *itr;
161 if (!target) return;
162 for (uint32 i = 0; i<3; ++i)
163 {
164 uint8 eff = spellInfo->Effect[i];
165 if (eff >= TOTAL_SPELL_EFFECTS)
166 continue;
167
168 Aura* Aur = new Aura(spellInfo, i, target, target, target);
169 target->AddAura(Aur);
170 }
171 }
172 }*/
173 }
174
176 {
177 if (Unit* unit = Unit::GetUnit(*me, guid))
178 {
179 if (DoGetThreat(unit))
180 DoModifyThreatPercent(unit, -100);
181 if (TargetThreat)
182 me->AddThreat(unit, TargetThreat);
183 }
184 }
185
187 {
188 if (!UpdateVictim())
189 return;
190
191 if (ArcingSmashTimer <= diff)
192 {
194 ArcingSmashTimer = 10000;
195 } else ArcingSmashTimer -= diff;
196
197 if (FelAcidTimer <= diff)
198 {
200 FelAcidTimer = 25000;
201 } else FelAcidTimer -= diff;
202
203 if (!me->HasAura(SPELL_BERSERK))
204 {
205 if (EnrageTimer <= diff)
206 {
209 } else EnrageTimer -= diff;
210 }
211
212 if (Phase1)
213 {
214 if (BewilderingStrikeTimer <= diff)
215 {
217 float mt_threat = DoGetThreat(me->GetVictim());
218 if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
219 me->AddThreat(target, mt_threat);
221 } else BewilderingStrikeTimer -= diff;
222
223 if (EjectTimer <= diff)
224 {
226 DoModifyThreatPercent(me->GetVictim(), -40);
227 EjectTimer = 15000;
228 } else EjectTimer -= diff;
229
230 if (AcidicWoundTimer <= diff)
231 {
233 AcidicWoundTimer = 10000;
234 } else AcidicWoundTimer -= diff;
235
236 if (BloodboilTimer <= diff)
237 {
238 if (BloodboilCount < 5) // Only cast it five times.
239 {
240 //CastBloodboil(); // Causes issues on windows, so is commented out.
244 }
245 } else BloodboilTimer -= diff;
246 }
247
248 if (!Phase1)
249 {
250 if (AcidGeyserTimer <= diff)
251 {
253 AcidGeyserTimer = 30000;
254 } else AcidGeyserTimer -= diff;
255
256 if (EjectTimer <= diff)
257 {
259 EjectTimer = 15000;
260 } else EjectTimer -= diff;
261 }
262
263 if (PhaseChangeTimer <= diff)
264 {
265 if (Phase1)
266 {
267 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
268 {
269 Phase1 = false;
270
271 TargetThreat = DoGetThreat(target);
272 TargetGUID = target->GetGUID();
273 target->CastSpell(me, SPELL_TAUNT_GURTOGG, true);
274 if (DoGetThreat(target))
275 DoModifyThreatPercent(target, -100);
276 me->AddThreat(target, 50000000.0f);
277 me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
278 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
279 // If VMaps are disabled, this spell can call the whole instance
281 DoCast(target, SPELL_FEL_RAGE_TARGET, true);
282 DoCast(target, SPELL_FEL_RAGE_2, true);
283 /* These spells do not work, comment them out for now.
284 DoCast(target, SPELL_FEL_RAGE_2, true);
285 DoCast(target, SPELL_FEL_RAGE_3, true);*/
286
287 //Cast this without triggered so that it appears in combat logs and shows visual.
289
291
292 AcidGeyserTimer = 1000;
293 PhaseChangeTimer = 30000;
294 }
295 }
296 else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage
297 {
298 if (TargetGUID)
300 TargetGUID = 0;
301 Phase1 = true;
302 BloodboilTimer = 10000;
303 BloodboilCount = 0;
304 AcidicWoundTimer += 2000;
305 ArcingSmashTimer += 2000;
306 FelAcidTimer += 2000;
307 EjectTimer += 2000;
308 PhaseChangeTimer = 60000;
309 me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
310 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
311 }
312 } else PhaseChangeTimer -= diff;
313
315 }
316 };
317};
318
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TYPEID_PLAYER
Definition Object.h:55
@ SPELL_EFFECT_ATTACK_ME
@ IMMUNITY_STATE
@ IMMUNITY_EFFECT
@ SPELL_AURA_MOD_TAUNT
@ SELECT_TARGET_TOPAGGRO
Definition UnitAI.h:24
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ DATA_GURTOGG_BLOODBOIL
@ SAY_SLAY
Bloodboil
@ SAY_DEATH
@ SPELL_BLOODBOIL
@ SPELL_FEL_RAGE_2
@ SPELL_ACIDIC_WOUND
@ SPELL_FEL_RAGE_TARGET
@ SPELL_BEWILDERING_STRIKE
@ SAY_AGGRO
@ SPELL_FEL_RAGE_3
@ SAY_SPECIAL
@ SAY_SLAY
@ SPELL_ARCING_SMASH
@ SPELL_FEL_ACID
@ SPELL_TAUNT_GURTOGG
@ SAY_ENRAGE
@ SPELL_INSIGNIFIGANCE
@ SPELL_BERSERK
@ SPELL_ACID_GEYSER
@ SPELL_EJECT2
@ SPELL_EJECT1
@ SPELL_FEL_RAGE_SELF
void AddSC_boss_gurtogg_bloodboil()
#define SAY_DEATH
#define SAY_AGGRO
@ SAY_ENRAGE
#define SPELL_BERSERK
@ SPELL_ARCING_SMASH
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
TypeID GetTypeId() const
Definition Object.h:131
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
bool IsAlive() const
Definition Unit.h:2032
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
CreatureAI * GetAI(Creature *creature) const OVERRIDE
Creature * me
float DoGetThreat(Unit *unit)
ScriptedAI(Creature *creature)
void DoModifyThreatPercent(Unit *unit, int32 pct)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================