mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-16 10:30:27 +00:00
fix(Core/Dungeon) Blackrock Depths - Ambassador Flamelash (#1803)
* Boss re-order * Revert "Boss re-order" This reverts commit 03289cb064ae51c38e3efebba11f3e3882ae350a. * Reworking Ambassador flamelash - Removed timers - Scripting the boss properly, missing event and talk emote * Update boss_ambassador_flamelash.cpp * Update boss_ambassador_flamelash.cpp * Ambassador Flamelash reworked - Burning spirits spawn at the correct places - When they get close to the boss they die, thus buffing the boss with a stackable buff - When encounter begins the runes start burning - Burning Spirits chase the boss around the room * Missing aggro emote and cleanup * travis * Cleaner code Changed the enum usage to a Vector and iterated over every gameobject entry to make them active or ready. * Cleanup Removed not used enum * types * Update boss_ambassador_flamelash.cpp * Added dynamic spawning algorithm Before this commit, Spirits could be summoned on the same rune. After this commit Spirits will not be summoned on the same position. * bad null conversion * declaration and initialization inside function changed randomPosition to an Int inside the getValidRandomPosition(). * wrong type declaration variable needs to be declared outside of while cycle. * useless variable * Bugfixing - New fireblast - When burning spirits die killed by the player, new event to summon new ones - Make them aggro the player and attack them * miss typed ; * Trying to fix mentioned issues - If spirits are in combat, keep summoning new ones - If spirits are in combat, then the boss can't kill them if they get close to them * IsInCombat typo * Exploit fixing * Summoning massive waves fix * Fixing last issue hopefully
This commit is contained in:
@@ -14,6 +14,11 @@ enum FactionIds
|
||||
FACTION_FRIEND = 35
|
||||
};
|
||||
|
||||
enum BRDBosses
|
||||
{
|
||||
BOSS_AMBASSADOR_FLAMELASH = 0,
|
||||
};
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
TYPE_RING_OF_LAW = 1,
|
||||
@@ -48,7 +53,7 @@ enum DataTypes
|
||||
DATA_SF_BRAZIER_S = 26,
|
||||
DATA_MOIRA = 27,
|
||||
|
||||
DATA_OPEN_COFFER_DOORS = 30,
|
||||
DATA_OPEN_COFFER_DOORS = 30
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,12 +6,40 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "blackrock_depths.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_FIREBLAST = 15573
|
||||
// Old fireblast value 15573
|
||||
SPELL_FIREBLAST = 13342,
|
||||
SPELL_BURNING_SPIRIT = 14744,
|
||||
};
|
||||
|
||||
enum AmbassadorEvents
|
||||
{
|
||||
AGGRO_TEXT = 0,
|
||||
EVENT_SPELL_FIREBLAST = 1,
|
||||
EVENT_SUMMON_SPIRITS = 2,
|
||||
EVENT_CHASE_AMBASSADOR = 3,
|
||||
EVENT_KILL_SPIRIT = 4,
|
||||
};
|
||||
|
||||
const uint32 NPC_FIRE_SPIRIT = 9178;
|
||||
const uint32 NPC_AMBASSADOR_FLAMELASHER = 9156;
|
||||
|
||||
const Position SummonPositions[7] =
|
||||
{
|
||||
{1028.786987f, -224.787186f, -61.840500f, 3.617599f},
|
||||
{1045.144775f, -241.108292f, -61.967422f, 3.617599f},
|
||||
{1028.852905f, -257.484222f, -61.981380f, 3.617599f},
|
||||
{1012.461060f, -273.803406f, -61.994171f, 3.617599f},
|
||||
{ 995.503052f, -257.563751f, -62.013153f, 3.617599f},
|
||||
{ 979.358704f, -240.535309f, -61.983044f, 3.617599f},
|
||||
{1012.252747f, -206.696487f, -61.980618f, 3.617599f},
|
||||
};
|
||||
|
||||
vector<int> gobjectDwarfRunesEntry { 170578, 170579, 170580, 170581, 170582, 170583, 170584 };
|
||||
|
||||
class boss_ambassador_flamelash : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -19,53 +47,222 @@ public:
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new boss_ambassador_flamelashAI(creature);
|
||||
return GetInstanceAI<boss_ambassador_flamelashAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_ambassador_flamelashAI : public ScriptedAI
|
||||
struct boss_ambassador_flamelashAI : public BossAI
|
||||
{
|
||||
boss_ambassador_flamelashAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
boss_ambassador_flamelashAI(Creature* creature) : BossAI(creature, BOSS_AMBASSADOR_FLAMELASH), summons(me) { }
|
||||
|
||||
uint32 FireBlast_Timer;
|
||||
uint32 Spirit_Timer;
|
||||
EventMap _events;
|
||||
|
||||
void Reset()
|
||||
// This will help reseting the boss
|
||||
SummonList summons;
|
||||
|
||||
// This will allow to find a valid position to spawn them
|
||||
vector<int> validPosition;
|
||||
bool foundValidPosition = false;
|
||||
|
||||
void JustSummoned(Creature* cr) override { summons.Summon(cr); }
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
FireBlast_Timer = 2000;
|
||||
Spirit_Timer = 24000;
|
||||
switch (param)
|
||||
{
|
||||
case EVENT_SUMMON_SPIRITS:
|
||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, urand(12, 14)*IN_MILLISECONDS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) { }
|
||||
|
||||
void SummonSpirits(Unit* victim)
|
||||
void Reset() override
|
||||
{
|
||||
if (Creature* Spirit = DoSpawnCreature(9178, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000))
|
||||
Spirit->AI()->AttackStart(victim);
|
||||
_events.Reset();
|
||||
summons.DespawnAll();
|
||||
TurnRunes(false);
|
||||
foundValidPosition = false;
|
||||
validPosition.clear();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
void TurnRunes(bool mode)
|
||||
{
|
||||
// Active makes the runes burn, ready turns them off
|
||||
GOState state = mode ? GO_STATE_ACTIVE : GO_STATE_READY;
|
||||
|
||||
for (int RuneEntry : gobjectDwarfRunesEntry)
|
||||
if (GameObject* dwarfRune = me->FindNearestGameObject(RuneEntry, 200.0f))
|
||||
dwarfRune->SetGoState(state);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 2 * IN_MILLISECONDS);
|
||||
|
||||
// Spawn 7 Embers initially
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 4 * IN_MILLISECONDS);
|
||||
|
||||
// Activate the runes (Start burning)
|
||||
TurnRunes(true);
|
||||
|
||||
Talk(AGGRO_TEXT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
TurnRunes(false);
|
||||
_events.Reset();
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
int getValidRandomPosition()
|
||||
{
|
||||
/* Generate a random position which
|
||||
* have not been used in 4 summonings.
|
||||
* Since we are calling the event whenever the Spirit
|
||||
* dies and not all at the time, we need to save at
|
||||
* least 4 positions until reseting the vector
|
||||
*/
|
||||
|
||||
// Searching a new position so reset this bool check
|
||||
foundValidPosition = false;
|
||||
int randomPosition;
|
||||
|
||||
while (!foundValidPosition)
|
||||
{
|
||||
/* When we have summoned 4 creatures, reset the vector
|
||||
* so we can summon new spirits in other positions.*/
|
||||
if (validPosition.size() == 4)
|
||||
validPosition.clear();
|
||||
|
||||
// The random ranges from the position 0 to the position 6
|
||||
randomPosition = urand(0, 6);
|
||||
|
||||
// When we have an empty vector we can use any random position generated.
|
||||
if (validPosition.empty())
|
||||
foundValidPosition = true;
|
||||
|
||||
/* This check is done to avoid running the vector
|
||||
* when it is empty. Because if it is empty, then any
|
||||
* position can be used to summon Spirits.
|
||||
*/
|
||||
if (!foundValidPosition)
|
||||
{
|
||||
// Check every position inside the vector
|
||||
for (int pos : validPosition)
|
||||
{
|
||||
// If the random is different, we found a temporary true,
|
||||
// until we find one that is equal, which means it has been used.
|
||||
if (pos != randomPosition)
|
||||
foundValidPosition = true;
|
||||
else
|
||||
{
|
||||
foundValidPosition = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We found a valid position. Save it and return it to summon.
|
||||
validPosition.emplace_back(randomPosition);
|
||||
return randomPosition;
|
||||
}
|
||||
|
||||
void SummonSpirits()
|
||||
{
|
||||
// Make the Spirits chase Ambassador Flamelash
|
||||
if (Creature* Spirit = me->SummonCreature(NPC_FIRE_SPIRIT, SummonPositions[getValidRandomPosition()], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000))
|
||||
Spirit->AI()->DoAction(EVENT_CHASE_AMBASSADOR);
|
||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, urand(12, 14) * IN_MILLISECONDS);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
//FireBlast_Timer
|
||||
if (FireBlast_Timer <= diff)
|
||||
switch(_events.ExecuteEvent())
|
||||
{
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
FireBlast_Timer = 7000;
|
||||
} else FireBlast_Timer -= diff;
|
||||
case EVENT_SPELL_FIREBLAST:
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
_events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 7 * IN_MILLISECONDS);
|
||||
break;
|
||||
case EVENT_SUMMON_SPIRITS:
|
||||
SummonSpirits();
|
||||
break;
|
||||
}
|
||||
|
||||
//Spirit_Timer
|
||||
if (Spirit_Timer <= diff)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class npc_burning_spirit : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_burning_spirit() : CreatureScript("npc_burning_spirit") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<npc_burning_spiritAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_burning_spiritAI : public CreatureAI
|
||||
{
|
||||
npc_burning_spiritAI(Creature* creature) : CreatureAI(creature) { }
|
||||
|
||||
EventMap _events;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
// TODO: Swap this with an execute event
|
||||
_events.ScheduleEvent(EVENT_CHASE_AMBASSADOR, 1);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
switch (param)
|
||||
{
|
||||
SummonSpirits(me->GetVictim());
|
||||
SummonSpirits(me->GetVictim());
|
||||
SummonSpirits(me->GetVictim());
|
||||
SummonSpirits(me->GetVictim());
|
||||
case EVENT_CHASE_AMBASSADOR:
|
||||
// TODO: Swap this with an execute event
|
||||
_events.ScheduleEvent(EVENT_CHASE_AMBASSADOR, 0.1f * IN_MILLISECONDS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Spirit_Timer = 30000;
|
||||
} else Spirit_Timer -= diff;
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
switch(_events.ExecuteEvent())
|
||||
{
|
||||
// Don't need to repeat this events because, once new spirits are summoned
|
||||
// those new spirits will summon new spirits. If we repeated we would have
|
||||
// an inmense number of spirits summoned if they were not all killed
|
||||
case EVENT_CHASE_AMBASSADOR:
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (Creature* boss = me->FindNearestCreature(NPC_AMBASSADOR_FLAMELASHER, 5000.0f, true))
|
||||
{
|
||||
if (me->GetDistance(boss->GetPosition()) <= 5.0f)
|
||||
{
|
||||
boss->CastSpell(boss, SPELL_BURNING_SPIRIT);
|
||||
boss->Kill(boss, me);
|
||||
}
|
||||
|
||||
if (me->IsAlive())
|
||||
me->GetMotionMaster()->MoveChase(boss);
|
||||
_events.ScheduleEvent(EVENT_CHASE_AMBASSADOR, 0.5f * IN_MILLISECONDS);
|
||||
}
|
||||
}
|
||||
else
|
||||
_events.ScheduleEvent(EVENT_CHASE_AMBASSADOR, 0.5f * IN_MILLISECONDS);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
@@ -75,4 +272,5 @@ public:
|
||||
void AddSC_boss_ambassador_flamelash()
|
||||
{
|
||||
new boss_ambassador_flamelash();
|
||||
new npc_burning_spirit();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ enum GameObjects
|
||||
GO_GOLEM_ROOM_S = 170574, // Magmus door Soutsh
|
||||
GO_THRONE_ROOM = 170575, // Throne door
|
||||
GO_SPECTRAL_CHALICE = 164869,
|
||||
GO_CHEST_SEVEN = 169243
|
||||
GO_CHEST_SEVEN = 169243,
|
||||
};
|
||||
|
||||
class instance_blackrock_depths : public InstanceMapScript
|
||||
@@ -212,13 +212,13 @@ public:
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_EVENSTARTER:
|
||||
TombEventStarterGUID = data;
|
||||
if (!TombEventStarterGUID)
|
||||
TombOfSevenReset();//reset
|
||||
else
|
||||
TombOfSevenStart();//start
|
||||
break;
|
||||
case DATA_EVENSTARTER:
|
||||
TombEventStarterGUID = data;
|
||||
if (!TombEventStarterGUID)
|
||||
TombOfSevenReset();//reset
|
||||
else
|
||||
TombOfSevenStart();//start
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,39 +230,39 @@ public:
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_RING_OF_LAW:
|
||||
encounter[0] = data;
|
||||
break;
|
||||
case TYPE_VAULT:
|
||||
encounter[1] = data;
|
||||
break;
|
||||
case TYPE_BAR:
|
||||
if (data == SPECIAL)
|
||||
++BarAleCount;
|
||||
else
|
||||
encounter[2] = data;
|
||||
break;
|
||||
case TYPE_TOMB_OF_SEVEN:
|
||||
encounter[3] = data;
|
||||
break;
|
||||
case TYPE_LYCEUM:
|
||||
encounter[4] = data;
|
||||
break;
|
||||
case TYPE_IRON_HALL:
|
||||
encounter[5] = data;
|
||||
break;
|
||||
case DATA_GHOSTKILL:
|
||||
GhostKillCount += data;
|
||||
break;
|
||||
case DATA_OPEN_COFFER_DOORS:
|
||||
OpenedCoofers += 1;
|
||||
if (OpenedCoofers == 12)
|
||||
{
|
||||
Position pos = {812.15f, -348.91f, -50.579f, 0.7f};
|
||||
if (TempSummon* summon = instance->SummonCreature(NPC_WATCHMAN_DOOMGRIP, pos))
|
||||
summon->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN);
|
||||
}
|
||||
break;
|
||||
case TYPE_RING_OF_LAW:
|
||||
encounter[0] = data;
|
||||
break;
|
||||
case TYPE_VAULT:
|
||||
encounter[1] = data;
|
||||
break;
|
||||
case TYPE_BAR:
|
||||
if (data == SPECIAL)
|
||||
++BarAleCount;
|
||||
else
|
||||
encounter[2] = data;
|
||||
break;
|
||||
case TYPE_TOMB_OF_SEVEN:
|
||||
encounter[3] = data;
|
||||
break;
|
||||
case TYPE_LYCEUM:
|
||||
encounter[4] = data;
|
||||
break;
|
||||
case TYPE_IRON_HALL:
|
||||
encounter[5] = data;
|
||||
break;
|
||||
case DATA_GHOSTKILL:
|
||||
GhostKillCount += data;
|
||||
break;
|
||||
case DATA_OPEN_COFFER_DOORS:
|
||||
OpenedCoofers += 1;
|
||||
if (OpenedCoofers == 12)
|
||||
{
|
||||
Position pos = {812.15f, -348.91f, -50.579f, 0.7f};
|
||||
if (TempSummon* summon = instance->SummonCreature(NPC_WATCHMAN_DOOMGRIP, pos))
|
||||
summon->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (data == DONE || GhostKillCount >= 7)
|
||||
|
||||
Reference in New Issue
Block a user