Scripts/Firelands: Baleroc Encounter

By  Krudor
This commit is contained in:
Aokromes committed 2016-07-03 14:21:02 +02:00
1 parent b790c23d54
commit f58a2441aa
7 files changed
+1063 -1

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
--
DELETE FROM `creature` WHERE `guid` =250021;
INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`) VALUES
(250021, 53494, 720, 15, 89.9669, -62.8343, 54.9484, 3.16296, 7200);
DELETE FROM `achievement_criteria_data` WHERE `criteria_id` = 17577;
INSERT INTO `achievement_criteria_data` VALUES (17577, 11, 0, 0, 'achievement_share_the_pain');
UPDATE `creature_template` SET `ScriptName`='boss_baleroc' WHERE `entry`=53494;
UPDATE `creature_template` SET `ScriptName`='npc_shard_of_torment' WHERE `entry`=53495;
DELETE FROM `creature_text` WHERE `entry`=53494;
INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(53494, 4, 2, 'Behold your weakness.', 14, 0, 100, 0, 0, 24451, 0, 0, 'Baleroc'),
(53494, 0, 0, 'You are forbidden from my master\'s domain, mortals.', 14, 0, 100, 0, 0, 24441, 0, 0, 'Baleroc'),
(53494, 1, 0, 'Fool mortals. Hurl yourselves into your own demise!', 14, 0, 100, 0, 0, 24446, 0, 0, 'Baleroc'),
(53494, 2, 0, 'Burn beneath my molten fury!', 14, 0, 100, 0, 0, 24459, 0, 0, 'Baleroc'),
(53494, 3, 0, 'By the Firelord\'s command, you, too, shall perish!', 14, 0, 100, 0, 0, 24447, 0, 0, 'Baleroc'),
(53494, 4, 0, 'None shall pass!', 14, 0, 100, 0, 0, 24452, 0, 0, 'Baleroc'),
(53494, 4, 1, 'You have been judged.', 14, 0, 100, 0, 0, 24449, 0, 0, 'Baleroc'),
(53494, 5, 0, 'Your flesh is forfeit to the fires of this realm.', 14, 0, 100, 0, 0, 24450, 0, 0, 'Baleroc'),
(53494, 7, 0, 'Mortal filth... the master\'s keep is forbidden...', 14, 0, 100, 0, 0, 24444, 0, 0, 'Baleroc'),
(53494, 6, 0, '%s goes into a berserker rage!', 16, 0, 100, 0, 0, 0, 0, 0, 'Baleroc'),
(53494, 8, 0, '|TInterface\\Icons\\inv_sword_09.blp:20|t%s readies his |cFFFF0000Inferno Blade|r!', 41, 0, 100, 0, 0, 0, 0, 0, 'Baleroc'),
(53494, 9, 0, '|TInterface\\Icons\\spell_shadow_curse:20|t%s readies his |cFF551A8BDecimation Blade|r!', 41, 0, 100, 0, 0, 0, 0, 0, 'Baleroc');
DELETE FROM `spell_script_names` WHERE `spell_id` IN (99253,99256,99259,99353,99489,99515,99516,99517,100230,100231,100232);
INSERT INTO `spell_script_names` VALUES
(99253, 'spell_baleroc_torment'),
(99256, 'spell_baleroc_tormented'),
(99259, 'spell_shards_of_torment'),
(99353, 'spell_decimating_strike'),
(99489, 'spell_baleroc_tormented_heroic'),
(99515, 'spell_countdown_p1'),
(99516, 'spell_countdown_p2'),
(99517, 'spell_countdown_p3'),
(100230, 'spell_baleroc_tormented'),
(100231, 'spell_baleroc_tormented'),
(100232, 'spell_baleroc_tormented');
+2 -1
View File
@@ -504,7 +504,8 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
// only for flyable vehicles
if (unit->IsFlying())
_me->CastSpell(unit, VEHICLE_SPELL_PARACHUTE, true);
if (_me->IsFriendlyTo(unit))
_me->CastSpell(unit, VEHICLE_SPELL_PARACHUTE, true);
if (_me->GetTypeId() == TYPEID_UNIT && _me->ToCreature()->IsAIEnabled)
_me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false);
+9
View File
@@ -3817,6 +3817,15 @@ void SpellMgr::LoadSpellInfoCorrections()
break;
// ENDOF ISLE OF CONQUEST SPELLS
//
// Firelands Spells
//
case 99256: // Torment
case 100230: //Torment
case 100231: //Torment
case 100232: //Torment
spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
break;
// End of Firelands Spells
default:
break;
}
@@ -0,0 +1,883 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
***To-do list***
***
***Implement Vital Spark - http://www.wowhead.com/spell=99262
***Implement Vital Flame - http://www.wowhead.com/spell=99263
***
***Redesign achievement data storage system
*/
#include "firelands.h"
enum Spells
{
SPELL_INFERNO_BLADE = 99350,
SPELL_INFERNO_STRIKE = 99351,
SPELL_DECIMATION_BLADE = 99352,
SPELL_DECIMATION_BLADE_2 = 99405,
SPELL_DECIMATING_STRIKE = 99353,
SPELL_BLAZE_OF_GLORY = 99252,
SPELL_INCENDIARY_SOUL = 99369,
SPELL_SHARDS_OF_TORMENT = 99259,
SPELL_SHARDS_OF_TORMENT_2 = 99260,
SPELL_TORMENT_COSMETIC_1 = 99258,
SPELL_TORMENT = 99254,
SPELL_TORMENT_PERIODIC = 99255,
SPELL_WAVE_OF_TORMENT = 99261,
SPELL_TORMENTED_20 = 99257,
SPELL_TORMENTED_30 = 99402,
SPELL_TORMENTED_40 = 99403,
SPELL_TORMENTED_60 = 99404,
SPELL_COUNTDOWN = 99515,
SPELL_COUNTDOWN_2 = 99516,
SPELL_COUNTDOWN_3 = 99517,
SPELL_COUNTDOWN_4 = 99518,
SPELL_COUNTDOWN_5 = 99519,
SPELL_BERSERK = 26662,
};
enum Events
{
EVENT_BLADE = 1,
EVENT_RESTORE_WEAPONS = 2,
EVENT_INCENDIARY_SOUL = 3,
EVENT_SHARDS_OF_TORMENT = 4,
EVENT_COUNTDOWN = 5,
EVENT_BERSERK = 6,
EVENT_SHARD_SPAWN_EFFECT = 7,
EVENT_UNLOCK_YELLSPAM = 8,
};
enum Emotes
{
EMOTE_AGGRO = 0,
EMOTE_SHARDS_OF_TORMENT = 1,
EMOTE_INFERNO_BLADE = 2,
EMOTE_DECIMATION_BLADE = 3,
EMOTE_KILL = 4,
EMOTE_ENRAGE = 5,
EMOTE_ENRAGE_2 = 6,
EMOTE_DEATH = 7,
ABILITY_INFERNO_BLADE = 8,
ABILITY_DECIMATION_BLADE = 9,
};
enum Guids
{
GUID_TORMENTED = 1,
};
enum Misc
{
EQUIP_DECIMATION_BLADE = 71082,
EQUIP_INFERNO_BLADE = 71138,
};
class boss_baleroc : public CreatureScript
{
public:
boss_baleroc() : CreatureScript("boss_baleroc") { }
struct boss_balerocAI : public BossAI
{
boss_balerocAI(Creature* creature) : BossAI(creature, DATA_BALEROC)
{
}
bool _canYellKilledPlayer;
void Reset() OVERRIDE
{
_Reset();
me->SetMaxPower(POWER_RAGE, 0);
SetEquipmentSlots(true);
me->SetCanDualWield(true);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
{
switch (spell->Id)
{
case SPELL_INFERNO_BLADE:
SetEquipmentSlots(false, EQUIP_INFERNO_BLADE, EQUIP_UNEQUIP);
me->SetCanDualWield(false);
events.ScheduleEvent(EVENT_RESTORE_WEAPONS, 15*IN_MILLISECONDS);
break;
case SPELL_DECIMATION_BLADE:
case SPELL_DECIMATION_BLADE_2:
SetEquipmentSlots(false, EQUIP_DECIMATION_BLADE, EQUIP_UNEQUIP);
me->SetCanDualWield(false);
events.ScheduleEvent(EVENT_RESTORE_WEAPONS, 15*IN_MILLISECONDS);
break;
default:
break;
}
}
void EnterCombat(Unit* target) OVERRIDE
{
_EnterCombat();
Talk(EMOTE_AGGRO);
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
events.ScheduleEvent(EVENT_INCENDIARY_SOUL, 8.5*IN_MILLISECONDS);
events.ScheduleEvent(EVENT_SHARDS_OF_TORMENT, 5*IN_MILLISECONDS);
if (me->GetMap()->IsHeroic())
events.ScheduleEvent(EVENT_COUNTDOWN, 26*IN_MILLISECONDS);
events.ScheduleEvent(EVENT_BLADE, 30.5*IN_MILLISECONDS);
events.ScheduleEvent(EVENT_BERSERK, 6*MINUTE*IN_MILLISECONDS);
//Reset our achievement list. We do this here and not in reset, as the debuff may have been spread after the boss has reset.
for (int i = 0; i < 25; i++)
{
_sharedThePain[i].player = 0;
_sharedThePain[i].tormented = 0;
}
}
void KilledUnit(Unit* who) OVERRIDE
{
if (who->GetTypeId() == TYPEID_PLAYER && _canYellKilledPlayer)
{
_canYellKilledPlayer = false;
events.ScheduleEvent(EVENT_UNLOCK_YELLSPAM, 8000);
Talk(EMOTE_KILL);
}
}
void JustDied(Unit* /*killer*/) OVERRIDE
{
_JustDied();
Talk(EMOTE_DEATH);
SetEquipmentSlots(true);
me->SetCanDualWield(true);;
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
if (Map* map = me->GetMap())
{
Map::PlayerList const &PlayerList = map->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (i->GetSource()->ToPlayer()->HasQuestForItem(69848))
{
DoCast(101093);
break;
}
}
}
void EnterEvadeMode() OVERRIDE
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLAZE_OF_GLORY);
me->GetMotionMaster()->MoveTargetedHome();
summons.DespawnAll();
_DespawnAtEvade();
}
void DoMeleeAttackIfReady() OVERRIDE
{
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
Unit* victim = me->GetVictim();
if (me->isAttackReady(BASE_ATTACK) && me->IsWithinMeleeRange(victim))
{
if (me->HasAura(SPELL_DECIMATION_BLADE) || me->HasAura(SPELL_DECIMATION_BLADE_2))
{
me->CastSpell(me->GetVictim(), SPELL_DECIMATING_STRIKE, false);
me->resetAttackTimer(BASE_ATTACK);
}
else if (me->HasAura(SPELL_INFERNO_BLADE))
{
me->CastSpell(me->GetVictim(), SPELL_INFERNO_STRIKE, false);
me->AttackerStateUpdate(victim);
me->resetAttackTimer(BASE_ATTACK);
}
else
{
me->AttackerStateUpdate(victim);
me->resetAttackTimer(BASE_ATTACK);
}
}
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK) && me->IsWithinMeleeRange(victim))
{
me->AttackerStateUpdate(victim, OFF_ATTACK);
me->resetAttackTimer(OFF_ATTACK);
}
}
void UpdateAI(uint32 diff) OVERRIDE
{
if (me->IsAlive())
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BLADE:
switch (urand(1, 2))
{
case 1:
DoCast(SPELL_INFERNO_BLADE);
Talk(EMOTE_INFERNO_BLADE);
Talk(ABILITY_INFERNO_BLADE);
break;
case 2:
DoCast(SPELL_DECIMATION_BLADE);
Talk(EMOTE_DECIMATION_BLADE);
Talk(ABILITY_DECIMATION_BLADE);
break;
}
events.ScheduleEvent(EVENT_BLADE, 47*IN_MILLISECONDS);
break;
case EVENT_RESTORE_WEAPONS:
SetEquipmentSlots(true);
me->SetCanDualWield(true);
break;
case EVENT_INCENDIARY_SOUL:
if (me->GetVictim())
{
DoCast(me->GetVictim(), SPELL_BLAZE_OF_GLORY, false);
DoCast(SPELL_INCENDIARY_SOUL);
}
events.ScheduleEvent(EVENT_INCENDIARY_SOUL, 11.5*IN_MILLISECONDS);
break;
case EVENT_SHARDS_OF_TORMENT:
Talk(EMOTE_SHARDS_OF_TORMENT);
DoCast(SPELL_SHARDS_OF_TORMENT);
events.ScheduleEvent(EVENT_SHARDS_OF_TORMENT, 34*IN_MILLISECONDS);
break;
case EVENT_COUNTDOWN:
DoCast(SPELL_COUNTDOWN);
events.ScheduleEvent(EVENT_COUNTDOWN, 48*IN_MILLISECONDS);
break;
case EVENT_BERSERK:
DoCast(SPELL_BERSERK);
Talk(EMOTE_ENRAGE);
Talk(EMOTE_ENRAGE_2);
break;
case EVENT_UNLOCK_YELLSPAM:
_canYellKilledPlayer = true;
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
void SetGUID(uint64 guid, int32 type = 0) OVERRIDE
{
switch (type)
{
case GUID_TORMENTED:
for (int i = 0; i < 25; i++)
{
if (_sharedThePain[i].player == guid)
{
_sharedThePain[i].tormented++;
break;
}
else if (_sharedThePain[i].player == 0)
{
_sharedThePain[i].player = guid;
_sharedThePain[i].tormented++;
break;
}
}
break;
default:
break;
}
}
bool SharedThePain()
{
for (int i = 0; _sharedThePain[i].player != 0; i++)
if (_sharedThePain[i].tormented > 3)
return false;
return true;
}
private:
struct _sharedThePain
{
uint64 player;
uint32 tormented;
}
_sharedThePain[25];
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
return GetFirelandsAI<boss_balerocAI>(creature);
}
};
//Used for achievements
typedef boss_baleroc::boss_balerocAI BalerocAI;
class npc_shard_of_torment : public CreatureScript
{
public:
npc_shard_of_torment() : CreatureScript("npc_shard_of_torment") { }
struct npc_shard_of_tormentAI : public ScriptedAI
{
npc_shard_of_tormentAI(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN);
me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
_instance = creature->GetInstanceScript();
}
void IsSummonedBy(Unit* summoner) OVERRIDE
{
if (summoner->GetEntry() == NPC_BALEROC)
{
if (_instance->GetBossState(DATA_BALEROC) != IN_PROGRESS)
me->DespawnOrUnsummon();
DoCast(SPELL_TORMENT_COSMETIC_1);
_events.ScheduleEvent(EVENT_SHARD_SPAWN_EFFECT, 5000);
me->SetInCombatWithZone();
_baleroc = summoner->ToCreature();
}
else
me->DespawnOrUnsummon();
}
void KilledUnit(Unit* who) OVERRIDE
{
if (who->GetTypeId() == TYPEID_PLAYER)
if (_baleroc)
_baleroc->AI()->KilledUnit(who);
}
void UpdateAI(uint32 diff)
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SHARD_SPAWN_EFFECT:
me->RemoveAurasDueToSpell(SPELL_TORMENT_COSMETIC_1);
DoCast(SPELL_TORMENT);
break;
default:
break;
}
}
}
private:
InstanceScript* _instance;
EventMap _events;
Creature* _baleroc;
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_shard_of_tormentAI(creature);
}
};
class spell_countdown_p1 : public SpellScriptLoader
{
public:
spell_countdown_p1() : SpellScriptLoader("spell_countdown_p1") { }
class spell_countdown_p1_SpellScript : public SpellScript
{
PrepareSpellScript(spell_countdown_p1_SpellScript);
bool Load()
{
return GetCaster()->GetTypeId() == TYPEID_UNIT;
}
void CastSpellLink()
{
if (target1->ToPlayer() && target2->ToPlayer())
target1->ToPlayer()->CastSpell(target2->ToPlayer(), SPELL_COUNTDOWN_5, true);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
GetCaster()->CastSpell(target, SPELL_COUNTDOWN_2, false);
}
void FilterTargets(std::list<WorldObject*>& targets)
{
//Remove current tank if we have one
if (GetCaster()->GetVictim())
targets.remove(GetCaster()->ToCreature()->GetVictim());
if (targets.size() < 2)
{
FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
return;
}
Trinity::Containers::RandomResizeList(targets, 2);
std::list<WorldObject*>::const_iterator itr = targets.begin();
target1 = (*itr);
itr++;
target2 = (*itr);
}
void Register() OVERRIDE
{
AfterCast += SpellCastFn(spell_countdown_p1_SpellScript::CastSpellLink);
OnEffectHitTarget += SpellEffectFn(spell_countdown_p1_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_countdown_p1_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
WorldObject* target1;
WorldObject* target2;
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_countdown_p1_SpellScript();
}
};
class spell_countdown_p2 : public SpellScriptLoader
{
public:
spell_countdown_p2() : SpellScriptLoader("spell_countdown_p2") { }
class spell_countdown_p2_AuraScript : public AuraScript
{
PrepareAuraScript(spell_countdown_p2_AuraScript);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
GetTarget()->CastSpell((Unit*)NULL, SPELL_COUNTDOWN_4, true);
GetTarget()->ToPlayer()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_5);
}
void Register() OVERRIDE
{
AfterEffectRemove += AuraEffectRemoveFn(spell_countdown_p2_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const OVERRIDE
{
return new spell_countdown_p2_AuraScript();
}
};
class spell_countdown_p3 : public SpellScriptLoader
{
public:
spell_countdown_p3() : SpellScriptLoader("spell_countdown_p3") { }
class spell_countdown_p3_SpellScript : public SpellScript
{
PrepareSpellScript(spell_countdown_p3_SpellScript);
bool Load()
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(Trinity::UnitAuraCheck(false, SPELL_COUNTDOWN_2));
targets.remove(GetCaster());
if (targets.empty())
return;
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
(*itr)->ToPlayer()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_2);
(*itr)->ToPlayer()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_5);
}
GetCaster()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_2);
GetCaster()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_5);
}
void Register() OVERRIDE
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_countdown_p3_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
}
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_countdown_p3_SpellScript();
}
};
class spell_decimating_strike : public SpellScriptLoader
{
public:
spell_decimating_strike() : SpellScriptLoader("spell_decimating_strike") { }
class spell_decimating_strike_SpellScript : public SpellScript
{
PrepareSpellScript(spell_decimating_strike_SpellScript);
bool Load()
{
if (GetCaster()->GetTypeId() != TYPEID_UNIT)
return false;
return true;
}
bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_DECIMATING_STRIKE))
return false;
return true;
}
void ChangeDamage()
{
if (GetCaster()->GetVictim())
{
uint32 health = GetCaster()->GetVictim()->GetMaxHealth();
if (health*0.9 < 250000)
SetHitDamage(uint32(250000));
else
SetHitDamage(uint32(health*0.9));
}
else
SetHitDamage(uint32(250000));
}
void Register()
{
OnHit += SpellHitFn(spell_decimating_strike_SpellScript::ChangeDamage);
}
};
SpellScript* GetSpellScript() const
{
return new spell_decimating_strike_SpellScript();
}
};
class spell_shards_of_torment : public SpellScriptLoader
{
public:
spell_shards_of_torment() : SpellScriptLoader("spell_shards_of_torment") { }
class spell_shards_of_torment_SpellScript : public SpellScript
{
PrepareSpellScript(spell_shards_of_torment_SpellScript);
bool Load()
{
return GetCaster()->GetTypeId() == TYPEID_UNIT;
}
void HandleScript(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
GetCaster()->CastSpell(GetHitUnit(), SPELL_SHARDS_OF_TORMENT_2, true);
}
void FilterTargets(std::list<WorldObject*>& targets)
{
uint8 numtargets;
if (GetCaster()->GetMap()->Is25ManRaid())
numtargets = 2;
else
numtargets = 1;
while(targets.size() < numtargets)
numtargets--;
if ((targets.size() > numtargets) && GetCaster()->GetVictim())
targets.remove(GetCaster()->ToCreature()->GetVictim()); //Safe to remove tank from list
Trinity::Containers::RandomResizeList(targets, numtargets);
}
void Register() OVERRIDE
{
OnEffectHitTarget += SpellEffectFn(spell_shards_of_torment_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_shards_of_torment_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_shards_of_torment_SpellScript();
}
};
class PlayerCheck
{
public:
bool operator()(WorldObject* object) const
{
if (object->GetTypeId() != TYPEID_PLAYER)
if (!object->ToPlayer()->IsAlive())
if (object->ToPlayer()->IsGameMaster())
return true;
return false;
}
};
class spell_baleroc_torment : public SpellScriptLoader
{
public:
spell_baleroc_torment() : SpellScriptLoader("spell_baleroc_torment") { }
class spell_baleroc_torment_SpellScript : public SpellScript
{
PrepareSpellScript(spell_baleroc_torment_SpellScript);
bool Load()
{
return GetCaster()->GetTypeId() == TYPEID_UNIT;
}
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(PlayerCheck());
if (targets.empty())
{
//No targets found, start pulsating immediately.
GetCaster()->ToCreature()->AI()->DoCast(SPELL_WAVE_OF_TORMENT);
return;
}
targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), true));
targets.resize(1);
if ((*targets.begin())->GetDistance2d(GetCaster()) > 15.0f)
GetCaster()->ToCreature()->AI()->DoCast(SPELL_WAVE_OF_TORMENT);
else
{
if ((*targets.begin())->ToPlayer()->GetAura(SPELL_TORMENT_PERIODIC))
if ((*targets.begin())->ToPlayer()->GetAura(SPELL_TORMENT_PERIODIC)->GetCaster() != GetCaster())
GetCaster()->CastSpell((*targets.begin())->ToPlayer(), SPELL_TORMENT_PERIODIC, false);
else{
}
else
GetCaster()->CastSpell((*targets.begin())->ToPlayer(), SPELL_TORMENT_PERIODIC, false);
}
}
void Register() OVERRIDE
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_baleroc_torment_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_baleroc_torment_SpellScript();
}
};
class spell_baleroc_tormented : public SpellScriptLoader
{
public:
spell_baleroc_tormented() : SpellScriptLoader("spell_baleroc_tormented") { }
class spell_baleroc_tormented_SpellScript : public SpellScript
{
PrepareSpellScript(spell_baleroc_tormented_SpellScript);
void ChangeDamage()
{
//SetHitDamage(GetHitDamage()*GetHitUnit()->GetAuraCount(m_scriptSpellId));
//The above example seems wrong, wowhead say the damage is 3000 per tick on normal, and 4250 on heroic,
//while logs from retail say its 4000 normal, and 5000 heroic.
if (GetHitUnit()->GetMap()->IsHeroic())
{
float damageMultiplier = 1.0f+((GetHitDamage()-4250)/4250);
SetHitDamage((5000*GetHitUnit()->GetAuraCount(m_scriptSpellId))*damageMultiplier);
}
else
{
float damageMultiplier = 1.0f+((GetHitDamage()-3000)/3000);
SetHitDamage((4000*GetHitUnit()->GetAuraCount(m_scriptSpellId))*damageMultiplier);
}
}
void Register()
{
OnHit += SpellHitFn(spell_baleroc_tormented_SpellScript::ChangeDamage);
}
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_baleroc_tormented_SpellScript();
}
class spell_baleroc_tormented_AuraScript : public AuraScript
{
PrepareAuraScript(spell_baleroc_tormented_AuraScript);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
{
if (GetTarget()->GetMap()->IsHeroic())
GetTarget()->CastSpell(GetTarget(), SPELL_TORMENTED_40, true);
else
GetTarget()->CastSpell(GetTarget(), SPELL_TORMENTED_20, true);
}
}
void Register() OVERRIDE
{
AfterEffectRemove += AuraEffectRemoveFn(spell_baleroc_tormented_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const OVERRIDE
{
return new spell_baleroc_tormented_AuraScript();
}
};
class spell_baleroc_tormented_debuff : public SpellScriptLoader
{
public:
spell_baleroc_tormented_debuff() : SpellScriptLoader("spell_baleroc_tormented_debuff") { }
class spell_baleroc_tormented_debuff_AuraScript : public AuraScript
{
PrepareAuraScript(spell_baleroc_tormented_debuff_AuraScript);
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (InstanceScript* instance = GetTarget()->GetInstanceScript())
if (Creature* baleroc = ObjectAccessor::GetCreature(*GetTarget(), instance->GetData64(DATA_BALEROC)))
baleroc->AI()->SetGUID(GetTarget()->GetGUID(), GUID_TORMENTED);
}
void Register() OVERRIDE
{
OnEffectApply += AuraEffectApplyFn(spell_baleroc_tormented_debuff_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const OVERRIDE
{
return new spell_baleroc_tormented_debuff_AuraScript();
}
};
class spell_baleroc_tormented_heroic : public SpellScriptLoader
{
public:
spell_baleroc_tormented_heroic() : SpellScriptLoader("spell_baleroc_tormented_heroic") { }
class spell_baleroc_tormented_heroic_SpellScript : public SpellScript
{
PrepareSpellScript(spell_baleroc_tormented_heroic_SpellScript);
bool Load()
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void HandleScript(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (GetCaster()->GetMap()->IsHeroic())
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_TORMENTED_40, true);
}
void Register() OVERRIDE
{
OnEffectHitTarget += SpellEffectFn(spell_baleroc_tormented_heroic_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_baleroc_tormented_heroic_SpellScript();
}
};
class achievement_share_the_pain : public AchievementCriteriaScript
{
public:
achievement_share_the_pain() : AchievementCriteriaScript("achievement_share_the_pain") { }
bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
{
if (!target)
return false;
if (BalerocAI* balerocAI = CAST_AI(BalerocAI, target->GetAI()))
return balerocAI->SharedThePain();
return false;
}
};
void AddSC_boss_baleroc()
{
new boss_baleroc();
new npc_shard_of_torment();
new spell_countdown_p1();
new spell_countdown_p2();
new spell_countdown_p3();
new spell_decimating_strike();
new spell_shards_of_torment();
new spell_baleroc_torment();
new spell_baleroc_tormented();
new spell_baleroc_tormented_heroic();
new spell_baleroc_tormented_debuff();
new achievement_share_the_pain();
};
@@ -39,6 +39,16 @@ enum DataTypes
enum CreatureIds
{
//Bosses
NPC_SHANNOX = 53691,
NPC_LORD_RHYOLITH = 52558,
NPC_BETH_TILAC = 52498,
NPC_ALYSRAZOR = 52530,
NPC_BALEROC = 53494,
NPC_MAJORDOMO_STAGHELM = 52571,
NPC_RAGNAROS = 52409,
//Alysrazor
NPC_BLAZING_MONSTROSITY_LEFT = 53786,
NPC_BLAZING_MONSTROSITY_RIGHT = 53791,
NPC_EGG_PILE = 53795,
@@ -47,6 +57,15 @@ enum CreatureIds
NPC_SMOULDERING_HATCHLING = 53794,
};
enum GameobjectIds
{
GO_LORD_RHYOLITH_BRIDGE = 209255,
GO_BETH_TILAC_DOOR = 208877,
GO_BALEROC_FIREWALL = 209066,
GO_MAJORDOMO_FIREWALL = 208906,
GO_RAGNAROS_DOOR = 209073,
};
class DelayedAttackStartEvent : public BasicEvent
{
public:
@@ -19,6 +19,16 @@
#include "InstanceScript.h"
#include "firelands.h"
DoorData const doorData[] =
{
{GO_LORD_RHYOLITH_BRIDGE, DATA_LORD_RHYOLITH, DOOR_TYPE_ROOM, BOUNDARY_E },
{GO_BETH_TILAC_DOOR, DATA_BETH_TILAC, DOOR_TYPE_ROOM, BOUNDARY_SE },
//{GO_BALEROC_FIREWALL, DATA_BALEROC, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_MAJORDOMO_FIREWALL, DATA_MAJORDOMO_STAGHELM, DOOR_TYPE_PASSAGE, BOUNDARY_N },
{GO_RAGNAROS_DOOR, DATA_RAGNAROS, DOOR_TYPE_ROOM, BOUNDARY_S },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, //END
}; //Baleroc door is special, it depends on the health status of the other bosses in the instance
class instance_firelands : public InstanceMapScript
{
public:
@@ -30,6 +40,9 @@ class instance_firelands : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
BalerocGUID = 0;
}
void OnCreatureCreate(Creature* creature) override
@@ -40,8 +53,104 @@ class instance_firelands : public InstanceMapScript
// Cannot directly start attacking here as the creature is not yet on map
creature->m_Events.AddEvent(new DelayedAttackStartEvent(creature), creature->m_Events.CalculateTime(500));
break;
case NPC_BALEROC:
BalerocGUID = creature->GetGUID();
break;
}
}
void OnGameObjectCreate(GameObject* go) OVERRIDE
{
switch(go->GetEntry())
{
case GO_LORD_RHYOLITH_BRIDGE:
case GO_BETH_TILAC_DOOR:
//case GO_BALEROC_FIREWALL:
case GO_MAJORDOMO_FIREWALL:
case GO_RAGNAROS_DOOR:
AddDoor(go, true);
break;
default:
break;
}
}
void OnGameObjectRemove(GameObject* go) OVERRIDE
{
switch (go->GetEntry())
{
case GO_LORD_RHYOLITH_BRIDGE:
case GO_BETH_TILAC_DOOR:
//case GO_BALEROC_FIREWALL:
case GO_MAJORDOMO_FIREWALL:
case GO_RAGNAROS_DOOR:
AddDoor(go, false);
break;
default:
break;
}
}
uint64 GetData64(uint32 type) const OVERRIDE
{
switch (type)
{
case DATA_BALEROC:
return BalerocGUID;
}
return 0;
}
std::string GetSaveData() OVERRIDE
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "F L " << GetBossSaveData();
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(const char* str) OVERRIDE
{
if (!str)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(str);
char dataHead1, dataHead2;
std::istringstream loadStream(str);
loadStream >> dataHead1 >> dataHead2;
if (dataHead1 == 'F' && dataHead2 == 'L')
{
for (uint32 i = 0; i < EncounterCount; ++i)
{
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
tmpState = NOT_STARTED;
SetBossState(i, EncounterState(tmpState));
}
uint32 temp = 0;
loadStream >> temp;
}
else
OUT_LOAD_INST_DATA_FAIL;
OUT_LOAD_INST_DATA_COMPLETE;
}
private:
uint64 BalerocGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -96,6 +96,7 @@ void AddSC_boss_altairus();
void AddSC_boss_asaad();
void AddSC_instance_firelands(); //Firelands
void AddSC_boss_alysrazor();
void AddSC_boss_baleroc();
void AddSC_ashenvale();
void AddSC_azshara();
@@ -201,6 +202,7 @@ void AddKalimdorScripts()
AddSC_boss_asaad();
AddSC_instance_firelands(); //Firelands
AddSC_boss_alysrazor();
AddSC_boss_baleroc();
AddSC_ashenvale();
AddSC_azshara();