Scripts/FoS: improved bronjahm encounter, thanks @Grimton1337, @tkrokli

Closes #14130

(cherry picked from commit 6dfc35d13c)
This commit is contained in:
joschiwald
2015-02-13 21:15:30 +01:00
parent 2b60b7e07d
commit e8c7d47641
4 changed files with 124 additions and 147 deletions

View File

@@ -27,7 +27,7 @@ enum Yells
SAY_SLAY = 1,
SAY_DEATH = 2,
SAY_SOUL_STORM = 3,
SAY_CORRUPT_SOUL = 4,
SAY_CORRUPT_SOUL = 4
};
enum Spells
@@ -39,9 +39,9 @@ enum Spells
SPELL_TELEPORT = 68988,
SPELL_FEAR = 68950,
SPELL_SOULSTORM = 68872,
SPELL_SOULSTORM_CHANNEL = 69008, // pre-fight
SPELL_SOULSTORM_VISUAL = 68870, // pre-cast soulstorm
SPELL_PURPLE_BANISH_VISUAL = 68862 // Used by Soul Fragment (Aura)
SPELL_SOULSTORM_CHANNEL = 69008, // Pre-fight
SPELL_SOULSTORM_VISUAL = 68870, // Pre-cast Soulstorm
SPELL_PURPLE_BANISH_VISUAL = 68862 // Used by Soul Fragment (Aura)
};
enum Events
@@ -50,7 +50,7 @@ enum Events
EVENT_SHADOW_BOLT = 2,
EVENT_CORRUPT_SOUL = 3,
EVENT_SOULSTORM = 4,
EVENT_FEAR = 5,
EVENT_FEAR = 5
};
enum CombatPhases
@@ -59,6 +59,11 @@ enum CombatPhases
PHASE_2 = 2
};
enum Misc
{
DATA_SOUL_POWER = 1
};
class boss_bronjahm : public CreatureScript
{
public:
@@ -73,33 +78,30 @@ class boss_bronjahm : public CreatureScript
void Reset() override
{
events.Reset();
_Reset();
events.SetPhase(PHASE_1);
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000);
events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 20000));
events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000, 35000), 0, PHASE_1);
instance->SetBossState(DATA_BRONJAHM, NOT_STARTED);
}
void JustReachedHome() override
{
_JustReachedHome();
DoCast(me, SPELL_SOULSTORM_CHANNEL, true);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
me->RemoveAurasDueToSpell(SPELL_SOULSTORM_CHANNEL);
instance->SetBossState(DATA_BRONJAHM, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
instance->SetBossState(DATA_BRONJAHM, DONE);
}
void KilledUnit(Unit* who) override
@@ -128,6 +130,23 @@ class boss_bronjahm : public CreatureScript
summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true);
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_SOUL_POWER)
{
uint32 count = 0;
for (ObjectGuid const& guid : summons)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
if (summon->GetEntry() == NPC_CORRUPTED_SOUL_FRAGMENT && summon->IsAlive())
++count;
}
return count;
}
return 0;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -143,13 +162,21 @@ class boss_bronjahm : public CreatureScript
switch (eventId)
{
case EVENT_MAGIC_BANE:
DoCastVictim(SPELL_MAGIC_S_BANE);
DoCastAOE(SPELL_MAGIC_S_BANE);
events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 20000));
break;
case EVENT_SHADOW_BOLT:
if (!me->IsWithinMeleeRange(me->GetVictim()))
if (events.IsInPhase(PHASE_2))
{
DoCastVictim(SPELL_SHADOW_BOLT);
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000);
events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(1, 2) * IN_MILLISECONDS);
}
else
{
if (!me->IsWithinMeleeRange(me->GetVictim()))
DoCastVictim(SPELL_SHADOW_BOLT);
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2 * IN_MILLISECONDS);
}
break;
case EVENT_CORRUPT_SOUL:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
@@ -165,8 +192,7 @@ class boss_bronjahm : public CreatureScript
me->CastSpell(me, SPELL_SOULSTORM, false);
break;
case EVENT_FEAR:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
me->CastCustomSpell(SPELL_FEAR, SPELLVALUE_MAX_TARGETS, 1, target, false);
me->CastCustomSpell(SPELL_FEAR, SPELLVALUE_MAX_TARGETS, 1, nullptr, false);
events.ScheduleEvent(EVENT_FEAR, urand(8000, 12000), 0, PHASE_2);
break;
default:
@@ -174,7 +200,8 @@ class boss_bronjahm : public CreatureScript
}
}
DoMeleeAttackIfReady();
if (!events.IsInPhase(PHASE_2))
DoMeleeAttackIfReady();
}
};
@@ -201,17 +228,11 @@ class npc_corrupted_soul_fragment : public CreatureScript
if (type != CHASE_MOTION_TYPE)
return;
if (TempSummon* summ = me->ToTempSummon())
{
ObjectGuid BronjahmGUID(instance->GetGuidData(DATA_BRONJAHM));
if (BronjahmGUID.GetCounter() != id)
return;
if (instance->GetGuidData(DATA_BRONJAHM).GetCounter() != id)
return;
if (Creature* bronjahm = ObjectAccessor::GetCreature(*me, BronjahmGUID))
me->CastSpell(bronjahm, SPELL_CONSUME_SOUL, true);
summ->UnSummon();
}
me->CastSpell((Unit*)nullptr, SPELL_CONSUME_SOUL, true);
me->DespawnOrUnsummon();
}
private:
@@ -220,7 +241,7 @@ class npc_corrupted_soul_fragment : public CreatureScript
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_corrupted_soul_fragmentAI>(creature);
return GetInstanceAI<npc_corrupted_soul_fragmentAI>(creature, FoSScriptName);
}
};
@@ -238,12 +259,10 @@ class spell_bronjahm_magic_bane : public SpellScriptLoader
if (GetHitUnit()->getPowerType() != POWER_MANA)
return;
const int32 maxDamage = GetCaster()->GetMap()->GetSpawnMode() == 1 ? 15000 : 10000;
int32 newDamage = GetHitDamage();
newDamage += GetHitUnit()->GetMaxPower(POWER_MANA)/2;
newDamage = std::min<int32>(maxDamage, newDamage);
int32 const maxDamage = GetCaster()->GetMap()->IsHeroic() ? 15000 : 10000;
int32 newDamage = GetHitDamage() + (GetHitUnit()->GetMaxPower(POWER_MANA) / 2);
SetHitDamage(newDamage);
SetHitDamage(std::min<int32>(maxDamage, newDamage));
}
void Register() override
@@ -261,7 +280,7 @@ class spell_bronjahm_magic_bane : public SpellScriptLoader
class spell_bronjahm_consume_soul : public SpellScriptLoader
{
public:
spell_bronjahm_consume_soul() : SpellScriptLoader("spell_bronjahm_consume_soul") { }
spell_bronjahm_consume_soul() : SpellScriptLoader("spell_bronjahm_consume_soul") { }
class spell_bronjahm_consume_soul_SpellScript : public SpellScript
{
@@ -285,38 +304,22 @@ class spell_bronjahm_consume_soul : public SpellScriptLoader
}
};
class spell_bronjahm_soulstorm_channel : public SpellScriptLoader
static uint32 const SoulstormVisualSpells[] =
{
public:
spell_bronjahm_soulstorm_channel() : SpellScriptLoader("spell_bronjahm_soulstorm_channel") { }
class spell_bronjahm_soulstorm_channel_AuraScript : public AuraScript
{
PrepareAuraScript(spell_bronjahm_soulstorm_channel_AuraScript);
void HandlePeriodicTick(AuraEffect const* /*aurEff*/)
{
PreventDefaultAction();
for (uint32 i = 68904; i <= 68907; ++i)
GetTarget()->CastSpell(GetTarget(), i, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_bronjahm_soulstorm_channel_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_bronjahm_soulstorm_channel_AuraScript();
}
68904,
68886,
68905,
68896,
68906,
68897,
68907,
68898
};
class spell_bronjahm_soulstorm_visual : public SpellScriptLoader
{
public:
spell_bronjahm_soulstorm_visual() : SpellScriptLoader("spell_bronjahm_soulstorm_visual") { }
spell_bronjahm_soulstorm_visual(char const* scriptName) : SpellScriptLoader(scriptName) { }
class spell_bronjahm_soulstorm_visual_AuraScript : public AuraScript
{
@@ -325,11 +328,7 @@ class spell_bronjahm_soulstorm_visual : public SpellScriptLoader
void HandlePeriodicTick(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (aurEff->GetTickNumber()%5)
return;
GetTarget()->CastSpell(GetTarget(), 68886, true);
for (uint32 i = 68896; i <= 68898; ++i)
GetTarget()->CastSpell(GetTarget(), i, true);
GetTarget()->CastSpell(GetTarget(), SoulstormVisualSpells[aurEff->GetTickNumber() % 8], true);
}
void Register() override
@@ -344,21 +343,6 @@ class spell_bronjahm_soulstorm_visual : public SpellScriptLoader
}
};
class DistanceCheck
{
public:
explicit DistanceCheck(Unit* _caster) : caster(_caster) { }
bool operator() (WorldObject* unit) const
{
if (caster->GetExactDist2d(unit) <= 10.0f)
return true;
return false;
}
Unit* caster;
};
class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader
{
public:
@@ -368,25 +352,19 @@ class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader
{
PrepareSpellScript(spell_bronjahm_soulstorm_targeting_SpellScript);
void FilterTargetsInitial(std::list<WorldObject*>& targets)
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(DistanceCheck(GetCaster()));
sharedTargets = targets;
}
// use the same target for first and second effect
void FilterTargetsSubsequent(std::list<WorldObject*>& targets)
{
targets = sharedTargets;
Unit* caster = GetCaster();
targets.remove_if([caster](WorldObject* target)
{
return caster->GetExactDist2d(target) <= 10.0f;
});
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsInitial, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
}
std::list<WorldObject*> sharedTargets;
};
SpellScript* GetSpellScript() const override
@@ -395,13 +373,25 @@ class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader
}
};
class achievement_bronjahm_soul_power : public AchievementCriteriaScript
{
public:
achievement_bronjahm_soul_power() : AchievementCriteriaScript("achievement_bronjahm_soul_power") { }
bool OnCheck(Player* /*source*/, Unit* target) override
{
return target && target->GetAI()->GetData(DATA_SOUL_POWER) >= 4;
}
};
void AddSC_boss_bronjahm()
{
new boss_bronjahm();
new npc_corrupted_soul_fragment();
new spell_bronjahm_magic_bane();
new spell_bronjahm_consume_soul();
new spell_bronjahm_soulstorm_channel();
new spell_bronjahm_soulstorm_visual();
new spell_bronjahm_soulstorm_visual("spell_bronjahm_soulstorm_channel");
new spell_bronjahm_soulstorm_visual("spell_bronjahm_soulstorm_visual");
new spell_bronjahm_soulstorm_targeting();
new achievement_bronjahm_soul_power();
}

View File

@@ -128,7 +128,7 @@ class boss_devourer_of_souls : public CreatureScript
struct boss_devourer_of_soulsAI : public BossAI
{
boss_devourer_of_soulsAI(Creature* creature) : BossAI(creature, DATA_DEVOURER_EVENT)
boss_devourer_of_soulsAI(Creature* creature) : BossAI(creature, DATA_DEVOURER_OF_SOULS)
{
Initialize();
beamAngle = 0.f;
@@ -143,20 +143,17 @@ class boss_devourer_of_souls : public CreatureScript
void Reset() override
{
_Reset();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
me->SetDisplayId(DISPLAY_ANGER);
me->SetReactState(REACT_AGGRESSIVE);
events.Reset();
summons.DespawnAll();
Initialize();
instance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_FACE_AGGRO);
if (!me->FindNearestCreature(NPC_CRUCIBLE_OF_SOULS, 60)) // Prevent double spawn
@@ -166,8 +163,6 @@ class boss_devourer_of_souls : public CreatureScript
events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000);
events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000);
events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000, 70000));
instance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS);
}
void KilledUnit(Unit* victim) override
@@ -175,7 +170,7 @@ class boss_devourer_of_souls : public CreatureScript
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
int32 textId = 0;
uint8 textId = 0;
switch (me->GetDisplayId())
{
case DISPLAY_ANGER:
@@ -197,14 +192,12 @@ class boss_devourer_of_souls : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
summons.DespawnAll();
_JustDied();
Position spawnPoint = {5618.139f, 2451.873f, 705.854f, 0};
Talk(SAY_FACE_DEATH);
instance->SetData(DATA_DEVOURER_EVENT, DONE);
int32 entryIndex;
if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
entryIndex = 0;
@@ -402,11 +395,6 @@ class spell_devourer_of_souls_mirrored_soul_proc : public SpellScriptLoader
return true;
}
bool Load() override
{
return true;
}
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
return GetCaster() && GetCaster()->IsAlive();

View File

@@ -15,38 +15,44 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEF_FORGE_OF_SOULS_H
#define DEF_FORGE_OF_SOULS_H
#ifndef FORGE_OF_SOULS_H_
#define FORGE_OF_SOULS_H_
#define FoSScriptName "instance_forge_of_souls"
#define DataHeader "FOS"
uint32 const EncounterCount = 2;
enum Data
{
DATA_BRONJAHM = 0,
DATA_DEVOURER = 1,
DATA_DEVOURER_EVENT = 2,
DATA_TEAM_IN_INSTANCE = 3,
// Encounter states and GUIDs
DATA_BRONJAHM = 0,
DATA_DEVOURER_OF_SOULS = 1,
// Additional Data
DATA_TEAM_IN_INSTANCE = 2
};
enum Creatures
{
CREATURE_BRONJAHM = 36497,
CREATURE_DEVOURER = 36502,
NPC_BRONJAHM = 36497,
NPC_DEVOURER = 36502,
NPC_CORRUPTED_SOUL_FRAGMENT = 36535,
NPC_SYLVANAS_PART1 = 37596,
NPC_SYLVANAS_PART2 = 38161,
NPC_JAINA_PART1 = 37597,
NPC_JAINA_PART2 = 38160,
NPC_KALIRA = 37583,
NPC_ELANDRA = 37774,
NPC_LORALEN = 37779,
NPC_KORELN = 37582,
NPC_CHAMPION_1_HORDE = 37584,
NPC_CHAMPION_2_HORDE = 37587,
NPC_CHAMPION_3_HORDE = 37588,
NPC_CHAMPION_1_ALLIANCE = 37496,
NPC_CHAMPION_2_ALLIANCE = 37497,
NPC_CRUCIBLE_OF_SOULS = 37094,
NPC_SYLVANAS_PART1 = 37596,
NPC_SYLVANAS_PART2 = 38161,
NPC_JAINA_PART1 = 37597,
NPC_JAINA_PART2 = 38160,
NPC_KALIRA = 37583,
NPC_ELANDRA = 37774,
NPC_LORALEN = 37779,
NPC_KORELN = 37582,
NPC_CHAMPION_1_HORDE = 37584,
NPC_CHAMPION_2_HORDE = 37587,
NPC_CHAMPION_3_HORDE = 37588,
NPC_CHAMPION_1_ALLIANCE = 37496,
NPC_CHAMPION_2_ALLIANCE = 37497,
NPC_CRUCIBLE_OF_SOULS = 37094
};
#endif
#endif // FORGE_OF_SOULS_H_

View File

@@ -20,13 +20,6 @@
#include "forge_of_souls.h"
#include "Player.h"
#define MAX_ENCOUNTER 2
/* Forge of Souls encounters:
0- Bronjahm, The Godfather of Souls
1- The Devourer of Souls
*/
class instance_forge_of_souls : public InstanceMapScript
{
public:
@@ -37,7 +30,7 @@ class instance_forge_of_souls : public InstanceMapScript
instance_forge_of_souls_InstanceScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTER);
SetBossNumber(EncounterCount);
teamInInstance = 0;
}
@@ -60,10 +53,10 @@ class instance_forge_of_souls : public InstanceMapScript
switch (creature->GetEntry())
{
case CREATURE_BRONJAHM:
case NPC_BRONJAHM:
bronjahm = creature->GetGUID();
break;
case CREATURE_DEVOURER:
case NPC_DEVOURER:
devourerOfSouls = creature->GetGUID();
break;
case NPC_SYLVANAS_PART1:
@@ -100,7 +93,7 @@ class instance_forge_of_souls : public InstanceMapScript
{
case DATA_BRONJAHM:
return bronjahm;
case DATA_DEVOURER:
case DATA_DEVOURER_OF_SOULS:
return devourerOfSouls;
default:
break;