mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-28 12:52:25 +01:00
Scripts: dropped most post Cataclysm PvE scripts
This commit is contained in:
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_ANTORUS_THE_BURNING_THRONE_H_
|
||||
#define DEF_ANTORUS_THE_BURNING_THRONE_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "ABT"
|
||||
#define ABTScriptName "instance_antorus_the_burning_throne"
|
||||
|
||||
uint32 const EncounterCount = 10;
|
||||
|
||||
enum AntorusDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_GAROTHI_WORLDBREAKER = 0,
|
||||
DATA_FELHOUNDS_OF_SAGERAS = 1,
|
||||
DATA_ANTORAN_HIGH_COMMAND = 2,
|
||||
DATA_PORTAL_KEEPER_HASABEL = 3,
|
||||
DATA_EONAR_THE_LIFE_BINDER = 4,
|
||||
DATA_IMONAR_THE_SOULHUNTER = 5,
|
||||
DATA_KINGAROTH = 6,
|
||||
DATA_VARIMATHRAS = 7,
|
||||
DATA_THE_COVEN_OF_SHIVARRA = 8,
|
||||
DATA_AGGRAMAR = 9,
|
||||
DATA_ARGUS_THE_UNMAKER = 10,
|
||||
|
||||
// Encounter related data
|
||||
DATA_DECIMATOR,
|
||||
DATA_ANNIHILATOR
|
||||
};
|
||||
|
||||
enum AntorusCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_GAROTHI_WORLDBREAKER = 122450,
|
||||
|
||||
// Encounter related creatures
|
||||
/*Garothi Worldbreaker*/
|
||||
NPC_DECIMATOR = 122773,
|
||||
NPC_ANNIHILATOR = 122778,
|
||||
NPC_ANNIHILATION = 122818,
|
||||
NPC_GAROTHI_WORLDBREAKER = 124167
|
||||
};
|
||||
|
||||
enum AntorusGameObjectIds
|
||||
{
|
||||
GO_COLLISION = 277365,
|
||||
GO_ROCK = 278488
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetAntorusTheBurningThroneAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, ABTScriptName);
|
||||
}
|
||||
|
||||
#define RegisterAntorusTheBurningThroneCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAntorusTheBurningThroneAI)
|
||||
|
||||
#endif
|
||||
@@ -1,883 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "Containers.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "antorus_the_burning_throne.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
// Garothi Worldbreaker
|
||||
SAY_AGGRO = 0,
|
||||
SAY_DISENGAGE = 1,
|
||||
SAY_ANNOUNCE_APOCALYPSE_DRIVE = 2,
|
||||
SAY_APOCALYPSE_DRIVE = 3,
|
||||
SAY_ANNOUNCE_ERADICATION = 4,
|
||||
SAY_FINISH_APOCALYPSE_DRIVE = 5,
|
||||
SAY_DECIMATION = 6,
|
||||
SAY_ANNIHILATION = 7,
|
||||
SAY_ANNOUNCE_FEL_BOMBARDMENT = 8,
|
||||
SAY_SLAY = 9,
|
||||
SAY_DEATH = 10,
|
||||
|
||||
// Decimator
|
||||
SAY_ANNOUNCE_DECIMATION = 0
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Garothi Worldbreaker
|
||||
SPELL_MELEE = 248229,
|
||||
SPELL_APOCALYPSE_DRIVE = 244152,
|
||||
SPELL_APOCALYPSE_DRIVE_PERIODIC_DAMAGE = 253300,
|
||||
SPELL_APOCALYPSE_DRIVE_FINAL_DAMAGE = 240277,
|
||||
SPELL_ERADICATION = 244969,
|
||||
SPELL_EMPOWERED = 245237,
|
||||
SPELL_RESTORE_HEALTH = 246012,
|
||||
SPELL_ANNIHILATOR_CANNON_EJECT = 245527,
|
||||
SPELL_DECIMATOR_CANNON_EJECT = 245515,
|
||||
SPELL_FEL_BOMBARDMENT_SELECTOR = 244150,
|
||||
SPELL_FEL_BOMBARDMENT_WARNING = 246220,
|
||||
SPELL_FEL_BOMBARDMENT_DUMMY = 245219,
|
||||
SPELL_FEL_BOMBARDMENT_PERIODIC = 244536,
|
||||
SPELL_CANNON_CHOOSER = 245124,
|
||||
SPELL_SEARING_BARRAGE_ANNIHILATOR = 246368,
|
||||
SPELL_SEARING_BARRAGE_DECIMATOR = 244395,
|
||||
SPELL_SEARING_BARRAGE_DUMMY_ANNIHILATOR = 244398,
|
||||
SPELL_SEARING_BARRAGE_DUMMY_DECIMATOR = 246369,
|
||||
SPELL_SEARING_BARRAGE_SELECTOR = 246360,
|
||||
SPELL_SEARING_BARRAGE_DAMAGE_ANNIHILATOR = 244400,
|
||||
SPELL_SEARING_BARRAGE_DAMAGE_DECIMATOR = 246373,
|
||||
SPELL_CARNAGE = 244106,
|
||||
|
||||
// Decimator
|
||||
SPELL_DECIMATION_SELECTOR = 244399,
|
||||
SPELL_DECIMATION_WARNING = 244410,
|
||||
SPELL_DECIMATION_CAST_VISUAL = 245338,
|
||||
SPELL_DECIMATION_MISSILE = 244448,
|
||||
|
||||
// Annihilator
|
||||
SPELL_ANNIHILATION_SUMMON = 244790,
|
||||
SPELL_ANNIHILATION_SELECTOR = 247572,
|
||||
SPELL_ANNIHILATION_DUMMY = 244294,
|
||||
SPELL_ANNIHILATION_DAMAGE_UNSPLITTED = 244762,
|
||||
|
||||
// Annihilation
|
||||
SPELL_ANNIHILATION_AREA_TRIGGER = 244795,
|
||||
SPELL_ANNIHILATION_WARNING = 244799,
|
||||
|
||||
// Garothi Worldbreaker (Surging Fel)
|
||||
SPELL_SURGING_FEL_AREA_TRIGGER = 246655,
|
||||
SPELL_SURGING_FEL_DAMAGE = 246663
|
||||
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
// Garothi Worldbreaker
|
||||
EVENT_REENGAGE_PLAYERS = 1,
|
||||
EVENT_FEL_BOMBARDMENT,
|
||||
EVENT_SEARING_BARRAGE,
|
||||
EVENT_CANNON_CHOOSER,
|
||||
EVENT_SURGING_FEL
|
||||
};
|
||||
|
||||
enum Data
|
||||
{
|
||||
DATA_LAST_FIRED_CANNON = 0
|
||||
};
|
||||
|
||||
enum AnimKits
|
||||
{
|
||||
ANIM_KIT_ID_CANNON_DESTROYED = 13264
|
||||
};
|
||||
|
||||
constexpr uint8 MIN_TARGETS_SIZE = 2;
|
||||
constexpr uint8 MAX_TARGETS_SIZE = 6;
|
||||
|
||||
enum Misc
|
||||
{
|
||||
SUMMON_GROUP_ID_SURGING_FEL = 0
|
||||
};
|
||||
|
||||
enum EncounterFrameIndexes
|
||||
{
|
||||
ENCOUNTER_FRAME_INDEX_BOSS = 1,
|
||||
ENCOUNTER_FRAME_INDEX_CANNONS = 2
|
||||
};
|
||||
|
||||
namespace TargetHandler
|
||||
{
|
||||
class VictimCheck
|
||||
{
|
||||
public:
|
||||
VictimCheck(Unit* caster, bool keepTank) : _caster(caster), _keepTank(keepTank) { }
|
||||
|
||||
bool operator()(WorldObject* object)
|
||||
{
|
||||
Unit* unit = object->ToUnit();
|
||||
if (!unit)
|
||||
return true;
|
||||
|
||||
if (_caster->GetVictim() && _caster->GetVictim() != unit)
|
||||
return _keepTank;
|
||||
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
Unit* _caster;
|
||||
bool _keepTank; // true = remove all nontank targets | false = remove current tank
|
||||
};
|
||||
|
||||
void PreferNonTankTargetsAndResizeTargets(std::list<WorldObject*>& targets, Unit* caster)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
std::list<WorldObject*> targetsCopy = targets;
|
||||
uint8 size = targetsCopy.size();
|
||||
// Selecting our prefered target size based on total targets (min 10 player: 2, max 30 player: 6)
|
||||
uint8 preferedSize = std::min<uint8>(std::max<uint8>(std::ceil(size / 5), MIN_TARGETS_SIZE), MAX_TARGETS_SIZE);
|
||||
|
||||
// Now we get rid of the tank as these abilities prefer non-tanks above tanks as long as there are alternatives
|
||||
targetsCopy.remove_if(TargetHandler::VictimCheck(caster, false));
|
||||
|
||||
// We have less available nontank targets than we want, include tanks
|
||||
if (targetsCopy.size() < preferedSize)
|
||||
Trinity::Containers::RandomResize(targets, preferedSize);
|
||||
else
|
||||
{
|
||||
// Our target list has enough alternative targets, resize
|
||||
Trinity::Containers::RandomResize(targetsCopy, preferedSize);
|
||||
targets = targetsCopy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint32 const MaxApocalypseDriveCount = 2;
|
||||
Position const AnnihilationCenterReferencePos = { -3296.72f, 9767.78f, -60.0f };
|
||||
|
||||
struct boss_garothi_worldbreaker : public BossAI
|
||||
{
|
||||
boss_garothi_worldbreaker(Creature* creature) : BossAI(creature, DATA_GAROTHI_WORLDBREAKER),
|
||||
_apocalypseDriveCount(0), _searingBarrageSpellId(0), _lastCanonEntry(NPC_DECIMATOR), _castEradication(false)
|
||||
{
|
||||
_apocalypseDriveHealthLimit = { };
|
||||
SetCombatMovement(false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
switch (GetDifficulty())
|
||||
{
|
||||
case DIFFICULTY_MYTHIC_RAID:
|
||||
case DIFFICULTY_HEROIC_RAID:
|
||||
_apocalypseDriveHealthLimit[0] = 65;
|
||||
_apocalypseDriveHealthLimit[1] = 35;
|
||||
break;
|
||||
case DIFFICULTY_NORMAL_RAID:
|
||||
case DIFFICULTY_LFR_NEW:
|
||||
_apocalypseDriveHealthLimit[0] = 60;
|
||||
_apocalypseDriveHealthLimit[1] = 20;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
me->SummonCreatureGroup(SUMMON_GROUP_ID_SURGING_FEL);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
DoCastSelf(SPELL_MELEE);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, ENCOUNTER_FRAME_INDEX_BOSS);
|
||||
events.ScheduleEvent(EVENT_FEL_BOMBARDMENT, 9s);
|
||||
events.ScheduleEvent(EVENT_CANNON_CHOOSER, 8s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
Talk(SAY_DISENGAGE);
|
||||
_EnterEvadeMode();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
events.Reset();
|
||||
CleanupEncounter();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
Talk(SAY_SLAY, victim);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
CleanupEncounter();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
switch (spell->Id)
|
||||
{
|
||||
case SPELL_APOCALYPSE_DRIVE_FINAL_DAMAGE:
|
||||
if (_apocalypseDriveCount < MaxApocalypseDriveCount)
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_REENGAGE_PLAYERS, 3s + 500ms);
|
||||
HideCannons();
|
||||
me->SetUninteractible(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
return;
|
||||
|
||||
if (me->HealthBelowPctDamaged(_apocalypseDriveHealthLimit[_apocalypseDriveCount], damage))
|
||||
{
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->SetFacingTo(me->GetHomePosition().GetOrientation());
|
||||
events.Reset();
|
||||
|
||||
if (IsHeroic() || IsMythic())
|
||||
events.ScheduleEvent(EVENT_SURGING_FEL, 8s);
|
||||
|
||||
DoCastSelf(SPELL_APOCALYPSE_DRIVE);
|
||||
DoCastSelf(SPELL_APOCALYPSE_DRIVE_FINAL_DAMAGE);
|
||||
Talk(SAY_ANNOUNCE_APOCALYPSE_DRIVE);
|
||||
Talk(SAY_APOCALYPSE_DRIVE);
|
||||
me->SetUninteractible(true);
|
||||
|
||||
if (Creature* decimator = instance->GetCreature(DATA_DECIMATOR))
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, decimator, ENCOUNTER_FRAME_INDEX_CANNONS);
|
||||
decimator->SetUnitFlag(UNIT_FLAG_IN_COMBAT);
|
||||
decimator->SetUninteractible(false);
|
||||
}
|
||||
|
||||
if (Creature* annihilator = instance->GetCreature(DATA_ANNIHILATOR))
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, annihilator, ENCOUNTER_FRAME_INDEX_CANNONS);
|
||||
annihilator->SetUnitFlag(UNIT_FLAG_IN_COMBAT);
|
||||
annihilator->SetUninteractible(false);
|
||||
}
|
||||
++_apocalypseDriveCount;
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
switch (summon->GetEntry())
|
||||
{
|
||||
case NPC_ANNIHILATION:
|
||||
summon->CastSpell(summon, SPELL_ANNIHILATION_WARNING);
|
||||
summon->CastSpell(summon, SPELL_ANNIHILATION_AREA_TRIGGER);
|
||||
break;
|
||||
case NPC_ANNIHILATOR:
|
||||
case NPC_DECIMATOR:
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
break;
|
||||
case NPC_GAROTHI_WORLDBREAKER:
|
||||
_surgingFelDummyGuids.insert(summon->GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
switch (summon->GetEntry())
|
||||
{
|
||||
case NPC_DECIMATOR:
|
||||
case NPC_ANNIHILATOR:
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->RemoveAurasDueToSpell(SPELL_APOCALYPSE_DRIVE);
|
||||
me->SetUninteractible(false);
|
||||
|
||||
if (summon->GetEntry() == NPC_ANNIHILATOR)
|
||||
_searingBarrageSpellId = SPELL_SEARING_BARRAGE_ANNIHILATOR;
|
||||
else
|
||||
_searingBarrageSpellId = SPELL_SEARING_BARRAGE_DECIMATOR;
|
||||
|
||||
if (_apocalypseDriveCount < MaxApocalypseDriveCount)
|
||||
events.Reset();
|
||||
|
||||
events.ScheduleEvent(EVENT_SEARING_BARRAGE, 3s + 500ms);
|
||||
events.ScheduleEvent(EVENT_REENGAGE_PLAYERS, 3s + 500ms);
|
||||
_castEradication = true;
|
||||
|
||||
if (summon->GetEntry() == NPC_DECIMATOR)
|
||||
DoCastSelf(SPELL_DECIMATOR_CANNON_EJECT);
|
||||
else
|
||||
DoCastSelf(SPELL_ANNIHILATOR_CANNON_EJECT);
|
||||
|
||||
me->PlayOneShotAnimKitId(ANIM_KIT_ID_CANNON_DESTROYED);
|
||||
HideCannons();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_LAST_FIRED_CANNON)
|
||||
return _lastCanonEntry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 value) override
|
||||
{
|
||||
if (type == DATA_LAST_FIRED_CANNON)
|
||||
_lastCanonEntry = value;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) && !me->HasAura(SPELL_APOCALYPSE_DRIVE))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_REENGAGE_PLAYERS:
|
||||
DoCastSelf(SPELL_EMPOWERED);
|
||||
DoCastSelf(SPELL_RESTORE_HEALTH);
|
||||
if (_castEradication)
|
||||
{
|
||||
DoCastSelf(SPELL_ERADICATION);
|
||||
Talk(SAY_ANNOUNCE_ERADICATION);
|
||||
Talk(SAY_FINISH_APOCALYPSE_DRIVE);
|
||||
_castEradication = false;
|
||||
}
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
events.ScheduleEvent(EVENT_FEL_BOMBARDMENT, 20s);
|
||||
events.ScheduleEvent(EVENT_CANNON_CHOOSER, 18s);
|
||||
break;
|
||||
case EVENT_FEL_BOMBARDMENT:
|
||||
DoCastAOE(SPELL_FEL_BOMBARDMENT_SELECTOR);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
case EVENT_SEARING_BARRAGE:
|
||||
DoCastSelf(_searingBarrageSpellId);
|
||||
break;
|
||||
case EVENT_CANNON_CHOOSER:
|
||||
DoCastSelf(SPELL_CANNON_CHOOSER);
|
||||
events.Repeat(16s);
|
||||
break;
|
||||
case EVENT_SURGING_FEL:
|
||||
{
|
||||
GuidSet guids = _surgingFelDummyGuids;
|
||||
guids.erase(_lastSurgingFelDummyGuid);
|
||||
_lastSurgingFelDummyGuid = Trinity::Containers::SelectRandomContainerElement(guids);
|
||||
if (Creature* dummy = ObjectAccessor::GetCreature(*me, _lastSurgingFelDummyGuid))
|
||||
dummy->CastSpell(dummy, SPELL_SURGING_FEL_AREA_TRIGGER);
|
||||
|
||||
events.Repeat(8s);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->GetVictim() || !me->GetVictim()->IsWithinMeleeRange(me))
|
||||
DoSpellAttackIfReady(SPELL_CARNAGE);
|
||||
}
|
||||
private:
|
||||
std::array<uint8, MaxApocalypseDriveCount> _apocalypseDriveHealthLimit;
|
||||
uint8 _apocalypseDriveCount;
|
||||
uint32 _searingBarrageSpellId;
|
||||
uint32 _lastCanonEntry;
|
||||
bool _castEradication;
|
||||
ObjectGuid _lastSurgingFelDummyGuid;
|
||||
GuidSet _surgingFelDummyGuids;
|
||||
|
||||
void CleanupEncounter()
|
||||
{
|
||||
if (Creature* decimator = instance->GetCreature(DATA_DECIMATOR))
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, decimator);
|
||||
|
||||
if (Creature* annihilator = instance->GetCreature(DATA_ANNIHILATOR))
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, annihilator);
|
||||
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DECIMATION_WARNING);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FEL_BOMBARDMENT_WARNING);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FEL_BOMBARDMENT_PERIODIC);
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void HideCannons()
|
||||
{
|
||||
if (Creature* decimator = instance->GetCreature(DATA_DECIMATOR))
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, decimator);
|
||||
decimator->SetUninteractible(true);
|
||||
decimator->SetUnitFlag(UNIT_FLAG_IMMUNE);
|
||||
}
|
||||
|
||||
if (Creature* annihilator = instance->GetCreature(DATA_ANNIHILATOR))
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, annihilator);
|
||||
annihilator->SetUninteractible(true);
|
||||
annihilator->SetUnitFlag(UNIT_FLAG_IMMUNE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct at_garothi_annihilation : AreaTriggerAI
|
||||
{
|
||||
at_garothi_annihilation(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_playerCount = 0;
|
||||
}
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
_playerCount++;
|
||||
|
||||
if (Unit* annihilation = at->GetCaster())
|
||||
annihilation->RemoveAurasDueToSpell(SPELL_ANNIHILATION_WARNING);
|
||||
}
|
||||
|
||||
void OnUnitExit(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
_playerCount--;
|
||||
|
||||
if (!_playerCount && !at->IsRemoved())
|
||||
if (Unit* annihilation = at->GetCaster())
|
||||
annihilation->CastSpell(annihilation, SPELL_ANNIHILATION_WARNING);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _playerCount;
|
||||
};
|
||||
|
||||
class spell_garothi_apocalypse_drive : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_APOCALYPSE_DRIVE_PERIODIC_DAMAGE });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_APOCALYPSE_DRIVE_PERIODIC_DAMAGE, aurEff);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_garothi_apocalypse_drive::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_fel_bombardment_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_FEL_BOMBARDMENT_WARNING,
|
||||
SPELL_FEL_BOMBARDMENT_DUMMY
|
||||
});
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
if (Unit* caster = GetCaster())
|
||||
targets.remove_if(TargetHandler::VictimCheck(caster, true));
|
||||
}
|
||||
|
||||
void HandleWarningEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* caster = GetCaster() ? GetCaster()->ToCreature() : nullptr;
|
||||
if (!caster || !caster->IsAIEnabled())
|
||||
return;
|
||||
|
||||
Unit* target = GetHitUnit();
|
||||
caster->AI()->Talk(SAY_ANNOUNCE_FEL_BOMBARDMENT, target);
|
||||
caster->CastSpell(target, SPELL_FEL_BOMBARDMENT_WARNING, true);
|
||||
caster->CastSpell(target, SPELL_FEL_BOMBARDMENT_DUMMY, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_garothi_fel_bombardment_selector::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_fel_bombardment_selector::HandleWarningEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_fel_bombardment_warning : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FEL_BOMBARDMENT_PERIODIC });
|
||||
}
|
||||
|
||||
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetTarget(), SPELL_FEL_BOMBARDMENT_PERIODIC, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_garothi_fel_bombardment_warning::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_fel_bombardment_periodic : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetTarget(), uint32(aurEff->GetSpellEffectInfo().CalcValue(caster)), true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_garothi_fel_bombardment_periodic::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_searing_barrage_dummy : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SEARING_BARRAGE_SELECTOR });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SEARING_BARRAGE_SELECTOR, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_BASE_POINT0, GetSpellInfo()->Id));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_searing_barrage_dummy::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_searing_barrage_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_SEARING_BARRAGE_DAMAGE_ANNIHILATOR,
|
||||
SPELL_SEARING_BARRAGE_DAMAGE_DECIMATOR,
|
||||
SPELL_SEARING_BARRAGE_DUMMY_ANNIHILATOR,
|
||||
SPELL_SEARING_BARRAGE_DUMMY_DECIMATOR
|
||||
});
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
TargetHandler::PreferNonTankTargetsAndResizeTargets(targets, GetCaster());
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
uint32 spellId = GetEffectValue() == SPELL_SEARING_BARRAGE_DUMMY_ANNIHILATOR ? SPELL_SEARING_BARRAGE_DAMAGE_ANNIHILATOR : SPELL_SEARING_BARRAGE_DAMAGE_DECIMATOR;
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetHitUnit(), spellId, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_garothi_searing_barrage_selector::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_searing_barrage_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_decimation_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DECIMATION_WARNING });
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
TargetHandler::PreferNonTankTargetsAndResizeTargets(targets, GetCaster());
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
caster->CastSpell(GetHitUnit(), SPELL_DECIMATION_WARNING, true);
|
||||
if (Creature* decimator = caster->ToCreature())
|
||||
if (decimator->IsAIEnabled())
|
||||
decimator->AI()->Talk(SAY_ANNOUNCE_DECIMATION, GetHitUnit());
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_garothi_decimation_selector::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_decimation_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_decimation_warning : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DECIMATION_MISSILE });
|
||||
}
|
||||
|
||||
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
caster->CastSpell(GetTarget(), SPELL_DECIMATION_MISSILE, true);
|
||||
if (!caster->HasUnitState(UNIT_STATE_CASTING))
|
||||
caster->CastSpell(caster, SPELL_DECIMATION_CAST_VISUAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_garothi_decimation_warning::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_carnage : public AuraScript
|
||||
{
|
||||
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& /*eventInfo`*/)
|
||||
{
|
||||
// Usually we could just handle this via spell_proc but since we want
|
||||
// to silence the console message because it's not a spell trigger proc, we need a script here.
|
||||
PreventDefaultAction();
|
||||
Remove();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_garothi_carnage::HandleProc, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_annihilation_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetHitUnit(), uint32(GetEffectInfo().CalcValue(caster)), true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_annihilation_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_annihilation_triggered : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_ANNIHILATION_DAMAGE_UNSPLITTED });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* target = GetHitUnit();
|
||||
if (target->HasAura(SPELL_ANNIHILATION_WARNING))
|
||||
target->CastSpell(target, SPELL_ANNIHILATION_DAMAGE_UNSPLITTED, true);
|
||||
|
||||
target->RemoveAllAuras();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_annihilation_triggered::HandleHit, EFFECT_1, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_eradication : public SpellScript
|
||||
{
|
||||
void ChangeDamage()
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
uint32 damageReduction = CalculatePct(GetHitDamage(), GetHitUnit()->GetDistance(caster));
|
||||
SetHitDamage(GetHitDamage() - damageReduction);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_garothi_eradication::ChangeDamage);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_surging_fel : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SURGING_FEL_DAMAGE });
|
||||
}
|
||||
|
||||
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_SURGING_FEL_DAMAGE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_garothi_surging_fel::AfterRemove, EFFECT_0, SPELL_AURA_AREA_TRIGGER, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_garothi_cannon_chooser : public SpellScript
|
||||
{
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* caster = GetHitCreature();
|
||||
if (!caster || !caster->IsAIEnabled())
|
||||
return;
|
||||
|
||||
InstanceScript* instance = caster->GetInstanceScript();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
Creature* decimator = instance->GetCreature(DATA_DECIMATOR);
|
||||
Creature* annihilator = instance->GetCreature(DATA_ANNIHILATOR);
|
||||
uint32 lastCannonEntry = caster->AI()->GetData(DATA_LAST_FIRED_CANNON);
|
||||
|
||||
if ((lastCannonEntry == NPC_ANNIHILATOR && decimator) || (decimator && !annihilator))
|
||||
{
|
||||
decimator->CastSpell(decimator, SPELL_DECIMATION_SELECTOR, true);
|
||||
caster->AI()->Talk(SAY_DECIMATION, decimator);
|
||||
lastCannonEntry = NPC_DECIMATOR;
|
||||
}
|
||||
else if ((lastCannonEntry == NPC_DECIMATOR && annihilator) || (annihilator && !decimator))
|
||||
{
|
||||
uint8 count = caster->GetMap()->IsMythic() ? MAX_TARGETS_SIZE :
|
||||
std::max<uint8>(MIN_TARGETS_SIZE, std::ceil(float(caster->GetMap()->GetPlayersCountExceptGMs()) / 5));
|
||||
|
||||
for (uint8 i = 0; i < count; i++)
|
||||
{
|
||||
float x = AnnihilationCenterReferencePos.GetPositionX() + cos(frand(0.0f, float(M_PI * 2))) * frand(15.0f, 30.0f);
|
||||
float y = AnnihilationCenterReferencePos.GetPositionY() + sin(frand(0.0f, float(M_PI * 2))) * frand(15.0f, 30.0f);
|
||||
float z = caster->GetMap()->GetHeight(caster->GetPhaseShift(), x, y, AnnihilationCenterReferencePos.GetPositionZ());
|
||||
annihilator->CastSpell(Position{ x, y, z }, SPELL_ANNIHILATION_SUMMON, true);
|
||||
}
|
||||
|
||||
annihilator->CastSpell(annihilator, SPELL_ANNIHILATION_DUMMY);
|
||||
annihilator->CastSpell(annihilator, SPELL_ANNIHILATION_SELECTOR);
|
||||
caster->AI()->Talk(SAY_ANNIHILATION);
|
||||
lastCannonEntry = NPC_ANNIHILATOR;
|
||||
}
|
||||
|
||||
caster->AI()->SetData(DATA_LAST_FIRED_CANNON, lastCannonEntry);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garothi_cannon_chooser::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_garothi_worldbreaker()
|
||||
{
|
||||
RegisterAntorusTheBurningThroneCreatureAI(boss_garothi_worldbreaker);
|
||||
RegisterAreaTriggerAI(at_garothi_annihilation);
|
||||
RegisterSpellScript(spell_garothi_apocalypse_drive);
|
||||
RegisterSpellScript(spell_garothi_fel_bombardment_selector);
|
||||
RegisterSpellScript(spell_garothi_fel_bombardment_warning);
|
||||
RegisterSpellScript(spell_garothi_fel_bombardment_periodic);
|
||||
RegisterSpellScript(spell_garothi_searing_barrage_dummy);
|
||||
RegisterSpellScript(spell_garothi_searing_barrage_selector);
|
||||
RegisterSpellScript(spell_garothi_decimation_selector);
|
||||
RegisterSpellScript(spell_garothi_decimation_warning);
|
||||
RegisterSpellScript(spell_garothi_carnage);
|
||||
RegisterSpellScript(spell_garothi_annihilation_selector);
|
||||
RegisterSpellScript(spell_garothi_annihilation_triggered);
|
||||
RegisterSpellScript(spell_garothi_eradication);
|
||||
RegisterSpellScript(spell_garothi_surging_fel);
|
||||
RegisterSpellScript(spell_garothi_cannon_chooser);
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "antorus_the_burning_throne.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_GAROTHI_WORLDBREAKER, DATA_GAROTHI_WORLDBREAKER },
|
||||
{ NPC_DECIMATOR, DATA_DECIMATOR },
|
||||
{ NPC_ANNIHILATOR, DATA_ANNIHILATOR },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_COLLISION, DATA_GAROTHI_WORLDBREAKER, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ GO_ROCK, DATA_GAROTHI_WORLDBREAKER, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_GAROTHI_WORLDBREAKER, {{ 2076 }} },
|
||||
{ DATA_FELHOUNDS_OF_SAGERAS, {{ 2074 }} },
|
||||
{ DATA_ANTORAN_HIGH_COMMAND, {{ 2070 }} },
|
||||
{ DATA_PORTAL_KEEPER_HASABEL, {{ 2064 }} },
|
||||
{ DATA_EONAR_THE_LIFE_BINDER, {{ 2075 }} },
|
||||
{ DATA_IMONAR_THE_SOULHUNTER, {{ 2082 }} },
|
||||
{ DATA_KINGAROTH, {{ 2088 }} },
|
||||
{ DATA_VARIMATHRAS, {{ 2069 }} },
|
||||
{ DATA_THE_COVEN_OF_SHIVARRA, {{ 2073 }} },
|
||||
{ DATA_AGGRAMAR, {{ 2063 }} },
|
||||
{ DATA_ARGUS_THE_UNMAKER, {{ 2092 }} }
|
||||
};
|
||||
|
||||
class instance_antorus_the_burning_throne : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_antorus_the_burning_throne() : InstanceMapScript(ABTScriptName, 1712) { }
|
||||
|
||||
struct instance_antorus_the_burning_throne_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_antorus_the_burning_throne_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_ANNIHILATION:
|
||||
if (Creature* garothi = GetCreature(DATA_GAROTHI_WORLDBREAKER))
|
||||
garothi->AI()->JustSummoned(creature);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_antorus_the_burning_throne_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_antorus_the_burning_throne()
|
||||
{
|
||||
new instance_antorus_the_burning_throne();
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_boss_garothi_worldbreaker();
|
||||
void AddSC_instance_antorus_the_burning_throne();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddArgusScripts()
|
||||
{
|
||||
AddSC_boss_garothi_worldbreaker(); // Antorus the Burning Throne
|
||||
AddSC_instance_antorus_the_burning_throne();
|
||||
}
|
||||
@@ -1,821 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "Containers.h"
|
||||
#include "Conversation.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellHistory.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "trial_of_valor.h"
|
||||
|
||||
enum GuarmSpells
|
||||
{
|
||||
SPELL_HELYATOSIS_AURA = 231561,
|
||||
SPELL_HELYATOSIS_INITIAL_ENERGIZE = 235130,
|
||||
SPELL_MULTI_HEADED_AURA = 227512,
|
||||
SPELL_MULTI_HEADED_DAMAGE = 227642,
|
||||
SPELL_FLASHING_FANGS = 227514,
|
||||
SPELL_OFF_THE_LEASH = 228201,
|
||||
|
||||
SPELL_FLAME_LICK_SELECTOR = 228226, // triggers 228227 missile
|
||||
SPELL_SHADOW_LICK_SELECTOR = 228250, // triggers 228251 missile
|
||||
SPELL_FROST_LICK_SELECTOR = 228246, // triggers 228247 missile
|
||||
|
||||
SPELL_BERSERK = 26662,
|
||||
SPELL_BERSERK_TRAMPLE_AOE = 232224,
|
||||
SPELL_BERSERK_CHARGE_AT = 232173, // triggers 232197
|
||||
|
||||
SPELL_GUARDIANS_BREATH_COLOR_SELECTOR = 228187,
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_RGB = 232811, // Red Green Blue
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_RBG = 232810, // Red Blue Green
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_GRB = 232775, // Green Red Blue
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_GBR = 232808, // Green Blue Red
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_BRG = 232809, // Blue Red Green
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_BGR = 232807, // Blue Green Red
|
||||
SPELL_GUARDIANS_BREATH_UNK = 227573,
|
||||
SPELL_GUARDIANS_BREATH_CAST_RGB = 227673, // Red Green Blue
|
||||
SPELL_GUARDIANS_BREATH_CAST_RBG = 227667, // Red Blue Green
|
||||
SPELL_GUARDIANS_BREATH_CAST_GRB = 227669, // Green Red Blue
|
||||
SPELL_GUARDIANS_BREATH_CAST_GBR = 227660, // Green Blue Red
|
||||
SPELL_GUARDIANS_BREATH_CAST_BRG = 227666, // Blue Red Green
|
||||
SPELL_GUARDIANS_BREATH_CAST_BGR = 227658, // Blue Green Red
|
||||
SPELL_FIERY_PHLEGM = 232777, // Red
|
||||
SPELL_FIERY_PHLEGM_AURA = 228758,
|
||||
SPELL_SALTY_SPITTLE = 232798, // Green
|
||||
SPELL_SALTY_SPITTLE_AURA = 228768,
|
||||
SPELL_DARK_DISCHARGE = 232800, // Blue
|
||||
SPELL_DARK_DISCHARGE_AURA = 228769,
|
||||
SPELL_FROTHING_RAGE = 228174, // applied x times where x players not getting hit by breath
|
||||
|
||||
SPELL_ROARING_LEAP_SELECTOR = 227894, // @TODO: requires TARGET_DEST_CASTER_CLUMP_CENTROID
|
||||
SPELL_ROARING_LEAP_INITIAL_KNOCKBACK = 227883,
|
||||
SPELL_ROARING_LEAP_JUMP = 229350, // triggers 227902
|
||||
SPELL_HEADLONG_CHARGE_INITIAL = 227816,
|
||||
SPELL_HEADLONG_CHARGE_PERIODIC_DAMAGE = 229480,
|
||||
SPELL_HEADLONG_CHARGE_DAMAGE = 228344,
|
||||
SPELL_HEADLONG_CHARGE_AT = 227833, // triggers 227843
|
||||
|
||||
// Mythic
|
||||
SPELL_VOLATILE_FOAM_INITIAL = 228824,
|
||||
SPELL_VOLATILE_FOAM_SELECTOR_RED = 228684,
|
||||
SPELL_VOLATILE_FOAM_SELECTOR_GREEN = 228809,
|
||||
SPELL_VOLATILE_FOAM_SELECTOR_BLUE = 228817,
|
||||
};
|
||||
|
||||
enum GuarmEvents
|
||||
{
|
||||
EVENT_FLASHING_FANGS = 1,
|
||||
EVENT_CHECK_ENERGY,
|
||||
EVENT_LICK,
|
||||
EVENT_ROARING_LEAP,
|
||||
EVENT_HEADLONG_CHARGE,
|
||||
EVENT_OFF_THE_LEASH,
|
||||
EVENT_VOLATILE_FOAM,
|
||||
EVENT_BERSERK,
|
||||
};
|
||||
|
||||
enum GuarmTalks
|
||||
{
|
||||
TALK_GUARDIANS_BREATH_ANNOUNCE = 0, // |TInterface\Icons\SPELL_FIRE_TWILIGHTFLAMEBREATH.BLP:20|t%s begins to cast |cFFFF0000|Hspell:227573|h[Guardian's Breath]|h|r!
|
||||
TALK_BERSERK = 1, // %s goes into a berserker rage!
|
||||
};
|
||||
|
||||
enum GuarmPoints
|
||||
{
|
||||
POINT_BERSERK_JUMP = 0,
|
||||
|
||||
POINT_HEADLONG_CHARGE = 50,
|
||||
POINT_HEADLONG_CHARGE_MAX = 53,
|
||||
};
|
||||
|
||||
enum GuarmPaths
|
||||
{
|
||||
PATH_HEADLONG_CHARGE1 = (114323 * 100) + 0,
|
||||
PATH_HEADLONG_CHARGE2 = (114323 * 100) + 1,
|
||||
PATH_HEADLONG_CHARGE3 = (114323 * 100) + 2,
|
||||
PATH_HEADLONG_CHARGE4 = (114323 * 100) + 3,
|
||||
PATH_BERSERK = (114323 * 100) + 4,
|
||||
};
|
||||
|
||||
enum GuarmSpellCategories
|
||||
{
|
||||
SPELL_CATEGORY_GUARM = 1152,
|
||||
};
|
||||
|
||||
enum GuarmConversations
|
||||
{
|
||||
CONVERSATION_DEATH = 3917
|
||||
};
|
||||
|
||||
enum GuarmActions
|
||||
{
|
||||
ACTION_BREATH_HIT_TARGET = 0,
|
||||
ACTION_HANDLE_FROTHING_RAGE,
|
||||
};
|
||||
|
||||
struct JumpMovePathPair
|
||||
{
|
||||
Position JumpPos;
|
||||
uint32 PathID;
|
||||
};
|
||||
|
||||
JumpMovePathPair const HeadlongChargePairs[] =
|
||||
{
|
||||
{ { 478.535f, 446.623f, 4.88632f }, PATH_HEADLONG_CHARGE1 },
|
||||
{ { 460.708f, 445.918f, 4.91909f }, PATH_HEADLONG_CHARGE2 },
|
||||
{ { 454.967f, 543.651f, 2.99177f }, PATH_HEADLONG_CHARGE3 },
|
||||
{ { 475.189f, 543.391f, 3.25487f }, PATH_HEADLONG_CHARGE4 },
|
||||
};
|
||||
|
||||
struct GuardiansBreathSpellPair
|
||||
{
|
||||
uint32 SummonATSpellID;
|
||||
uint32 CastSpellID;
|
||||
};
|
||||
|
||||
GuardiansBreathSpellPair const GuardiansBreathSpellPairs[] =
|
||||
{
|
||||
{ SPELL_GUARDIANS_BREATH_SUMMON_ATS_RGB, SPELL_GUARDIANS_BREATH_CAST_RGB },
|
||||
{ SPELL_GUARDIANS_BREATH_SUMMON_ATS_RBG, SPELL_GUARDIANS_BREATH_CAST_RBG },
|
||||
{ SPELL_GUARDIANS_BREATH_SUMMON_ATS_GRB, SPELL_GUARDIANS_BREATH_CAST_GRB },
|
||||
{ SPELL_GUARDIANS_BREATH_SUMMON_ATS_GBR, SPELL_GUARDIANS_BREATH_CAST_GBR },
|
||||
{ SPELL_GUARDIANS_BREATH_SUMMON_ATS_BRG, SPELL_GUARDIANS_BREATH_CAST_BRG },
|
||||
{ SPELL_GUARDIANS_BREATH_SUMMON_ATS_BGR, SPELL_GUARDIANS_BREATH_CAST_BGR }
|
||||
};
|
||||
|
||||
JumpMovePathPair const BerserkerPair = { { 464.035f, 549.979f, 2.95187f }, PATH_BERSERK };
|
||||
|
||||
// 114323 - Guarm
|
||||
struct boss_guarm : public BossAI
|
||||
{
|
||||
boss_guarm(Creature* creature) : BossAI(creature, DATA_GUARM), _lickCount(0), _unitsHitByBreathCount(0) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCastAOE(SPELL_MULTI_HEADED_AURA);
|
||||
me->SetMaxPower(POWER_ENERGY, 100); // power is set to 0 in Creature::UpdateMaxPower
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
Conversation::CreateConversation(CONVERSATION_DEATH, me, me->GetPosition(), ObjectGuid::Empty);
|
||||
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
summons.DespawnAll();
|
||||
_EnterEvadeMode();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
|
||||
DoCastAOE(SPELL_HELYATOSIS_AURA);
|
||||
DoCastAOE(SPELL_HELYATOSIS_INITIAL_ENERGIZE);
|
||||
|
||||
events.ScheduleEvent(EVENT_FLASHING_FANGS, 6s);
|
||||
events.ScheduleEvent(EVENT_LICK, 12s);
|
||||
events.ScheduleEvent(EVENT_CHECK_ENERGY, 500ms);
|
||||
events.ScheduleEvent(EVENT_OFF_THE_LEASH, 45s);
|
||||
|
||||
if (IsMythic())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_VOLATILE_FOAM, 11s);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 4min + 4s);
|
||||
}
|
||||
else if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_BERSERK, 5min);
|
||||
else if (GetDifficulty() == DIFFICULTY_NORMAL_RAID)
|
||||
events.ScheduleEvent(EVENT_BERSERK, 6min);
|
||||
else // LFR
|
||||
events.ScheduleEvent(EVENT_BERSERK, 7min);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_FLASHING_FANGS:
|
||||
DoCastVictim(SPELL_FLASHING_FANGS);
|
||||
events.ScheduleEvent(EVENT_FLASHING_FANGS, 21s + 500ms);
|
||||
break;
|
||||
case EVENT_LICK:
|
||||
_lickCount++;
|
||||
DoCastAOE(RAND(SPELL_FLAME_LICK_SELECTOR, SPELL_SHADOW_LICK_SELECTOR, SPELL_FROST_LICK_SELECTOR));
|
||||
events.ScheduleEvent(EVENT_LICK, (_lickCount % 2) ? 4s : 10s);
|
||||
break;
|
||||
case EVENT_CHECK_ENERGY:
|
||||
{
|
||||
events.ScheduleEvent(EVENT_CHECK_ENERGY, 500ms);
|
||||
if (me->GetPower(POWER_ENERGY) < 100)
|
||||
break;
|
||||
|
||||
_unitsHitByBreathCount = 0;
|
||||
if (DoCastVictim(SPELL_GUARDIANS_BREATH_COLOR_SELECTOR) == SPELL_CAST_OK)
|
||||
Talk(TALK_GUARDIANS_BREATH_ANNOUNCE);
|
||||
|
||||
break;
|
||||
}
|
||||
case EVENT_ROARING_LEAP:
|
||||
DoCastAOE(SPELL_ROARING_LEAP_SELECTOR);
|
||||
break;
|
||||
case EVENT_HEADLONG_CHARGE:
|
||||
DoCastAOE(SPELL_HEADLONG_CHARGE_INITIAL);
|
||||
break;
|
||||
case EVENT_OFF_THE_LEASH:
|
||||
DoCastAOE(SPELL_OFF_THE_LEASH);
|
||||
events.ScheduleEvent(EVENT_OFF_THE_LEASH, 75s);
|
||||
events.ScheduleEvent(EVENT_ROARING_LEAP, 3s);
|
||||
events.ScheduleEvent(EVENT_HEADLONG_CHARGE, 13s);
|
||||
events.CancelEvent(EVENT_FLASHING_FANGS);
|
||||
events.CancelEvent(EVENT_LICK);
|
||||
events.CancelEvent(EVENT_VOLATILE_FOAM);
|
||||
break;
|
||||
case EVENT_VOLATILE_FOAM:
|
||||
DoCastAOE(SPELL_VOLATILE_FOAM_INITIAL);
|
||||
events.ScheduleEvent(EVENT_VOLATILE_FOAM, 22s);
|
||||
break;
|
||||
case EVENT_BERSERK:
|
||||
DoCastAOE(SPELL_BERSERK);
|
||||
Talk(TALK_BERSERK, me);
|
||||
events.CancelEvent(EVENT_FLASHING_FANGS);
|
||||
events.CancelEvent(EVENT_LICK);
|
||||
me->GetMotionMaster()->Clear(); // remove ChaseMovementGen
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->MoveJump(BerserkerPair.JumpPos, 42.0f, 21.5f, POINT_BERSERK_JUMP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
events.ScheduleEvent(EVENT_FLASHING_FANGS, 16s);
|
||||
events.ScheduleEvent(EVENT_LICK, 18s);
|
||||
if (IsMythic())
|
||||
events.ScheduleEvent(EVENT_VOLATILE_FOAM, 20s);
|
||||
|
||||
// Headlong Charge
|
||||
if (pathId != BerserkerPair.PathID)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_HEADLONG_CHARGE_PERIODIC_DAMAGE);
|
||||
me->RemoveAurasDueToSpell(SPELL_HEADLONG_CHARGE_AT);
|
||||
events.ScheduleEvent(EVENT_ROARING_LEAP, 5s);
|
||||
}
|
||||
else // Berserk
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_BERSERK_CHARGE_AT);
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type == EFFECT_MOTION_TYPE)
|
||||
{
|
||||
if (pointId >= POINT_HEADLONG_CHARGE && pointId <= POINT_HEADLONG_CHARGE_MAX)
|
||||
{
|
||||
uint32 headlongChargeId = pointId - POINT_HEADLONG_CHARGE;
|
||||
DoCastAOE(SPELL_HEADLONG_CHARGE_DAMAGE, true); // manually trigger first damage tick
|
||||
DoCastAOE(SPELL_HEADLONG_CHARGE_PERIODIC_DAMAGE, true);
|
||||
DoCastAOE(SPELL_HEADLONG_CHARGE_AT, true);
|
||||
|
||||
me->GetMotionMaster()->MovePath(HeadlongChargePairs[headlongChargeId].PathID, false, {}, 35.0f);
|
||||
}
|
||||
else if (pointId == POINT_BERSERK_JUMP)
|
||||
{
|
||||
DoCastAOE(SPELL_BERSERK_TRAMPLE_AOE);
|
||||
DoCastAOE(SPELL_BERSERK_CHARGE_AT);
|
||||
DoCastAOE(SPELL_ROARING_LEAP_INITIAL_KNOCKBACK, true);
|
||||
|
||||
me->GetMotionMaster()->MovePath(BerserkerPair.PathID, false, {}, 35.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
switch (param)
|
||||
{
|
||||
case ACTION_BREATH_HIT_TARGET:
|
||||
_unitsHitByBreathCount++;
|
||||
break;
|
||||
case ACTION_HANDLE_FROTHING_RAGE:
|
||||
{
|
||||
uint32 engagedPlayers = 0;
|
||||
for (auto const& itr : me->GetThreatManager().GetUnsortedThreatList())
|
||||
{
|
||||
if (itr->GetVictim()->IsPlayer())
|
||||
engagedPlayers++;
|
||||
}
|
||||
|
||||
uint32 frothingRageStacks = engagedPlayers - _unitsHitByBreathCount;
|
||||
if (frothingRageStacks > 0)
|
||||
{
|
||||
if (Aura* aura = me->GetAura(SPELL_FROTHING_RAGE))
|
||||
frothingRageStacks += aura->GetStackAmount();
|
||||
me->SetAuraStack(SPELL_FROTHING_RAGE, me, frothingRageStacks);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _lickCount;
|
||||
uint8 _unitsHitByBreathCount;
|
||||
};
|
||||
|
||||
// 227512 - Multi-Headed
|
||||
class spell_multi_headed_proc_guarm : public AuraScript
|
||||
{
|
||||
void HandleProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_MULTI_HEADED_DAMAGE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnProc += AuraProcFn(spell_multi_headed_proc_guarm::HandleProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 227642 - Multi-Headed
|
||||
class spell_multi_headed_damage_guarm : public SpellScript
|
||||
{
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.size() < 2)
|
||||
return;
|
||||
|
||||
targets.sort(Trinity::ObjectDistanceOrderPred(GetExplTargetUnit()));
|
||||
targets.pop_front(); // skip expl target if multiple players are in range
|
||||
targets.resize(1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_multi_headed_damage_guarm::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 228226 - Flame Lick
|
||||
// 228250 - Shadow Lick
|
||||
// 228246 - Frost Lick
|
||||
class spell_lick_selector_guarm : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellInfo({ (uint32)spellInfo->GetEffect(EFFECT_0).BasePoints }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } });
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), GetEffectValue(), true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_lick_selector_guarm::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 228187 - Guardian's Breath
|
||||
class spell_guardians_breath_color_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_RGB,
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_RBG,
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_GRB,
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_GBR,
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_BRG,
|
||||
SPELL_GUARDIANS_BREATH_SUMMON_ATS_BGR,
|
||||
SPELL_GUARDIANS_BREATH_UNK,
|
||||
SPELL_GUARDIANS_BREATH_CAST_RGB,
|
||||
SPELL_GUARDIANS_BREATH_CAST_RBG,
|
||||
SPELL_GUARDIANS_BREATH_CAST_GRB,
|
||||
SPELL_GUARDIANS_BREATH_CAST_GBR,
|
||||
SPELL_GUARDIANS_BREATH_CAST_BRG,
|
||||
SPELL_GUARDIANS_BREATH_CAST_BGR
|
||||
});
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
GuardiansBreathSpellPair const& pair = GuardiansBreathSpellPairs[urand(0, 6)];
|
||||
caster->CastSpell(nullptr, pair.CastSpellID);
|
||||
caster->CastSpell(nullptr, pair.SummonATSpellID);
|
||||
caster->CastSpell(nullptr, SPELL_GUARDIANS_BREATH_UNK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_guardians_breath_color_selector::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
// 227673 - Guardian's Breath
|
||||
// 227667 - Guardian's Breath
|
||||
// 227669 - Guardian's Breath
|
||||
// 227660 - Guardian's Breath
|
||||
// 227666 - Guardian's Breath
|
||||
// 227658 - Guardian's Breath
|
||||
class spell_guardians_breath : public SpellScript
|
||||
{
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster->IsAIEnabled())
|
||||
return;
|
||||
|
||||
caster->GetAI()->DoAction(ACTION_HANDLE_FROTHING_RAGE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_guardians_breath::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Guarm
|
||||
v
|
||||
Color: R-- Spell: 232803 AreaTrigger: 13352
|
||||
Color: -R- Spell: 232773 AreaTrigger: 13352
|
||||
Color: --R Spell: 232804 AreaTrigger: 13352
|
||||
Color: G-- Spell: 232774 AreaTrigger: 13353
|
||||
Color: -G- Spell: 232805 AreaTrigger: 13353
|
||||
Color: --G Spell: 232806 AreaTrigger: 13353
|
||||
Color: B-- Spell: 232801 AreaTrigger: 13354
|
||||
Color: -B- Spell: 232802 AreaTrigger: 13354
|
||||
Color: --B Spell: 232776 AreaTrigger: 13354
|
||||
*/
|
||||
|
||||
// 232803 - Guardian's Breath
|
||||
// 232773 - Guardian's Breath
|
||||
// 232804 - Guardian's Breath
|
||||
// 232774 - Guardian's Breath
|
||||
// 232805 - Guardian's Breath
|
||||
// 232806 - Guardian's Breath
|
||||
// 232801 - Guardian's Breath
|
||||
// 232802 - Guardian's Breath
|
||||
// 232776 - Guardian's Breath
|
||||
template<uint32 ColorSpellId>
|
||||
class at_guardians_breath : public AreaTriggerEntityScript
|
||||
{
|
||||
public:
|
||||
at_guardians_breath(char const* script) : AreaTriggerEntityScript(script) { }
|
||||
|
||||
template<uint32 ColorSpell>
|
||||
struct at_guardians_breathAI : AreaTriggerAI
|
||||
{
|
||||
at_guardians_breathAI(AreaTrigger* at) : AreaTriggerAI(at) { }
|
||||
|
||||
uint32 GetBreathDebuffByDamageSpell(uint32 breathDamageSpell) const
|
||||
{
|
||||
switch (breathDamageSpell)
|
||||
{
|
||||
case SPELL_FIERY_PHLEGM:
|
||||
return SPELL_FIERY_PHLEGM_AURA;
|
||||
case SPELL_SALTY_SPITTLE:
|
||||
return SPELL_SALTY_SPITTLE_AURA;
|
||||
case SPELL_DARK_DISCHARGE:
|
||||
return SPELL_DARK_DISCHARGE_AURA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OnRemove() override
|
||||
{
|
||||
InstanceScript* instance = at->GetInstanceScript();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
Creature* guarm = instance->GetCreature(DATA_GUARM);
|
||||
if (!guarm)
|
||||
return;
|
||||
|
||||
if (!guarm->IsAIEnabled())
|
||||
return;
|
||||
|
||||
for (ObjectGuid const& guid : at->GetInsideUnits())
|
||||
{
|
||||
Player* player = ObjectAccessor::GetPlayer(*at, guid);
|
||||
if (!player)
|
||||
continue;
|
||||
|
||||
if (player->isDead())
|
||||
continue;
|
||||
|
||||
guarm->GetAI()->DoAction(ACTION_BREATH_HIT_TARGET);
|
||||
guarm->CastSpell(player, ColorSpell, true);
|
||||
player->CastSpell(nullptr, GetBreathDebuffByDamageSpell(ColorSpell));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AreaTriggerAI* GetAI(AreaTrigger* at) const override
|
||||
{
|
||||
return new at_guardians_breathAI<ColorSpellId>(at);
|
||||
}
|
||||
};
|
||||
|
||||
// 227720 - Mixed Elements
|
||||
// 227721 - Mixed Elements
|
||||
// 227735 - Mixed Elements
|
||||
template<uint32 SpellId1, uint32 SpellId2>
|
||||
class spell_mixed_elements : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SpellId1,
|
||||
SpellId2
|
||||
});
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if([](WorldObject* target)
|
||||
{
|
||||
Player* unit = target->ToPlayer();
|
||||
if (!unit)
|
||||
return true;
|
||||
|
||||
if (!unit->HasAura(SpellId1) || !unit->HasAura(SpellId2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mixed_elements::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 227894 - Roaring Leap
|
||||
class spell_roaring_leap_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_ROARING_LEAP_INITIAL_KNOCKBACK, SPELL_ROARING_LEAP_JUMP });
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
// @TODO: cast 232036 + implement (achievement)
|
||||
// @TODO: related to achievement aswell: 232393
|
||||
caster->CastSpell(nullptr, SPELL_ROARING_LEAP_INITIAL_KNOCKBACK, true);
|
||||
caster->CastSpell(*GetHitDest(), SPELL_ROARING_LEAP_JUMP);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_roaring_leap_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 227816 - Headlong Charge
|
||||
class spell_headlong_charge_trigger : public SpellScript
|
||||
{
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* caster = GetCaster()->ToCreature();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
uint8 pairId = urand(0, 3);
|
||||
caster->GetMotionMaster()->Clear(); // remove ChaseMovementGen
|
||||
caster->SetReactState(REACT_PASSIVE);
|
||||
caster->GetMotionMaster()->MoveJump(HeadlongChargePairs[pairId].JumpPos, 42.0f, 21.5f, POINT_HEADLONG_CHARGE + pairId);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_headlong_charge_trigger::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 228201 - Off the Leash
|
||||
class spell_off_the_leash : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_HELYATOSIS_AURA });
|
||||
}
|
||||
|
||||
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/ )
|
||||
{
|
||||
GetTarget()->RemoveAurasDueToSpell(SPELL_HELYATOSIS_AURA);
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->CastSpell(nullptr, SPELL_HELYATOSIS_AURA);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_off_the_leash::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectApplyFn(spell_off_the_leash::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 228824 - Volatile Foam
|
||||
class spell_volatile_foam_initial : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_VOLATILE_FOAM_SELECTOR_RED,
|
||||
SPELL_VOLATILE_FOAM_SELECTOR_GREEN,
|
||||
SPELL_VOLATILE_FOAM_SELECTOR_BLUE
|
||||
});
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(nullptr, RAND(SPELL_VOLATILE_FOAM_SELECTOR_RED, SPELL_VOLATILE_FOAM_SELECTOR_GREEN, SPELL_VOLATILE_FOAM_SELECTOR_BLUE));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_volatile_foam_initial::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
// 228684 - Volatile Foam // Red
|
||||
// 228809 - Volatile Foam // Green
|
||||
// 228817 - Volatile Foam // Blue
|
||||
template<uint32 ExcludeSpellId>
|
||||
class spell_volatile_foam_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellInfo({ (uint32)spellInfo->GetEffect(EFFECT_0).BasePoints });
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if([](WorldObject* target)
|
||||
{
|
||||
Unit* unit = target->ToUnit();
|
||||
if (!unit)
|
||||
return true;
|
||||
|
||||
if (unit->HasAura(ExcludeSpellId))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), GetEffectValue(), true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_volatile_foam_selector::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_volatile_foam_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 228794 - Flaming Volatile Foam // after dispel
|
||||
// 228811 - Briney Volatile Foam // after dispel
|
||||
// 228819 - Shadowy Volatile Foam // after dispel
|
||||
class spell_volatile_foam : public SpellScript
|
||||
{
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.sort(Trinity::ObjectDistanceOrderPred(GetExplTargetUnit()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_volatile_foam::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_volatile_foam::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ALLY);
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_volatile_foam::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ALLY);
|
||||
}
|
||||
};
|
||||
|
||||
// 228744 - Flaming Volatile Foam // initial
|
||||
// 228794 - Flaming Volatile Foam // after dispel
|
||||
// 228810 - Briney Volatile Foam // initial
|
||||
// 228811 - Briney Volatile Foam // after dispel
|
||||
// 228818 - Shadowy Volatile Foam // initial
|
||||
// 228819 - Shadowy Volatile Foam // after dispel
|
||||
template<uint32 SpellIdOnExpire>
|
||||
class spell_volatile_foam_aura : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo(
|
||||
{
|
||||
(uint32)spellInfo->GetEffect(EFFECT_0).CalcValue(), // SpellIdOnDispel
|
||||
SpellIdOnExpire
|
||||
});
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
|
||||
AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
|
||||
if (removeMode == AURA_REMOVE_BY_EXPIRE)
|
||||
target->CastSpell(target, SpellIdOnExpire);
|
||||
else if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL)
|
||||
target->CastSpell(nullptr, GetSpellInfo()->GetEffect(EFFECT_0).CalcValue());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_volatile_foam_aura::OnRemove, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_guarm()
|
||||
{
|
||||
RegisterTrialOfValorCreatureAI(boss_guarm);
|
||||
RegisterSpellScript(spell_multi_headed_proc_guarm);
|
||||
RegisterSpellScript(spell_multi_headed_damage_guarm);
|
||||
RegisterSpellScript(spell_lick_selector_guarm);
|
||||
RegisterSpellScript(spell_guardians_breath_color_selector);
|
||||
RegisterSpellScript(spell_guardians_breath);
|
||||
new at_guardians_breath<SPELL_FIERY_PHLEGM>("at_guardians_breath_red");
|
||||
new at_guardians_breath<SPELL_SALTY_SPITTLE>("at_guardians_breath_green");
|
||||
new at_guardians_breath<SPELL_DARK_DISCHARGE>("at_guardians_breath_blue");
|
||||
RegisterSpellScriptWithArgs((spell_mixed_elements<SPELL_FIERY_PHLEGM_AURA, SPELL_SALTY_SPITTLE_AURA>), "spell_mixed_elements_red_green");
|
||||
RegisterSpellScriptWithArgs((spell_mixed_elements<SPELL_FIERY_PHLEGM_AURA, SPELL_DARK_DISCHARGE_AURA>), "spell_mixed_elements_red_blue");
|
||||
RegisterSpellScriptWithArgs((spell_mixed_elements<SPELL_SALTY_SPITTLE_AURA, SPELL_DARK_DISCHARGE_AURA>), "spell_mixed_elements_green_blue");
|
||||
RegisterSpellScript(spell_roaring_leap_selector);
|
||||
RegisterSpellScript(spell_headlong_charge_trigger);
|
||||
RegisterSpellScript(spell_off_the_leash);
|
||||
RegisterSpellScript(spell_volatile_foam_initial);
|
||||
RegisterSpellScriptWithArgs(spell_volatile_foam_selector<SPELL_FIERY_PHLEGM_AURA>, "spell_volatile_foam_selector_red");
|
||||
RegisterSpellScriptWithArgs(spell_volatile_foam_selector<SPELL_SALTY_SPITTLE_AURA>, "spell_volatile_foam_selector_green");
|
||||
RegisterSpellScriptWithArgs(spell_volatile_foam_selector<SPELL_DARK_DISCHARGE_AURA>, "spell_volatile_foam_selector_blue");
|
||||
RegisterSpellScriptWithArgs(spell_volatile_foam_aura<SPELL_FIERY_PHLEGM_AURA>, "spell_volatile_foam_aura_initial_red");
|
||||
RegisterSpellScriptWithArgs(spell_volatile_foam_aura<SPELL_SALTY_SPITTLE_AURA>, "spell_volatile_foam_aura_initial_green");
|
||||
RegisterSpellScriptWithArgs(spell_volatile_foam_aura<SPELL_DARK_DISCHARGE_AURA>, "spell_volatile_foam_aura_initial_blue");
|
||||
RegisterSpellAndAuraScriptPairWithArgs(spell_volatile_foam, spell_volatile_foam_aura<SPELL_FIERY_PHLEGM_AURA>, "spell_volatile_foam_aura_red");
|
||||
RegisterSpellAndAuraScriptPairWithArgs(spell_volatile_foam, spell_volatile_foam_aura<SPELL_SALTY_SPITTLE_AURA>, "spell_volatile_foam_aura_green");
|
||||
RegisterSpellAndAuraScriptPairWithArgs(spell_volatile_foam, spell_volatile_foam_aura<SPELL_DARK_DISCHARGE_AURA>, "spell_volatile_foam_aura_blue");
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaBoundary.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "trial_of_valor.h"
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ DATA_GUARM, new RectangleBoundary(443.320f, 492.354f, 430.713f, 561.020f) }
|
||||
};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_ODYN, DATA_ODYN },
|
||||
{ BOSS_GUARM, DATA_GUARM },
|
||||
{ BOSS_HELYA, DATA_HELYA },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_GUARM_BOSS_DOOR_ENTRANCE, DATA_GUARM, EncounterDoorBehavior::OpenWhenNotInProgress },
|
||||
{ GO_GUARM_BOSS_DOOR_EXIT, DATA_GUARM, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_ODYN, {{ 1958 }} },
|
||||
{ DATA_GUARM, {{ 1962 }} },
|
||||
{ DATA_HELYA, {{ 2008 }} },
|
||||
};
|
||||
|
||||
class instance_trial_of_valor : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_trial_of_valor() : InstanceMapScript(TOVScriptName, 1648) { }
|
||||
|
||||
struct instance_trial_of_valor_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_trial_of_valor_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
LoadBossBoundaries(boundaries);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
}
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_trial_of_valor_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_trial_of_valor()
|
||||
{
|
||||
new instance_trial_of_valor();
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_AZURE_VAULT_H_
|
||||
#define DEF_AZURE_VAULT_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "TrialOfValor"
|
||||
#define TOVScriptName "instance_trial_of_valor"
|
||||
|
||||
uint32 const EncounterCount = 3;
|
||||
|
||||
enum TOVDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_ODYN = 0,
|
||||
DATA_GUARM,
|
||||
DATA_HELYA,
|
||||
};
|
||||
|
||||
enum TOVCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_ODYN = 114263,
|
||||
BOSS_GUARM = 114323,
|
||||
BOSS_HELYA = 114537,
|
||||
};
|
||||
|
||||
enum TOVGameObjectIds
|
||||
{
|
||||
GO_GUARM_BOSS_DOOR_ENTRANCE = 266532,
|
||||
GO_GUARM_BOSS_DOOR_EXIT = 266533,
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetTrialOfValorAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, TOVScriptName);
|
||||
}
|
||||
|
||||
#define RegisterTrialOfValorCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetTrialOfValorAI)
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
|
||||
// Trial of Valor
|
||||
void AddSC_boss_guarm();
|
||||
void AddSC_instance_trial_of_valor();
|
||||
|
||||
// Orderhalls
|
||||
void AddSC_orderhall_warrior();
|
||||
void AddSC_zone_mardum();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddBrokenIslesScripts()
|
||||
{
|
||||
// Trial of Valor
|
||||
AddSC_boss_guarm();
|
||||
AddSC_instance_trial_of_valor();
|
||||
|
||||
AddSC_orderhall_warrior();
|
||||
AddSC_zone_mardum();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,925 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "Containers.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MovementTypedefs.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
enum ValarjarSpells
|
||||
{
|
||||
SPELL_EMOTE_BELCH = 65937,
|
||||
SPELL_WARRIOR_ORDER_FORMATION_SCENE = 193709,
|
||||
SPELL_CANCEL_COMPLETE_SCENE_WARRIOR_ORDER_FORMATION = 193711
|
||||
};
|
||||
|
||||
enum Phases
|
||||
{
|
||||
PHASE_ODYN = 5107,
|
||||
PHASE_DANICA = 5090
|
||||
};
|
||||
|
||||
enum Quests
|
||||
{
|
||||
QUEST_ODYN_AND_THE_VALARJAR = 39654
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_KILL_CREDIT_FOLLOWED_DANICA = 103036,
|
||||
NPC_DANICA_THE_RECLAIMER = 93823,
|
||||
NPC_KILL_CREDIT_ARRIVED_AT_ODYN = 96532
|
||||
};
|
||||
|
||||
enum Items
|
||||
{
|
||||
ITEM_MONSTER_ITEM_MUTTON_WITH_BITE = 2202,
|
||||
ITEM_MONSTER_ITEM_TANKARD_WOODEN = 2703,
|
||||
ITEM_HOV_2H_AXE = 137176,
|
||||
ITEM_HOV_1H_SWORD = 137263,
|
||||
ITEM_HOV_SHIELD_2 = 137265
|
||||
};
|
||||
|
||||
struct npc_danica_the_reclaimer : public ScriptedAI
|
||||
{
|
||||
npc_danica_the_reclaimer(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
Position const DanicaPath01[6] =
|
||||
{
|
||||
{ 1050.219f, 7232.470f, 100.5846f },
|
||||
{ 1046.207f, 7240.372f, 100.5846f },
|
||||
{ 1040.963f, 7245.498f, 100.6819f },
|
||||
{ 1034.726f, 7250.083f, 100.5846f },
|
||||
{ 1027.422f, 7257.835f, 100.5846f },
|
||||
{ 1027.542f, 7259.735f, 100.5846f }
|
||||
};
|
||||
|
||||
using DanicaPath01Size = std::extent<decltype(DanicaPath01)>;
|
||||
|
||||
Position const DanicaPath02[6] =
|
||||
{
|
||||
{ 1018.493f, 7247.438f, 100.5846f },
|
||||
{ 1013.535f, 7243.327f, 100.5846f },
|
||||
{ 1007.063f, 7235.723f, 100.5846f },
|
||||
{ 1003.337f, 7229.650f, 100.5846f },
|
||||
{ 995.4549f, 7227.286f, 100.5846f },
|
||||
{ 984.4410f, 7224.357f, 100.5846f }
|
||||
};
|
||||
|
||||
using DanicaPath02Size = std::extent<decltype(DanicaPath02)>;
|
||||
|
||||
Position const DanicaPath03[5] =
|
||||
{
|
||||
{ 962.5208f, 7223.089f, 100.5846f },
|
||||
{ 934.2795f, 7223.116f, 100.5846f },
|
||||
{ 911.8507f, 7223.776f, 100.5846f },
|
||||
{ 879.0139f, 7224.100f, 100.9079f },
|
||||
{ 851.691f, 7224.5490f, 109.5846f }
|
||||
};
|
||||
|
||||
using DanicaPath03Size = std::extent<decltype(DanicaPath03)>;
|
||||
|
||||
enum Texts
|
||||
{
|
||||
SAY_FIRST_LINE = 1,
|
||||
SAY_SECOND_LINE = 2,
|
||||
SAY_THIRD_LINE = 3
|
||||
};
|
||||
|
||||
enum Points
|
||||
{
|
||||
POINT_FORGE_OF_ODYN,
|
||||
POINT_INTRODUCE_MEAD_HALL,
|
||||
POINT_ODYN
|
||||
};
|
||||
|
||||
// Should be the player
|
||||
// Personal spawn ? Demon Creator is the player who accepts the quest, no phasing involved but the quest giver dissapears and gets replaced with a new one
|
||||
void IsSummonedBy(WorldObject* summoner) override
|
||||
{
|
||||
if (summoner->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
_summonerGuid = summoner->GetGUID();
|
||||
_scheduler.Schedule(2s, [this, summoner](TaskContext /*context*/)
|
||||
{
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_FORGE_OF_ODYN, DanicaPath01, DanicaPath01Size::value, false, true);
|
||||
Talk(SAY_FIRST_LINE, summoner);
|
||||
});
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case POINT_FORGE_OF_ODYN:
|
||||
_scheduler.Schedule(10s, [this](TaskContext /*context*/)
|
||||
{
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(_summonerGuid);
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_INTRODUCE_MEAD_HALL, DanicaPath02, DanicaPath02Size::value, false, true);
|
||||
Talk(SAY_SECOND_LINE, player);
|
||||
});
|
||||
break;
|
||||
case POINT_INTRODUCE_MEAD_HALL:
|
||||
_scheduler.Schedule(10s, [this](TaskContext /*context*/)
|
||||
{
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(_summonerGuid);
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_ODYN, DanicaPath03, DanicaPath03Size::value, false, true);
|
||||
Talk(SAY_THIRD_LINE, player);
|
||||
|
||||
if (player)
|
||||
player->KilledMonsterCredit(NPC_KILL_CREDIT_FOLLOWED_DANICA);
|
||||
});
|
||||
break;
|
||||
case POINT_ODYN:
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
// Should be some other way to do this...
|
||||
void OnQuestAccept(Player* player, Quest const* /*quest*/) override
|
||||
{
|
||||
TempSummon* summon = player->SummonCreature(NPC_DANICA_THE_RECLAIMER, 1059.613f, 7224.605f, 100.4608f, 0.03462749f, TEMPSUMMON_MANUAL_DESPAWN, 0s, player->GetGUID());
|
||||
if (!summon)
|
||||
return;
|
||||
|
||||
summon->SetDemonCreatorGUID(player->GetGUID());
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
ObjectGuid _summonerGuid;
|
||||
};
|
||||
|
||||
struct npc_feasting_valarjar : public ScriptedAI
|
||||
{
|
||||
npc_feasting_valarjar(Creature* creature) : ScriptedAI(creature),
|
||||
_randomEmotes({ EMOTE_ONESHOT_EAT_NO_SHEATHE, EMOTE_ONESHOT_LAUGH_NO_SHEATHE, EMOTE_ONESHOT_ROAR, EMOTE_ONESHOT_LAUGH, EMOTE_ONESHOT_POINT,
|
||||
EMOTE_ONESHOT_TALK, EMOTE_ONESHOT_CHEER_NO_SHEATHE }) { }
|
||||
|
||||
enum Points
|
||||
{
|
||||
POINT_LEAVING
|
||||
};
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.Schedule(5s, 30s, [this](TaskContext context)
|
||||
{
|
||||
Emote emoteID = Trinity::Containers::SelectRandomContainerElement(_randomEmotes);
|
||||
if (emoteID == EMOTE_ONESHOT_EAT_NO_SHEATHE)
|
||||
{
|
||||
me->SetVirtualItem(0, urand(0, 1) ? ITEM_MONSTER_ITEM_MUTTON_WITH_BITE : ITEM_MONSTER_ITEM_TANKARD_WOODEN);
|
||||
_scheduler.Schedule(1s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetVirtualItem(0, 0);
|
||||
if (roll_chance_i(85))
|
||||
DoCastSelf(SPELL_EMOTE_BELCH);
|
||||
});
|
||||
}
|
||||
|
||||
me->HandleEmoteCommand(emoteID);
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(5min, 20min, [this](TaskContext /*context*/)
|
||||
{
|
||||
float direction = me->GetOrientation() + M_PI;
|
||||
me->GetMotionMaster()->MovePoint(POINT_LEAVING, me->GetFirstCollisionPosition(5.0f, direction));
|
||||
});
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case POINT_LEAVING:
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::unordered_set<Emote> _randomEmotes;
|
||||
};
|
||||
|
||||
struct npc_valarjar_paying_respect_to_odyn : ScriptedAI
|
||||
{
|
||||
npc_valarjar_paying_respect_to_odyn(Creature* creature) : ScriptedAI(creature),
|
||||
_randomEmotes({ EMOTE_ONESHOT_POINT, EMOTE_ONESHOT_TALK, EMOTE_ONESHOT_NO }) { }
|
||||
|
||||
enum Points
|
||||
{
|
||||
POINT_TABLE,
|
||||
POINT_ODYN,
|
||||
POINT_DESPAWN
|
||||
};
|
||||
|
||||
virtual size_t GetPathToTableSize() const = 0;
|
||||
virtual Position const* GetPathToTable() const = 0;
|
||||
virtual size_t GetPathToOdynSize() const = 0;
|
||||
virtual Position const* GetPathToOdyn() const = 0;
|
||||
virtual size_t GetPathToDespawnPointSize() const = 0;
|
||||
virtual Position const* GetPathToDespawnPoint() const = 0;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_TABLE, GetPathToTable(), GetPathToTableSize(), true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case POINT_TABLE:
|
||||
_scheduler.Schedule(3s, 6s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->HandleEmoteCommand(Trinity::Containers::SelectRandomContainerElement(_randomEmotes));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(7s, 15s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_ODYN, GetPathToOdyn(), GetPathToOdynSize(), true);
|
||||
});
|
||||
break;
|
||||
case POINT_ODYN:
|
||||
_scheduler.Schedule(1s, 3s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->PlayOneShotAnimKitId(1431);
|
||||
_scheduler.Schedule(3s, 10s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_DESPAWN, GetPathToDespawnPoint(), GetPathToDespawnPointSize());
|
||||
});
|
||||
});
|
||||
break;
|
||||
case POINT_DESPAWN:
|
||||
me->DespawnOrUnsummon(2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::unordered_set<Emote> _randomEmotes;
|
||||
};
|
||||
|
||||
struct npc_incoming_valarjar_aspirant_1 : public npc_valarjar_paying_respect_to_odyn
|
||||
{
|
||||
npc_incoming_valarjar_aspirant_1(Creature* creature) : npc_valarjar_paying_respect_to_odyn(creature) { }
|
||||
|
||||
Position const IncommingValarjarAspirantPath01[11] =
|
||||
{
|
||||
{ 876.7396f, 7220.805f, 98.91662f },
|
||||
{ 870.6129f, 7220.945f, 101.8951f },
|
||||
{ 865.0677f, 7220.975f, 103.7846f },
|
||||
{ 854.6389f, 7221.030f, 106.7846f },
|
||||
{ 851.1597f, 7220.292f, 106.7846f },
|
||||
{ 848.0573f, 7216.386f, 106.7846f },
|
||||
{ 844.7570f, 7210.920f, 106.7846f },
|
||||
{ 841.9844f, 7207.228f, 106.7846f },
|
||||
{ 839.2396f, 7203.619f, 107.5846f },
|
||||
{ 836.4844f, 7200.202f, 107.5846f },
|
||||
{ 834.2430f, 7196.000f, 107.5846f }
|
||||
};
|
||||
|
||||
using IncommingValarjarAspirantPath01Size = std::extent<decltype(IncommingValarjarAspirantPath01)>;
|
||||
|
||||
Position const IncommingValarjarAspirantPath02[5] =
|
||||
{
|
||||
{ 828.5851f, 7204.096f, 106.7846f },
|
||||
{ 819.4636f, 7212.124f, 106.7846f },
|
||||
{ 814.2853f, 7215.074f, 106.7846f },
|
||||
{ 809.4948f, 7217.543f, 106.7846f },
|
||||
{ 806.0313f, 7219.614f, 106.7846f }
|
||||
};
|
||||
|
||||
using IncommingValarjarAspirantPath02Size = std::extent<decltype(IncommingValarjarAspirantPath02)>;
|
||||
|
||||
Position const IncommingValarjarAspirantPath03[9] =
|
||||
{
|
||||
{ 824.1597f, 7221.822f, 106.7846f },
|
||||
{ 831.7500f, 7221.092f, 106.7846f },
|
||||
{ 842.4236f, 7222.208f, 106.7846f },
|
||||
{ 853.5781f, 7222.473f, 106.7846f },
|
||||
{ 863.9618f, 7223.012f, 103.7846f },
|
||||
{ 867.9358f, 7223.165f, 103.3735f },
|
||||
{ 880.6215f, 7222.569f, 97.78457f },
|
||||
{ 887.8438f, 7221.310f, 97.78457f },
|
||||
{ 903.7118f, 7215.743f, 97.78458f }
|
||||
};
|
||||
|
||||
using IncommingValarjarAspirantPath03Size = std::extent<decltype(IncommingValarjarAspirantPath03)>;
|
||||
|
||||
size_t GetPathToTableSize() const override { return IncommingValarjarAspirantPath01Size::value; }
|
||||
Position const* GetPathToTable() const override { return IncommingValarjarAspirantPath01; }
|
||||
size_t GetPathToOdynSize() const override { return IncommingValarjarAspirantPath02Size::value; }
|
||||
Position const* GetPathToOdyn() const override { return IncommingValarjarAspirantPath02; }
|
||||
size_t GetPathToDespawnPointSize() const override { return IncommingValarjarAspirantPath03Size::value; }
|
||||
Position const* GetPathToDespawnPoint() const override { return IncommingValarjarAspirantPath03; }
|
||||
};
|
||||
|
||||
struct npc_incoming_valarjar_aspirant_2 : public npc_valarjar_paying_respect_to_odyn
|
||||
{
|
||||
npc_incoming_valarjar_aspirant_2(Creature* creature) : npc_valarjar_paying_respect_to_odyn(creature) { }
|
||||
|
||||
Position const IncommingValarjarAspirantPath01[12] =
|
||||
{
|
||||
{ 890.5521f, 7235.710f, 97.78457f },
|
||||
{ 883.8073f, 7233.402f, 97.78457f },
|
||||
{ 872.1979f, 7234.018f, 101.2886f },
|
||||
{ 863.5941f, 7234.594f, 103.7846f },
|
||||
{ 855.2899f, 7235.626f, 106.7593f },
|
||||
{ 849.8177f, 7236.571f, 106.7846f },
|
||||
{ 845.7830f, 7241.082f, 106.7846f },
|
||||
{ 841.8489f, 7246.654f, 106.7846f },
|
||||
{ 839.7205f, 7250.986f, 106.7846f },
|
||||
{ 840.8889f, 7254.773f, 107.5846f },
|
||||
{ 841.9254f, 7259.517f, 107.5846f },
|
||||
{ 840.6077f, 7266.662f, 107.5846f }
|
||||
};
|
||||
|
||||
using IncommingValarjarAspirantPath01Size = std::extent<decltype(IncommingValarjarAspirantPath01)>;
|
||||
|
||||
Position const IncommingValarjarAspirantPath02[6] =
|
||||
{
|
||||
{ 838.1493f, 7260.027f, 107.5846f },
|
||||
{ 832.2691f, 7253.756f, 106.7846f },
|
||||
{ 823.1996f, 7246.677f, 106.7846f },
|
||||
{ 821.2500f, 7244.573f, 106.7846f },
|
||||
{ 815.8906f, 7241.437f, 106.7846f },
|
||||
{ 809.8281f, 7239.580f, 106.7846f }
|
||||
};
|
||||
|
||||
using IncommingValarjarAspirantPath02Size = std::extent<decltype(IncommingValarjarAspirantPath02)>;
|
||||
|
||||
Position const IncommingValarjarAspirantPath03[10] =
|
||||
{
|
||||
{ 827.4757f, 7236.593f, 106.7846f },
|
||||
{ 837.1840f, 7236.047f, 106.7846f },
|
||||
{ 847.1684f, 7235.377f, 106.7846f },
|
||||
{ 854.7185f, 7235.294f, 106.7846f },
|
||||
{ 862.3524f, 7234.287f, 104.4290f },
|
||||
{ 882.3489f, 7233.743f, 97.78457f },
|
||||
{ 894.3768f, 7233.098f, 97.78457f },
|
||||
{ 906.0660f, 7232.520f, 97.78458f },
|
||||
{ 915.0070f, 7233.368f, 97.78458f },
|
||||
{ 924.6910f, 7233.694f, 97.78458f }
|
||||
};
|
||||
|
||||
using IncommingValarjarAspirantPath03Size = std::extent<decltype(IncommingValarjarAspirantPath03)>;
|
||||
|
||||
size_t GetPathToTableSize() const override { return IncommingValarjarAspirantPath01Size::value; }
|
||||
Position const* GetPathToTable() const override { return IncommingValarjarAspirantPath01; }
|
||||
size_t GetPathToOdynSize() const override { return IncommingValarjarAspirantPath02Size::value; }
|
||||
Position const* GetPathToOdyn() const override { return IncommingValarjarAspirantPath02; }
|
||||
size_t GetPathToDespawnPointSize() const override { return IncommingValarjarAspirantPath03Size::value; }
|
||||
Position const* GetPathToDespawnPoint() const override { return IncommingValarjarAspirantPath03; }
|
||||
};
|
||||
|
||||
struct npc_leaving_valarjar_1 : public npc_valarjar_paying_respect_to_odyn
|
||||
{
|
||||
npc_leaving_valarjar_1(Creature* creature) : npc_valarjar_paying_respect_to_odyn(creature) { }
|
||||
|
||||
Position const PathLeavingValarjar01[8] =
|
||||
{
|
||||
{ 802.5903f, 7304.605f, 106.7846f },
|
||||
{ 809.3333f, 7296.529f, 106.7846f },
|
||||
{ 811.8004f, 7293.676f, 106.7846f },
|
||||
{ 817.4219f, 7287.498f, 106.7846f },
|
||||
{ 821.0313f, 7283.637f, 106.7846f },
|
||||
{ 822.1111f, 7275.672f, 106.7846f },
|
||||
{ 826.4662f, 7270.601f, 107.5846f },
|
||||
{ 830.8212f, 7268.729f, 107.5846f }
|
||||
};
|
||||
|
||||
using PathLeavingValarjar01Size = std::extent<decltype(PathLeavingValarjar01)>;
|
||||
|
||||
Position const PathLeavingValarjar02[6] =
|
||||
{
|
||||
{ 824.9757f, 7261.047f, 107.5846f },
|
||||
{ 822.0989f, 7256.705f, 106.7846f },
|
||||
{ 819.0261f, 7253.674f, 106.7846f },
|
||||
{ 813.1910f, 7249.034f, 106.7846f },
|
||||
{ 809.1493f, 7245.616f, 106.7846f },
|
||||
{ 806.3559f, 7243.057f, 106.7846f }
|
||||
};
|
||||
|
||||
using PathLeavingValarjar02Size = std::extent<decltype(PathLeavingValarjar02)>;
|
||||
|
||||
Position const PathLeavingValarjar03[10] =
|
||||
{
|
||||
{ 825.3177f, 7244.253f, 106.7846f },
|
||||
{ 837.5816f, 7243.241f, 106.7846f },
|
||||
{ 845.0243f, 7240.063f, 106.7846f },
|
||||
{ 853.7274f, 7238.423f, 106.7953f },
|
||||
{ 862.9948f, 7238.000f, 103.9737f },
|
||||
{ 872.7899f, 7236.939f, 100.8285f },
|
||||
{ 882.8333f, 7235.922f, 97.78457f },
|
||||
{ 897.2813f, 7235.469f, 97.78457f },
|
||||
{ 908.8090f, 7234.836f, 97.78458f },
|
||||
{ 919.8750f, 7238.241f, 97.78458f }
|
||||
};
|
||||
|
||||
using PathLeavingValarjar03Size = std::extent<decltype(PathLeavingValarjar03)>;
|
||||
|
||||
size_t GetPathToTableSize() const override { return PathLeavingValarjar01Size::value; }
|
||||
Position const* GetPathToTable() const override { return PathLeavingValarjar01; }
|
||||
size_t GetPathToOdynSize() const override { return PathLeavingValarjar02Size::value; }
|
||||
Position const* GetPathToOdyn() const override { return PathLeavingValarjar02; }
|
||||
size_t GetPathToDespawnPointSize() const override { return PathLeavingValarjar03Size::value; }
|
||||
Position const* GetPathToDespawnPoint() const override { return PathLeavingValarjar03; }
|
||||
};
|
||||
|
||||
struct npc_leaving_valarjar_2 : public npc_valarjar_paying_respect_to_odyn
|
||||
{
|
||||
npc_leaving_valarjar_2(Creature* creature) : npc_valarjar_paying_respect_to_odyn(creature) { }
|
||||
|
||||
Position const PathLeavingValarjar01[7] =
|
||||
{
|
||||
{ 787.2361f, 7155.902f, 107.5846f },
|
||||
{ 792.4844f, 7154.038f, 106.7846f },
|
||||
{ 798.7830f, 7154.968f, 106.7846f },
|
||||
{ 807.8160f, 7162.251f, 106.7846f },
|
||||
{ 813.2882f, 7167.856f, 106.7846f },
|
||||
{ 816.4913f, 7170.818f, 106.7846f },
|
||||
{ 819.8299f, 7166.373f, 107.6281f }
|
||||
};
|
||||
|
||||
using PathLeavingValarjar01Size = std::extent<decltype(PathLeavingValarjar01)>;
|
||||
|
||||
Position const PathLeavingValarjar02[7] =
|
||||
{
|
||||
{ 818.2708f, 7175.469f, 106.7846f },
|
||||
{ 819.5643f, 7185.691f, 106.7846f },
|
||||
{ 818.4184f, 7193.082f, 106.7846f },
|
||||
{ 818.8750f, 7199.256f, 106.7846f },
|
||||
{ 815.2361f, 7203.648f, 106.7846f },
|
||||
{ 809.6198f, 7208.319f, 106.7846f },
|
||||
{ 804.2743f, 7215.379f, 106.7846f }
|
||||
};
|
||||
|
||||
using PathLeavingValarjar02Size = std::extent<decltype(PathLeavingValarjar02)>;
|
||||
|
||||
Position const PathLeavingValarjar03[6] =
|
||||
{
|
||||
{ 810.8403f, 7231.531f, 106.7846f },
|
||||
{ 807.5087f, 7248.719f, 106.7846f },
|
||||
{ 801.2587f, 7254.592f, 106.7846f },
|
||||
{ 794.6649f, 7265.814f, 107.5846f },
|
||||
{ 792.0191f, 7274.151f, 107.5846f },
|
||||
{ 790.1823f, 7282.182f, 107.5846f }
|
||||
};
|
||||
|
||||
using PathLeavingValarjar03Size = std::extent<decltype(PathLeavingValarjar03)>;
|
||||
|
||||
size_t GetPathToTableSize() const override { return PathLeavingValarjar01Size::value; }
|
||||
Position const* GetPathToTable() const override { return PathLeavingValarjar01; }
|
||||
size_t GetPathToOdynSize() const override { return PathLeavingValarjar02Size::value; }
|
||||
Position const* GetPathToOdyn() const override { return PathLeavingValarjar02; }
|
||||
size_t GetPathToDespawnPointSize() const override { return PathLeavingValarjar03Size::value; }
|
||||
Position const* GetPathToDespawnPoint() const override { return PathLeavingValarjar03; }
|
||||
};
|
||||
|
||||
struct npc_odyn : public ScriptedAI
|
||||
{
|
||||
npc_odyn(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
// Should be an better way of doing this...
|
||||
// What about a QuestScript with a hook "OnPlayerChangeArea" ? But The Great Mead Hall does not have a specific area...
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (Player* player = who->ToPlayer())
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_ODYN_AND_THE_VALARJAR) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
if (player->IsInDist(me, 60.0f))
|
||||
{
|
||||
player->KilledMonsterCredit(NPC_KILL_CREDIT_ARRIVED_AT_ODYN); // SPELL_WARRIOR_ORDER_FORMATION_SCENE does not has this credit.
|
||||
player->CastSpell(player, SPELL_WARRIOR_ORDER_FORMATION_SCENE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_spectating_valarjar : public ScriptedAI
|
||||
{
|
||||
npc_spectating_valarjar(Creature* creature) : ScriptedAI(creature),
|
||||
_randomEmotes({ EMOTE_ONESHOT_CHEER_NO_SHEATHE, EMOTE_ONESHOT_SALUTE, EMOTE_ONESHOT_ROAR, EMOTE_ONESHOT_POINT, EMOTE_ONESHOT_SHOUT }) { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.Schedule(5s, 30s, [this](TaskContext context)
|
||||
{
|
||||
me->HandleEmoteCommand(Trinity::Containers::SelectRandomContainerElement(_randomEmotes));
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(5min, 20min, [this](TaskContext /*context*/)
|
||||
{
|
||||
float direction = me->GetOrientation() + M_PI;
|
||||
me->GetMotionMaster()->MovePoint(0, me->GetFirstCollisionPosition(5.0f, direction));
|
||||
});
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0:
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::unordered_set<Emote> _randomEmotes;
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn : public ScriptedAI
|
||||
{
|
||||
npc_valkyr_of_odyn(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
virtual Position const* GetPath() const = 0;
|
||||
virtual size_t GetPathSize() const = 0;
|
||||
|
||||
enum Points
|
||||
{
|
||||
POINT_DESPAWN = 1,
|
||||
POINT_JUMP,
|
||||
POINT_DESPAWN_JUMP
|
||||
};
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (me->GetPositionZ() >= 100.0f)
|
||||
{
|
||||
_scheduler.Schedule(3s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_JUMP, GetPath(), GetPathSize(), false, true);
|
||||
});
|
||||
}
|
||||
else
|
||||
me->GetMotionMaster()->MoveSmoothPath(POINT_DESPAWN, GetPath(), GetPathSize(), false, true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case POINT_JUMP:
|
||||
_scheduler.Schedule(250ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
/*
|
||||
* (MovementMonsterSpline) (MovementSpline) MoveTime: 3111
|
||||
* (MovementMonsterSpline) (MovementSpline) JumpGravity: 19.2911 -> +-Movement::gravity
|
||||
* 1.4125f is guessed value. Which makes the JumpGravity way closer to the intended one. Not sure how to do it 100% blizzlike.
|
||||
* Also the MoveTime is not correct but I don't know how to set it here.
|
||||
*/
|
||||
me->GetMotionMaster()->MoveJump({ 1107.84f, 7222.57f, 38.9725f, me->GetOrientation() }, me->GetSpeed(MOVE_RUN), Movement::gravity * 1.4125f, POINT_DESPAWN_JUMP);
|
||||
});
|
||||
break;
|
||||
case POINT_DESPAWN:
|
||||
me->DespawnOrUnsummon(500ms);
|
||||
break;
|
||||
case POINT_DESPAWN_JUMP:
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_1 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_1(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[7] =
|
||||
{
|
||||
{ 996.5347f, 7321.393f, 124.0931f },
|
||||
{ 1009.880f, 7311.655f, 118.0898f },
|
||||
{ 1024.688f, 7293.689f, 120.4009f },
|
||||
{ 1038.288f, 7266.321f, 122.2708f },
|
||||
{ 1049.439f, 7235.418f, 120.1065f },
|
||||
{ 1067.825f, 7229.589f, 114.6320f },
|
||||
{ 1082.800f, 7223.660f, 98.63562f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_2 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_2(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[18] =
|
||||
{
|
||||
{ 1113.635f, 7214.023f, 7.808200f },
|
||||
{ 1110.443f, 7213.999f, 17.28479f },
|
||||
{ 1108.583f, 7213.984f, 22.80371f },
|
||||
{ 1103.488f, 7221.702f, 70.68047f },
|
||||
{ 1101.911f, 7222.535f, 82.51234f },
|
||||
{ 1098.861f, 7222.271f, 90.03111f },
|
||||
{ 1095.129f, 7223.033f, 94.15130f },
|
||||
{ 1089.240f, 7223.335f, 97.94925f },
|
||||
{ 1077.932f, 7222.822f, 110.2143f },
|
||||
{ 1068.802f, 7223.216f, 110.2143f },
|
||||
{ 1045.356f, 7224.674f, 114.5371f },
|
||||
{ 1023.946f, 7224.304f, 120.0150f },
|
||||
{ 1002.535f, 7224.943f, 121.1011f },
|
||||
{ 911.7552f, 7227.165f, 121.7384f },
|
||||
{ 879.1285f, 7227.272f, 121.7384f },
|
||||
{ 830.8785f, 7233.613f, 121.7384f },
|
||||
{ 809.5052f, 7267.270f, 121.7384f },
|
||||
{ 795.2899f, 7311.849f, 121.7384f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_3 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_3(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[14] =
|
||||
{
|
||||
{ 1133.929f, 7223.167f, 38.90330f },
|
||||
{ 1124.510f, 7222.310f, 42.15336f },
|
||||
{ 1119.903f, 7221.891f, 43.74335f },
|
||||
{ 1103.934f, 7227.212f, 69.99904f },
|
||||
{ 1097.554f, 7226.132f, 89.09371f },
|
||||
{ 1092.602f, 7224.059f, 101.1545f },
|
||||
{ 1078.701f, 7228.348f, 109.5599f },
|
||||
{ 1068.967f, 7232.247f, 116.7876f },
|
||||
{ 1053.540f, 7229.623f, 117.8927f },
|
||||
{ 1044.104f, 7242.757f, 118.7891f },
|
||||
{ 1031.111f, 7256.717f, 118.7891f },
|
||||
{ 1029.684f, 7288.019f, 126.3048f },
|
||||
{ 1029.889f, 7325.333f, 126.3061f },
|
||||
{ 1039.043f, 7365.176f, 133.2310f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_4 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_4(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[7] =
|
||||
{
|
||||
{ 914.8663f, 7204.922f, 128.1687f },
|
||||
{ 945.4445f, 7216.170f, 128.1687f },
|
||||
{ 987.2483f, 7220.554f, 125.4318f },
|
||||
{ 1015.882f, 7222.849f, 126.0546f },
|
||||
{ 1053.023f, 7224.076f, 119.6729f },
|
||||
{ 1071.891f, 7222.934f, 108.9545f },
|
||||
{ 1081.530f, 7224.331f, 98.63076f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_5 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_5(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[12] =
|
||||
{
|
||||
{ 1038.141f, 7134.033f, 105.8965f },
|
||||
{ 1033.373f, 7134.492f, 105.8965f },
|
||||
{ 1027.882f, 7136.373f, 105.8965f },
|
||||
{ 1026.943f, 7144.288f, 105.8965f },
|
||||
{ 1027.608f, 7167.030f, 108.4167f },
|
||||
{ 1027.767f, 7180.922f, 108.4167f },
|
||||
{ 1028.484f, 7197.977f, 108.4167f },
|
||||
{ 1034.113f, 7207.747f, 108.4167f },
|
||||
{ 1041.977f, 7216.452f, 108.4167f },
|
||||
{ 1054.269f, 7223.207f, 108.4167f },
|
||||
{ 1075.891f, 7224.811f, 101.7954f },
|
||||
{ 1082.438f, 7224.540f, 99.12900f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_6 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_6(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[17] =
|
||||
{
|
||||
{ 1112.011f, 7233.799f, 45.87240f },
|
||||
{ 1107.887f, 7234.073f, 54.97818f },
|
||||
{ 1106.264f, 7234.181f, 58.56218f },
|
||||
{ 1099.969f, 7236.397f, 75.87664f },
|
||||
{ 1096.552f, 7233.196f, 85.53920f },
|
||||
{ 1095.531f, 7229.387f, 89.86687f },
|
||||
{ 1092.981f, 7225.366f, 97.69602f },
|
||||
{ 1082.800f, 7221.249f, 109.4660f },
|
||||
{ 1070.983f, 7218.749f, 112.6827f },
|
||||
{ 1057.455f, 7216.709f, 112.6827f },
|
||||
{ 1051.859f, 7210.338f, 112.6827f },
|
||||
{ 1042.427f, 7200.762f, 112.6827f },
|
||||
{ 1032.616f, 7183.982f, 112.6827f },
|
||||
{ 1027.792f, 7157.764f, 112.6827f },
|
||||
{ 1026.870f, 7126.981f, 112.6827f },
|
||||
{ 1053.083f, 7102.808f, 125.9283f },
|
||||
{ 1055.122f, 7059.807f, 130.4395f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_valkyr_of_odyn_7 : public npc_valkyr_of_odyn
|
||||
{
|
||||
npc_valkyr_of_odyn_7(Creature* creature) : npc_valkyr_of_odyn(creature) { }
|
||||
|
||||
Position const Path[10] =
|
||||
{
|
||||
{ 1064.076f, 7305.979f, 117.5428f },
|
||||
{ 1058.290f, 7305.543f, 117.5428f },
|
||||
{ 1046.578f, 7305.583f, 117.5428f },
|
||||
{ 1034.373f, 7295.979f, 117.5428f },
|
||||
{ 1026.639f, 7275.582f, 114.1900f },
|
||||
{ 1030.729f, 7251.381f, 114.1900f },
|
||||
{ 1040.950f, 7237.213f, 114.1900f },
|
||||
{ 1057.274f, 7229.228f, 114.1900f },
|
||||
{ 1070.297f, 7226.421f, 111.7502f },
|
||||
{ 1082.146f, 7225.846f, 101.0798f }
|
||||
};
|
||||
|
||||
using PathSize = std::extent<decltype(Path)>;
|
||||
|
||||
Position const* GetPath() const override { return Path; }
|
||||
size_t GetPathSize() const override { return PathSize::value; }
|
||||
};
|
||||
|
||||
struct npc_weapon_inspector_valarjar : public ScriptedAI
|
||||
{
|
||||
npc_weapon_inspector_valarjar(Creature* creature) : ScriptedAI(creature),
|
||||
_randomWeapons({ { ITEM_HOV_2H_AXE, 0 }, { ITEM_HOV_1H_SWORD, ITEM_HOV_SHIELD_2 } }) { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.Schedule(15s, 20s, [this](TaskContext context)
|
||||
{
|
||||
me->SetAIAnimKitId(0);
|
||||
std::pair<uint32, uint32> weapons = Trinity::Containers::SelectRandomContainerElement(_randomWeapons);
|
||||
me->SetVirtualItem(0, weapons.first);
|
||||
me->SetVirtualItem(1, weapons.second);
|
||||
|
||||
context.Schedule(8s, 10s, [this](TaskContext context)
|
||||
{
|
||||
me->SetVirtualItem(0, 0);
|
||||
me->SetVirtualItem(1, 0);
|
||||
context.Schedule(10s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetAIAnimKitId(1583);
|
||||
});
|
||||
});
|
||||
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::unordered_set<std::pair<uint32, uint32>> _randomWeapons;
|
||||
};
|
||||
|
||||
class scene_odyn_intro : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_odyn_intro() : SceneScript("scene_odyn_intro") { }
|
||||
|
||||
void OnSceneStart(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
PhasingHandler::RemovePhase(player, PHASE_DANICA, false);
|
||||
PhasingHandler::RemovePhase(player, PHASE_ODYN, true);
|
||||
player->SetControlled(true, UNIT_STATE_ROOT);
|
||||
}
|
||||
|
||||
// Called when a scene is canceled
|
||||
void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
Finish(player);
|
||||
}
|
||||
|
||||
// Called when a scene is completed
|
||||
void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
Finish(player);
|
||||
}
|
||||
|
||||
void Finish(Player* player)
|
||||
{
|
||||
PhasingHandler::AddPhase(player, PHASE_ODYN, true);
|
||||
player->SetControlled(false, UNIT_STATE_ROOT);
|
||||
player->CastSpell(player, SPELL_CANCEL_COMPLETE_SCENE_WARRIOR_ORDER_FORMATION);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_orderhall_warrior()
|
||||
{
|
||||
RegisterCreatureAI(npc_danica_the_reclaimer);
|
||||
RegisterCreatureAI(npc_feasting_valarjar);
|
||||
RegisterCreatureAI(npc_incoming_valarjar_aspirant_1);
|
||||
RegisterCreatureAI(npc_incoming_valarjar_aspirant_2);
|
||||
RegisterCreatureAI(npc_leaving_valarjar_1);
|
||||
RegisterCreatureAI(npc_leaving_valarjar_2);
|
||||
RegisterCreatureAI(npc_odyn);
|
||||
RegisterCreatureAI(npc_spectating_valarjar);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_1);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_2);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_3);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_4);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_5);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_6);
|
||||
RegisterCreatureAI(npc_valkyr_of_odyn_7);
|
||||
RegisterCreatureAI(npc_weapon_inspector_valarjar);
|
||||
new scene_odyn_intro();
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_assault_on_the_dark_portal();
|
||||
void AddSC_draenor_shadowmoon_valley();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddDraenorScripts()
|
||||
{
|
||||
AddSC_assault_on_the_dark_portal();
|
||||
AddSC_draenor_shadowmoon_valley();
|
||||
}
|
||||
@@ -1,456 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedFollowerAI.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
enum AssaultOnTheDarkPortalSpells
|
||||
{
|
||||
SPELL_ALTAR_ALTERCATION_CANCEL_AURAS = 167547, // Serverside Spell
|
||||
SPELL_BLEEDING_HOLLOW_HOLDOUT = 164609,
|
||||
SPELL_BLEEDING_HOLLOW_KILROGG_REVEAL = 161771,
|
||||
SPELL_BLEEDING_HOLLOW_TRAIL_OF_FLAME = 164611,
|
||||
SPELL_BLEEDING_HOLLOW_SNEAKY_ARMY = 165061,
|
||||
SPELL_BLOOD_RITUAL_ORB_BEAM = 170044,
|
||||
SPELL_CANCEL_PHASE_AURA = 165053,
|
||||
SPELL_CANCEL_TRAIL_OF_FLAME_VISUAL = 165993,
|
||||
SPELL_DARK_PORTAL_RUN_AWAY = 158985,
|
||||
SPELL_HUT_CREDIT = 164613, // Serverside Spell
|
||||
SPELL_ON_ALTAR = 161637,
|
||||
SPELL_PUSH_ARMY = 165072,
|
||||
SPELL_TRAIL_OF_FLAME_LARGE = 165991,
|
||||
SPELL_UPDATE_PHASE_SHIFT_PLAYER = 82238
|
||||
};
|
||||
|
||||
enum AssaultOnTheDarkPortalQuests
|
||||
{
|
||||
QUEST_FLAG_ARMY_PUSHED = 35297,
|
||||
QUEST_ALTAR_ALTERCATION = 34423,
|
||||
};
|
||||
|
||||
enum AssaultOnTheDarkPortalQuestObjectives
|
||||
{
|
||||
OBJECTIVE_ALTAR_ALTERCATION_SPEAK_WITH_ARIOK = 273075,
|
||||
OBJECTIVE_ALTAR_ALTERCATION_ESCORT_ARIOK = 273677,
|
||||
};
|
||||
|
||||
enum AssaultOnTheDarkPortalNPCs
|
||||
{
|
||||
NPC_ALTAR_ALTERCATION_ARIOK = 80087,
|
||||
NPC_ALTAR_ALTERCATION_KILROGG = 81926,
|
||||
NPC_BLEEDING_HOLLOW_BLOODCHOSEN = 81895
|
||||
};
|
||||
|
||||
enum AssaultOnTheDarkPortalTexts
|
||||
{
|
||||
// Ariok
|
||||
SAY_ARIOK_INTRO_1 = 0,
|
||||
SAY_ARIOK_INTRO_2 = 1,
|
||||
SAY_ARIOK_INTRO_3 = 2,
|
||||
SAY_ARIOK_ON_ALTAR_1 = 3,
|
||||
SAY_ARIOK_ON_ALTAR_2 = 4,
|
||||
SAY_ARIOK_MIDDLE_ORB_INTERACT = 5,
|
||||
SAY_ARIOK_ALTAR_KILROGG_REVEAL = 6,
|
||||
|
||||
// Kilrogg
|
||||
SAY_KILROGG_WEST_ORB_INTERACT = 0,
|
||||
SAY_KILROGG_ENTER_ALTAR_AT = 1
|
||||
};
|
||||
|
||||
enum AssaultOnTheDarkPortalActions
|
||||
{
|
||||
ACTION_INTRO = 1,
|
||||
ACTION_ON_ALTAR = 2
|
||||
};
|
||||
|
||||
enum AssaultOnTheDarkPortalEvents
|
||||
{
|
||||
EVENT_TALK_1 = 1,
|
||||
EVENT_TALK_2,
|
||||
EVENT_TALK_3,
|
||||
EVENT_ALTAR
|
||||
};
|
||||
|
||||
// 621 - Dark Portal: Run away
|
||||
class scene_dark_portal_run_away : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_dark_portal_run_away() : SceneScript("scene_dark_portal_run_away") { }
|
||||
|
||||
void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->RemoveAurasDueToSpell(SPELL_DARK_PORTAL_RUN_AWAY);
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
}
|
||||
};
|
||||
|
||||
// 34420 - The Cost of War
|
||||
class quest_the_cost_of_war : public QuestScript
|
||||
{
|
||||
public:
|
||||
quest_the_cost_of_war() : QuestScript("quest_the_cost_of_war") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
|
||||
{
|
||||
if (newStatus == QUEST_STATUS_NONE)
|
||||
{
|
||||
player->RemoveAurasDueToSpell(SPELL_DARK_PORTAL_RUN_AWAY);
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
}
|
||||
else if (newStatus == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
player->CastSpell(player, SPELL_DARK_PORTAL_RUN_AWAY, TRIGGERED_FULL_MASK);
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 34422 - Blaze of Glory
|
||||
class quest_blaze_of_glory : public QuestScript
|
||||
{
|
||||
public:
|
||||
quest_blaze_of_glory() : QuestScript("quest_blaze_of_glory") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
|
||||
{
|
||||
if (newStatus == QUEST_STATUS_NONE)
|
||||
{
|
||||
player->RemoveAurasDueToSpell(SPELL_BLEEDING_HOLLOW_HOLDOUT);
|
||||
player->RemoveAurasDueToSpell(SPELL_BLEEDING_HOLLOW_TRAIL_OF_FLAME);
|
||||
player->RemoveAurasDueToSpell(SPELL_PUSH_ARMY);
|
||||
player->RemoveRewardedQuest(QUEST_FLAG_ARMY_PUSHED);
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
}
|
||||
else if (newStatus == QUEST_STATUS_INCOMPLETE)
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
else if (newStatus == QUEST_STATUS_COMPLETE)
|
||||
player->RemoveAurasDueToSpell(SPELL_BLEEDING_HOLLOW_TRAIL_OF_FLAME);
|
||||
}
|
||||
};
|
||||
|
||||
// 770 - Bleeding Hollow: Holdout
|
||||
class scene_bleeding_hollow_holdout : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_bleeding_hollow_holdout() : SceneScript("scene_bleeding_hollow_holdout") { }
|
||||
|
||||
void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->RemoveAurasDueToSpell(SPELL_BLEEDING_HOLLOW_HOLDOUT);
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
}
|
||||
|
||||
void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& triggerName) override
|
||||
{
|
||||
if (triggerName == "Push")
|
||||
player->CastSpell(player, SPELL_PUSH_ARMY, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 771 - Bleeding Hollow: Trail of Flame
|
||||
class scene_bleeding_hollow_trail_of_flame : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_bleeding_hollow_trail_of_flame() : SceneScript("scene_bleeding_hollow_trail_of_flame") { }
|
||||
|
||||
void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& triggerName) override
|
||||
{
|
||||
if (triggerName == "Visual")
|
||||
player->CastSpell(player, SPELL_TRAIL_OF_FLAME_LARGE, true);
|
||||
else if (triggerName == "Clear")
|
||||
player->CastSpell(player, SPELL_CANCEL_TRAIL_OF_FLAME_VISUAL, true);
|
||||
else if (triggerName == "Credit")
|
||||
player->CastSpell(player, SPELL_HUT_CREDIT, true);
|
||||
}
|
||||
};
|
||||
|
||||
// 34423 - Altar Altercation
|
||||
class quest_altar_altercation : public QuestScript
|
||||
{
|
||||
public:
|
||||
quest_altar_altercation() : QuestScript("quest_altar_altercation") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
|
||||
{
|
||||
if (newStatus == QUEST_STATUS_NONE)
|
||||
player->CastSpell(player, SPELL_ALTAR_ALTERCATION_CANCEL_AURAS, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
// 161618 - Summon Ariok
|
||||
class spell_altar_altercation_summon_ariok : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_UPDATE_PHASE_SHIFT_PLAYER });
|
||||
}
|
||||
|
||||
void HandleOnCast()
|
||||
{
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_UPDATE_PHASE_SHIFT_PLAYER, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
BeforeCast += SpellCastFn(spell_altar_altercation_summon_ariok::HandleOnCast);
|
||||
}
|
||||
};
|
||||
|
||||
// 694 - Bleeding Hollow: Kilrogg Reveal
|
||||
class scene_bleeding_hollow_kilrogg_reveal : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_bleeding_hollow_kilrogg_reveal() : SceneScript("scene_bleeding_hollow_kilrogg_reveal") { }
|
||||
|
||||
void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->CastSpell(player, SPELL_CANCEL_PHASE_AURA, false);
|
||||
}
|
||||
|
||||
void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& triggerName) override
|
||||
{
|
||||
if (triggerName == "FreeCamera")
|
||||
player->CastSpell(player, SPELL_CANCEL_PHASE_AURA, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 167955 - Destroying
|
||||
class spell_altar_altercation_destroying : public SpellScript
|
||||
{
|
||||
void HandleOnHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* creature = GetHitUnit()->ToCreature();
|
||||
if (!creature)
|
||||
return;
|
||||
|
||||
creature->DespawnOrUnsummon(); // @TODO: Spawntracking should cause despawn for casting player only and respawn on abandon quest
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_altar_altercation_destroying::HandleOnHit, EFFECT_1, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 80087 - Ariok
|
||||
struct npc_altar_altercation_ariok : public FollowerAI
|
||||
{
|
||||
npc_altar_altercation_ariok(Creature* creature) : FollowerAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoAction(ACTION_INTRO);
|
||||
|
||||
if (TempSummon const* tempSummon = me->ToTempSummon())
|
||||
{
|
||||
if (Player* summoner = tempSummon->GetSummoner()->ToPlayer())
|
||||
{
|
||||
if (!summoner)
|
||||
return;
|
||||
|
||||
StartFollow(summoner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_INTRO:
|
||||
{
|
||||
events.ScheduleEvent(EVENT_TALK_1, 1s);
|
||||
break;
|
||||
}
|
||||
case ACTION_ON_ALTAR:
|
||||
{
|
||||
Talk(SAY_ARIOK_ON_ALTAR_1);
|
||||
me->AddUnitState(UNIT_STATE_ROOT);
|
||||
events.ScheduleEvent(EVENT_ALTAR, 5s + 400ms);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_TALK_1:
|
||||
Talk(SAY_ARIOK_INTRO_1);
|
||||
events.ScheduleEvent(EVENT_TALK_2, 5s + 700ms);
|
||||
break;
|
||||
case EVENT_TALK_2:
|
||||
Talk(SAY_ARIOK_INTRO_2);
|
||||
events.ScheduleEvent(EVENT_TALK_3, 7s + 400ms);
|
||||
break;
|
||||
case EVENT_TALK_3:
|
||||
Talk(SAY_ARIOK_INTRO_3);
|
||||
break;
|
||||
case EVENT_ALTAR:
|
||||
me->ClearUnitState(UNIT_STATE_ROOT);
|
||||
Talk(SAY_ARIOK_ON_ALTAR_2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
// 164979 - (Serverside/Non-DB2) Trigger Ariok
|
||||
class spell_trigger_ariok_altar_altercation : public SpellScript
|
||||
{
|
||||
void HandleOnHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* creature = GetHitUnit()->ToCreature();
|
||||
|
||||
if (!creature)
|
||||
return;
|
||||
|
||||
if (GetCaster()->HasAura(SPELL_BLEEDING_HOLLOW_KILROGG_REVEAL))
|
||||
{
|
||||
creature->AI()->Talk(SAY_ARIOK_ALTAR_KILROGG_REVEAL);
|
||||
creature->DespawnOrUnsummon();
|
||||
}
|
||||
else if (GetCaster()->HasAura(SPELL_ON_ALTAR))
|
||||
creature->AI()->DoAction(ACTION_ON_ALTAR);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_trigger_ariok_altar_altercation::HandleOnHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 83670 - Blood Ritual Orb
|
||||
struct npc_altar_altercation_blood_ritual_orb : public ScriptedAI
|
||||
{
|
||||
npc_altar_altercation_blood_ritual_orb(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
if (Creature* bloodChosen = me->FindNearestCreature(NPC_BLEEDING_HOLLOW_BLOODCHOSEN, 50.0f))
|
||||
me->CastSpell(bloodChosen, SPELL_BLOOD_RITUAL_ORB_BEAM, true);
|
||||
}
|
||||
|
||||
void OnSpellClick(Unit* clicker, bool /*spellClickHandled*/) override
|
||||
{
|
||||
if (me->HasStringId("west_orb"))
|
||||
{
|
||||
Creature* kilrogg = clicker->FindNearestCreatureWithOptions(50.0f, { .CreatureId = NPC_ALTAR_ALTERCATION_KILROGG, .IgnorePhases = true });
|
||||
if (!kilrogg)
|
||||
return;
|
||||
|
||||
kilrogg->AI()->Talk(SAY_KILROGG_WEST_ORB_INTERACT, clicker);
|
||||
}
|
||||
else if (me->HasStringId("middle_orb"))
|
||||
{
|
||||
Creature* ariok = clicker->FindNearestCreatureWithOptions(50.0f, { .CreatureId = NPC_ALTAR_ALTERCATION_ARIOK, .IsSummon = true, .IgnorePhases = true, .OwnerGuid = clicker->GetGUID() });
|
||||
if (!ariok)
|
||||
return;
|
||||
|
||||
clicker->CastSpell(clicker, SPELL_BLEEDING_HOLLOW_SNEAKY_ARMY, true);
|
||||
ariok->AI()->Talk(SAY_ARIOK_MIDDLE_ORB_INTERACT);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
UpdateVictim();
|
||||
}
|
||||
};
|
||||
|
||||
// Id - 52
|
||||
struct at_altar_altercation_kilrogg_talk : AreaTriggerAI
|
||||
{
|
||||
at_altar_altercation_kilrogg_talk(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
Creature* kilrogg = unit->FindNearestCreature(NPC_ALTAR_ALTERCATION_KILROGG, 100.0f);
|
||||
if (!kilrogg)
|
||||
return;
|
||||
|
||||
kilrogg->AI()->Talk(SAY_KILROGG_ENTER_ALTAR_AT, player);
|
||||
}
|
||||
};
|
||||
|
||||
// Id - 50
|
||||
struct at_altar_altercation_reach_altar : AreaTriggerAI
|
||||
{
|
||||
at_altar_altercation_reach_altar(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (!player->IsQuestObjectiveComplete(QUEST_ALTAR_ALTERCATION, OBJECTIVE_ALTAR_ALTERCATION_SPEAK_WITH_ARIOK))
|
||||
return;
|
||||
|
||||
if (player->IsQuestObjectiveComplete(QUEST_ALTAR_ALTERCATION, OBJECTIVE_ALTAR_ALTERCATION_ESCORT_ARIOK))
|
||||
return;
|
||||
|
||||
player->CastSpell(nullptr, SPELL_ON_ALTAR);
|
||||
}
|
||||
|
||||
void OnUnitExit(Unit* unit) override
|
||||
{
|
||||
unit->RemoveAurasDueToSpell(SPELL_ON_ALTAR);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_assault_on_the_dark_portal()
|
||||
{
|
||||
new scene_dark_portal_run_away();
|
||||
new quest_the_cost_of_war();
|
||||
new quest_blaze_of_glory();
|
||||
new scene_bleeding_hollow_holdout();
|
||||
new scene_bleeding_hollow_trail_of_flame();
|
||||
|
||||
new quest_altar_altercation();
|
||||
RegisterSpellScript(spell_altar_altercation_summon_ariok);
|
||||
new scene_bleeding_hollow_kilrogg_reveal();
|
||||
RegisterSpellScript(spell_altar_altercation_destroying);
|
||||
RegisterCreatureAI(npc_altar_altercation_ariok);
|
||||
RegisterSpellScript(spell_trigger_ariok_altar_altercation);
|
||||
RegisterCreatureAI(npc_altar_altercation_blood_ritual_orb);
|
||||
RegisterAreaTriggerAI(at_altar_altercation_kilrogg_talk);
|
||||
RegisterAreaTriggerAI(at_altar_altercation_reach_altar);
|
||||
};
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
// 79243 - Baros Alexston
|
||||
enum BarosAlexstonMisc
|
||||
{
|
||||
// Quest
|
||||
QUEST_ESTABLISH_YOUR_GARRISON = 34586,
|
||||
|
||||
// Gossip
|
||||
GOSSIP_OPTION_ESTABLISH_GARRISON = 0,
|
||||
|
||||
// Text
|
||||
SAY_START_CONSTRUCTION = 0,
|
||||
|
||||
// Spells
|
||||
SPELL_QUEST_34586_KILLCREDIT = 161033,
|
||||
SPELL_CREATE_GARRISON_SHADOWMOON_VALLEY_ALLIANCE = 156020,
|
||||
SPELL_DESPAWN_ALL_SUMMONS_GARRISON_INTRO_ONLY = 160938
|
||||
};
|
||||
|
||||
Position const GarrisonLevelOneCreationPlayerPosition = { 1904.58f, 312.906f, 88.9542f, 4.303615f };
|
||||
|
||||
struct npc_baros_alexston : public ScriptedAI
|
||||
{
|
||||
npc_baros_alexston(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
|
||||
{
|
||||
if (gossipListId == GOSSIP_OPTION_ESTABLISH_GARRISON)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
player->CastSpell(player, SPELL_QUEST_34586_KILLCREDIT, true);
|
||||
player->CastSpell(player, SPELL_CREATE_GARRISON_SHADOWMOON_VALLEY_ALLIANCE, true);
|
||||
player->CastSpell(player, SPELL_DESPAWN_ALL_SUMMONS_GARRISON_INTRO_ONLY, true);
|
||||
player->NearTeleportTo(GarrisonLevelOneCreationPlayerPosition);
|
||||
|
||||
PhasingHandler::OnConditionChange(player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnQuestAccept(Player* player , Quest const* quest) override
|
||||
{
|
||||
if (quest->GetQuestId() == QUEST_ESTABLISH_YOUR_GARRISON)
|
||||
Talk(SAY_START_CONSTRUCTION, player);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_draenor_shadowmoon_valley()
|
||||
{
|
||||
RegisterCreatureAI(npc_baros_alexston);
|
||||
};
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "Conversation.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Unit.h"
|
||||
#include "aberrus_the_shadowed_crucible.h"
|
||||
|
||||
enum AberrusEvents
|
||||
{
|
||||
EVENT_SABELLIAN_MOVE = 1,
|
||||
EVENT_SABELLIAN_MOVE_HOME_POS,
|
||||
EVENT_KAZZARA_INTRO,
|
||||
EVENT_KAZZARA_INTRO_DONE
|
||||
};
|
||||
|
||||
enum AberrusPaths
|
||||
{
|
||||
PATH_SARKARETH = (202416 * 10) << 3,
|
||||
PATH_WINGLORD_DEZRAN = (202610 * 10) << 3,
|
||||
PATH_ZSKARN = (202637 * 10) << 3
|
||||
};
|
||||
|
||||
enum AberrusSpells
|
||||
{
|
||||
SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_1 = 400785, // Sabellian and Wrathion
|
||||
SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_2 = 403340, // Sabellian and Sarkareth
|
||||
};
|
||||
|
||||
enum AberrusMisc
|
||||
{
|
||||
// Sabellian intro
|
||||
CONVO_ACTOR_IDX_SABELLIAN = 0,
|
||||
|
||||
CONVO_SABELLIAN_INTRO_LINE_01 = 56690,
|
||||
CONVO_SABELLIAN_INTRO_LINE_02 = 56692,
|
||||
|
||||
// Kazzara intro
|
||||
CONVO_ACTOR_IDX_WINGLORD_DEZRAN = 0,
|
||||
CONVO_ACTOR_IDX_ZSKARN = 1,
|
||||
CONVO_ACTOR_IDX_SARKARETH = 2,
|
||||
|
||||
CONVO_SARKARETH_LAST_LINE = 57821
|
||||
};
|
||||
|
||||
Position const SabellianIntroConvoMovePosition = { 2250.6372f, 2482.3003f, 711.9592f };
|
||||
|
||||
// Id 26 - Areatrigger
|
||||
struct at_aberrus_sabellian_conversation_intro : AreaTriggerAI
|
||||
{
|
||||
at_aberrus_sabellian_conversation_intro(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
Creature* sabellian = unit->FindNearestCreature(NPC_SABELLIAN_AT_ABERRUS_ENTRANCE, 50.0f);
|
||||
|
||||
if (!sabellian)
|
||||
return;
|
||||
|
||||
sabellian->CastSpell(nullptr, SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_1);
|
||||
at->Remove();
|
||||
}
|
||||
};
|
||||
|
||||
// Id 27 - Areatrigger
|
||||
struct at_aberrus_sarkareth_conversation_intro : AreaTriggerAI
|
||||
{
|
||||
at_aberrus_sarkareth_conversation_intro(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
Creature* sabellian = unit->FindNearestCreature(NPC_SABELLIAN_AT_ABERRUS_ENTRANCE, 50.0f);
|
||||
|
||||
if (!sabellian)
|
||||
return;
|
||||
|
||||
sabellian->CastSpell(nullptr, SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_2);
|
||||
at->Remove();
|
||||
}
|
||||
};
|
||||
|
||||
// 20800 - Conversation
|
||||
class conversation_aberrus_sabellian_intro : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_aberrus_sabellian_intro() : ConversationScript("conversation_aberrus_sabellian_intro") { }
|
||||
|
||||
void OnConversationStart(Conversation* conversation) override
|
||||
{
|
||||
if (Milliseconds const* sabellianMoveStartTime = conversation->GetLineStartTime(DEFAULT_LOCALE, CONVO_SABELLIAN_INTRO_LINE_01))
|
||||
_events.ScheduleEvent(EVENT_SABELLIAN_MOVE, *sabellianMoveStartTime);
|
||||
|
||||
if (Milliseconds const* sabellianHomeMoveStartTime = conversation->GetLineStartTime(DEFAULT_LOCALE, CONVO_SABELLIAN_INTRO_LINE_02))
|
||||
_events.ScheduleEvent(EVENT_SABELLIAN_MOVE_HOME_POS, *sabellianHomeMoveStartTime + Seconds(2));
|
||||
}
|
||||
|
||||
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SABELLIAN_MOVE:
|
||||
{
|
||||
Creature* sabellian = conversation->GetActorCreature(CONVO_ACTOR_IDX_SABELLIAN);
|
||||
if (!sabellian)
|
||||
break;
|
||||
|
||||
sabellian->SetWalk(true);
|
||||
sabellian->GetMotionMaster()->MovePoint(0, SabellianIntroConvoMovePosition);
|
||||
break;
|
||||
}
|
||||
case EVENT_SABELLIAN_MOVE_HOME_POS:
|
||||
{
|
||||
Creature* sabellian = conversation->GetActorCreature(CONVO_ACTOR_IDX_SABELLIAN);
|
||||
if (!sabellian)
|
||||
break;
|
||||
|
||||
sabellian->SetWalk(true);
|
||||
sabellian->GetMotionMaster()->MovePoint(0, sabellian->ToCreature()->GetHomePosition(), false, sabellian->ToCreature()->GetHomePosition().GetOrientation());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
// 20985 - Conversation
|
||||
class conversation_aberrus_kazzara_intro : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_aberrus_kazzara_intro() : ConversationScript("conversation_aberrus_kazzara_intro") { }
|
||||
|
||||
void OnConversationStart(Conversation* conversation) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_KAZZARA_INTRO, conversation->GetLineEndTime(DEFAULT_LOCALE, CONVO_SARKARETH_LAST_LINE));
|
||||
}
|
||||
|
||||
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_KAZZARA_INTRO:
|
||||
{
|
||||
Creature* winglordDezran = conversation->GetActorCreature(CONVO_ACTOR_IDX_WINGLORD_DEZRAN);
|
||||
Creature* zskarn = conversation->GetActorCreature(CONVO_ACTOR_IDX_ZSKARN);
|
||||
Creature* sarkareth = conversation->GetActorCreature(CONVO_ACTOR_IDX_SARKARETH);
|
||||
|
||||
if (!winglordDezran || !zskarn || !sarkareth)
|
||||
return;
|
||||
|
||||
sarkareth->GetMotionMaster()->MovePath(PATH_SARKARETH, false);
|
||||
sarkareth->DespawnOrUnsummon(45s);
|
||||
|
||||
winglordDezran->GetMotionMaster()->MovePath(PATH_WINGLORD_DEZRAN, false);
|
||||
winglordDezran->DespawnOrUnsummon(45s);
|
||||
|
||||
zskarn->GetMotionMaster()->MovePath(PATH_ZSKARN, false);
|
||||
zskarn->DespawnOrUnsummon(45s, Seconds::max()); // override respawn time to prevent instant respawn due to CREATURE_FLAG_EXTRA_DUNGEON_BOSS
|
||||
|
||||
if (InstanceScript* instance = conversation->GetInstanceScript())
|
||||
{
|
||||
instance->SetData(DATA_KAZZARA_INTRO_STATE, DONE);
|
||||
if (Creature* kazzara = instance->GetCreature(DATA_KAZZARA_THE_HELLFORGED))
|
||||
kazzara->AI()->DoAction(ACTION_START_KAZZARA_INTRO);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
void AddSC_aberrus_the_shadowed_crucible()
|
||||
{
|
||||
RegisterAreaTriggerAI(at_aberrus_sabellian_conversation_intro);
|
||||
RegisterAreaTriggerAI(at_aberrus_sarkareth_conversation_intro);
|
||||
|
||||
new conversation_aberrus_sabellian_intro();
|
||||
new conversation_aberrus_kazzara_intro();
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_ABERRUS_THE_SHADOWED_CRUCIBLE_H_
|
||||
#define DEF_ABERRUS_THE_SHADOWED_CRUCIBLE_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define ATSCScriptName "instance_aberrus_the_shadowed_crucible"
|
||||
#define DataHeader "Aberrus"
|
||||
|
||||
uint32 const EncounterCount = 9;
|
||||
|
||||
enum AberrusDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_KAZZARA_THE_HELLFORGED = 0,
|
||||
DATA_THE_AMALGAMATION_CHAMBER = 1,
|
||||
DATA_THE_FORGOTTEN_EXPERIMENTS = 2,
|
||||
DATA_ASSAULT_OF_THE_ZAQALI = 3,
|
||||
DATA_RASHOK_THE_ELDER = 4,
|
||||
DATA_ZSKARN_THE_VIGILANT_STEWARD = 5,
|
||||
DATA_MAGMORAX = 6,
|
||||
DATA_ECHO_OF_NELTHARION = 7,
|
||||
DATA_SCALECOMMANDER_SARKARETH = 8,
|
||||
|
||||
// Creatures
|
||||
DATA_SARKARETH_AT_KAZZARA,
|
||||
|
||||
// Gameobjects
|
||||
DATA_KAZZARA_GATE,
|
||||
|
||||
// Misc
|
||||
DATA_KAZZARA_INTRO_STATE
|
||||
};
|
||||
|
||||
enum AberrusCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_KAZZARA_THE_HELLFORGED = 201261,
|
||||
|
||||
BOSS_ETERNAL_BLAZE = 201773,
|
||||
BOSS_ESSENCE_OF_SHADOW = 201774,
|
||||
BOSS_SHADOWFLAME_AMALGAMATION = 201934,
|
||||
|
||||
BOSS_NELDRIS = 200912,
|
||||
BOSS_THADRION = 200913,
|
||||
BOSS_RIONTHUS = 200918,
|
||||
|
||||
BOSS_WARLORD_KAGNI = 199659,
|
||||
BOSS_RASHOK_THE_ELDER = 201320,
|
||||
BOSS_ZSKARN_THE_VIGILANT_STEWARD = 202637,
|
||||
BOSS_MAGMORAX = 201579,
|
||||
BOSS_ECHO_OF_NELTHARION = 204223,
|
||||
BOSS_SCALECOMMANDER_SARKARETH = 205319,
|
||||
|
||||
// Kazzara Trash
|
||||
NPC_SCALECOMMANDER_SARKARETH_AT_KAZZARA = 202416,
|
||||
NPC_SUNDERED_DEVASTATOR = 198869,
|
||||
NPC_SUNDERED_SCALEGUARD = 198871,
|
||||
NPC_SUNDERED_MANAWEAVER = 198872,
|
||||
NPC_SUNDERED_EDGELORD = 198873,
|
||||
|
||||
// Misc
|
||||
NPC_SABELLIAN_AT_ABERRUS_ENTRANCE = 201575
|
||||
};
|
||||
|
||||
enum AberrusGameObjectIds
|
||||
{
|
||||
GO_KAZZARA_DOOR = 398742,
|
||||
GO_KAZZARA_GATE = 397996,
|
||||
GO_INVISIBLE_DOOR = 398588
|
||||
};
|
||||
|
||||
enum AberrusSharedActions
|
||||
{
|
||||
ACTION_START_KAZZARA_INTRO = 0,
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetAberrusTheShadowedCrucibleAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, ATSCScriptName);
|
||||
}
|
||||
|
||||
#define RegisterAberrusTheShadowedCrucibleCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAberrusTheShadowedCrucibleAI)
|
||||
|
||||
#endif
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "aberrus_the_shadowed_crucible.h"
|
||||
|
||||
enum KazzaraSpells
|
||||
{
|
||||
// Sundered NPCs
|
||||
SPELL_FEAR = 220540,
|
||||
|
||||
// Kazzara
|
||||
SPELL_DREAD_LANDING = 411872,
|
||||
SPELL_KAZZARA_INTRO = 410541
|
||||
};
|
||||
|
||||
// 201261 - Kazzara the Hellforged
|
||||
struct boss_kazzara_the_hellforged : public BossAI
|
||||
{
|
||||
boss_kazzara_the_hellforged(Creature* creature) : BossAI(creature, DATA_KAZZARA_THE_HELLFORGED) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
if (instance->GetData(DATA_KAZZARA_INTRO_STATE) != DONE)
|
||||
{
|
||||
me->SetUninteractible(true);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 actionId) override
|
||||
{
|
||||
switch (actionId)
|
||||
{
|
||||
case ACTION_START_KAZZARA_INTRO:
|
||||
{
|
||||
if (GameObject* gate = instance->GetGameObject(DATA_KAZZARA_GATE))
|
||||
{
|
||||
gate->SetFlag(GO_FLAG_IN_USE);
|
||||
gate->SetGoState(GO_STATE_READY);
|
||||
}
|
||||
|
||||
me->SetVisible(true);
|
||||
|
||||
DoCast(SPELL_DREAD_LANDING);
|
||||
DoCast(SPELL_KAZZARA_INTRO);
|
||||
|
||||
scheduler.Schedule(1s + 500ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
std::vector<Creature*> sunderedMobs;
|
||||
GetCreatureListWithOptionsInGrid(sunderedMobs, me, 50.0f, { .StringId = "sundered_mob" });
|
||||
for (Creature* sunderedMob : sunderedMobs)
|
||||
{
|
||||
if (!sunderedMob->IsAlive() || sunderedMob->IsInCombat())
|
||||
continue;
|
||||
|
||||
sunderedMob->CastSpell(nullptr, SPELL_FEAR, false);
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.Schedule(12s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetUninteractible(false);
|
||||
me->SetImmuneToAll(false);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_kazzara_the_hellforged()
|
||||
{
|
||||
RegisterAberrusTheShadowedCrucibleCreatureAI(boss_kazzara_the_hellforged);
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "aberrus_the_shadowed_crucible.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_KAZZARA_THE_HELLFORGED, DATA_KAZZARA_THE_HELLFORGED },
|
||||
{ BOSS_SHADOWFLAME_AMALGAMATION, DATA_THE_AMALGAMATION_CHAMBER },
|
||||
{ BOSS_RIONTHUS, DATA_THE_FORGOTTEN_EXPERIMENTS },
|
||||
{ BOSS_WARLORD_KAGNI, DATA_ASSAULT_OF_THE_ZAQALI },
|
||||
{ BOSS_RASHOK_THE_ELDER, DATA_RASHOK_THE_ELDER },
|
||||
{ BOSS_ZSKARN_THE_VIGILANT_STEWARD, DATA_ZSKARN_THE_VIGILANT_STEWARD },
|
||||
{ BOSS_MAGMORAX, DATA_MAGMORAX },
|
||||
{ BOSS_ECHO_OF_NELTHARION, DATA_ECHO_OF_NELTHARION },
|
||||
{ BOSS_SCALECOMMANDER_SARKARETH, DATA_SCALECOMMANDER_SARKARETH },
|
||||
{ NPC_SCALECOMMANDER_SARKARETH_AT_KAZZARA, DATA_SARKARETH_AT_KAZZARA },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_KAZZARA_DOOR, DATA_KAZZARA_THE_HELLFORGED, EncounterDoorBehavior::OpenWhenNotInProgress },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
|
||||
};
|
||||
|
||||
ObjectData const objectData[] =
|
||||
{
|
||||
{ GO_KAZZARA_GATE, DATA_KAZZARA_GATE },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_KAZZARA_THE_HELLFORGED, {{ 2688 }} },
|
||||
{ DATA_THE_AMALGAMATION_CHAMBER, {{ 2687 }} },
|
||||
{ DATA_THE_FORGOTTEN_EXPERIMENTS, {{ 2693 }} },
|
||||
{ DATA_ASSAULT_OF_THE_ZAQALI, {{ 2682 }} },
|
||||
{ DATA_RASHOK_THE_ELDER, {{ 2680 }} },
|
||||
{ DATA_ZSKARN_THE_VIGILANT_STEWARD, {{ 2689 }} },
|
||||
{ DATA_MAGMORAX, {{ 2683 }} },
|
||||
{ DATA_ECHO_OF_NELTHARION, {{ 2684 }} },
|
||||
{ DATA_SCALECOMMANDER_SARKARETH, {{ 2685 }} }
|
||||
};
|
||||
|
||||
enum AberrusInstanceSpells
|
||||
{
|
||||
SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_3 = 403409 // Winglord Dezran, Sarkareth and Zskarn (Kazzara Summon)
|
||||
};
|
||||
|
||||
class instance_aberrus_the_shadowed_crucible : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_aberrus_the_shadowed_crucible() : InstanceMapScript(ATSCScriptName, 2569) { }
|
||||
|
||||
struct instance_aberrus_the_shadowed_crucible_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_aberrus_the_shadowed_crucible_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, objectData);
|
||||
LoadDoorData(doorData);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
|
||||
_kazzaraIntroState = NOT_STARTED;
|
||||
_kazzaraAliveIntroNPCs = 0;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 dataId) const override
|
||||
{
|
||||
switch (dataId)
|
||||
{
|
||||
case DATA_KAZZARA_INTRO_STATE:
|
||||
return _kazzaraIntroState;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 dataId, uint32 value) override
|
||||
{
|
||||
switch (dataId)
|
||||
{
|
||||
case DATA_KAZZARA_INTRO_STATE:
|
||||
_kazzaraIntroState = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
if (creature->HasStringId("kazzara_intro_trash"))
|
||||
_kazzaraAliveIntroNPCs++;
|
||||
}
|
||||
|
||||
void OnUnitDeath(Unit* unit) override
|
||||
{
|
||||
Creature* creature = unit->ToCreature();
|
||||
if (!creature)
|
||||
return;
|
||||
|
||||
if (creature->HasStringId("kazzara_intro_trash"))
|
||||
{
|
||||
if (_kazzaraIntroState != NOT_STARTED)
|
||||
return;
|
||||
|
||||
_kazzaraAliveIntroNPCs--;
|
||||
if (_kazzaraAliveIntroNPCs > 0)
|
||||
return;
|
||||
|
||||
_kazzaraIntroState = IN_PROGRESS;
|
||||
|
||||
Creature* sarkareth = GetCreature(DATA_SARKARETH_AT_KAZZARA);
|
||||
if (!sarkareth)
|
||||
return;
|
||||
|
||||
sarkareth->CastSpell(nullptr, SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_3);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _kazzaraAliveIntroNPCs;
|
||||
uint8 _kazzaraIntroState;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_aberrus_the_shadowed_crucible_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_aberrus_the_shadowed_crucible()
|
||||
{
|
||||
new instance_aberrus_the_shadowed_crucible();
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_AZURE_VAULT_H_
|
||||
#define DEF_AZURE_VAULT_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "AzureVault"
|
||||
#define AVScriptName "instance_azure_vault"
|
||||
|
||||
uint32 const EncounterCount = 4;
|
||||
|
||||
enum AVDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_LEYMOR = 0,
|
||||
DATA_AZUREBLADE,
|
||||
DATA_TELASH_GREYWING,
|
||||
DATA_UMBRELSKUL,
|
||||
|
||||
DATA_LEYMOR_INTRO_DONE
|
||||
};
|
||||
|
||||
enum AVCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_LEYMOR = 186644,
|
||||
BOSS_AZUREBLADE = 186739,
|
||||
BOSS_TELASH_GREYWING = 199614,
|
||||
BOSS_UMBRELSKUL = 186738,
|
||||
|
||||
// Leymor
|
||||
NPC_ARCANE_TENDER = 191164,
|
||||
};
|
||||
|
||||
enum AVGameObjectIds
|
||||
{
|
||||
GO_ARCANE_VAULTS_DOOR_LEYMOR_ENTRANCE = 380536,
|
||||
GO_ARCANE_VAULTS_DOOR_LEYMOR_EXIT = 377951
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetAzureVaultAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, AVScriptName);
|
||||
}
|
||||
|
||||
#define RegisterAzureVaultCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAzureVaultAI)
|
||||
|
||||
#endif
|
||||
@@ -1,573 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "azure_vault.h"
|
||||
|
||||
enum LeymorSpells
|
||||
{
|
||||
// Leymor
|
||||
SPELL_STASIS = 375729,
|
||||
SPELL_ARCANE_ERUPTION = 375749,
|
||||
SPELL_LEY_LINE_SPROUTS = 374364,
|
||||
SPELL_LEY_LINE_SPROUTS_MISSILE = 374362,
|
||||
SPELL_CONSUMING_STOMP = 374720,
|
||||
SPELL_CONSUMING_STOMP_DAMAGE = 374731,
|
||||
SPELL_ERUPTING_FISSURE = 386660,
|
||||
SPELL_ERUPTING_FISSURE_SPROUT_SELECTOR = 394154,
|
||||
SPELL_EXPLOSIVE_BRAND = 374567,
|
||||
SPELL_EXPLOSIVE_BRAND_DAMAGE = 374570,
|
||||
SPELL_EXPLOSIVE_BRAND_KNOCKBACK = 374582,
|
||||
SPELL_INFUSED_STRIKE = 374789,
|
||||
|
||||
// Ley-Line Sprout
|
||||
SPELL_VOLATILE_SAPLING = 388654,
|
||||
SPELL_LEY_LINE_SPROUT_AT = 374161,
|
||||
SPELL_ARCANE_POWER = 374736,
|
||||
|
||||
// Volatile Sapling
|
||||
SPELL_SAPPY_BURST = 375591,
|
||||
|
||||
// Arcane Tender
|
||||
SPELL_STASIS_RITUAL = 375732,
|
||||
SPELL_STASIS_RITUAL_MISSILE = 375738,
|
||||
SPELL_ERRATIC_GROWTH_CHANNEL = 375596,
|
||||
SPELL_WILD_ERUPTION = 375652,
|
||||
SPELL_WILD_ERUPTION_MISSILE = 375650
|
||||
};
|
||||
|
||||
enum LeymorEvents
|
||||
{
|
||||
// Leymor
|
||||
EVENT_LEYMOR_AWAKE = 1,
|
||||
EVENT_LEY_LINE_SPROUTS,
|
||||
EVENT_CONSUMING_STOMP,
|
||||
EVENT_ERUPTING_FISSURE,
|
||||
EVENT_EXPLOSIVE_BRAND,
|
||||
EVENT_INFUSED_STRIKE,
|
||||
|
||||
// Arcane Tender
|
||||
EVENT_ERRATIC_GROWTH = 1,
|
||||
EVENT_WILD_ERUPTION,
|
||||
EVENT_INFUSED_GROUND,
|
||||
};
|
||||
|
||||
enum LeymorTexts
|
||||
{
|
||||
SAY_ANNOUNCE_AWAKEN = 0
|
||||
};
|
||||
|
||||
enum LeymorVisuals
|
||||
{
|
||||
SPELL_VISUAL_KIT_SPROUT_DEATH = 159239
|
||||
};
|
||||
|
||||
enum LeymorNpcs
|
||||
{
|
||||
NPC_LEYLINE_SPROUTS = 190509
|
||||
};
|
||||
|
||||
enum LeymorActions
|
||||
{
|
||||
ACTION_ARCANE_TENDER_DEATH = 1
|
||||
};
|
||||
|
||||
// 186644 - Leymor
|
||||
struct boss_leymor : public BossAI
|
||||
{
|
||||
boss_leymor(Creature* creature) : BossAI(creature, DATA_LEYMOR), _killedArcaneTender(0) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
if (instance->GetData(DATA_LEYMOR_INTRO_DONE))
|
||||
return;
|
||||
|
||||
me->SetUnitFlag(UnitFlags(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC));
|
||||
DoCastSelf(SPELL_STASIS);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_ARCANE_TENDER_DEATH)
|
||||
{
|
||||
_killedArcaneTender++;
|
||||
if (_killedArcaneTender >= 3)
|
||||
{
|
||||
instance->SetData(DATA_LEYMOR_INTRO_DONE, 1);
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_STASIS);
|
||||
me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC));
|
||||
DoCastSelf(SPELL_ARCANE_ERUPTION);
|
||||
Talk(SAY_ANNOUNCE_AWAKEN);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
summons.DespawnAll();
|
||||
_EnterEvadeMode();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void OnChannelFinished(SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_CONSUMING_STOMP)
|
||||
DoCastAOE(SPELL_CONSUMING_STOMP_DAMAGE, true);
|
||||
};
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
events.ScheduleEvent(EVENT_LEY_LINE_SPROUTS, 3s);
|
||||
events.ScheduleEvent(EVENT_CONSUMING_STOMP, 45s);
|
||||
events.ScheduleEvent(EVENT_ERUPTING_FISSURE, 20s);
|
||||
events.ScheduleEvent(EVENT_EXPLOSIVE_BRAND, 31s);
|
||||
events.ScheduleEvent(EVENT_INFUSED_STRIKE, 10s);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_LEY_LINE_SPROUTS:
|
||||
DoCastSelf(SPELL_LEY_LINE_SPROUTS);
|
||||
events.ScheduleEvent(EVENT_LEY_LINE_SPROUTS, 48s);
|
||||
break;
|
||||
case EVENT_CONSUMING_STOMP:
|
||||
DoCastSelf(SPELL_CONSUMING_STOMP);
|
||||
events.ScheduleEvent(EVENT_CONSUMING_STOMP, 48s);
|
||||
break;
|
||||
case EVENT_ERUPTING_FISSURE:
|
||||
DoCastVictim(SPELL_ERUPTING_FISSURE);
|
||||
events.ScheduleEvent(EVENT_ERUPTING_FISSURE, 48s);
|
||||
break;
|
||||
case EVENT_EXPLOSIVE_BRAND:
|
||||
DoCastSelf(SPELL_EXPLOSIVE_BRAND);
|
||||
events.ScheduleEvent(EVENT_EXPLOSIVE_BRAND, 48s);
|
||||
break;
|
||||
case EVENT_INFUSED_STRIKE:
|
||||
DoCastVictim(SPELL_INFUSED_STRIKE);
|
||||
events.ScheduleEvent(EVENT_INFUSED_STRIKE, 48s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int32 _killedArcaneTender;
|
||||
};
|
||||
|
||||
// 191164 - Arcane Tender
|
||||
struct npc_arcane_tender : public ScriptedAI
|
||||
{
|
||||
npc_arcane_tender(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Creature* leymor = me->GetInstanceScript()->GetCreature(DATA_LEYMOR);
|
||||
if (!leymor)
|
||||
return;
|
||||
|
||||
if (!leymor->IsAIEnabled())
|
||||
return;
|
||||
|
||||
leymor->AI()->DoAction(ACTION_ARCANE_TENDER_DEATH);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
Creature* leymor = me->GetInstanceScript()->GetCreature(DATA_LEYMOR);
|
||||
if (!leymor)
|
||||
return;
|
||||
|
||||
DoCast(leymor, SPELL_STASIS_RITUAL);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
JustAppeared();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_events.Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_ERRATIC_GROWTH, 22s);
|
||||
_events.ScheduleEvent(EVENT_WILD_ERUPTION, 12s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_ERRATIC_GROWTH:
|
||||
DoCastAOE(SPELL_ERRATIC_GROWTH_CHANNEL);
|
||||
_events.ScheduleEvent(EVENT_ERRATIC_GROWTH, 22s);
|
||||
break;
|
||||
case EVENT_WILD_ERUPTION:
|
||||
DoCastAOE(SPELL_WILD_ERUPTION);
|
||||
_events.ScheduleEvent(EVENT_WILD_ERUPTION, 12s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
// 190509 - Ley-Line Sprout
|
||||
struct npc_ley_line_sprouts : public ScriptedAI
|
||||
{
|
||||
npc_ley_line_sprouts(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCastSelf(SPELL_LEY_LINE_SPROUT_AT);
|
||||
|
||||
DoCastAOE(SPELL_ARCANE_POWER, true);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
Creature* leymor = me->GetInstanceScript()->GetCreature(DATA_LEYMOR);
|
||||
if (!leymor)
|
||||
return;
|
||||
|
||||
if (!leymor->IsAIEnabled())
|
||||
return;
|
||||
|
||||
leymor->AI()->JustSummoned(summon);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (IsMythic() || IsMythicPlus())
|
||||
DoCastAOE(SPELL_VOLATILE_SAPLING, true);
|
||||
|
||||
if (TempSummon* tempSummon = me->ToTempSummon())
|
||||
{
|
||||
if (Unit* summoner = tempSummon->GetSummonerUnit())
|
||||
{
|
||||
if (Aura* aura = summoner->GetAura(SPELL_ARCANE_POWER))
|
||||
aura->ModStackAmount(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id != SPELL_EXPLOSIVE_BRAND_DAMAGE && spellInfo->Id != SPELL_ERUPTING_FISSURE_SPROUT_SELECTOR)
|
||||
return;
|
||||
|
||||
me->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SPROUT_DEATH, 0, 0);
|
||||
me->KillSelf();
|
||||
}
|
||||
};
|
||||
|
||||
// 196559 - Volatile Sapling
|
||||
struct npc_volatile_sapling : public ScriptedAI
|
||||
{
|
||||
npc_volatile_sapling(Creature* creature) : ScriptedAI(creature), _isSappyBurstCast(false) { }
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
|
||||
{
|
||||
if (me->GetHealth() <= damage)
|
||||
{
|
||||
damage = me->GetHealth() - 1;
|
||||
|
||||
if (!_isSappyBurstCast)
|
||||
{
|
||||
me->CastSpell(nullptr, SPELL_SAPPY_BURST, false);
|
||||
_isSappyBurstCast = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnSpellFailed(SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id != SPELL_SAPPY_BURST)
|
||||
return;
|
||||
|
||||
me->KillSelf();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isSappyBurstCast;
|
||||
};
|
||||
|
||||
static Position const LeyLineSproutGroupOrigin[] =
|
||||
{
|
||||
{ -5129.39f, 1253.30f, 555.58f },
|
||||
{ -5101.68f, 1253.71f, 555.90f },
|
||||
{ -5114.70f, 1230.28f, 555.89f },
|
||||
{ -5141.62f, 1230.33f, 555.83f },
|
||||
{ -5155.62f, 1253.60f, 555.87f },
|
||||
{ -5141.42f, 1276.70f, 555.89f },
|
||||
{ -5114.78f, 1277.42f, 555.87f }
|
||||
};
|
||||
|
||||
// 374364 - Ley-Line Sprouts
|
||||
class spell_ley_line_sprouts : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_LEY_LINE_SPROUTS_MISSILE });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
for (Position const& pos : LeyLineSproutGroupOrigin)
|
||||
{
|
||||
for (int8 i = 0; i < 2; i++)
|
||||
GetCaster()->CastSpell(pos, SPELL_LEY_LINE_SPROUTS_MISSILE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_ley_line_sprouts::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 375732 - Stasis Ritual
|
||||
class spell_stasis_ritual : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_STASIS_RITUAL_MISSILE });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(nullptr, SPELL_STASIS_RITUAL_MISSILE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_stasis_ritual::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 375652 - Wild Eruption
|
||||
class spell_wild_eruption : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_WILD_ERUPTION_MISSILE });
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(*GetHitDest(), SPELL_WILD_ERUPTION_MISSILE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_wild_eruption::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 375749 - Arcane Eruption
|
||||
struct at_leymor_arcane_eruption : AreaTriggerAI
|
||||
{
|
||||
at_leymor_arcane_eruption(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
unit->ApplyMovementForce(at->GetGUID(), at->GetPosition(), -20.0f, MovementForceType::Gravity);
|
||||
}
|
||||
|
||||
void OnUnitExit(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
unit->RemoveMovementForce(at->GetGUID());
|
||||
}
|
||||
};
|
||||
|
||||
// 374567 - Explosive Brand
|
||||
class spell_explosive_brand : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_EXPLOSIVE_BRAND_KNOCKBACK });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(nullptr, SPELL_EXPLOSIVE_BRAND_KNOCKBACK, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_explosive_brand::HandleHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
|
||||
}
|
||||
};
|
||||
|
||||
// 374567 - Explosive Brand
|
||||
class spell_explosive_brand_AuraScript : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_EXPLOSIVE_BRAND_DAMAGE });
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
|
||||
return;
|
||||
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetTarget(), SPELL_EXPLOSIVE_BRAND_DAMAGE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_explosive_brand_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 374720 - Consuming Stomp
|
||||
class spell_consuming_stomp : public AuraScript
|
||||
{
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->KillSelf();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_consuming_stomp::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 386660 - Erupting Fissure
|
||||
class spell_erupting_fissure : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_ERUPTING_FISSURE_SPROUT_SELECTOR });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(*GetHitDest(), SPELL_ERUPTING_FISSURE_SPROUT_SELECTOR, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_erupting_fissure::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 375591 - Sappy Burst
|
||||
class spell_sappy_burst : public SpellScript
|
||||
{
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->KillSelf();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_sappy_burst::HandleHitTarget, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_leymor()
|
||||
{
|
||||
// Creature
|
||||
RegisterAzureVaultCreatureAI(boss_leymor);
|
||||
RegisterAzureVaultCreatureAI(npc_arcane_tender);
|
||||
RegisterAzureVaultCreatureAI(npc_ley_line_sprouts);
|
||||
RegisterAzureVaultCreatureAI(npc_volatile_sapling);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_ley_line_sprouts);
|
||||
RegisterSpellScript(spell_stasis_ritual);
|
||||
RegisterSpellScript(spell_wild_eruption);
|
||||
RegisterSpellScript(spell_consuming_stomp);
|
||||
RegisterSpellScript(spell_erupting_fissure);
|
||||
RegisterSpellScript(spell_sappy_burst);
|
||||
RegisterSpellAndAuraScriptPair(spell_explosive_brand, spell_explosive_brand_AuraScript);
|
||||
|
||||
// AreaTrigger
|
||||
RegisterAreaTriggerAI(at_leymor_arcane_eruption);
|
||||
}
|
||||
@@ -1,501 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "Map.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "azure_vault.h"
|
||||
|
||||
enum TelashSpells
|
||||
{
|
||||
// Telash
|
||||
SPELL_POWER_ENERGIZE_ICE_POWER_PERIODIC = 389453,
|
||||
SPELL_FROST_BOMB_CAST = 386781,
|
||||
SPELL_FROST_BOMB_AURA = 386881,
|
||||
SPELL_FROST_BOMB_DAMAGE = 386910,
|
||||
SPELL_FROZEN_GROUND_AT = 387149,
|
||||
SPELL_ICY_DEVASTATOR = 387151,
|
||||
SPELL_ABSOLUTE_ZERO_CAST = 387928,
|
||||
SPELL_ABSOLUTE_ZERO_JUMP = 387981,
|
||||
SPELL_ABSOLUTE_ZERO_JUMP_BACK = 388082,
|
||||
SPELL_ABSOLUTE_ZERO_SHIELD = 388084,
|
||||
SPELL_ABSOLUTE_ZERO_DAMAGE = 388008,
|
||||
SPELL_ACTIVATE_VAULT_RUNE = 390209,
|
||||
SPELL_VAULT_RUNE_AT_AURA = 388065,
|
||||
SPELL_VAULT_RUNE_SHIELD = 390201,
|
||||
SPELL_INACTIVE_VAULT_RUNE = 390238,
|
||||
|
||||
// Conversation
|
||||
SPELL_TELASH_APPROACH_CONV = 389379
|
||||
};
|
||||
|
||||
enum TelashEvents
|
||||
{
|
||||
EVENT_FROST_BOMB = 1,
|
||||
EVENT_ICY_DEVASTATOR = 2,
|
||||
EVENT_ABSOLUTE_ZERO = 3
|
||||
};
|
||||
|
||||
enum TelashSummonGroups
|
||||
{
|
||||
SUMMON_GROUP_TELASH_VAULT_RUNES = 0
|
||||
};
|
||||
|
||||
enum TelashActions
|
||||
{
|
||||
ACTION_RESCHEDULE_SPELLS = 1,
|
||||
};
|
||||
|
||||
enum TelashText
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_FROST_BOMB = 1,
|
||||
SAY_ICY_DEVASTATOR = 2,
|
||||
SAY_FLY_TO_MIDDLE = 3,
|
||||
SAY_ANNOUNCE_ABSOLUTE_ZERO = 4,
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
|
||||
Position const TelashJumpPosition = { -5336.8003f, 1066.6493f, 344.32678f };
|
||||
|
||||
Position const TelashJumpBackPositions[] =
|
||||
{
|
||||
{ -5350.0835f, 1089.8976f, 340.5709f, 5.0882f },
|
||||
{ -5310.4464f, 1066.8134f, 340.5967f, 3.9184f },
|
||||
{ -5350.3934f, 1043.9323f, 340.5894f, 2.0924f }
|
||||
};
|
||||
|
||||
// 186737 - Telash Greywing
|
||||
struct boss_telash_greywing : public BossAI
|
||||
{
|
||||
boss_telash_greywing(Creature* creature) : BossAI(creature, DATA_TELASH_GREYWING), _isInCenter(false), _frostBombRemaining(0), _icyDevastatorRemaining(0) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
me->SummonCreatureGroup(SUMMON_GROUP_TELASH_VAULT_RUNES);
|
||||
me->SetPower(me->GetPowerType(), 60);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
|
||||
_frostBombRemaining = 1;
|
||||
_icyDevastatorRemaining = 1;
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
DoCast(SPELL_POWER_ENERGIZE_ICE_POWER_PERIODIC);
|
||||
events.ScheduleEvent(EVENT_FROST_BOMB, 3500ms);
|
||||
events.ScheduleEvent(EVENT_ICY_DEVASTATOR, 14500ms);
|
||||
events.ScheduleEvent(EVENT_ABSOLUTE_ZERO, 500ms);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
summons.DespawnAll();
|
||||
_EnterEvadeMode();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
if (id == EVENT_JUMP)
|
||||
{
|
||||
if (!_isInCenter)
|
||||
{
|
||||
DoCastSelf(SPELL_ABSOLUTE_ZERO_DAMAGE);
|
||||
_isInCenter = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastSelf(SPELL_POWER_ENERGIZE_ICE_POWER_PERIODIC);
|
||||
me->RemoveAurasDueToSpell(SPELL_ABSOLUTE_ZERO_SHIELD);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
_isInCenter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FROST_BOMB:
|
||||
{
|
||||
Talk(SAY_FROST_BOMB);
|
||||
DoCastSelf(SPELL_FROST_BOMB_CAST);
|
||||
|
||||
_frostBombRemaining--;
|
||||
if (!_frostBombRemaining)
|
||||
{
|
||||
if (_icyDevastatorRemaining == 1)
|
||||
{
|
||||
events.CancelEvent(EVENT_ICY_DEVASTATOR);
|
||||
events.ScheduleEvent(EVENT_ICY_DEVASTATOR, 10800ms);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_FROST_BOMB, _frostBombRemaining == 2 ? 18200ms : 15800ms);
|
||||
break;
|
||||
}
|
||||
case EVENT_ICY_DEVASTATOR:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 75.0f, true))
|
||||
{
|
||||
Talk(SAY_ICY_DEVASTATOR);
|
||||
DoCast(target, SPELL_ICY_DEVASTATOR);
|
||||
|
||||
_icyDevastatorRemaining--;
|
||||
if (!_icyDevastatorRemaining)
|
||||
{
|
||||
if (_frostBombRemaining == 1)
|
||||
{
|
||||
events.CancelEvent(EVENT_FROST_BOMB);
|
||||
events.ScheduleEvent(EVENT_FROST_BOMB, 7300ms);
|
||||
}
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ICY_DEVASTATOR, 23100ms);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_ABSOLUTE_ZERO:
|
||||
if (me->GetPower(me->GetPowerType()) >= 100)
|
||||
{
|
||||
Talk(SAY_FLY_TO_MIDDLE);
|
||||
Talk(SAY_ANNOUNCE_ABSOLUTE_ZERO);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetDisableGravity(true, true);
|
||||
me->RemoveAurasDueToSpell(SPELL_POWER_ENERGIZE_ICE_POWER_PERIODIC);
|
||||
DoCastSelf(SPELL_ABSOLUTE_ZERO_CAST);
|
||||
DoCastSelf(SPELL_ABSOLUTE_ZERO_SHIELD);
|
||||
DoCastSelf(SPELL_ACTIVATE_VAULT_RUNE);
|
||||
events.CancelEvent(EVENT_FROST_BOMB);
|
||||
events.CancelEvent(EVENT_ICY_DEVASTATOR);
|
||||
}
|
||||
events.Repeat(500ms);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_RESCHEDULE_SPELLS)
|
||||
{
|
||||
_frostBombRemaining = 3;
|
||||
_icyDevastatorRemaining = 2;
|
||||
|
||||
events.ScheduleEvent(EVENT_FROST_BOMB, 4300ms);
|
||||
events.ScheduleEvent(EVENT_ICY_DEVASTATOR, 15200ms);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isInCenter;
|
||||
uint8 _frostBombRemaining;
|
||||
uint8 _icyDevastatorRemaining;
|
||||
};
|
||||
|
||||
// 30743 - Vault Rune
|
||||
struct at_telash_greywing_vault_rune : AreaTriggerAI
|
||||
{
|
||||
at_telash_greywing_vault_rune(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
Unit* caster = at->GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if (caster->HasAura(SPELL_VAULT_RUNE_SHIELD))
|
||||
return;
|
||||
|
||||
caster->CastSpell(nullptr, SPELL_VAULT_RUNE_SHIELD, true);
|
||||
}
|
||||
|
||||
void OnUnitExit(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
for (ObjectGuid const& guid : at->GetInsideUnits())
|
||||
{
|
||||
Player* player = ObjectAccessor::GetPlayer(*at, guid);
|
||||
if (!player)
|
||||
continue;
|
||||
|
||||
if (player->isDead())
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* caster = at->GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
caster->RemoveAurasDueToSpell(SPELL_VAULT_RUNE_SHIELD);
|
||||
}
|
||||
|
||||
void OnRemove() override
|
||||
{
|
||||
if (!at->GetMap()->IsMythic() && !at->GetMap()->IsMythicPlus())
|
||||
return;
|
||||
|
||||
for (ObjectGuid const& guid : at->GetInsideUnits())
|
||||
{
|
||||
Player* player = ObjectAccessor::GetPlayer(*at, guid);
|
||||
if (!player)
|
||||
continue;
|
||||
|
||||
if (player->isDead())
|
||||
continue;
|
||||
|
||||
Unit* caster = at->GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
caster->CastSpell(caster, SPELL_INACTIVE_VAULT_RUNE, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 389453 - Ice Power (periodic)
|
||||
class spell_telash_ice_power_periodic : public AuraScript
|
||||
{
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
target->SetPower(target->GetPowerType(), target->GetPower(POWER_ENERGY) + 2);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_telash_ice_power_periodic::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 386781 - Frost Bomb
|
||||
class spell_telash_frost_bomb_cast : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FROST_BOMB_AURA });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_FROST_BOMB_AURA, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_telash_frost_bomb_cast::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 386881 - Frost Bomb
|
||||
class spell_telash_frost_bomb_aura : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_FROST_BOMB_DAMAGE,
|
||||
SPELL_FROZEN_GROUND_AT
|
||||
});
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
|
||||
return;
|
||||
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
caster->CastSpell(GetTarget(), SPELL_FROZEN_GROUND_AT, true);
|
||||
caster->CastSpell(GetTarget(), SPELL_FROST_BOMB_DAMAGE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_telash_frost_bomb_aura::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 387928 - Absolute Zero
|
||||
class spell_telash_absolute_zero_cast : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_ABSOLUTE_ZERO_JUMP });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(TelashJumpPosition, SPELL_ABSOLUTE_ZERO_JUMP, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_telash_absolute_zero_cast::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 390209 - Activate Vault Rune
|
||||
class spell_telash_activate_vault_rune : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_VAULT_RUNE_AT_AURA,
|
||||
SPELL_INACTIVE_VAULT_RUNE
|
||||
});
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetHitUnit()->HasAura(SPELL_INACTIVE_VAULT_RUNE))
|
||||
return;
|
||||
|
||||
GetHitUnit()->CastSpell(nullptr, SPELL_VAULT_RUNE_AT_AURA, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_telash_activate_vault_rune::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 388008 - Absolute Zero
|
||||
class spell_telash_absolute_zero_damage : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_ABSOLUTE_ZERO_JUMP_BACK,
|
||||
SPELL_VAULT_RUNE_AT_AURA,
|
||||
SPELL_VAULT_RUNE_SHIELD
|
||||
});
|
||||
}
|
||||
|
||||
Position const& GetClosestPositionToMaxThreatTarget(Unit* victim)
|
||||
{
|
||||
float nearestDist = std::numeric_limits<float>::max();
|
||||
Position const* nearestPos = &TelashJumpBackPositions[0];
|
||||
|
||||
for (Position const& pos : TelashJumpBackPositions)
|
||||
{
|
||||
float dist = victim->GetDistance(pos);
|
||||
if (dist < nearestDist)
|
||||
{
|
||||
nearestDist = dist;
|
||||
nearestPos = &pos;
|
||||
}
|
||||
}
|
||||
|
||||
return *nearestPos;
|
||||
}
|
||||
|
||||
void HandleAfterCast()
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
UnitAI* casterAI = caster->GetAI();
|
||||
if (!casterAI)
|
||||
return;
|
||||
|
||||
Unit* victim = casterAI->SelectTarget(SelectTargetMethod::MaxThreat);
|
||||
if (!victim)
|
||||
return;
|
||||
|
||||
casterAI->DoAction(ACTION_RESCHEDULE_SPELLS);
|
||||
caster->CastSpell(GetClosestPositionToMaxThreatTarget(victim), SPELL_ABSOLUTE_ZERO_JUMP_BACK, true);
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetHitUnit()->RemoveAurasDueToSpell(SPELL_VAULT_RUNE_AT_AURA);
|
||||
GetHitUnit()->RemoveAurasDueToSpell(SPELL_VAULT_RUNE_SHIELD);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterCast += SpellCastFn(spell_telash_absolute_zero_damage::HandleAfterCast);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_telash_absolute_zero_damage::HandleHitTarget, EFFECT_1, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_telash_greywing()
|
||||
{
|
||||
// Creature
|
||||
RegisterAzureVaultCreatureAI(boss_telash_greywing);
|
||||
|
||||
// AreaTrigger
|
||||
RegisterAreaTriggerAI(at_telash_greywing_vault_rune);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_telash_ice_power_periodic);
|
||||
RegisterSpellScript(spell_telash_frost_bomb_cast);
|
||||
RegisterSpellScript(spell_telash_frost_bomb_aura);
|
||||
RegisterSpellScript(spell_telash_absolute_zero_cast);
|
||||
RegisterSpellScript(spell_telash_activate_vault_rune);
|
||||
RegisterSpellScript(spell_telash_absolute_zero_damage);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaBoundary.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "azure_vault.h"
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ DATA_LEYMOR, new CircleBoundary(Position(-5129.39f, 1253.30f), 75.0f) }
|
||||
};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_LEYMOR, DATA_LEYMOR },
|
||||
{ BOSS_AZUREBLADE, DATA_AZUREBLADE },
|
||||
{ BOSS_TELASH_GREYWING, DATA_TELASH_GREYWING },
|
||||
{ BOSS_UMBRELSKUL, DATA_UMBRELSKUL },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_ARCANE_VAULTS_DOOR_LEYMOR_ENTRANCE, DATA_LEYMOR, EncounterDoorBehavior::OpenWhenNotInProgress },
|
||||
{ GO_ARCANE_VAULTS_DOOR_LEYMOR_EXIT, DATA_LEYMOR, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_LEYMOR, {{ 2582 }} },
|
||||
{ DATA_AZUREBLADE, {{ 2585 }} },
|
||||
{ DATA_TELASH_GREYWING, {{ 2583 }} },
|
||||
{ DATA_UMBRELSKUL, {{ 2584 }} },
|
||||
};
|
||||
|
||||
class instance_azure_vault : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_azure_vault() : InstanceMapScript(AVScriptName, 2515) { }
|
||||
|
||||
struct instance_azure_vault_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_azure_vault_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
LoadBossBoundaries(boundaries);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
|
||||
_leymorIntroDone = false;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 dataId) const override
|
||||
{
|
||||
switch (dataId)
|
||||
{
|
||||
case DATA_LEYMOR_INTRO_DONE:
|
||||
return _leymorIntroDone ? 1 : 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 dataId, uint32 /*value*/) override
|
||||
{
|
||||
switch (dataId)
|
||||
{
|
||||
case DATA_LEYMOR_INTRO_DONE:
|
||||
_leymorIntroDone = true; // no need to pass value, it will never reset to false
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _leymorIntroDone;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_azure_vault_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_azure_vault()
|
||||
{
|
||||
new instance_azure_vault();
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ruby_life_pools.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_MELIDRUSSA_CHILLWORN, DATA_MELIDRUSSA_CHILLWORN },
|
||||
{ BOSS_KOKIA_BLAZEHOOF, DATA_KOKIA_BLAZEHOOF },
|
||||
{ BOSS_KYRAKKA, DATA_KYRAKKA_AND_ERKHART_STORMVEIN },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_FIRE_WALL, DATA_KOKIA_BLAZEHOOF, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_MELIDRUSSA_CHILLWORN, {{ 2609 }} },
|
||||
{ DATA_KOKIA_BLAZEHOOF, {{ 2606 }} },
|
||||
{ DATA_KYRAKKA_AND_ERKHART_STORMVEIN, {{ 2623 }} }
|
||||
};
|
||||
|
||||
class instance_ruby_life_pools : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_ruby_life_pools() : InstanceMapScript(RLPScriptName, 2521) { }
|
||||
|
||||
struct instance_ruby_life_pools_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_ruby_life_pools_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
}
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_ruby_life_pools_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_ruby_life_pools()
|
||||
{
|
||||
new instance_ruby_life_pools();
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Unit.h"
|
||||
#include "ruby_life_pools.h"
|
||||
|
||||
enum RLPSpells
|
||||
{
|
||||
// Flashfrost Chillweaver
|
||||
SPELL_ICE_SHIELD = 372749,
|
||||
|
||||
// Primal Juggernaut
|
||||
SPELL_EXCAVATE = 373497
|
||||
};
|
||||
|
||||
// 371652 - Executed
|
||||
class spell_ruby_life_pools_executed : public AuraScript
|
||||
{
|
||||
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
target->SetUnitFlag3(UNIT_FLAG3_FAKE_DEAD);
|
||||
target->SetUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
|
||||
target->SetUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_ruby_life_pools_executed::HandleEffectApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 384933 - Ice Shield
|
||||
class spell_ruby_life_pools_ice_shield : public AuraScript
|
||||
{
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (Aura* iceShield = target->GetAura(SPELL_ICE_SHIELD))
|
||||
iceShield->RefreshDuration();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ruby_life_pools_ice_shield::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 372793 - Excavate
|
||||
class spell_ruby_life_pools_excavate : public AuraScript
|
||||
{
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetTarget(), SPELL_EXCAVATE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ruby_life_pools_excavate::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 395029 - Storm Infusion
|
||||
class spell_ruby_life_pools_storm_infusion : public SpellScript
|
||||
{
|
||||
void SetDest(SpellDestination& dest)
|
||||
{
|
||||
dest.RelocateOffset({ 9.0f, 0.0f, 4.0f, 0.0f });
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_ruby_life_pools_storm_infusion::SetDest, EFFECT_1, TARGET_DEST_DEST);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_ruby_life_pools()
|
||||
{
|
||||
RegisterSpellScript(spell_ruby_life_pools_executed);
|
||||
RegisterSpellScript(spell_ruby_life_pools_ice_shield);
|
||||
RegisterSpellScript(spell_ruby_life_pools_excavate);
|
||||
RegisterSpellScript(spell_ruby_life_pools_storm_infusion);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_RUBY_LIFE_POOLS_H_
|
||||
#define DEF_RUBY_LIFE_POOLS_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "RLP"
|
||||
#define RLPScriptName "instance_ruby_life_pools"
|
||||
|
||||
uint32 const EncounterCount = 3;
|
||||
|
||||
enum RLPDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_MELIDRUSSA_CHILLWORN = 0,
|
||||
DATA_KOKIA_BLAZEHOOF = 1,
|
||||
DATA_KYRAKKA_AND_ERKHART_STORMVEIN = 2
|
||||
};
|
||||
|
||||
enum RLPCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_MELIDRUSSA_CHILLWORN = 188252,
|
||||
BOSS_KOKIA_BLAZEHOOF = 189232,
|
||||
BOSS_KYRAKKA = 190484
|
||||
};
|
||||
|
||||
enum RLPGameObjectIds
|
||||
{
|
||||
GO_FIRE_WALL = 377194
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetRubyLifePoolsAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, RLPScriptName);
|
||||
}
|
||||
|
||||
#define RegisterRubyLifePoolsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetRubyLifePoolsAI)
|
||||
|
||||
#endif
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_zone_the_forbidden_reach();
|
||||
|
||||
// Ruby Life Pools
|
||||
void AddSC_instance_ruby_life_pools();
|
||||
void AddSC_ruby_life_pools();
|
||||
|
||||
// Azure Vault
|
||||
void AddSC_instance_azure_vault();
|
||||
void AddSC_boss_leymor();
|
||||
void AddSC_boss_telash_greywing();
|
||||
|
||||
// Aberrus the Shadowed Crucible
|
||||
void AddSC_instance_aberrus_the_shadowed_crucible();
|
||||
void AddSC_aberrus_the_shadowed_crucible();
|
||||
void AddSC_boss_kazzara_the_hellforged();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddDragonIslesScripts()
|
||||
{
|
||||
AddSC_zone_the_forbidden_reach();
|
||||
|
||||
// Ruby Life Pools
|
||||
AddSC_instance_ruby_life_pools();
|
||||
AddSC_ruby_life_pools();
|
||||
|
||||
// Azure Vault
|
||||
AddSC_instance_azure_vault();
|
||||
AddSC_boss_leymor();
|
||||
AddSC_boss_telash_greywing();
|
||||
|
||||
// Aberrus the Shadowed Crucible
|
||||
AddSC_instance_aberrus_the_shadowed_crucible();
|
||||
AddSC_aberrus_the_shadowed_crucible();
|
||||
AddSC_boss_kazzara_the_hellforged();
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "Player.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellScript.h"
|
||||
#include "Log.h"
|
||||
|
||||
enum DracthyrLoginSpells
|
||||
{
|
||||
// Spells
|
||||
SPELL_DRACTHYR_LOGIN = 369728, // teleports to random room, plays scene for the room, binds the home position
|
||||
SPELL_STASIS_1 = 369735, // triggers 366620
|
||||
SPELL_STASIS_2 = 366620, // triggers 366636
|
||||
SPELL_STASIS_3 = 366636, // removes 365560, sends first quest (64864)
|
||||
SPELL_STASIS_4 = 365560, // freeze the target
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_01 = 394245, // scene for room 1
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_02 = 394279, // scene for room 2
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_03 = 394281, // scene for room 3
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_04 = 394282, // scene for room 4
|
||||
//SPELL_DRACTHYR_MOVIE_ROOM_05 = 394283, // scene for room 5 (only plays sound, unused?)
|
||||
SPELL_MAINTAIN_DERVISHIAN = 369731, // Alliance Personal Summon
|
||||
SPELL_MAINTAIN_KODETHI = 370112, // Horde Personal Summon
|
||||
SPELL_AWAKEN_DRACTYHR_QUEST_ABANDON = 369744,
|
||||
SPELL_STASIS_FEEDBACK_KNOCKBACK = 364074,
|
||||
SPELL_STASIS_FEEDBACK_VISUAL = 374633
|
||||
};
|
||||
|
||||
struct DracthyrLoginRoom
|
||||
{
|
||||
uint32 MovieSpellId;
|
||||
Position PlayerPosition;
|
||||
Position SummonPosition;
|
||||
};
|
||||
|
||||
std::array<DracthyrLoginRoom, 4> LoginRoomData =
|
||||
{
|
||||
{
|
||||
{
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_01,
|
||||
{ 5725.32f, -3024.26f, 251.047f, 0.01745329238474369f },
|
||||
{ 5739.97216796875f, -3023.970458984375f, 251.172332763671875f, 3.193952560424804687f }
|
||||
},
|
||||
{
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_02,
|
||||
{ 5743.03f, -3067.28f, 251.047f, 0.798488140106201171f },
|
||||
{ 5754.3046875f, -3056.34716796875f, 251.1725006103515625f, 3.926990747451782226f }
|
||||
},
|
||||
{
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_03,
|
||||
{ 5787.1597f, -3083.3906f, 251.04698f, 1.570796370506286621f },
|
||||
{ 5787.44970703125f, -3069.335205078125f, 251.168121337890625f, 4.729842185974121093f }
|
||||
},
|
||||
{
|
||||
SPELL_DRACTHYR_MOVIE_ROOM_04,
|
||||
{ 5829.32f, -3064.49f, 251.047f, 2.364955902099609375f },
|
||||
{ 5818.533203125f, -3054.5625f, 251.3630828857421875f, 5.480333805084228515f }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 369728 - Dracthyr Login
|
||||
// 369744 - Awaken, Dracthyr OnquestAbandon
|
||||
class spell_dracthyr_login : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DRACTHYR_MOVIE_ROOM_01, SPELL_DRACTHYR_MOVIE_ROOM_02, SPELL_DRACTHYR_MOVIE_ROOM_03, SPELL_DRACTHYR_MOVIE_ROOM_04 });
|
||||
}
|
||||
|
||||
void HandleTeleport(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
DracthyrLoginRoom const& room = LoginRoomData[urand(0, 3)];
|
||||
|
||||
WorldLocation dest = GetHitUnit()->GetWorldLocation();
|
||||
SetExplTargetDest(dest);
|
||||
|
||||
GetHitDest()->Relocate(room.PlayerPosition);
|
||||
|
||||
GetCaster()->CastSpell(GetHitUnit(), room.MovieSpellId, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_dracthyr_login::HandleTeleport, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS);
|
||||
}
|
||||
};
|
||||
|
||||
// 3730 - Dracthyr Evoker Intro (Post Movie)
|
||||
class scene_dracthyr_evoker_intro : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_dracthyr_evoker_intro() : SceneScript("scene_dracthyr_evoker_intro") { }
|
||||
|
||||
void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->CastSpell(player, SPELL_STASIS_1, true);
|
||||
}
|
||||
|
||||
void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->CastSpell(player, SPELL_STASIS_1, true);
|
||||
}
|
||||
};
|
||||
|
||||
// 369730 - Summon Dervishian
|
||||
// 370111 - Summon Kodethi
|
||||
class spell_dracthyr_summon_dervishian : public SpellScript
|
||||
{
|
||||
void SetDest(SpellDestination& dest)
|
||||
{
|
||||
float currentDist = 1000.0f;
|
||||
DracthyrLoginRoom const* currentRoom = nullptr;
|
||||
|
||||
for (DracthyrLoginRoom const& room : LoginRoomData)
|
||||
{
|
||||
float dist = GetCaster()->GetDistance(room.PlayerPosition);
|
||||
if (dist < currentDist)
|
||||
{
|
||||
currentDist = dist;
|
||||
currentRoom = &room;
|
||||
}
|
||||
}
|
||||
if (!currentRoom)
|
||||
return;
|
||||
|
||||
dest.Relocate(currentRoom->SummonPosition);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_dracthyr_summon_dervishian::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
|
||||
}
|
||||
};
|
||||
|
||||
// 64864 - Awaken, Dracthyr
|
||||
class quest_awaken_dracthyr : public QuestScript
|
||||
{
|
||||
public:
|
||||
quest_awaken_dracthyr() : QuestScript("quest_awaken_dracthyr") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
|
||||
{
|
||||
if (newStatus == QUEST_STATUS_NONE)
|
||||
player->CastSpell(player, SPELL_AWAKEN_DRACTYHR_QUEST_ABANDON, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 30308 - Stasis Feedback
|
||||
struct at_dracthyr_stasis_feedback : AreaTriggerAI
|
||||
{
|
||||
at_dracthyr_stasis_feedback(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
unit->CastSpell(nullptr, SPELL_STASIS_FEEDBACK_KNOCKBACK, false);
|
||||
if (Unit* caster = at->GetCaster())
|
||||
caster->CastSpell(caster->GetPosition(), SPELL_STASIS_FEEDBACK_VISUAL, true);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_zone_the_forbidden_reach()
|
||||
{
|
||||
RegisterSpellScript(spell_dracthyr_login);
|
||||
new scene_dracthyr_evoker_intro();
|
||||
RegisterSpellScript(spell_dracthyr_summon_dervishian);
|
||||
new quest_awaken_dracthyr();
|
||||
RegisterAreaTriggerAI(at_dracthyr_stasis_feedback);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_zone_exiles_reach();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddExilesReachScripts()
|
||||
{
|
||||
AddSC_zone_exiles_reach();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
|
||||
void AddSC_zone_boralus();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddKulTirasScripts()
|
||||
{
|
||||
AddSC_zone_boralus();
|
||||
}
|
||||
@@ -1,807 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "Containers.h"
|
||||
#include "Conversation.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
enum GetYourBearingsData
|
||||
{
|
||||
QUEST_GET_YOUR_BEARINGS = 47099,
|
||||
|
||||
KILL_CREDIT_FERRY_DOCK_VISITED = 124588,
|
||||
KILL_CREDIT_COUNTING_HOUSE_VISITED = 124586,
|
||||
KILL_CREDIT_SNUG_HARBOR_INN_VISITED = 124768,
|
||||
KILL_CREDIT_FLIGHT_MASTER_VISITED = 124587,
|
||||
|
||||
OBJECTIVE_FERRY_DOCK_VISITED = 291081,
|
||||
OBJECTIVE_COUNTING_HOUSE_VISITED = 291079,
|
||||
OBJECTIVE_SNUG_HARBOR_INN_VISITED = 291080,
|
||||
OBJECTIVE_FLIGHT_MASTER_VISITED = 291171,
|
||||
|
||||
NPC_SUMMONED_KULTIRAN_GUARD = 124630,
|
||||
|
||||
CONVO_ACTOR_KULTIRAN_GUARD = 59582,
|
||||
|
||||
POINT_KULTIRAN_GUARD = 1,
|
||||
POINT_KULTIRAN_GUARD_FLIGHT_MASTER = 2,
|
||||
|
||||
SPELL_HUB_TOUR_CONVO_FERRY = 247669,
|
||||
SPELL_HUB_TOUR_CONVO_BANK = 247749,
|
||||
SPELL_HUB_TOUR_CONVO_INN = 247894,
|
||||
SPELL_HUB_TOUR_CONVO_FLIGHT_MASTER = 247753
|
||||
};
|
||||
|
||||
enum TheOldKnightData
|
||||
{
|
||||
QUEST_THE_OLD_KNIGHT = 46729,
|
||||
|
||||
NPC_CYRUS_CRESTFALL = 122370,
|
||||
NPC_GENN_GREYMANE = 120788,
|
||||
NPC_GREYGUARD = 120599,
|
||||
|
||||
GOSSIP_MENU_CYRUS_SHAKING_HANDS = 22543,
|
||||
GOSSIP_OPTION_CYRUS_SHAKING_HANDS = 0,
|
||||
|
||||
CONVO_ACCEPT_OLD_KNIGHT_QUEST = 9556,
|
||||
CONVO_CYRUS_MEETS_GENN_IN_OFFICE = 8062,
|
||||
CONVO_CYRUS_SHAKING_HAND = 7653,
|
||||
|
||||
CONVO_ACTOR_CYRUS_CRESTFAL = 59635,
|
||||
|
||||
OBJECTIVE_ENTER_HARBORMASTERS_OFFICE = 335127,
|
||||
|
||||
KILLCREDIT_SPEAK_WITH_CYRUS_OLD_KNIGHT = 137009,
|
||||
KILLCREDIT_HEAR_CYRUS_TALE_OLD_KNIGHT = 137877,
|
||||
|
||||
PATH_KULTIRAN_GUARD_ENTER_OFFICE = 12463000,
|
||||
PATH_KULTIRAN_GUARD_AFTER_SCENE_OFFICE = 12463001,
|
||||
PATH_CYRUS_CRESTFAL_AFTER_SCENE_OFFICE = 12237000,
|
||||
PATH_GENN_GREYMANE_AFTER_SCENE_OFFICE = 12078800,
|
||||
PATH_GREYGUARD_TWO_AFTER_SCENE_OFFICE = 12059900,
|
||||
PATH_GREYGUARD_ONE_AFTER_SCENE_OFFICE = 12059901,
|
||||
|
||||
SPELL_ENTER_HARBOR_MASTERS_OFFICE = 268759,
|
||||
SPELL_FIND_CYRUS_OBJECTIVE_COMPLETE = 269054,
|
||||
SPELL_CLIENT_SCENE_CYRUS_AND_GENN = 271234
|
||||
};
|
||||
|
||||
// 124630 - Taelia
|
||||
struct npc_taelia_get_your_bearings : public ScriptedAI
|
||||
{
|
||||
npc_taelia_get_your_bearings(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void IsSummonedBy(WorldObject* summoner) override
|
||||
{
|
||||
// might be handled by SummonProperties
|
||||
if (Player* player = summoner->ToPlayer())
|
||||
me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
}
|
||||
|
||||
void OnQuestAccept(Player* player, Quest const* quest) override
|
||||
{
|
||||
if (quest->GetQuestId() == QUEST_THE_OLD_KNIGHT)
|
||||
Conversation::CreateConversation(CONVO_ACCEPT_OLD_KNIGHT_QUEST, player, *player, player->GetGUID(), nullptr, false);
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id != SPELL_FIND_CYRUS_OBJECTIVE_COMPLETE)
|
||||
return;
|
||||
|
||||
me->GetMotionMaster()->MovePath(PATH_KULTIRAN_GUARD_AFTER_SCENE_OFFICE, false);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (pointId == POINT_KULTIRAN_GUARD)
|
||||
{
|
||||
if (Unit* summoner = me->GetOwner())
|
||||
me->SetFacingToObject(summoner);
|
||||
}
|
||||
}
|
||||
|
||||
void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
|
||||
{
|
||||
if (pathId == PATH_KULTIRAN_GUARD_AFTER_SCENE_OFFICE)
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
};
|
||||
|
||||
// 5360 - Conversation
|
||||
class conversation_boralus_hub_tour_00 : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_boralus_hub_tour_00() : ConversationScript("conversation_boralus_hub_tour_00") { }
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
Creature* kultiranGuard = creator->FindNearestCreatureWithOptions(20.0f, { .CreatureId = NPC_SUMMONED_KULTIRAN_GUARD, .IgnorePhases = true, .OwnerGuid = creator->GetGUID() });
|
||||
if (!kultiranGuard)
|
||||
return;
|
||||
|
||||
conversation->AddActor(CONVO_ACTOR_KULTIRAN_GUARD, 0, kultiranGuard->GetGUID());
|
||||
conversation->Start();
|
||||
}
|
||||
};
|
||||
|
||||
// XX - Boralus - Get your Bearings (Ferry)
|
||||
// XX - Boralus - Get your Bearings (Bank)
|
||||
// XX - Boralus - Get your Bearings (Inn)
|
||||
// XX - Boralus - Get your Bearings (Flightmaster)
|
||||
template<uint32 QuestId, uint32 ObjectiveId, uint32 SpellId>
|
||||
struct at_boralus_get_your_bearings : AreaTriggerAI
|
||||
{
|
||||
at_boralus_get_your_bearings(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player || player->GetQuestStatus(QuestId) != QUEST_STATUS_INCOMPLETE || player->GetQuestObjectiveData(QuestId, ObjectiveId))
|
||||
return;
|
||||
|
||||
player->CastSpell(nullptr, SpellId, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 5362 - Conversation - Get your Bearings (Ferry)
|
||||
class conversation_boralus_hub_tour : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_boralus_hub_tour(char const* scriptName) : ConversationScript(scriptName) { }
|
||||
|
||||
enum ConversationFerryData
|
||||
{
|
||||
EVENT_TAELIA_CREDIT = 1
|
||||
};
|
||||
|
||||
virtual Position const& GetGuardMovePosition() = 0;
|
||||
virtual uint32 GetKillCreditId() = 0;
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
Creature* kultiranGuard = creator->FindNearestCreatureWithOptions(20.0f, { .CreatureId = NPC_SUMMONED_KULTIRAN_GUARD, .IgnorePhases = true, .OwnerGuid = creator->GetGUID() });
|
||||
if (!kultiranGuard)
|
||||
return;
|
||||
|
||||
kultiranGuard->GetMotionMaster()->Clear();
|
||||
kultiranGuard->GetMotionMaster()->MovePoint(POINT_KULTIRAN_GUARD, GetGuardMovePosition());
|
||||
|
||||
conversation->AddActor(CONVO_ACTOR_KULTIRAN_GUARD, 0, kultiranGuard->GetGUID());
|
||||
conversation->Start();
|
||||
}
|
||||
|
||||
void OnConversationStart(Conversation* conversation) override
|
||||
{
|
||||
LocaleConstant privateOwnerLocale = conversation->GetPrivateObjectOwnerLocale();
|
||||
|
||||
_events.ScheduleEvent(EVENT_TAELIA_CREDIT, conversation->GetLastLineEndTime(privateOwnerLocale));
|
||||
}
|
||||
|
||||
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_TAELIA_CREDIT:
|
||||
{
|
||||
Player* player = ObjectAccessor::GetPlayer(*conversation, conversation->GetPrivateObjectOwner());
|
||||
if (!player)
|
||||
break;
|
||||
|
||||
Creature* kultiranGuard = player->FindNearestCreatureWithOptions(50.0f, { .CreatureId = NPC_SUMMONED_KULTIRAN_GUARD, .IgnorePhases = true, .OwnerGuid = player->GetGUID() });
|
||||
if (!kultiranGuard)
|
||||
break;
|
||||
|
||||
player->KilledMonsterCredit(GetKillCreditId());
|
||||
kultiranGuard->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
Position const TaeliaFerryPos = { 1039.5955f, -598.00653f, 1.458778f };
|
||||
|
||||
// 5362 - Conversation - Get your Bearings (Ferry)
|
||||
class conversation_boralus_hub_tour_ferry : public conversation_boralus_hub_tour
|
||||
{
|
||||
public:
|
||||
conversation_boralus_hub_tour_ferry() : conversation_boralus_hub_tour("conversation_boralus_hub_tour_ferry") { }
|
||||
|
||||
Position const& GetGuardMovePosition()
|
||||
{
|
||||
return TaeliaFerryPos;
|
||||
}
|
||||
|
||||
uint32 GetKillCreditId()
|
||||
{
|
||||
return KILL_CREDIT_FERRY_DOCK_VISITED;
|
||||
}
|
||||
};
|
||||
|
||||
Position const TaeliaBankPos = { 1118.7385f, -622.4115f, 17.76035f };
|
||||
|
||||
// 5365 - Conversation Get your Bearings (Counting House)
|
||||
class conversation_boralus_hub_tour_counting_house : public conversation_boralus_hub_tour
|
||||
{
|
||||
public:
|
||||
conversation_boralus_hub_tour_counting_house() : conversation_boralus_hub_tour("conversation_boralus_hub_tour_counting_house") { }
|
||||
|
||||
Position const& GetGuardMovePosition()
|
||||
{
|
||||
return TaeliaBankPos;
|
||||
}
|
||||
|
||||
uint32 GetKillCreditId()
|
||||
{
|
||||
return KILL_CREDIT_COUNTING_HOUSE_VISITED;
|
||||
}
|
||||
};
|
||||
|
||||
Position const TaeliaInnPos = { 1177.39f, -587.682f, 31.557224f };
|
||||
|
||||
// 5375 - Conversation Get your Bearings (Harbor Inn)
|
||||
class conversation_boralus_hub_tour_harbor_inn : public conversation_boralus_hub_tour
|
||||
{
|
||||
public:
|
||||
conversation_boralus_hub_tour_harbor_inn() : conversation_boralus_hub_tour("conversation_boralus_hub_tour_harbor_inn") { }
|
||||
|
||||
Position const& GetGuardMovePosition()
|
||||
{
|
||||
return TaeliaInnPos;
|
||||
}
|
||||
|
||||
uint32 GetKillCreditId()
|
||||
{
|
||||
return KILL_CREDIT_SNUG_HARBOR_INN_VISITED;
|
||||
}
|
||||
};
|
||||
|
||||
Position const TaeliaFlightMasterPos = { 1149.82f, -471.071f, 30.503826f };
|
||||
|
||||
// 5366 - Conversation Get your Bearings (Flight Master)
|
||||
class conversation_boralus_hub_tour_flight_master : public conversation_boralus_hub_tour
|
||||
{
|
||||
public:
|
||||
conversation_boralus_hub_tour_flight_master() : conversation_boralus_hub_tour("conversation_boralus_hub_tour_flight_master") { }
|
||||
|
||||
Position const& GetGuardMovePosition()
|
||||
{
|
||||
return TaeliaFlightMasterPos;
|
||||
}
|
||||
|
||||
uint32 GetKillCreditId()
|
||||
{
|
||||
return KILL_CREDIT_FLIGHT_MASTER_VISITED;
|
||||
}
|
||||
};
|
||||
|
||||
// 9556 - Conversation The Old Knight (accept Quest)
|
||||
class conversation_boralus_accept_old_knight : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_boralus_accept_old_knight() : ConversationScript("conversation_boralus_accept_old_knight") { }
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
Creature* kultiranGuard = creator->FindNearestCreatureWithOptions(20.0f, { .CreatureId = NPC_SUMMONED_KULTIRAN_GUARD, .IgnorePhases = true, .OwnerGuid = creator->GetGUID() });
|
||||
if (!kultiranGuard)
|
||||
return;
|
||||
|
||||
conversation->AddActor(CONVO_ACTOR_KULTIRAN_GUARD, 0, kultiranGuard->GetGUID());
|
||||
conversation->Start();
|
||||
}
|
||||
};
|
||||
|
||||
// XX - Boralus The Old Knight (Enter the Harbormasters Office)
|
||||
struct at_boralus_old_knight_enter_harbormasters_office : AreaTriggerAI
|
||||
{
|
||||
at_boralus_old_knight_enter_harbormasters_office(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player || player->GetQuestStatus(QUEST_THE_OLD_KNIGHT) != QUEST_STATUS_INCOMPLETE || player->GetQuestObjectiveData(QUEST_THE_OLD_KNIGHT, OBJECTIVE_ENTER_HARBORMASTERS_OFFICE))
|
||||
return;
|
||||
|
||||
player->CastSpell(nullptr, SPELL_ENTER_HARBOR_MASTERS_OFFICE, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 7605 - Conversation The Old Knight (Enter the Harbormasters Office)
|
||||
class conversation_boralus_enter_harbormaster_office : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_boralus_enter_harbormaster_office() : ConversationScript("conversation_boralus_enter_harbormaster_office") { }
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
Creature* kultiranGuard = creator->FindNearestCreatureWithOptions(20.0f, { .CreatureId = NPC_SUMMONED_KULTIRAN_GUARD, .IgnorePhases = true, .OwnerGuid = creator->GetGUID() });
|
||||
if (!kultiranGuard)
|
||||
return;
|
||||
|
||||
kultiranGuard->GetMotionMaster()->Clear();
|
||||
kultiranGuard->GetMotionMaster()->MovePath(PATH_KULTIRAN_GUARD_ENTER_OFFICE, false);
|
||||
|
||||
conversation->AddActor(CONVO_ACTOR_KULTIRAN_GUARD, 0, kultiranGuard->GetGUID());
|
||||
conversation->Start();
|
||||
}
|
||||
};
|
||||
|
||||
// XX - Boralus The Old Knight (Genn Greymane arrives Boralus)
|
||||
struct at_boralus_old_knight_genn_arrives_boralus : AreaTriggerAI
|
||||
{
|
||||
at_boralus_old_knight_genn_arrives_boralus(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player || player->GetQuestStatus(QUEST_THE_OLD_KNIGHT) != QUEST_STATUS_INCOMPLETE || player->GetQuestObjectiveData(QUEST_THE_OLD_KNIGHT, OBJECTIVE_ENTER_HARBORMASTERS_OFFICE))
|
||||
return;
|
||||
|
||||
player->CastSpell(nullptr, SPELL_CLIENT_SCENE_CYRUS_AND_GENN, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 1960 - Client Scene: Cyrus and Genn
|
||||
class scene_boralus_client_scene_cyrus_and_genn : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_boralus_client_scene_cyrus_and_genn() : SceneScript("scene_boralus_client_scene_cyrus_and_genn") { }
|
||||
|
||||
void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->CastSpell(player, SPELL_FIND_CYRUS_OBJECTIVE_COMPLETE, true);
|
||||
}
|
||||
|
||||
void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
|
||||
{
|
||||
player->CastSpell(player, SPELL_FIND_CYRUS_OBJECTIVE_COMPLETE, true);
|
||||
}
|
||||
};
|
||||
|
||||
Position const TaeliaTeleportOfficePos = { 1054.29f, -469.776f, 11.7166f, 3.065999f };
|
||||
|
||||
// 269054 - Find Cyrus Objective Complete
|
||||
class spell_boralus_find_cyrus_objective_complete : public SpellScript
|
||||
{
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Player* player = GetHitUnit()->ToPlayer())
|
||||
{
|
||||
player->KilledMonsterCredit(NPC_CYRUS_CRESTFALL);
|
||||
Conversation::CreateConversation(CONVO_CYRUS_MEETS_GENN_IN_OFFICE, player, *player, player->GetGUID(), nullptr, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetHitUnit()->GetEntry() != NPC_SUMMONED_KULTIRAN_GUARD)
|
||||
return;
|
||||
|
||||
GetHitUnit()->NearTeleportTo(TaeliaTeleportOfficePos);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_boralus_find_cyrus_objective_complete::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
Position const CyrusOfficePos = { 1056.310f, -470.567f, 11.656f, 5.80610f };
|
||||
Position const GennOfficePos = { 1052.689f, -470.200f, 11.692f, 0.24838f };
|
||||
Position const GreyguardOneOfficePos = { 1044.979f, -468.523f, 8.386f, 6.03047f };
|
||||
Position const GreyguardTwoOfficePos = { 1042.359f, -467.738f, 8.386f, 6.04665f };
|
||||
|
||||
// 8062 - Conversation
|
||||
class conversation_boralus_cyrus_meets_genn : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_boralus_cyrus_meets_genn() : ConversationScript("conversation_boralus_cyrus_meets_genn") { }
|
||||
|
||||
enum OldKnightsConversationData
|
||||
{
|
||||
CONVO_LINE_CYRUS_AND_GENN_DESPAWN = 18298,
|
||||
|
||||
EVENT_OLD_KNIGHTS_CLONE_DESPAWN = 1
|
||||
};
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
Creature* cyrusObject = GetClosestCreatureWithOptions(creator, 30.0f, { .CreatureId = NPC_CYRUS_CRESTFALL, .IgnorePhases = true });
|
||||
Creature* gennObject = GetClosestCreatureWithOptions(creator, 30.0f, { .CreatureId = NPC_GENN_GREYMANE, .IgnorePhases = true });
|
||||
Creature* greyguardOneObject = GetClosestCreatureWithOptions(creator, 30.0f, { .CreatureId = NPC_GREYGUARD, .StringId = "GreyguardOne", .IgnorePhases = true });
|
||||
Creature* greyguardTwoObject = GetClosestCreatureWithOptions(creator, 30.0f, { .CreatureId = NPC_GREYGUARD, .StringId = "GreyguardTwo", .IgnorePhases = true });
|
||||
if (!cyrusObject || !gennObject || !greyguardOneObject || !greyguardTwoObject)
|
||||
return;
|
||||
|
||||
TempSummon* cyrusClone = cyrusObject->SummonPersonalClone(CyrusOfficePos, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, creator->ToPlayer());
|
||||
TempSummon* gennClone = gennObject->SummonPersonalClone(GennOfficePos, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, creator->ToPlayer());
|
||||
TempSummon* greyguardOneClone = greyguardOneObject->SummonPersonalClone(GreyguardOneOfficePos, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, creator->ToPlayer());
|
||||
TempSummon* greyguardTwoClone = greyguardTwoObject->SummonPersonalClone(GreyguardTwoOfficePos, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, creator->ToPlayer());
|
||||
if (!cyrusClone || !gennClone || !greyguardOneClone || !greyguardTwoClone)
|
||||
return;
|
||||
|
||||
_gennCloneGUID = gennClone->GetGUID();
|
||||
|
||||
cyrusClone->RemoveNpcFlag(NPCFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER));
|
||||
gennClone->RemoveNpcFlag(NPCFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER));
|
||||
|
||||
cyrusClone->GetMotionMaster()->MovePath(PATH_CYRUS_CRESTFAL_AFTER_SCENE_OFFICE, false);
|
||||
gennClone->GetMotionMaster()->MovePath(PATH_GENN_GREYMANE_AFTER_SCENE_OFFICE, false);
|
||||
greyguardOneClone->GetMotionMaster()->MovePath(PATH_GREYGUARD_ONE_AFTER_SCENE_OFFICE, false);
|
||||
greyguardTwoClone->GetMotionMaster()->MovePath(PATH_GREYGUARD_TWO_AFTER_SCENE_OFFICE, false);
|
||||
|
||||
conversation->AddActor(CONVO_ACTOR_CYRUS_CRESTFAL, 0, cyrusClone->GetGUID());
|
||||
conversation->Start();
|
||||
}
|
||||
|
||||
void OnConversationStart(Conversation* conversation) override
|
||||
{
|
||||
LocaleConstant privateOwnerLocale = conversation->GetPrivateObjectOwnerLocale();
|
||||
|
||||
_events.ScheduleEvent(EVENT_OLD_KNIGHTS_CLONE_DESPAWN, conversation->GetLineEndTime(privateOwnerLocale, CONVO_LINE_CYRUS_AND_GENN_DESPAWN));
|
||||
}
|
||||
|
||||
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_OLD_KNIGHTS_CLONE_DESPAWN:
|
||||
{
|
||||
Creature* cyrusClone = conversation->GetActorCreature(0);
|
||||
if (!cyrusClone)
|
||||
break;
|
||||
|
||||
Unit* privateObjectOwner = ObjectAccessor::GetUnit(*conversation, conversation->GetPrivateObjectOwner());
|
||||
if (!privateObjectOwner)
|
||||
return;
|
||||
|
||||
if (Creature* gennClone = ObjectAccessor::GetCreature(*conversation, _gennCloneGUID))
|
||||
gennClone->DespawnOrUnsummon();
|
||||
|
||||
cyrusClone->DespawnOrUnsummon();
|
||||
PhasingHandler::OnConditionChange(privateObjectOwner);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _gennCloneGUID;
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
// 122370 - Cyrus Crestfall
|
||||
struct npc_cyrus_crestfall_old_knight : public ScriptedAI
|
||||
{
|
||||
npc_cyrus_crestfall_old_knight(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
|
||||
{
|
||||
// Quest 46729 - The Old Knight
|
||||
if (menuId == GOSSIP_MENU_CYRUS_SHAKING_HANDS && gossipListId == GOSSIP_OPTION_CYRUS_SHAKING_HANDS)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
player->KilledMonsterCredit(KILLCREDIT_SPEAK_WITH_CYRUS_OLD_KNIGHT);
|
||||
Conversation::CreateConversation(CONVO_CYRUS_SHAKING_HAND, player, *player, player->GetGUID(), nullptr, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Position const CyrusMoveToOfficeFirePos = { 1075.257f, -487.25696f, 9.812291f };
|
||||
Position const CyrusStaticOfficePos = { 1071.428f, -486.312f, 9.783f, 3.4995f };
|
||||
|
||||
// 7653 - Conversation
|
||||
class conversation_cyrus_crestfall_shaking_hands : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_cyrus_crestfall_shaking_hands() : ConversationScript("conversation_cyrus_crestfall_shaking_hands") { }
|
||||
|
||||
enum ShakingHandsConversationData
|
||||
{
|
||||
CONVO_LINE_CYRUS_START_WALK_TO_FIRE = 17416,
|
||||
CONVO_LINE_CYRUS_CHANGE_FACING_GENN = 17419,
|
||||
CONVO_LINE_CYRUS_MOVE_BACK_TO_GENN = 17421,
|
||||
CONVO_LINE_CYRUS_DESPAWN_CLONE_OFFICE = 17423,
|
||||
|
||||
EVENT_CYRUS_START_WALK_TO_FIRE = 1,
|
||||
EVENT_CYRUS_CHANGE_FACING_GENN = 2,
|
||||
EVENT_CYRUS_MOVE_BACK_TO_GENN = 3,
|
||||
EVENT_CYRUS_DESPAWN_CLONE_OFFICE = 4,
|
||||
|
||||
POINT_CYRUS_MOVE_TO_OFFICE_FIRE = 1,
|
||||
POINT_CYRUS_MOVE_BACK_TO_GENN = 2
|
||||
};
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
Creature* cyrusObject = GetClosestCreatureWithOptions(creator, 10.0f, { .CreatureId = NPC_CYRUS_CRESTFALL, .IgnorePhases = true });
|
||||
if (!cyrusObject)
|
||||
return;
|
||||
|
||||
TempSummon* cyrusClone = cyrusObject->SummonPersonalClone(cyrusObject->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, creator->ToPlayer());
|
||||
if (!cyrusClone)
|
||||
return;
|
||||
|
||||
cyrusClone->RemoveNpcFlag(NPCFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER));
|
||||
|
||||
conversation->AddActor(CONVO_ACTOR_CYRUS_CRESTFAL, 1, cyrusClone->GetGUID());
|
||||
conversation->Start();
|
||||
}
|
||||
|
||||
void OnConversationStart(Conversation* conversation) override
|
||||
{
|
||||
LocaleConstant privateOwnerLocale = conversation->GetPrivateObjectOwnerLocale();
|
||||
|
||||
_events.ScheduleEvent(EVENT_CYRUS_START_WALK_TO_FIRE, conversation->GetLineEndTime(privateOwnerLocale, CONVO_LINE_CYRUS_START_WALK_TO_FIRE));
|
||||
_events.ScheduleEvent(EVENT_CYRUS_CHANGE_FACING_GENN, conversation->GetLineEndTime(privateOwnerLocale, CONVO_LINE_CYRUS_CHANGE_FACING_GENN));
|
||||
_events.ScheduleEvent(EVENT_CYRUS_MOVE_BACK_TO_GENN, conversation->GetLineEndTime(privateOwnerLocale, CONVO_LINE_CYRUS_MOVE_BACK_TO_GENN));
|
||||
_events.ScheduleEvent(EVENT_CYRUS_DESPAWN_CLONE_OFFICE, conversation->GetLineEndTime(privateOwnerLocale, CONVO_LINE_CYRUS_DESPAWN_CLONE_OFFICE));
|
||||
}
|
||||
|
||||
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CYRUS_START_WALK_TO_FIRE:
|
||||
{
|
||||
Creature* cyrusClone = conversation->GetActorCreature(1);
|
||||
if (!cyrusClone)
|
||||
break;
|
||||
|
||||
cyrusClone->SetWalk(true);
|
||||
cyrusClone->GetMotionMaster()->MovePoint(POINT_CYRUS_MOVE_TO_OFFICE_FIRE, CyrusMoveToOfficeFirePos);
|
||||
break;
|
||||
}
|
||||
case EVENT_CYRUS_CHANGE_FACING_GENN:
|
||||
{
|
||||
Creature* cyrusClone = conversation->GetActorCreature(1);
|
||||
if (!cyrusClone)
|
||||
break;
|
||||
|
||||
cyrusClone->SetFacingTo(3.49956f);
|
||||
break;
|
||||
}
|
||||
case EVENT_CYRUS_MOVE_BACK_TO_GENN:
|
||||
{
|
||||
Creature* cyrusClone = conversation->GetActorCreature(1);
|
||||
if (!cyrusClone)
|
||||
break;
|
||||
|
||||
Player* privateObjectOwner = ObjectAccessor::GetPlayer(*conversation, conversation->GetPrivateObjectOwner());
|
||||
if (!privateObjectOwner)
|
||||
return;
|
||||
|
||||
cyrusClone->SetWalk(true);
|
||||
cyrusClone->GetMotionMaster()->MovePoint(POINT_CYRUS_MOVE_BACK_TO_GENN, CyrusStaticOfficePos);
|
||||
privateObjectOwner->KilledMonsterCredit(KILLCREDIT_HEAR_CYRUS_TALE_OLD_KNIGHT);
|
||||
break;
|
||||
}
|
||||
case EVENT_CYRUS_DESPAWN_CLONE_OFFICE:
|
||||
{
|
||||
Creature* cyrusClone = conversation->GetActorCreature(1);
|
||||
if (!cyrusClone)
|
||||
break;
|
||||
|
||||
cyrusClone->DespawnOrUnsummon();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
enum SanctumOfTheSagesData
|
||||
{
|
||||
QUEST_SANCTUM_OF_THE_SAGES = 47186,
|
||||
|
||||
NPC_7TH_LEGION_MAGUS_WITH_GOSSIP = 137066,
|
||||
NPC_7TH_LEGION_MAGUS = 143613,
|
||||
|
||||
GOSSIP_MENU_OPEN_CITY_PORTALS = 22548,
|
||||
GOSSIP_OPTION_OPEN_CITY_PORTALS = 0,
|
||||
|
||||
CONVO_SANCTUM_OF_THE_SAGES = 8356,
|
||||
|
||||
KILLCREDIT_OPEN_CAPITAL_PORTALS = 137066,
|
||||
|
||||
SPELL_LEGION_MAGUS_ARCANE_CHANNEL = 54219,
|
||||
|
||||
PATH_MAGUS_OPEN_PORTAL_STORMWIND = 13706600,
|
||||
PATH_MAGUS_FINISH_PORTAL_STORMWIND = 13706601,
|
||||
PATH_MAGUS_OPEN_PORTAL_EXODAR = 14361300,
|
||||
PATH_MAGUS_FINISH_PORTAL_EXODAR = 14361301,
|
||||
PATH_MAGUS_OPEN_PORTAL_IRONFORGE = 14361302,
|
||||
PATH_MAGUS_FINISH_PORTAL_IRONFORGE = 14361303
|
||||
};
|
||||
|
||||
// 137066 - 7th Legion Magus
|
||||
// 143613 - 7th Legion Magus
|
||||
struct npc_7th_legion_magus_sanctum_of_the_sages : public ScriptedAI
|
||||
{
|
||||
npc_7th_legion_magus_sanctum_of_the_sages(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
|
||||
{
|
||||
// Quest 47186 - Sanctum of the Sages
|
||||
if (menuId == GOSSIP_MENU_OPEN_CITY_PORTALS && gossipListId == GOSSIP_OPTION_OPEN_CITY_PORTALS)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
player->KilledMonsterCredit(KILLCREDIT_OPEN_CAPITAL_PORTALS);
|
||||
|
||||
Creature* magusStormwind = GetClosestCreatureWithOptions(player, 10.0f, { .CreatureId = NPC_7TH_LEGION_MAGUS_WITH_GOSSIP, .StringId = "MagusStormwind", .IgnorePhases = true});
|
||||
Creature* magusExodar = GetClosestCreatureWithOptions(player, 10.0f, { .CreatureId = NPC_7TH_LEGION_MAGUS, .StringId = "MagusExodar", .IgnorePhases = true});
|
||||
Creature* magusIronforge = GetClosestCreatureWithOptions(player, 10.0f, { .CreatureId = NPC_7TH_LEGION_MAGUS, .StringId = "MagusIronforge", .IgnorePhases = true});
|
||||
if (!magusStormwind || !magusExodar || !magusIronforge)
|
||||
return true;
|
||||
|
||||
TempSummon* magusStormwindClone = magusStormwind->SummonPersonalClone(magusStormwind->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player);
|
||||
TempSummon* magusExodarClone = magusExodar->SummonPersonalClone(magusExodar->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player);
|
||||
TempSummon* magusIronforgeClone = magusIronforge->SummonPersonalClone(magusIronforge->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player);
|
||||
if (!magusStormwindClone || !magusExodarClone || !magusIronforgeClone)
|
||||
return true;
|
||||
|
||||
magusStormwindClone->RemoveNpcFlag(NPCFlags(UNIT_NPC_FLAG_GOSSIP));
|
||||
magusStormwindClone->GetMotionMaster()->MovePath(PATH_MAGUS_OPEN_PORTAL_STORMWIND, false);
|
||||
magusExodarClone->GetMotionMaster()->MovePath(PATH_MAGUS_OPEN_PORTAL_EXODAR, false);
|
||||
magusIronforgeClone->GetMotionMaster()->MovePath(PATH_MAGUS_OPEN_PORTAL_IRONFORGE, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaypointReached(uint32 /*waypointId*/, uint32 pathId) override
|
||||
{
|
||||
if (pathId == PATH_MAGUS_OPEN_PORTAL_EXODAR)
|
||||
{
|
||||
DoCastAOE(SPELL_LEGION_MAGUS_ARCANE_CHANNEL);
|
||||
_scheduler.Schedule(3s + 500ms, [this](TaskContext task)
|
||||
{
|
||||
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||
task.Schedule(1s + 500ms, [this](TaskContext /*task*/)
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(PATH_MAGUS_FINISH_PORTAL_EXODAR, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (pathId == PATH_MAGUS_OPEN_PORTAL_IRONFORGE)
|
||||
{
|
||||
DoCastAOE(SPELL_LEGION_MAGUS_ARCANE_CHANNEL);
|
||||
_scheduler.Schedule(3s + 500ms, [this](TaskContext task)
|
||||
{
|
||||
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||
task.Schedule(1s + 500ms, [this](TaskContext /*task*/)
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(PATH_MAGUS_FINISH_PORTAL_IRONFORGE, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (pathId == PATH_MAGUS_OPEN_PORTAL_STORMWIND)
|
||||
{
|
||||
DoCastAOE(SPELL_LEGION_MAGUS_ARCANE_CHANNEL);
|
||||
_scheduler.Schedule(3s + 500ms, [this](TaskContext task)
|
||||
{
|
||||
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||
task.Schedule(1s + 500ms, [this](TaskContext /*task*/)
|
||||
{
|
||||
TempSummon* summon = me->ToTempSummon();
|
||||
if (!summon)
|
||||
return;
|
||||
|
||||
Unit* summoner = summon->GetSummonerUnit();
|
||||
if (!summoner)
|
||||
return;
|
||||
|
||||
PhasingHandler::OnConditionChange(summoner);
|
||||
me->GetMotionMaster()->MovePath(PATH_MAGUS_FINISH_PORTAL_STORMWIND, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (pathId == PATH_MAGUS_FINISH_PORTAL_STORMWIND || pathId == PATH_MAGUS_FINISH_PORTAL_EXODAR || pathId == PATH_MAGUS_FINISH_PORTAL_IRONFORGE)
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
// 64 - Boralus - Sanctum of the Sages
|
||||
struct at_boralus_sanctum_of_the_sages_conversation : AreaTriggerAI
|
||||
{
|
||||
at_boralus_sanctum_of_the_sages_conversation(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player || player->GetQuestStatus(QUEST_SANCTUM_OF_THE_SAGES) != QUEST_STATUS_COMPLETE)
|
||||
return;
|
||||
|
||||
Conversation::CreateConversation(CONVO_SANCTUM_OF_THE_SAGES, player, *player, player->GetGUID(), nullptr, true);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_zone_boralus()
|
||||
{
|
||||
// Creature
|
||||
RegisterCreatureAI(npc_taelia_get_your_bearings);
|
||||
RegisterCreatureAI(npc_cyrus_crestfall_old_knight);
|
||||
RegisterCreatureAI(npc_7th_legion_magus_sanctum_of_the_sages);
|
||||
|
||||
// Conversation
|
||||
new conversation_boralus_hub_tour_00();
|
||||
new conversation_boralus_hub_tour_ferry();
|
||||
new conversation_boralus_hub_tour_counting_house();
|
||||
new conversation_boralus_hub_tour_harbor_inn();
|
||||
new conversation_boralus_hub_tour_flight_master();
|
||||
new conversation_boralus_accept_old_knight();
|
||||
new conversation_boralus_enter_harbormaster_office();
|
||||
new conversation_boralus_cyrus_meets_genn();
|
||||
new conversation_cyrus_crestfall_shaking_hands();
|
||||
|
||||
// Scene
|
||||
new scene_boralus_client_scene_cyrus_and_genn();
|
||||
|
||||
// AreaTrigger
|
||||
RegisterAreaTriggerAI(at_boralus_old_knight_enter_harbormasters_office);
|
||||
RegisterAreaTriggerAI(at_boralus_old_knight_genn_arrives_boralus);
|
||||
RegisterAreaTriggerAI(at_boralus_sanctum_of_the_sages_conversation);
|
||||
|
||||
// AreaTrigger Template
|
||||
new GenericAreaTriggerEntityScript<at_boralus_get_your_bearings<QUEST_GET_YOUR_BEARINGS, OBJECTIVE_FERRY_DOCK_VISITED, SPELL_HUB_TOUR_CONVO_FERRY>>("at_boralus_get_your_bearings_ferry");
|
||||
new GenericAreaTriggerEntityScript<at_boralus_get_your_bearings<QUEST_GET_YOUR_BEARINGS, OBJECTIVE_COUNTING_HOUSE_VISITED, SPELL_HUB_TOUR_CONVO_BANK>>("at_boralus_get_your_bearings_counting_house");
|
||||
new GenericAreaTriggerEntityScript<at_boralus_get_your_bearings<QUEST_GET_YOUR_BEARINGS, OBJECTIVE_SNUG_HARBOR_INN_VISITED, SPELL_HUB_TOUR_CONVO_INN>>("at_boralus_get_your_bearings_inn");
|
||||
new GenericAreaTriggerEntityScript<at_boralus_get_your_bearings<QUEST_GET_YOUR_BEARINGS, OBJECTIVE_FLIGHT_MASTER_VISITED, SPELL_HUB_TOUR_CONVO_FLIGHT_MASTER>>("at_boralus_get_your_bearings_flight_master");
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_boralus_find_cyrus_objective_complete);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts loading function should be declared:
|
||||
void AddSC_zone_the_wandering_isle();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddPandariaScripts()
|
||||
{
|
||||
AddSC_zone_the_wandering_isle();
|
||||
}
|
||||
@@ -1,409 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "CellImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
enum TraineeMisc
|
||||
{
|
||||
SAY_FINISH_FIGHT = 0,
|
||||
|
||||
SPELL_BLACKOUT_KICK = 109080,
|
||||
|
||||
QUEST_29524_KILLCREDIT = 54586,
|
||||
|
||||
POINT_DESPAWN = 0,
|
||||
|
||||
NPC_HUOJIN_TRAINEE_MALE = 54586,
|
||||
NPC_HUOJIN_TRAINEE_FEMALE = 65470,
|
||||
NPC_TUSHUI_TRAINEE_MALE = 54587,
|
||||
NPC_TUSHUI_TRAINEE_FEMALE = 65471,
|
||||
};
|
||||
|
||||
Position const TraineeEndpoints[] = {
|
||||
{ 1465.3872f, 3283.8604f, 137.69096f },
|
||||
{ 1431.401f, 3264.001f, 136.02579f },
|
||||
{ 1397.2067f, 3276.5618f, 133.84508f },
|
||||
{ 1441.566f, 3232.8013f, 135.01802f },
|
||||
{ 1403.632f, 3229.1094f, 132.14877f },
|
||||
{ 1347.1927f, 3286.5842f, 131.94803f },
|
||||
{ 1365.1865f, 3338.9502f, 128.57233f },
|
||||
{ 1349.6024f, 3315.0574f, 130.97443f },
|
||||
{ 1335.4618f, 3344.019f, 130.42047f },
|
||||
{ 1360.1198f, 3378.02f, 127.34183f },
|
||||
{ 1435.8524f, 3355.6423f, 173.77744f },
|
||||
{ 1432.7031f, 3385.1572f, 184.4187f },
|
||||
{ 1452.6094f, 3373.3315f, 187.0402f },
|
||||
{ 1426.7778f, 3364.7517f, 184.39569f },
|
||||
{ 1450.3646f, 3361.264f, 184.42484f },
|
||||
};
|
||||
|
||||
Emote constexpr TraineeEmotes[5] =
|
||||
{
|
||||
EMOTE_ONESHOT_MONKOFFENSE_ATTACKUNARMED,
|
||||
EMOTE_ONESHOT_MONKOFFENSE_SPECIALUNARMED,
|
||||
EMOTE_ONESHOT_MONKOFFENSE_PARRYUNARMED,
|
||||
EMOTE_ONESHOT_PALMSTRIKE,
|
||||
EMOTE_ONESHOT_MONKOFFENSE_ATTACKUNARMEDOFF,
|
||||
};
|
||||
|
||||
// 54586 - Huojin Trainee
|
||||
// 65470 - Huojin Trainee
|
||||
// 54587 - Tushui Trainee
|
||||
// 65471 - Tushui Trainee
|
||||
struct npc_tushui_huojin_trainee : public ScriptedAI
|
||||
{
|
||||
npc_tushui_huojin_trainee(Creature* creature) : ScriptedAI(creature), _defeated(false) { }
|
||||
|
||||
Emote PlayRandomEmote() const
|
||||
{
|
||||
Emote emote = Trinity::Containers::SelectRandomContainerElement(TraineeEmotes);
|
||||
me->HandleEmoteCommand(emote);
|
||||
return emote;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(20, damage))
|
||||
{
|
||||
damage = 0;
|
||||
if (_defeated)
|
||||
return;
|
||||
|
||||
_defeated = true;
|
||||
if (attacker)
|
||||
{
|
||||
if (Player* player = attacker->ToPlayer())
|
||||
player->KilledMonsterCredit(QUEST_29524_KILLCREDIT);
|
||||
}
|
||||
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
me->CombatStop();
|
||||
|
||||
_scheduler.Schedule(Seconds(1), [this](TaskContext /*task*/)
|
||||
{
|
||||
Talk(SAY_FINISH_FIGHT);
|
||||
});
|
||||
|
||||
_scheduler.Schedule(Seconds(3), [this](TaskContext /*task*/)
|
||||
{
|
||||
Position currentPosition;
|
||||
float currentDist = 1000.0f;
|
||||
for (Position const& pos : TraineeEndpoints)
|
||||
{
|
||||
float dist = pos.GetExactDist(me);
|
||||
if (dist >= currentDist)
|
||||
continue;
|
||||
|
||||
currentPosition = pos;
|
||||
currentDist = dist;
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, currentPosition);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (id != POINT_DESPAWN)
|
||||
return;
|
||||
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
_scheduler.Schedule(Seconds(4), [this](TaskContext task)
|
||||
{
|
||||
if (me->GetVictim())
|
||||
DoCastVictim(SPELL_BLACKOUT_KICK);
|
||||
|
||||
task.Repeat(Seconds(8));
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (!_defeated)
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
protected:
|
||||
TaskScheduler _scheduler;
|
||||
bool _defeated;
|
||||
};
|
||||
|
||||
enum HuojinTraineeMisc
|
||||
{
|
||||
ACTION_PARTNER_ENTERED_COMBAT = 1,
|
||||
};
|
||||
|
||||
class HuojinTraineePartnerSearch
|
||||
{
|
||||
public:
|
||||
HuojinTraineePartnerSearch(Creature* partner) : _partner(partner), _minDist(10.0f) { }
|
||||
|
||||
bool operator()(Creature const* target)
|
||||
{
|
||||
if (target->GetEntry() != NPC_HUOJIN_TRAINEE_MALE && target->GetEntry() != NPC_HUOJIN_TRAINEE_FEMALE)
|
||||
return false;
|
||||
if (target == _partner)
|
||||
return false;
|
||||
if (target->IsInCombat())
|
||||
return false;
|
||||
if (target->IsInEvadeMode())
|
||||
return false;
|
||||
if (target->isDead())
|
||||
return false;
|
||||
|
||||
float dist = target->GetDistance(_partner);
|
||||
if (dist >= _minDist)
|
||||
return false;
|
||||
|
||||
_minDist = dist;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Unit* _partner;
|
||||
float _minDist;
|
||||
};
|
||||
|
||||
// 54586 - Huojin Trainee
|
||||
// 65470 - Huojin Trainee
|
||||
struct npc_huojin_trainee : public npc_tushui_huojin_trainee
|
||||
{
|
||||
npc_huojin_trainee(Creature* creature) : npc_tushui_huojin_trainee(creature) { }
|
||||
|
||||
void JustEngagedWith(Unit* attacker) override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
npc_tushui_huojin_trainee::JustEngagedWith(attacker);
|
||||
|
||||
Creature* partner = ObjectAccessor::GetCreature(*me, _partnerGuid);
|
||||
if (!partner)
|
||||
return;
|
||||
|
||||
if (partner->AI())
|
||||
partner->AI()->DoAction(ACTION_PARTNER_ENTERED_COMBAT);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_PARTNER_ENTERED_COMBAT)
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
_scheduler.Schedule(Seconds(1), [this](TaskContext /*task*/ )
|
||||
{
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void BeginSparring(ObjectGuid guid)
|
||||
{
|
||||
_partnerGuid = guid;
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
|
||||
|
||||
_scheduler.Schedule(Seconds(1), [this](TaskContext /*task*/)
|
||||
{
|
||||
me->SetEmoteState(EMOTE_STATE_MONKOFFENSE_READYUNARMED);
|
||||
});
|
||||
|
||||
_scheduler.Schedule(Seconds(4), [this](TaskContext task)
|
||||
{
|
||||
PlayRandomEmote();
|
||||
task.Repeat(Seconds(4));
|
||||
});
|
||||
}
|
||||
|
||||
Creature* GetNewPartner() const
|
||||
{
|
||||
Creature* partner = nullptr;
|
||||
HuojinTraineePartnerSearch check(me);
|
||||
Trinity::CreatureLastSearcher<HuojinTraineePartnerSearch> searcher(me, partner, check);
|
||||
Cell::VisitGridObjects(me, searcher, 10.0f);
|
||||
return partner;
|
||||
}
|
||||
|
||||
void BeginSparringDelayed(ObjectGuid partnerGuid)
|
||||
{
|
||||
_partnerGuid = partnerGuid;
|
||||
_scheduler.Schedule(Seconds(1), [this, partnerGuid](TaskContext /*task*/)
|
||||
{
|
||||
BeginSparring(partnerGuid);
|
||||
});
|
||||
}
|
||||
|
||||
void InitiateSparring()
|
||||
{
|
||||
Creature* partner = GetNewPartner();
|
||||
|
||||
if (!partner)
|
||||
return;
|
||||
|
||||
BeginSparring(partner->GetGUID());
|
||||
if (Creature* partner = ObjectAccessor::GetCreature(*me, _partnerGuid))
|
||||
{
|
||||
if (npc_huojin_trainee* ai = CAST_AI(npc_huojin_trainee, partner->GetAI()))
|
||||
ai->BeginSparringDelayed(me->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
InitiateSparring();
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
// partner is already assigned, sparring start is delayed
|
||||
if (!ObjectAccessor::GetCreature(*me, _partnerGuid))
|
||||
InitiateSparring();
|
||||
}
|
||||
private:
|
||||
ObjectGuid _partnerGuid;
|
||||
};
|
||||
|
||||
class TushuiTraineeSearch
|
||||
{
|
||||
public:
|
||||
TushuiTraineeSearch(Creature* leader, float maxDist) : _leader(leader), _maxDist(maxDist) { }
|
||||
|
||||
bool operator()(Creature const* target) const
|
||||
{
|
||||
if (target->GetEntry() != NPC_TUSHUI_TRAINEE_MALE && target->GetEntry() != NPC_TUSHUI_TRAINEE_FEMALE)
|
||||
return false;
|
||||
if (target->IsInCombat())
|
||||
return false;
|
||||
if (target->IsInEvadeMode())
|
||||
return false;
|
||||
if (target->GetDistance(_leader) >= _maxDist)
|
||||
return false;
|
||||
if (target->isDead())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Creature* _leader;
|
||||
float _maxDist;
|
||||
};
|
||||
|
||||
void HandleEmoteNearbyTushuiTrainees(Creature* leader, Emote emote)
|
||||
{
|
||||
std::list<Creature*> traineeList;
|
||||
TushuiTraineeSearch check(leader, 10.0f);
|
||||
Trinity::CreatureListSearcher<TushuiTraineeSearch> searcher(leader, traineeList, check);
|
||||
Cell::VisitGridObjects(leader, searcher, 10.0f);
|
||||
|
||||
for (Creature* trainee : traineeList)
|
||||
trainee->HandleEmoteCommand(emote);
|
||||
}
|
||||
|
||||
// 54587 - Tushui Trainee
|
||||
// 65471 - Tushui Trainee
|
||||
struct npc_tushui_leading_trainee : public npc_tushui_huojin_trainee
|
||||
{
|
||||
npc_tushui_leading_trainee(Creature* creature) : npc_tushui_huojin_trainee(creature) { }
|
||||
|
||||
void ScheduleEmoteExecution()
|
||||
{
|
||||
_scheduler.Schedule(Seconds(1), [this](TaskContext task)
|
||||
{
|
||||
Emote emote = PlayRandomEmote();
|
||||
HandleEmoteNearbyTushuiTrainees(me, emote);
|
||||
task.Repeat(Seconds(6));
|
||||
});
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
ScheduleEmoteExecution();
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
ScheduleEmoteExecution();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* attacker) override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
npc_tushui_huojin_trainee::JustEngagedWith(attacker);
|
||||
}
|
||||
};
|
||||
|
||||
// 61411 - Instructor Zhi
|
||||
struct npc_instructor_zhi : public ScriptedAI
|
||||
{
|
||||
npc_instructor_zhi(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
_scheduler.Schedule(Seconds(6), [this](TaskContext task)
|
||||
{
|
||||
Emote emote = Trinity::Containers::SelectRandomContainerElement(TraineeEmotes);
|
||||
me->HandleEmoteCommand(emote);
|
||||
|
||||
task.Schedule(Seconds(1), [this, emote](TaskContext /*task*/)
|
||||
{
|
||||
HandleEmoteNearbyTushuiTrainees(me, emote);
|
||||
});
|
||||
task.Repeat(Seconds(6));
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
void AddSC_zone_the_wandering_isle()
|
||||
{
|
||||
RegisterCreatureAI(npc_tushui_huojin_trainee);
|
||||
RegisterCreatureAI(npc_huojin_trainee);
|
||||
RegisterCreatureAI(npc_tushui_leading_trainee);
|
||||
RegisterCreatureAI(npc_instructor_zhi);
|
||||
}
|
||||
@@ -1,489 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "Conversation.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "sanctum_of_domination.h"
|
||||
|
||||
Position const SylvanasIntroPos[4] =
|
||||
{
|
||||
{ 231.15799f, -832.816f, 4105.0386f },
|
||||
{ 242.00348f, -840.51215f, 4105.0386f },
|
||||
{ 241.23091f, -830.0955f, 4105.0386f },
|
||||
{ 225.73611f, -844.0746f, 4104.9882f, 1.3613f }
|
||||
};
|
||||
|
||||
enum SylvanasSpells
|
||||
{
|
||||
// Stances
|
||||
SPELL_RANGER_BOW_STANCE = 347560,
|
||||
SPELL_RANGER_DAGGERS_STANCE = 348010,
|
||||
|
||||
// Miscellanea
|
||||
SPELL_GENERIC_ANCHOR_HERE = 45313,
|
||||
SPELL_GENERIC_DUAL_WIELD = 42459,
|
||||
SPELL_SYLVANAS_DISPLAY_POWER_SUFFERING = 352311,
|
||||
SPELL_SYLVANAS_ROOT = 347608
|
||||
};
|
||||
|
||||
enum SylvanasPhases
|
||||
{
|
||||
PHASE_ONE = 1,
|
||||
PHASE_INTERMISSION = 4,
|
||||
PHASE_TWO = 2,
|
||||
PHASE_THREE = 3,
|
||||
PHASE_INTERMISSION_WORLD_STATE = 11
|
||||
};
|
||||
|
||||
enum SylvanasEventGroups
|
||||
{
|
||||
EVENT_GROUP_NORMAL_EVENTS = 1,
|
||||
EVENT_GROUP_WINDRUNNER_EVENTS = 2
|
||||
};
|
||||
|
||||
enum SylvanasEvents
|
||||
{
|
||||
EVENT_INTRODUCTION = 1,
|
||||
EVENT_SIZE_MAX = 200
|
||||
};
|
||||
|
||||
enum SylvanasTexts
|
||||
{
|
||||
SAY_ENGAGE = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_DISENGAGE = 2
|
||||
};
|
||||
|
||||
enum SylvanasConversations
|
||||
{
|
||||
CONVERSATION_SYLVANAS_INTRODUCTION = 17368,
|
||||
CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_SYLVANAS_ID = 0,
|
||||
CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_BOLVAR_ID = 1
|
||||
};
|
||||
|
||||
enum SylvanasSpawnGroups
|
||||
{
|
||||
SPAWN_GROUP_CHAMPIONS_FIRST_PHASE = 0,
|
||||
SPAWN_GROUP_CHAMPIONS_THIRD_PHASE,
|
||||
SPAWN_GROUP_CHAMPIONS_OUTRODUCTION
|
||||
};
|
||||
|
||||
enum SylvanasPoints
|
||||
{
|
||||
POINT_INTRODUCTION = 1
|
||||
};
|
||||
|
||||
enum SylvanasSpellVisualKits
|
||||
{
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_01 = 150067,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_02 = 150068,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_03 = 150069,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_04 = 150071,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_05 = 150072,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_06 = 150070,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_07 = 150074,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_08 = 150077,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_09 = 150076,
|
||||
SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_10 = 150075,
|
||||
SPELL_VISUAL_KIT_BOLVAR_INTRODUCTION_TALK_01 = 150073,
|
||||
|
||||
SPELL_VISUAL_KIT_SYLVANAS_TELEPORT = 150078
|
||||
};
|
||||
|
||||
// 178355 - Sylvanas Shadowcopy (Riding)
|
||||
struct npc_sylvanas_windrunner_shadowcopy_riding : public ScriptedAI
|
||||
{
|
||||
npc_sylvanas_windrunner_shadowcopy_riding(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
me->SetImmuneToAll(true, true);
|
||||
me->SetUninteractible(true);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
};
|
||||
|
||||
// 175732 - Sylvanas Windrunner
|
||||
struct boss_sylvanas_windrunner : public BossAI
|
||||
{
|
||||
boss_sylvanas_windrunner(Creature* creature) : BossAI(creature, DATA_SYLVANAS_WINDRUNNER) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCastSelf(SPELL_GENERIC_DUAL_WIELD, true);
|
||||
DoCastSelf(SPELL_SYLVANAS_DISPLAY_POWER_SUFFERING, true);
|
||||
|
||||
me->SetPower(me->GetPowerType(), 0);
|
||||
|
||||
if (instance->GetData(DATA_SYLVANAS_INTRODUCTION) == DONE)
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetSpeed(MOVE_RUN, 14.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetSpeed(MOVE_RUN, 4.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
Talk(SAY_DISENGAGE);
|
||||
|
||||
_EnterEvadeMode();
|
||||
|
||||
summons.DespawnAll();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
// Note: every creature involved in the fight adds UNIT_FLAG_PET_IN_COMBAT or UNIT_FLAG_RENAME when engaging, meaning they're most likely summoned by Sylvanas.
|
||||
me->SummonCreatureGroup(SPAWN_GROUP_CHAMPIONS_FIRST_PHASE);
|
||||
|
||||
instance->DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_PHASE, PHASE_ONE);
|
||||
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (id == POINT_INTRODUCTION)
|
||||
DoCastSelf(SPELL_GENERIC_ANCHOR_HERE, true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (!victim->IsPlayer())
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
|
||||
|
||||
Talk(SAY_ENGAGE);
|
||||
|
||||
instance->DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_PHASE, PHASE_ONE);
|
||||
|
||||
events.SetPhase(PHASE_ONE);
|
||||
|
||||
// Note: Sylvanas uses her root with 2s at the beginning of the encounter, most likely to avoid moving when engaging at stance switch.
|
||||
DoCastSelf(SPELL_SYLVANAS_ROOT, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_DURATION, 2000));
|
||||
|
||||
// Note: we won't allow engaging until Phase 1 PR is merged.
|
||||
me->Say("Only introduction is implemented so far, evading.", LANG_UNIVERSAL);
|
||||
EnterEvadeMode(EvadeReason::Other);
|
||||
}
|
||||
};
|
||||
|
||||
// 45 - Sylvanas Windrunner's Position Z Check (Serverside)
|
||||
struct at_sylvanas_windrunner_z_check : AreaTriggerAI
|
||||
{
|
||||
at_sylvanas_windrunner_z_check(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsAlive())
|
||||
return;
|
||||
|
||||
if (Player* player = unit->ToPlayer())
|
||||
{
|
||||
if (player->IsGameMaster())
|
||||
return;
|
||||
|
||||
if (player->IsAlive())
|
||||
player->KillSelf(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 46 - Sylvanas Windrunner's Conversation Introduction (Serverside)
|
||||
struct at_sylvanas_windrunner_introduction : AreaTriggerAI
|
||||
{
|
||||
at_sylvanas_windrunner_introduction(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
InstanceScript* instance = at->GetInstanceScript();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
Player* player = unit->ToPlayer();
|
||||
if (!player || player->IsGameMaster())
|
||||
return;
|
||||
|
||||
if (Creature* sylvanas = instance->GetCreature(DATA_SYLVANAS_WINDRUNNER))
|
||||
Conversation::CreateConversation(CONVERSATION_SYLVANAS_INTRODUCTION, sylvanas, sylvanas->GetPosition(), ObjectGuid::Empty);
|
||||
|
||||
at->Remove();
|
||||
}
|
||||
};
|
||||
|
||||
// 17368 - Sylvanas Windrunner's Introduction (Conversation)
|
||||
class conversation_sylvanas_windrunner_introduction : public ConversationScript
|
||||
{
|
||||
public:
|
||||
conversation_sylvanas_windrunner_introduction() : ConversationScript("conversation_sylvanas_windrunner_introduction") { }
|
||||
|
||||
void OnConversationCreate(Conversation* conversation, Unit* creator) override
|
||||
{
|
||||
InstanceScript* instance = creator->GetInstanceScript();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
Creature* bolvar = instance->GetCreature(DATA_BOLVAR_FORDRAGON_PINNACLE);
|
||||
if (!bolvar)
|
||||
return;
|
||||
|
||||
instance->SetData(DATA_SYLVANAS_INTRODUCTION, IN_PROGRESS);
|
||||
conversation->AddActor(NPC_BOLVAR_FORDRAGON_PINNACLE, CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_BOLVAR_ID, bolvar->GetGUID());
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION, 5s + 500ms);
|
||||
}
|
||||
|
||||
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
uint32 eventId = _events.ExecuteEvent();
|
||||
Creature* sylvanas = nullptr;
|
||||
Creature* bolvar = nullptr;
|
||||
|
||||
if (eventId)
|
||||
{
|
||||
sylvanas = conversation->GetActorCreature(CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_SYLVANAS_ID);
|
||||
if (!sylvanas)
|
||||
return;
|
||||
|
||||
bolvar = conversation->GetActorCreature(CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_BOLVAR_ID);
|
||||
if (!bolvar)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_INTRODUCTION:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_01, 0, 0);
|
||||
sylvanas->SetFacingToObject(bolvar);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 1, 1s + 140ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 1:
|
||||
{
|
||||
sylvanas->GetMotionMaster()->MovePoint(POINT_INTRODUCTION, SylvanasIntroPos[0], false);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 2, 1s + 500ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 2:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_02, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 3, 3s + 360ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 3:
|
||||
{
|
||||
sylvanas->GetMotionMaster()->MovePoint(POINT_INTRODUCTION, SylvanasIntroPos[1], false);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 4, 469ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 4:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_03, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 5, 3s + 500ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 5:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_04, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 6, 2s);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 6:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_05, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 7, 5s);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 7:
|
||||
{
|
||||
sylvanas->SetFacingToObject(bolvar);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 8, 750ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 8:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_06, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 9, 457ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 9:
|
||||
{
|
||||
sylvanas->GetMotionMaster()->MovePoint(POINT_INTRODUCTION, SylvanasIntroPos[2], false);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 10, 5s + 89ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 10:
|
||||
{
|
||||
bolvar->SetFacingToObject(sylvanas);
|
||||
bolvar->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_BOLVAR_INTRODUCTION_TALK_01, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 11, 13s + 567ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 11:
|
||||
{
|
||||
sylvanas->SetFacingToObject(bolvar);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 12, 484ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 12:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_07, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 13, 5s + 516ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 13:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_08, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 14, 1s + 516ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 14:
|
||||
{
|
||||
sylvanas->NearTeleportTo(SylvanasIntroPos[3], false);
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_TELEPORT, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 15, 1s + 265ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 15:
|
||||
{
|
||||
sylvanas->SetFacingToObject(bolvar);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 16, 969ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 16:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_09, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 17, 4s + 766ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 17:
|
||||
{
|
||||
sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_10, 0, 0);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 18, 3s + 250ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 18:
|
||||
{
|
||||
sylvanas->CastSpell(sylvanas, SPELL_RANGER_BOW_STANCE);
|
||||
|
||||
_events.ScheduleEvent(EVENT_INTRODUCTION + 19, 16ms);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_INTRODUCTION + 19:
|
||||
{
|
||||
sylvanas->CastSpell(sylvanas, SPELL_GENERIC_ANCHOR_HERE);
|
||||
|
||||
if (InstanceScript* instance = sylvanas->GetInstanceScript())
|
||||
instance->SetData(DATA_SYLVANAS_INTRODUCTION, DONE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
void AddSC_boss_sylvanas_windrunner()
|
||||
{
|
||||
RegisterSanctumOfDominationCreatureAI(boss_sylvanas_windrunner);
|
||||
RegisterSanctumOfDominationCreatureAI(npc_sylvanas_windrunner_shadowcopy_riding);
|
||||
|
||||
RegisterAreaTriggerAI(at_sylvanas_windrunner_z_check);
|
||||
RegisterAreaTriggerAI(at_sylvanas_windrunner_introduction);
|
||||
|
||||
new conversation_sylvanas_windrunner_introduction();
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "GameObject.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "sanctum_of_domination.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_SYLVANAS_WINDRUNNER, DATA_SYLVANAS_WINDRUNNER },
|
||||
{ NPC_SYLVANAS_SHADOWCOPY_RIDING, DATA_SYLVANAS_SHADOWCOPY_RIDING },
|
||||
{ NPC_BOLVAR_FORDRAGON_PINNACLE, DATA_BOLVAR_FORDRAGON_PINNACLE },
|
||||
{ NPC_JAINA_PROUDMOORE_PINNACLE, DATA_JAINA_PROUDMOORE_PINNACLE },
|
||||
{ NPC_THRALL_PINNACLE, DATA_THRALL_PINNACLE },
|
||||
{ NPC_THRONE_OF_THE_DAMNED, DATA_THRONE_OF_THE_DAMNED },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_THE_TARRAGRUE, {{ 2423 }} },
|
||||
{ DATA_THE_EYE_OF_THE_JAILER, {{ 2433 }} },
|
||||
{ DATA_THE_NINE, {{ 2429 }} },
|
||||
{ DATA_REMNANT_OF_NERZHUL, {{ 2432 }} },
|
||||
{ DATA_SOULRENDER_DORMAZAIN, {{ 2434 }} },
|
||||
{ DATA_PAINSMITH_RAZNAL, {{ 2430 }} },
|
||||
{ DATA_GUARDIAN_OF_THE_FIRST_ONES, {{ 2436 }} },
|
||||
{ DATA_FATESCRIBE_ROHKALO, {{ 2431 }} },
|
||||
{ DATA_KELTHUZAD, {{ 2422 }} },
|
||||
{ DATA_SYLVANAS_WINDRUNNER, {{ 2435 }} }
|
||||
};
|
||||
|
||||
class instance_sanctum_of_domination : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_sanctum_of_domination() : InstanceMapScript(SODScriptName, 2450) { }
|
||||
|
||||
struct instance_sanctum_of_domination_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_sanctum_of_domination_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
|
||||
SylvanasIntroductionState = NOT_STARTED;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case BOSS_SYLVANAS_WINDRUNNER:
|
||||
SylvanasGUID = creature->GetGUID();
|
||||
break;
|
||||
|
||||
case NPC_SYLVANAS_SHADOWCOPY_RIDING:
|
||||
SylvanasShadowcopyRidingGUID = creature->GetGUID();
|
||||
break;
|
||||
|
||||
case NPC_BOLVAR_FORDRAGON_PINNACLE:
|
||||
BolvarPinnacleGUID = creature->GetGUID();
|
||||
break;
|
||||
|
||||
case NPC_JAINA_PROUDMOORE_PINNACLE:
|
||||
JainaPinnacleGUID = creature->GetGUID();
|
||||
break;
|
||||
|
||||
case NPC_THRALL_PINNACLE:
|
||||
ThrallPinnacleGUID = creature->GetGUID();
|
||||
break;
|
||||
|
||||
case NPC_THRONE_OF_THE_DAMNED:
|
||||
ThroneOfTheDamnedGUID = creature->GetGUID();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_01:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_02:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_03:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_04:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_05:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_06:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_07:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_08:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_09:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_10:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_11:
|
||||
case GAMEOBJECT_TORGHAST_SPIKE_12:
|
||||
TorghastSpikeGUIDs.push_back(go->GetGUID());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_SYLVANAS_WINDRUNNER:
|
||||
return SylvanasGUID;
|
||||
case DATA_BOLVAR_FORDRAGON_PINNACLE:
|
||||
return BolvarPinnacleGUID;
|
||||
case DATA_JAINA_PROUDMOORE_PINNACLE:
|
||||
return JainaPinnacleGUID;
|
||||
case DATA_THRALL_PINNACLE:
|
||||
return ThrallPinnacleGUID;
|
||||
case DATA_THRONE_OF_THE_DAMNED:
|
||||
return ThroneOfTheDamnedGUID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 id, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(id, state))
|
||||
return false;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case DATA_SYLVANAS_WINDRUNNER:
|
||||
{
|
||||
if (state == NOT_STARTED)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_STARTED, 0);
|
||||
|
||||
if (Creature* throneTeleporter = GetCreature(DATA_THRONE_OF_THE_DAMNED))
|
||||
throneTeleporter->SetVisible(true);
|
||||
|
||||
for (ObjectGuid const& spikeGUID : TorghastSpikeGUIDs)
|
||||
if (GameObject* torghastSpike = instance->GetGameObject(spikeGUID))
|
||||
torghastSpike->SetSpellVisualId(0);
|
||||
}
|
||||
else if (state == IN_PROGRESS)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_STARTED, 1);
|
||||
|
||||
if (Creature* throneTeleporter = GetCreature(DATA_THRONE_OF_THE_DAMNED))
|
||||
throneTeleporter->SetVisible(false);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_SYLVANAS_INTRODUCTION:
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case IN_PROGRESS:
|
||||
SylvanasIntroductionState = IN_PROGRESS;
|
||||
if (Creature* sylvanas = GetCreature(DATA_SYLVANAS_WINDRUNNER))
|
||||
sylvanas->SetHomePosition(SylvanasRespawnPos);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
SylvanasIntroductionState = DONE;
|
||||
if (Creature* sylvanas = GetCreature(DATA_SYLVANAS_WINDRUNNER))
|
||||
{
|
||||
sylvanas->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
sylvanas->SetImmuneToAll(false);
|
||||
sylvanas->SetSpeed(MOVE_RUN, 14.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_SYLVANAS_INTRODUCTION:
|
||||
return SylvanasIntroductionState;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
ObjectGuid SylvanasGUID;
|
||||
ObjectGuid SylvanasShadowcopyRidingGUID;
|
||||
ObjectGuid BolvarPinnacleGUID;
|
||||
ObjectGuid JainaPinnacleGUID;
|
||||
ObjectGuid ThrallPinnacleGUID;
|
||||
ObjectGuid ThroneOfTheDamnedGUID;
|
||||
std::vector<ObjectGuid> TorghastSpikeGUIDs;
|
||||
uint8 SylvanasIntroductionState;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_sanctum_of_domination_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_sanctum_of_domination()
|
||||
{
|
||||
new instance_sanctum_of_domination();
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_SANCTUM_OF_DOMINATION_H_
|
||||
#define DEF_SANCTUM_OF_DOMINATION_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "SanctumOfDomination"
|
||||
#define SODScriptName "instance_sanctum_of_domination"
|
||||
|
||||
uint32 const EncounterCount = 10;
|
||||
|
||||
Position const SylvanasRespawnPos = { 225.73611f, -844.0746f, 4104.9882f, 1.3613f };
|
||||
|
||||
enum SanctumOfDominationDataTypes
|
||||
{
|
||||
DATA_THE_TARRAGRUE = 0,
|
||||
DATA_THE_EYE_OF_THE_JAILER = 1,
|
||||
DATA_THE_NINE = 2,
|
||||
DATA_REMNANT_OF_NERZHUL = 3,
|
||||
DATA_SOULRENDER_DORMAZAIN = 4,
|
||||
DATA_PAINSMITH_RAZNAL = 5,
|
||||
DATA_GUARDIAN_OF_THE_FIRST_ONES = 6,
|
||||
DATA_FATESCRIBE_ROHKALO = 7,
|
||||
DATA_KELTHUZAD = 8,
|
||||
DATA_SYLVANAS_WINDRUNNER = 9,
|
||||
|
||||
/* Encounter-related data */
|
||||
|
||||
/* Sylvanas Windrunner */
|
||||
DATA_SYLVANAS_INTRODUCTION,
|
||||
DATA_SYLVANAS_SHADOWCOPY_RIDING,
|
||||
DATA_BOLVAR_FORDRAGON_PINNACLE,
|
||||
DATA_JAINA_PROUDMOORE_PINNACLE,
|
||||
DATA_THRALL_PINNACLE,
|
||||
DATA_THRONE_OF_THE_DAMNED
|
||||
};
|
||||
|
||||
enum SanctumOfDominationCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_SYLVANAS_WINDRUNNER = 175732,
|
||||
|
||||
/* Encounter-related creatures */
|
||||
|
||||
/* Sylvanas Windrunner Encounter */
|
||||
NPC_SYLVANAS_SHADOWCOPY_RIDING = 178355,
|
||||
NPC_BOLVAR_FORDRAGON_PINNACLE = 178081,
|
||||
NPC_JAINA_PROUDMOORE_PINNACLE = 176533,
|
||||
NPC_THRALL_PINNACLE = 176532,
|
||||
|
||||
NPC_THRONE_OF_THE_DAMNED = 180803
|
||||
};
|
||||
|
||||
enum SanctumOfDominationGameObjectIds
|
||||
{
|
||||
GAMEOBJECT_TORGHAST_SPIKE_01 = 368743,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_02 = 368744,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_03 = 368745,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_04 = 368746,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_05 = 368747,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_06 = 368748,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_07 = 368749,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_08 = 368750,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_09 = 368751,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_10 = 368752,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_11 = 368753,
|
||||
GAMEOBJECT_TORGHAST_SPIKE_12 = 368754
|
||||
};
|
||||
|
||||
enum SanctumOfDominationAreas
|
||||
{
|
||||
AREA_PINNACLE_OF_DOMINANCE = 13653,
|
||||
AREA_EDGE_OF_THE_ABYSS = 13654,
|
||||
AREA_THE_CRUCIBLE = 13655
|
||||
};
|
||||
|
||||
enum SanctumofDominationWorldStates
|
||||
{
|
||||
WORLD_STATE_SYLVANAS_ENCOUNTER_STARTED = 20346,
|
||||
WORLD_STATE_SYLVANAS_ENCOUNTER_COMPLETED = 20347,
|
||||
WORLD_STATE_SYLVANAS_ENCOUNTER_PHASE = 20348,
|
||||
WORLD_STATE_SYLVANAS_UNK_01 = 21210, // Info: sets to 0 several times on phase 3.
|
||||
WORLD_STATE_SYLVANAS_UNK_02 = 21166, // Info: sets to 1 when SPELL_FINAL_SCENE is cast on players.
|
||||
WORLD_STATE_SYLVANAS_UNK_03 = 21120, // Info: sets to 1 when 353687 spell is cast by NPC 179262.
|
||||
WORLD_STATE_SYLVANAS_ACHIEVEMENT_COMPLETED = 21134,
|
||||
WORLD_STATE_SYLVANAS_UNK_04 = 20439, // Info: this is always 1 on INIT and the following are 0.
|
||||
WORLD_STATE_SYLVANAS_UNK_05 = 20440,
|
||||
WORLD_STATE_SYLVANAS_UNK_06 = 20441,
|
||||
WORLD_STATE_SYLVANAS_UNK_07 = 20442,
|
||||
WORLD_STATE_SYLVANAS_UNK_08 = 20443
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetSanctumOfDominationAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, SODScriptName);
|
||||
}
|
||||
|
||||
#define RegisterSanctumOfDominationCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetSanctumOfDominationAI)
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaBoundary.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "sepulcher_of_the_first_ones.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
// Anduin Wrynn
|
||||
{ BOSS_ANDUIN_WRYNN, DATA_ANDUIN_WRYNN },
|
||||
{ BOSS_REMNANT_OF_A_FALLEN_KING, DATA_REMNANT_OF_A_FALLEN_KING },
|
||||
{ NPC_UTHER_THE_LIGHTBRINGER_ANDUIN, DATA_UTHER_THE_LIGHTBRINGER_ANDUIN },
|
||||
{ NPC_LADY_JAINA_PROUDMOORE_ANDUIN, DATA_JAINA_PROUDMOORE_ANDUIN },
|
||||
{ NPC_SYLVANAS_WINDRUNNER_ANDUIN, DATA_SYLVANAS_WINDRUNNER_ANDUIN },
|
||||
{ NPC_THRALL_ANDUIN, DATA_THRALL_ANDUIN },
|
||||
{ NPC_FIRIM_ANDUIN, DATA_FIRIM_ANDUIN },
|
||||
{ NPC_ANDUIN_SOUL, DATA_ANDUIN_SOUL },
|
||||
{ NPC_BEACON_OF_HOPE, DATA_BEACON_OF_HOPE },
|
||||
{ NPC_QUARTERMASTER_RAHM_ANDUIN, DATA_QUARTERMASTER_RAHM_ANDUIN },
|
||||
{ NPC_BOLVAR_FORDRAGON_ANDUIN, DATA_BOLVAR_FORDRAGON_ANDUIN },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ DATA_ANDUIN_WRYNN, new CircleBoundary({ -3825.0601f, -2715.4600f }, 45.0)},
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GAMEOBJECT_BRIDGE_TO_ANDUIN, DATA_ANDUIN_WRYNN, EncounterDoorBehavior::OpenWhenInProgress },
|
||||
{ GAMEOBJECT_BRIDGE_AFTER_ANDUIN, DATA_ANDUIN_WRYNN, EncounterDoorBehavior::OpenWhenNotDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenInProgress }
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_ANDUIN_WRYNN, {{ 2546 }} },
|
||||
};
|
||||
|
||||
class instance_sepulcher_of_the_first_ones : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_sepulcher_of_the_first_ones() : InstanceMapScript(SFOScriptName, 2481) { }
|
||||
|
||||
struct instance_sepulcher_of_the_first_ones_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_sepulcher_of_the_first_ones_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
LoadBossBoundaries(boundaries);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
|
||||
AnduinIntroductionState = NOT_STARTED;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 id, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(id, state))
|
||||
return false;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case DATA_ANDUIN_WRYNN:
|
||||
{
|
||||
if (state == NOT_STARTED)
|
||||
DoUpdateWorldState(WORLD_STATE_ANDUIN_ENCOUNTER_STARTED, 0);
|
||||
else if (state == IN_PROGRESS)
|
||||
{
|
||||
Creature* anduin = GetCreature(DATA_ANDUIN_WRYNN);
|
||||
if (!anduin)
|
||||
return false;
|
||||
|
||||
DoUpdateWorldState(WORLD_STATE_ANDUIN_ENCOUNTER_STARTED, 1);
|
||||
|
||||
// @TODO: uther, sylvanas and jaina should attack anduin but keep faction 35; we lack core support
|
||||
if (Creature* uther = GetCreature(DATA_UTHER_THE_LIGHTBRINGER_ANDUIN))
|
||||
uther->AI()->AttackStart(anduin);
|
||||
|
||||
for (uint32 data : { DATA_SYLVANAS_WINDRUNNER_ANDUIN, DATA_JAINA_PROUDMOORE_ANDUIN })
|
||||
{
|
||||
if (Creature* creature = GetCreature(data))
|
||||
creature->AI()->AttackStartCaster(anduin, 25.0f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_ANDUIN_WRYNN_INTRODUCTION:
|
||||
{
|
||||
AnduinIntroductionState = data;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_ANDUIN_WRYNN_INTRODUCTION:
|
||||
return AnduinIntroductionState;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8 AnduinIntroductionState;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_sepulcher_of_the_first_ones_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_sepulcher_of_the_first_ones()
|
||||
{
|
||||
new instance_sepulcher_of_the_first_ones();
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_SEPULCHER_OF_THE_FIRST_ONES_H_
|
||||
#define DEF_SEPULCHER_OF_THE_FIRST_ONES_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "SepulcherOfTheFirstOnes"
|
||||
#define SFOScriptName "instance_sepulcher_of_the_first_ones"
|
||||
|
||||
uint32 const EncounterCount = 11;
|
||||
|
||||
enum SepulcherOfTheFirstOnesDataTypes
|
||||
{
|
||||
// Bosses
|
||||
DATA_VIGILANT_CUSTODIAN = 0,
|
||||
DATA_SKOLEX = 1,
|
||||
DATA_ARTIFICER_XYMOX = 2,
|
||||
DATA_HALONDRUS = 3,
|
||||
DATA_DAUSEGNE = 4,
|
||||
DATA_PROTOTYPE_PANTHEON = 5,
|
||||
DATA_LIHUVIM = 6,
|
||||
DATA_ANDUIN_WRYNN = 7,
|
||||
DATA_LORDS_OF_DREAD = 8,
|
||||
DATA_RYGELON = 10,
|
||||
DATA_JAILER = 11,
|
||||
|
||||
// Anduin Wrynn Encounter
|
||||
DATA_ANDUIN_WRYNN_INTRODUCTION,
|
||||
DATA_REMNANT_OF_A_FALLEN_KING,
|
||||
DATA_SYLVANAS_WINDRUNNER_ANDUIN,
|
||||
DATA_ANDUIN_SOUL,
|
||||
DATA_BEACON_OF_HOPE,
|
||||
DATA_JAINA_PROUDMOORE_ANDUIN,
|
||||
DATA_UTHER_THE_LIGHTBRINGER_ANDUIN,
|
||||
DATA_FIRIM_ANDUIN,
|
||||
DATA_ANDUIN_TREASURE,
|
||||
DATA_BOLVAR_FORDRAGON_ANDUIN,
|
||||
DATA_THRALL_ANDUIN,
|
||||
DATA_QUARTERMASTER_RAHM_ANDUIN,
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_VIGILANT_CUSTODIAN = 184522,
|
||||
BOSS_VIGILANT_GUARDIAN = 180773,
|
||||
BOSS_ANDUIN_WRYNN = 181954,
|
||||
BOSS_REMNANT_OF_A_FALLEN_KING = 183463,
|
||||
|
||||
// Anduin Wrynn Encounter
|
||||
NPC_LADY_JAINA_PROUDMOORE_ANDUIN = 183664,
|
||||
NPC_UTHER_THE_LIGHTBRINGER_ANDUIN = 183665,
|
||||
NPC_SYLVANAS_WINDRUNNER_ANDUIN = 183666,
|
||||
NPC_FIRIM_ANDUIN = 184589,
|
||||
NPC_BEFOULED_BARRIER = 184585,
|
||||
NPC_ANDUIN_SOUL = 184519,
|
||||
NPC_ANDUIN_DESPAIR = 184520,
|
||||
NPC_ANDUIN_HOPE = 184493,
|
||||
NPC_ANDUIN_DOUBT = 184494,
|
||||
NPC_EMPTY_VESSEL = 183452,
|
||||
NPC_LOST_SOUL = 185607,
|
||||
NPC_MONSTROUS_SOUL = 183671,
|
||||
NPC_FIENDISH_SOUL = 183669,
|
||||
NPC_MARCH_OF_THE_DAMNED = 183793,
|
||||
NPC_GRIM_REFLECTION = 183033,
|
||||
NPC_BEACON_OF_HOPE = 184830,
|
||||
NPC_BOLVAR_FORDRAGON_ANDUIN = 184601,
|
||||
NPC_QUARTERMASTER_RAHM_ANDUIN = 186785,
|
||||
NPC_THRALL_ANDUIN = 184599,
|
||||
NPC_KNIGHT_OF_EBON_BLADE_ANDUIN = 184613,
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesTranslocatorIds
|
||||
{
|
||||
NPC_ANCIENT_TRANSLOCATOR = 182431,
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesGameObjectIds
|
||||
{
|
||||
GAMEOBJECT_BRIDGE_TO_ANDUIN = 375110,
|
||||
GAMEOBJECT_BRIDGE_AFTER_ANDUIN = 375035,
|
||||
GAMEOBJECT_ANDUIN_CHEST_LOOT = 375901,
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesEvents
|
||||
{
|
||||
EVENT_RESET_PLAYERS_ON_TRANSLOCATOR = 1
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesActions
|
||||
{
|
||||
ACTION_START_ANDUIN_OUTRODUCTION = 1,
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesAreas
|
||||
{
|
||||
AREA_DOMINATION_GRASP = 13965,
|
||||
AREA_SEPULCHER_OF_THE_FIRST_ONES = 13742,
|
||||
};
|
||||
|
||||
enum SepulcherOfTheFirstOnesWorldStates
|
||||
{
|
||||
WORLD_STATE_ANDUIN_ENCOUNTER_STARTED = 21243,
|
||||
WORLD_STATE_ANDUIN_INTERMISSION = 21433,
|
||||
WORLD_STATE_ANDUIN_ENCOUNTER_COMPLETED = 21242,
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetSepulcherOfTheFirstOnesAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, SFOScriptName);
|
||||
}
|
||||
|
||||
#define RegisterSepulcherOfTheFirstOnesCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetSepulcherOfTheFirstOnesAI)
|
||||
|
||||
#endif
|
||||
@@ -1,360 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellHistory.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "Unit.h"
|
||||
|
||||
// 297721 - Subjugator's Manacles
|
||||
class spell_torghast_subjugators_manacles : public AuraScript
|
||||
{
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& procInfo)
|
||||
{
|
||||
if (_triggeredTargets.contains(procInfo.GetProcTarget()->GetGUID()))
|
||||
return false;
|
||||
|
||||
_triggeredTargets.insert(procInfo.GetProcTarget()->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResetMarkedTargets(bool isNowInCombat)
|
||||
{
|
||||
if (!isNowInCombat)
|
||||
_triggeredTargets.clear();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_torghast_subjugators_manacles::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
OnEnterLeaveCombat += AuraEnterLeaveCombatFn(spell_torghast_subjugators_manacles::ResetMarkedTargets);
|
||||
}
|
||||
|
||||
std::unordered_set<ObjectGuid> _triggeredTargets;
|
||||
};
|
||||
|
||||
// 300771 - Blade of the Lifetaker
|
||||
class spell_torghast_blade_of_the_lifetaker : public AuraScript
|
||||
{
|
||||
void HandleProc(AuraEffect* aurEff, ProcEventInfo& procInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
procInfo.GetActor()->CastSpell(procInfo.GetProcTarget(), aurEff->GetSpellEffectInfo().TriggerSpell, CastSpellExtraArgs(aurEff)
|
||||
.AddSpellMod(SPELLVALUE_BASE_POINT0, GetTarget()->CountPctFromMaxHealth(aurEff->GetAmount()))
|
||||
.SetTriggeringSpell(procInfo.GetProcSpell()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_torghast_blade_of_the_lifetaker::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 300796 - Touch of the Unseen
|
||||
class spell_torghast_touch_of_the_unseen : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_DOOR_OF_SHADOWS = 300728;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DOOR_OF_SHADOWS });
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->Id == SPELL_DOOR_OF_SHADOWS;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect* aurEff, ProcEventInfo& procInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
procInfo.GetActor()->CastSpell(procInfo.GetProcTarget(), aurEff->GetSpellEffectInfo().TriggerSpell, CastSpellExtraArgs(aurEff)
|
||||
.AddSpellMod(SPELLVALUE_BASE_POINT0, GetTarget()->CountPctFromMaxHealth(aurEff->GetAmount()))
|
||||
.SetTriggeringSpell(procInfo.GetProcSpell()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_torghast_touch_of_the_unseen::CheckProc);
|
||||
OnEffectProc += AuraEffectProcFn(spell_torghast_touch_of_the_unseen::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 305060 - Yel'Shir's Powerglove
|
||||
class spell_torghast_yelshirs_powerglove : public SpellScript
|
||||
{
|
||||
void CalculateDamage(Unit const* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) const
|
||||
{
|
||||
if (SpellInfo const* triggeringSpell = GetTriggeringSpell())
|
||||
if (Aura const* triggerAura = GetCaster()->GetAura(triggeringSpell->Id))
|
||||
pctMod *= triggerAura->GetStackAmount();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
CalcDamage += SpellCalcDamageFn(spell_torghast_yelshirs_powerglove::CalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
// 321706 - Dimensional Blade
|
||||
class spell_torghast_dimensional_blade : public SpellScript
|
||||
{
|
||||
static constexpr uint32 SPELL_MAGE_BLINK = 1953;
|
||||
static constexpr uint32 SPELL_MAGE_SHIMMER = 212653;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MAGE_BLINK, SPELL_MAGE_SHIMMER });
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (!targets.empty())
|
||||
{
|
||||
GetCaster()->GetSpellHistory()->RestoreCharge(sSpellMgr->AssertSpellInfo(SPELL_MAGE_BLINK, DIFFICULTY_NONE)->ChargeCategoryId);
|
||||
GetCaster()->GetSpellHistory()->RestoreCharge(sSpellMgr->AssertSpellInfo(SPELL_MAGE_SHIMMER, DIFFICULTY_NONE)->ChargeCategoryId);
|
||||
}
|
||||
|
||||
// filter targets by entry here and not with conditions table because we need to know if any enemy was hit for charge restoration, not just mawrats
|
||||
targets.remove_if([](WorldObject const* target)
|
||||
{
|
||||
switch (target->GetEntry())
|
||||
{
|
||||
case 151353: // Mawrat
|
||||
case 179458: // Protective Mawrat
|
||||
case 154030: // Oddly Large Mawrat
|
||||
case 169871: // Hungry Mawrat
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_torghast_dimensional_blade::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 341324 - Uncontrolled Darkness
|
||||
class spell_torghast_uncontrolled_darkness : public AuraScript
|
||||
{
|
||||
void Register() override
|
||||
{
|
||||
// just a value holder, no hooks
|
||||
}
|
||||
|
||||
public:
|
||||
int32 KillCounter = 0;
|
||||
};
|
||||
|
||||
// 343174 - Uncontrolled Darkness
|
||||
class spell_torghast_uncontrolled_darkness_proc : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_UNCONTROLLED_DARKNESS = 341324;
|
||||
static constexpr uint32 SPELL_UNCONTROLLED_DARKNESS_BUFF = 341375;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellEffect({ { SPELL_UNCONTROLLED_DARKNESS, EFFECT_1 } })
|
||||
&& ValidateSpellInfo({ SPELL_UNCONTROLLED_DARKNESS_BUFF });
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& /*procInfo*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
Aura* uncontrolledDarkness = caster->GetAura(SPELL_UNCONTROLLED_DARKNESS, caster->GetGUID());
|
||||
if (!uncontrolledDarkness)
|
||||
return;
|
||||
|
||||
spell_torghast_uncontrolled_darkness* script = uncontrolledDarkness->GetScript<spell_torghast_uncontrolled_darkness>();
|
||||
if (!script)
|
||||
return;
|
||||
|
||||
if (caster->HasAura(SPELL_UNCONTROLLED_DARKNESS_BUFF))
|
||||
{
|
||||
if (++script->KillCounter >= uncontrolledDarkness->GetSpellInfo()->GetEffect(EFFECT_1).CalcValue())
|
||||
{
|
||||
caster->RemoveAura(SPELL_UNCONTROLLED_DARKNESS_BUFF);
|
||||
script->KillCounter = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++script->KillCounter >= uncontrolledDarkness->GetSpellInfo()->GetEffect(EFFECT_0).CalcValue())
|
||||
{
|
||||
caster->CastSpell(caster, SPELL_UNCONTROLLED_DARKNESS_BUFF, true);
|
||||
script->KillCounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_torghast_uncontrolled_darkness_proc::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 342632 - Malevolent Stitching
|
||||
class spell_torghast_fleshcraft_shield_proc : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_LABEL_FLESHCRAFT_BUFF = 1103;
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_FLESHCRAFT_BUFF);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_torghast_fleshcraft_shield_proc::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 342779 - Crystallized Dreams
|
||||
class spell_torghast_soulshape_proc : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_LABEL_SOULSHAPE = 1100;
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_SOULSHAPE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_torghast_soulshape_proc::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 342793 - Murmuring Shawl
|
||||
// 342799 - Gnarled Key
|
||||
class spell_torghast_door_of_shadows_proc : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_LABEL_DOOR_OF_SHADOWS = 726;
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_DOOR_OF_SHADOWS);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_torghast_door_of_shadows_proc::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 348908 - Ethereal Wildseed
|
||||
class spell_torghast_flicker_proc : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_LABEL_FLICKER = 1105;
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_FLICKER);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_torghast_flicker_proc::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 354569 - Potent Potion
|
||||
class spell_torghast_potent_potion_proc : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_LABEL_REJUVENATING_SIPHONED_ESSENCE = 1290;
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_REJUVENATING_SIPHONED_ESSENCE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_torghast_potent_potion_proc::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 354706 - Spiritual Rejuvenation Potion
|
||||
class spell_torghast_potent_potion_calc : public SpellScript
|
||||
{
|
||||
static constexpr uint32 SPELL_LABEL_SPIRITUAL_REJUVENATION_POTION = 354568;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellEffect({ { SPELL_LABEL_SPIRITUAL_REJUVENATION_POTION, EFFECT_1 } });
|
||||
}
|
||||
|
||||
void SetValue(SpellEffIndex effIndex)
|
||||
{
|
||||
SetEffectValue(sSpellMgr->AssertSpellInfo(SPELL_LABEL_SPIRITUAL_REJUVENATION_POTION, GetCastDifficulty())->GetEffect(effIndex)
|
||||
.CalcValue(GetCaster(), nullptr, GetHitUnit()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectLaunchTarget += SpellEffectFn(spell_torghast_potent_potion_calc::SetValue, EFFECT_0, SPELL_EFFECT_HEAL);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_torghast_potent_potion_calc::SetValue, EFFECT_1, SPELL_EFFECT_ENERGIZE);
|
||||
}
|
||||
};
|
||||
|
||||
// 373761 - Poisonous Spores
|
||||
class spell_torghast_poisonous_spores : public AuraScript
|
||||
{
|
||||
void HandleProc(AuraEffect* aurEff, ProcEventInfo& procInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
Spell const* procSpell = procInfo.GetProcSpell();
|
||||
procInfo.GetActor()->CastSpell(*procSpell->m_targets.GetDst(), aurEff->GetSpellEffectInfo().TriggerSpell,
|
||||
CastSpellExtraArgs(aurEff).SetTriggeringSpell(procSpell));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_torghast_poisonous_spores::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_torghast_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_torghast_subjugators_manacles);
|
||||
RegisterSpellScript(spell_torghast_blade_of_the_lifetaker);
|
||||
RegisterSpellScript(spell_torghast_touch_of_the_unseen);
|
||||
RegisterSpellScript(spell_torghast_yelshirs_powerglove);
|
||||
RegisterSpellScript(spell_torghast_dimensional_blade);
|
||||
RegisterSpellScript(spell_torghast_uncontrolled_darkness);
|
||||
RegisterSpellScript(spell_torghast_uncontrolled_darkness_proc);
|
||||
RegisterSpellScript(spell_torghast_fleshcraft_shield_proc);
|
||||
RegisterSpellScript(spell_torghast_soulshape_proc);
|
||||
RegisterSpellScript(spell_torghast_door_of_shadows_proc);
|
||||
RegisterSpellScript(spell_torghast_flicker_proc);
|
||||
RegisterSpellScript(spell_torghast_potent_potion_proc);
|
||||
RegisterSpellScript(spell_torghast_potent_potion_calc);
|
||||
RegisterSpellScript(spell_torghast_poisonous_spores);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_covenant_spell_scripts();
|
||||
void AddSC_torghast_spell_scripts();
|
||||
|
||||
void AddSC_boss_sylvanas_windrunner();
|
||||
void AddSC_instance_sanctum_of_domination();
|
||||
|
||||
void AddSC_boss_anduin_wrynn();
|
||||
void AddSC_instance_sepulcher_of_the_first_ones();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddShadowlandsScripts()
|
||||
{
|
||||
AddSC_covenant_spell_scripts();
|
||||
AddSC_torghast_spell_scripts();
|
||||
|
||||
// Sanctum of Domination
|
||||
AddSC_boss_sylvanas_windrunner();
|
||||
AddSC_instance_sanctum_of_domination();
|
||||
|
||||
// Sepulcher of The First Ones
|
||||
AddSC_boss_anduin_wrynn();
|
||||
AddSC_instance_sepulcher_of_the_first_ones();
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "Unit.h"
|
||||
|
||||
// 323916 - Sulfuric Emission
|
||||
class spell_soulbind_sulfuric_emission : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_SULFURIC_EMISSION_COOLDOWN_AURA = 347684;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SULFURIC_EMISSION_COOLDOWN_AURA });
|
||||
}
|
||||
|
||||
bool CheckProc(AuraEffect const* aurEff, ProcEventInfo& procInfo)
|
||||
{
|
||||
if (!procInfo.GetProcTarget()->HealthBelowPct(aurEff->GetAmount()))
|
||||
return false;
|
||||
|
||||
if (procInfo.GetProcTarget()->HasAura(SPELL_SULFURIC_EMISSION_COOLDOWN_AURA))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_soulbind_sulfuric_emission::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 332753 - Superior Tactics
|
||||
class spell_soulbind_superior_tactics : public AuraScript
|
||||
{
|
||||
static constexpr uint32 SPELL_SUPERIOR_TACTICS_COOLDOWN_AURA = 332926;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SUPERIOR_TACTICS_COOLDOWN_AURA });
|
||||
}
|
||||
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& procInfo)
|
||||
{
|
||||
if (GetTarget()->HasAura(SPELL_SUPERIOR_TACTICS_COOLDOWN_AURA))
|
||||
return false;
|
||||
|
||||
// only dispels from friendly targets count
|
||||
if (procInfo.GetHitMask() & PROC_HIT_DISPEL && !(procInfo.GetTypeMask() & (PROC_FLAG_DEAL_HELPFUL_ABILITY | PROC_FLAG_DEAL_HELPFUL_SPELL | PROC_FLAG_DEAL_HELPFUL_PERIODIC)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_soulbind_superior_tactics::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_covenant_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_soulbind_sulfuric_emission);
|
||||
RegisterSpellScript(spell_soulbind_superior_tactics);
|
||||
}
|
||||
@@ -1,646 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "AzeritePackets.h"
|
||||
#include "Containers.h"
|
||||
#include "Player.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
class spell_azerite_gen_aura_calc_from_2nd_effect_triggered_spell : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } }) && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_1).TriggerSpell });
|
||||
}
|
||||
|
||||
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
amount = 0;
|
||||
canBeRecalculated = false;
|
||||
for (auto const& [_, aurApp] : Trinity::Containers::MapEqualRange(caster->GetAppliedAuras(), GetEffectInfo(EFFECT_1).TriggerSpell))
|
||||
if (aurApp->HasEffect(EFFECT_0))
|
||||
amount += aurApp->GetBase()->GetEffect(EFFECT_0)->GetAmount();
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_azerite_gen_aura_calc_from_2nd_effect_triggered_spell::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_RATING);
|
||||
}
|
||||
};
|
||||
|
||||
// 270658 - Azerite Fortification
|
||||
class spell_item_azerite_fortification : public AuraScript
|
||||
{
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
Spell const* procSpell = eventInfo.GetProcSpell();
|
||||
if (!procSpell)
|
||||
return false;
|
||||
|
||||
return procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_STUN)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_ROOT)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_ROOT_2)
|
||||
|| procSpell->GetSpellInfo()->HasEffect(SPELL_EFFECT_KNOCK_BACK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_azerite_fortification::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
enum StrengthInNumbers
|
||||
{
|
||||
SPELL_STRENGTH_IN_NUMBERS_TRAIT = 271546,
|
||||
SPELL_STRENGTH_IN_NUMBERS_BUFF = 271550
|
||||
};
|
||||
|
||||
// 271548 - Strength in Numbers
|
||||
class spell_item_strength_in_numbers : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_STRENGTH_IN_NUMBERS_TRAIT, SPELL_STRENGTH_IN_NUMBERS_BUFF });
|
||||
}
|
||||
|
||||
void TriggerHealthBuff()
|
||||
{
|
||||
if (AuraEffect const* trait = GetCaster()->GetAuraEffect(SPELL_STRENGTH_IN_NUMBERS_TRAIT, EFFECT_0, GetCaster()->GetGUID()))
|
||||
if (int64 enemies = GetUnitTargetCountForEffect(EFFECT_0))
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_STRENGTH_IN_NUMBERS_BUFF, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
|
||||
.AddSpellMod(SPELLVALUE_BASE_POINT0, trait->GetAmount())
|
||||
.AddSpellMod(SPELLVALUE_AURA_STACK, enemies));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_item_strength_in_numbers::TriggerHealthBuff);
|
||||
}
|
||||
};
|
||||
|
||||
enum BlessedPortents
|
||||
{
|
||||
SPELL_BLESSED_PORTENTS_TRAIT = 267889,
|
||||
SPELL_BLESSED_PORTENTS_HEAL = 280052,
|
||||
};
|
||||
|
||||
// 271843 - Blessed Portents
|
||||
class spell_item_blessed_portents : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_BLESSED_PORTENTS_TRAIT, SPELL_BLESSED_PORTENTS_HEAL });
|
||||
}
|
||||
|
||||
void CheckProc(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
|
||||
{
|
||||
if (GetTarget()->HealthBelowPctDamaged(50, dmgInfo.GetDamage()))
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (AuraEffect const* trait = caster->GetAuraEffect(SPELL_BLESSED_PORTENTS_TRAIT, EFFECT_0, caster->GetGUID()))
|
||||
caster->CastSpell(GetTarget(), SPELL_BLESSED_PORTENTS_HEAL, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
|
||||
.AddSpellMod(SPELLVALUE_BASE_POINT0, trait->GetAmount()));
|
||||
}
|
||||
else
|
||||
PreventDefaultAction();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectAbsorb += AuraEffectAbsorbFn(spell_item_blessed_portents::CheckProc, EFFECT_0);
|
||||
}
|
||||
};
|
||||
|
||||
enum ConcentratedMending
|
||||
{
|
||||
SPELL_CONCENTRATED_MENDING_TRAIT = 267882,
|
||||
};
|
||||
|
||||
// 272260 - Concentrated Mending
|
||||
class spell_item_concentrated_mending : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_CONCENTRATED_MENDING_TRAIT });
|
||||
}
|
||||
|
||||
void RecalculateHealAmount(AuraEffect* aurEff)
|
||||
{
|
||||
if (Unit const* caster = GetCaster())
|
||||
if (AuraEffect const* trait = caster->GetAuraEffect(SPELL_CONCENTRATED_MENDING_TRAIT, EFFECT_0, caster->GetGUID()))
|
||||
aurEff->ChangeAmount(trait->GetAmount() * aurEff->GetTickNumber());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_item_concentrated_mending::RecalculateHealAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
|
||||
}
|
||||
};
|
||||
|
||||
enum BracingChill
|
||||
{
|
||||
SPELL_BRACING_CHILL_TRAIT = 267884,
|
||||
SPELL_BRACING_CHILL = 272276,
|
||||
SPELL_BRACING_CHILL_HEAL = 272428,
|
||||
SPELL_BRACING_CHILL_SEARCH_JUMP_TARGET = 272436,
|
||||
};
|
||||
|
||||
// 272276 - Bracing Chill
|
||||
class spell_item_bracing_chill_proc : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_BRACING_CHILL_TRAIT, SPELL_BRACING_CHILL_HEAL, SPELL_BRACING_CHILL_SEARCH_JUMP_TARGET });
|
||||
}
|
||||
|
||||
bool CheckHealCaster(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
return GetCasterGUID() == eventInfo.GetActor()->GetGUID();
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& procInfo)
|
||||
{
|
||||
Unit* caster = procInfo.GetActor();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if (AuraEffect const* trait = caster->GetAuraEffect(SPELL_BRACING_CHILL_TRAIT, EFFECT_0, caster->GetGUID()))
|
||||
caster->CastSpell(procInfo.GetProcTarget(), SPELL_BRACING_CHILL_HEAL,
|
||||
CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_BASE_POINT0, trait->GetAmount()));
|
||||
|
||||
if (GetStackAmount() > 1)
|
||||
caster->CastSpell(nullptr, SPELL_BRACING_CHILL_SEARCH_JUMP_TARGET,
|
||||
CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount() - 1));
|
||||
|
||||
Remove();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_bracing_chill_proc::CheckHealCaster, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
AfterEffectProc += AuraEffectProcFn(spell_item_bracing_chill_proc::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 272436 - Bracing Chill
|
||||
class spell_item_bracing_chill_search_jump_target : public SpellScript
|
||||
{
|
||||
void FilterTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
std::list<WorldObject*> copy = targets;
|
||||
Trinity::Containers::RandomResize(copy, [&](WorldObject* target)
|
||||
{
|
||||
return target->IsUnit() && !target->ToUnit()->HasAura(SPELL_BRACING_CHILL, GetCaster()->GetGUID());
|
||||
}, 1);
|
||||
|
||||
if (!copy.empty())
|
||||
{
|
||||
// found a preferred target, use that
|
||||
targets.swap(copy);
|
||||
return;
|
||||
}
|
||||
|
||||
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
|
||||
targets.clear();
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
void MoveAura(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_BRACING_CHILL,
|
||||
CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetSpellValue()->AuraStackAmount));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_bracing_chill_search_jump_target::FilterTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_item_bracing_chill_search_jump_target::MoveAura, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 272837 - Trample the Weak
|
||||
class spell_item_trample_the_weak : public AuraScript
|
||||
{
|
||||
bool CheckHealthPct(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
return eventInfo.GetActor()->GetHealthPct() > eventInfo.GetActionTarget()->GetHealthPct();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_trample_the_weak::CheckHealthPct, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 272892 - Wracking Brilliance
|
||||
class spell_item_wracking_brilliance : public AuraScript
|
||||
{
|
||||
enum
|
||||
{
|
||||
SPELL_AGONY_SOUL_SHARD_GAIN = 210067
|
||||
};
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_AGONY_SOUL_SHARD_GAIN });
|
||||
}
|
||||
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
if (spellInfo->Id != SPELL_AGONY_SOUL_SHARD_GAIN)
|
||||
return false;
|
||||
|
||||
_canTrigger = !_canTrigger; // every other soul shard gain
|
||||
return _canTrigger;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_wracking_brilliance::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
|
||||
bool _canTrigger = true;
|
||||
};
|
||||
|
||||
enum OrbitalPrecision
|
||||
{
|
||||
SPELL_MAGE_FROZEN_ORB = 84714
|
||||
};
|
||||
|
||||
// 275514 - Orbital Precision
|
||||
class spell_item_orbital_precision : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MAGE_FROZEN_ORB });
|
||||
}
|
||||
|
||||
bool CheckFrozenOrbActive(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
return eventInfo.GetActor()->GetAreaTrigger(SPELL_MAGE_FROZEN_ORB) != nullptr;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_orbital_precision::CheckFrozenOrbActive, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
enum BlurOfTalons
|
||||
{
|
||||
SPELL_HUNTER_COORDINATED_ASSAULT = 266779
|
||||
};
|
||||
|
||||
// 277966 - Blur of Talons
|
||||
class spell_item_blur_of_talons : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_HUNTER_COORDINATED_ASSAULT });
|
||||
}
|
||||
|
||||
bool CheckCoordinatedAssaultActive(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
return eventInfo.GetActor()->HasAura(SPELL_HUNTER_COORDINATED_ASSAULT, eventInfo.GetActor()->GetGUID());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_blur_of_talons::CheckCoordinatedAssaultActive, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 278519 - Divine Right
|
||||
class spell_item_divine_right : public AuraScript
|
||||
{
|
||||
bool CheckHealthPct(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
return eventInfo.GetProcTarget()->HasAuraState(AURA_STATE_WOUNDED_20_PERCENT, eventInfo.GetSpellInfo(), eventInfo.GetActor());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_divine_right::CheckHealthPct, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 280409 - Blood Rite
|
||||
class spell_item_blood_rite : public AuraScript
|
||||
{
|
||||
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& /*procInfo*/)
|
||||
{
|
||||
RefreshDuration();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectProc += AuraEffectProcFn(spell_item_blood_rite::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 281843 - Tradewinds
|
||||
class spell_item_tradewinds : public AuraScript
|
||||
{
|
||||
enum
|
||||
{
|
||||
SPELL_TRADEWINDS_ALLY_BUFF = 281844
|
||||
};
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_TRADEWINDS_ALLY_BUFF });
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (AuraEffect const* trait = GetTarget()->GetAuraEffect(GetEffectInfo(EFFECT_1).TriggerSpell, EFFECT_1))
|
||||
GetTarget()->CastSpell(nullptr, SPELL_TRADEWINDS_ALLY_BUFF,
|
||||
CastSpellExtraArgs(aurEff).AddSpellMod(SPELLVALUE_BASE_POINT0, trait->GetAmount()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_item_tradewinds::HandleRemove, EFFECT_0, SPELL_AURA_MOD_RATING, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 287379 - Bastion of Might
|
||||
class spell_item_bastion_of_might : public SpellScript
|
||||
{
|
||||
enum
|
||||
{
|
||||
SPELL_WARRIOR_IGNORE_PAIN = 190456
|
||||
};
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_WARRIOR_IGNORE_PAIN });
|
||||
}
|
||||
|
||||
void TriggerIgnorePain()
|
||||
{
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_WARRIOR_IGNORE_PAIN, GetSpell());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_item_bastion_of_might::TriggerIgnorePain);
|
||||
}
|
||||
};
|
||||
|
||||
// 287650 - Echoing Blades
|
||||
class spell_item_echoing_blades : public AuraScript
|
||||
{
|
||||
void PrepareProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (eventInfo.GetProcSpell())
|
||||
{
|
||||
if (eventInfo.GetProcSpell()->m_castId != _lastFanOfKnives)
|
||||
GetEffect(EFFECT_0)->RecalculateAmount();
|
||||
|
||||
_lastFanOfKnives = eventInfo.GetProcSpell()->m_castId;
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckFanOfKnivesCounter(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
return aurEff->GetAmount() > 0;
|
||||
}
|
||||
|
||||
void ReduceCounter(AuraEffect* aurEff, ProcEventInfo& /*procInfo*/)
|
||||
{
|
||||
aurEff->SetAmount(aurEff->GetAmount() - 1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoPrepareProc += AuraProcFn(spell_item_echoing_blades::PrepareProc);
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_echoing_blades::CheckFanOfKnivesCounter, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
AfterEffectProc += AuraEffectProcFn(spell_item_echoing_blades::ReduceCounter, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
|
||||
ObjectGuid _lastFanOfKnives;
|
||||
};
|
||||
|
||||
// 287653 - Echoing Blades
|
||||
class spell_item_echoing_blades_damage : public SpellScript
|
||||
{
|
||||
enum
|
||||
{
|
||||
SPELL_ECHOING_BLADES_TRAIT = 287649
|
||||
};
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellEffect({ { SPELL_ECHOING_BLADES_TRAIT, EFFECT_2 } });
|
||||
}
|
||||
|
||||
void CalculateDamage(Unit const* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/) const
|
||||
{
|
||||
if (AuraEffect const* trait = GetCaster()->GetAuraEffect(SPELL_ECHOING_BLADES_TRAIT, EFFECT_2))
|
||||
damage = trait->GetAmount() * 2;
|
||||
}
|
||||
|
||||
void ForceCritical(Unit const* /*victim*/, float& critChance)
|
||||
{
|
||||
critChance = 100.0f;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
CalcDamage += SpellCalcDamageFn(spell_item_echoing_blades_damage::CalculateDamage);
|
||||
OnCalcCritChance += SpellOnCalcCritChanceFn(spell_item_echoing_blades_damage::ForceCritical);
|
||||
}
|
||||
};
|
||||
|
||||
// 288882 - Hour of Reaping
|
||||
class spell_item_hour_of_reaping : public AuraScript
|
||||
{
|
||||
enum
|
||||
{
|
||||
SPELL_DH_SOUL_BARRIER = 263648
|
||||
};
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_SOUL_BARRIER });
|
||||
}
|
||||
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
return GetStackAmount() == GetAura()->CalcMaxStackAmount();
|
||||
}
|
||||
|
||||
void TriggerSoulBarrier(AuraEffect* aurEff, ProcEventInfo& /*procInfo*/)
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_DH_SOUL_BARRIER, aurEff);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_hour_of_reaping::CheckProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
AfterEffectProc += AuraEffectProcFn(spell_item_hour_of_reaping::TriggerSoulBarrier, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 304086 - Azerite Fortification
|
||||
class spell_item_conflict_wearer_on_stun_proc : public AuraScript
|
||||
{
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
Spell const* procSpell = eventInfo.GetProcSpell();
|
||||
if (!procSpell)
|
||||
return false;
|
||||
|
||||
return procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_STUN)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_STUN_DISABLE_GRAVITY);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_item_conflict_wearer_on_stun_proc::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 305723 - Strife (Azerite Essence)
|
||||
class spell_item_conflict_rank3 : public AuraScript
|
||||
{
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (eventInfo.GetHitMask() & (PROC_HIT_INTERRUPT | PROC_HIT_DISPEL))
|
||||
return true;
|
||||
|
||||
Spell const* procSpell = eventInfo.GetProcSpell();
|
||||
if (!procSpell)
|
||||
return false;
|
||||
|
||||
bool isCrowdControl = procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_CONFUSE)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_FEAR)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_STUN)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_PACIFY)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_ROOT)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_SILENCE)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_PACIFY_SILENCE)
|
||||
|| procSpell->GetSpellInfo()->HasAura(SPELL_AURA_MOD_ROOT_2);
|
||||
|
||||
if (!isCrowdControl)
|
||||
return false;
|
||||
|
||||
return eventInfo.GetActionTarget()->HasAura([&](Aura const* aura) { return aura->GetCastId() == procSpell->m_castId; });
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_item_conflict_rank3::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 277253 - Heart of Azeroth
|
||||
class spell_item_heart_of_azeroth : public AuraScript
|
||||
{
|
||||
void SetEquippedFlag(AuraEffect const* /*effect*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
SetState(true);
|
||||
}
|
||||
|
||||
void ClearEquippedFlag(AuraEffect const* /*effect*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
SetState(false);
|
||||
}
|
||||
|
||||
void SetState(bool equipped) const
|
||||
{
|
||||
if (Player* target = GetTarget()->ToPlayer())
|
||||
{
|
||||
target->ApplyAllAzeriteEmpoweredItemMods(equipped);
|
||||
|
||||
WorldPackets::Azerite::PlayerAzeriteItemEquippedStatusChanged statusChanged;
|
||||
statusChanged.IsHeartEquipped = equipped;
|
||||
target->SendDirectMessage(statusChanged.Write());
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_item_heart_of_azeroth::SetEquippedFlag, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_item_heart_of_azeroth::ClearEquippedFlag, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 315176 - Grasping Tendrils
|
||||
class spell_item_corruption_grasping_tendrils : public AuraScript
|
||||
{
|
||||
bool Load() override
|
||||
{
|
||||
return GetUnitOwner()->IsPlayer();
|
||||
}
|
||||
|
||||
void CalcAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
|
||||
{
|
||||
Player* player = GetUnitOwner()->ToPlayer();
|
||||
amount = std::clamp(10.0f + player->GetRatingBonusValue(CR_CORRUPTION) - player->GetRatingBonusValue(CR_CORRUPTION_RESISTANCE), 0.0f, 99.0f);
|
||||
canBeRecalculated = false;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_corruption_grasping_tendrils::CalcAmount, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_azerite_item_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_azerite_gen_aura_calc_from_2nd_effect_triggered_spell);
|
||||
RegisterSpellScript(spell_item_azerite_fortification);
|
||||
RegisterSpellScript(spell_item_strength_in_numbers);
|
||||
RegisterSpellScript(spell_item_blessed_portents);
|
||||
RegisterSpellScript(spell_item_concentrated_mending);
|
||||
RegisterSpellScript(spell_item_bracing_chill_proc);
|
||||
RegisterSpellScript(spell_item_bracing_chill_search_jump_target);
|
||||
RegisterSpellScript(spell_item_trample_the_weak);
|
||||
RegisterSpellScript(spell_item_wracking_brilliance);
|
||||
RegisterSpellScript(spell_item_orbital_precision);
|
||||
RegisterSpellScript(spell_item_blur_of_talons);
|
||||
RegisterSpellScript(spell_item_divine_right);
|
||||
RegisterSpellScript(spell_item_blood_rite);
|
||||
RegisterSpellScript(spell_item_tradewinds);
|
||||
RegisterSpellScript(spell_item_bastion_of_might);
|
||||
RegisterSpellScript(spell_item_echoing_blades);
|
||||
RegisterSpellScript(spell_item_echoing_blades_damage);
|
||||
RegisterSpellScript(spell_item_hour_of_reaping);
|
||||
RegisterSpellScript(spell_item_conflict_wearer_on_stun_proc);
|
||||
RegisterSpellScript(spell_item_conflict_rank3);
|
||||
|
||||
RegisterSpellScript(spell_item_heart_of_azeroth);
|
||||
|
||||
RegisterSpellScript(spell_item_corruption_grasping_tendrils);
|
||||
}
|
||||
@@ -1,514 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Scripts for spells with SPELLFAMILY_DEMONHUNTER and SPELLFAMILY_GENERIC spells used by demon hunter players.
|
||||
* Ordered alphabetically using scriptname.
|
||||
* Scriptnames of files in this file should be prefixed with "spell_dh_".
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellHistory.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "Unit.h"
|
||||
|
||||
enum DemonHunterSpells
|
||||
{
|
||||
AREATRIGGER_DH_SHATTERED_SOULS_HAVOC = 8352,
|
||||
AREATRIGGER_DH_SHATTERED_SOULS_HAVOC_DEMON = 11231,
|
||||
AREATRIGGER_DH_SHATTERED_SOULS_VENGEANCE = 11266,
|
||||
AREATRIGGER_DH_SHATTERED_SOULS_VENGEANCE_DEMON = 10693,
|
||||
AREATRIGGER_DH_SOUL_FRAGMENT_HAVOC = 12929,
|
||||
AREATRIGGER_DH_SOUL_FRAGMENT_VENGEANCE = 10665,
|
||||
|
||||
SPELL_DH_ABYSSAL_STRIKE = 207550,
|
||||
SPELL_DH_ANNIHILATION = 201427,
|
||||
SPELL_DH_ANNIHILATION_MH = 227518,
|
||||
SPELL_DH_ANNIHILATION_OH = 201428,
|
||||
SPELL_DH_AWAKEN_THE_DEMON_WITHIN_CD = 207128,
|
||||
SPELL_DH_BLUR = 212800,
|
||||
SPELL_DH_BLUR_TRIGGER = 198589,
|
||||
SPELL_DH_BURNING_ALIVE = 207739,
|
||||
SPELL_DH_BURNING_ALIVE_TARGET_SELECTOR = 207760,
|
||||
SPELL_DH_CHAOS_NOVA = 179057,
|
||||
SPELL_DH_CHAOS_STRIKE = 162794,
|
||||
SPELL_DH_CHAOS_STRIKE_ENERGIZE = 193840,
|
||||
SPELL_DH_CHAOS_STRIKE_MH = 222031,
|
||||
SPELL_DH_CHAOS_STRIKE_OH = 199547,
|
||||
SPELL_DH_CONSUME_SOUL_HAVOC = 228542,
|
||||
SPELL_DH_CONSUME_SOUL_HAVOC_DEMON = 228556,
|
||||
SPELL_DH_CONSUME_SOUL_HAVOC_SHATTERED = 228540,
|
||||
SPELL_DH_CONSUME_SOUL_HEAL = 203794,
|
||||
SPELL_DH_CONSUME_SOUL_VENGEANCE = 208014,
|
||||
SPELL_DH_CONSUME_SOUL_VENGEANCE_DEMON = 210050,
|
||||
SPELL_DH_CONSUME_SOUL_VENGEANCE_SHATTERED = 210047,
|
||||
SPELL_DH_DARKNESS_ABSORB = 209426,
|
||||
SPELL_DH_DEMON_BLADES_DMG = 203796,
|
||||
SPELL_DH_DEMON_SPIKES = 203819,
|
||||
SPELL_DH_DEMON_SPIKES_TRIGGER = 203720,
|
||||
SPELL_DH_DEMONIC = 213410,
|
||||
SPELL_DH_DEMONIC_ORIGINS = 235893,
|
||||
SPELL_DH_DEMONIC_ORIGINS_BUFF = 235894,
|
||||
SPELL_DH_DEMONIC_TRAMPLE_DMG = 208645,
|
||||
SPELL_DH_DEMONIC_TRAMPLE_STUN = 213491,
|
||||
SPELL_DH_DEMONS_BITE = 162243,
|
||||
SPELL_DH_EYE_BEAM = 198013,
|
||||
SPELL_DH_EYE_BEAM_DMG = 198030,
|
||||
SPELL_DH_EYE_OF_LEOTHERAS_DMG = 206650,
|
||||
SPELL_DH_FEAST_OF_SOULS = 207697,
|
||||
SPELL_DH_FEAST_OF_SOULS_PERIODIC_HEAL = 207693,
|
||||
SPELL_DH_FEED_THE_DEMON = 218612,
|
||||
SPELL_DH_FEL_BARRAGE = 211053,
|
||||
SPELL_DH_FEL_BARRAGE_DMG = 211052,
|
||||
SPELL_DH_FEL_BARRAGE_PROC = 222703,
|
||||
SPELL_DH_FEL_DEVASTATION = 212084,
|
||||
SPELL_DH_FEL_DEVASTATION_DMG = 212105,
|
||||
SPELL_DH_FEL_DEVASTATION_HEAL = 212106,
|
||||
SPELL_DH_FEL_RUSH = 195072,
|
||||
SPELL_DH_FEL_RUSH_DMG = 192611,
|
||||
SPELL_DH_FEL_RUSH_GROUND = 197922,
|
||||
SPELL_DH_FEL_RUSH_WATER_AIR = 197923,
|
||||
SPELL_DH_FELBLADE = 232893,
|
||||
SPELL_DH_FELBLADE_CHARGE = 213241,
|
||||
SPELL_DH_FELBLADE_DMG = 213243,
|
||||
SPELL_DH_FELBLADE_PROC = 203557,
|
||||
SPELL_DH_FELBLADE_PROC_VISUAL = 204497,
|
||||
SPELL_DH_FELBLADE_PROC1 = 236167,
|
||||
SPELL_DH_FIERY_BRAND = 204021,
|
||||
SPELL_DH_FIERY_BRAND_DMG_REDUCTION_DEBUFF = 207744,
|
||||
SPELL_DH_FIERY_BRAND_DOT = 207771,
|
||||
SPELL_DH_FIRST_BLOOD = 206416,
|
||||
SPELL_DH_FLAME_CRASH = 227322,
|
||||
SPELL_DH_FRAILTY = 224509,
|
||||
SPELL_DH_GLIDE = 131347,
|
||||
SPELL_DH_GLIDE_DURATION = 197154,
|
||||
SPELL_DH_GLIDE_KNOCKBACK = 196353,
|
||||
SPELL_DH_HAVOC_MASTERY = 185164,
|
||||
SPELL_DH_ILLIDANS_GRASP = 205630,
|
||||
SPELL_DH_ILLIDANS_GRASP_DAMAGE = 208618,
|
||||
SPELL_DH_ILLIDANS_GRASP_JUMP_DEST = 208175,
|
||||
SPELL_DH_INFERNAL_STRIKE_CAST = 189110,
|
||||
SPELL_DH_INFERNAL_STRIKE_IMPACT_DAMAGE = 189112,
|
||||
SPELL_DH_INFERNAL_STRIKE_JUMP = 189111,
|
||||
SPELL_DH_JAGGED_SPIKES = 205627,
|
||||
SPELL_DH_JAGGED_SPIKES_DMG = 208790,
|
||||
SPELL_DH_JAGGED_SPIKES_PROC = 208796,
|
||||
SPELL_DH_MANA_RIFT_DMG_POWER_BURN = 235904,
|
||||
SPELL_DH_METAMORPHOSIS = 191428,
|
||||
SPELL_DH_METAMORPHOSIS_DUMMY = 191427,
|
||||
SPELL_DH_METAMORPHOSIS_IMPACT_DAMAGE = 200166,
|
||||
SPELL_DH_METAMORPHOSIS_RESET = 320645,
|
||||
SPELL_DH_METAMORPHOSIS_TRANSFORM = 162264,
|
||||
SPELL_DH_METAMORPHOSIS_VENGEANCE_TRANSFORM = 187827,
|
||||
SPELL_DH_MOMENTUM = 208628,
|
||||
SPELL_DH_NEMESIS_ABERRATIONS = 208607,
|
||||
SPELL_DH_NEMESIS_BEASTS = 208608,
|
||||
SPELL_DH_NEMESIS_CRITTERS = 208609,
|
||||
SPELL_DH_NEMESIS_DEMONS = 208608,
|
||||
SPELL_DH_NEMESIS_DRAGONKIN = 208610,
|
||||
SPELL_DH_NEMESIS_ELEMENTALS = 208611,
|
||||
SPELL_DH_NEMESIS_GIANTS = 208612,
|
||||
SPELL_DH_NEMESIS_HUMANOIDS = 208605,
|
||||
SPELL_DH_NEMESIS_MECHANICALS = 208613,
|
||||
SPELL_DH_NEMESIS_UNDEAD = 208614,
|
||||
SPELL_DH_RAIN_FROM_ABOVE = 206803,
|
||||
SPELL_DH_RAIN_OF_CHAOS = 205628,
|
||||
SPELL_DH_RAIN_OF_CHAOS_IMPACT = 232538,
|
||||
SPELL_DH_RAZOR_SPIKES = 210003,
|
||||
SPELL_DH_SEVER = 235964,
|
||||
SPELL_DH_SHATTER_SOUL = 209980,
|
||||
SPELL_DH_SHATTER_SOUL_1 = 209981,
|
||||
SPELL_DH_SHATTER_SOUL_2 = 210038,
|
||||
SPELL_DH_SHATTERED_SOUL = 226258,
|
||||
SPELL_DH_SHATTERED_SOUL_LESSER_SOUL_FRAGMENT_1 = 228533,
|
||||
SPELL_DH_SHATTERED_SOUL_LESSER_SOUL_FRAGMENT_2 = 237867,
|
||||
SPELL_DH_SHEAR = 203782,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_AREA_SELECTOR = 204834,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_GRIP = 208674,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_JUMP = 208674,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_SLOW = 204843,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_SNARE = 204843,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_TARGET_SELECT = 204834,
|
||||
SPELL_DH_SIGIL_OF_CHAINS_VISUAL = 208673,
|
||||
SPELL_DH_SIGIL_OF_FLAME_AOE = 204598,
|
||||
SPELL_DH_SIGIL_OF_FLAME_DAMAGE = 204598,
|
||||
SPELL_DH_SIGIL_OF_FLAME_FLAME_CRASH = 228973,
|
||||
SPELL_DH_SIGIL_OF_MISERY = 207685,
|
||||
SPELL_DH_SIGIL_OF_MISERY_AOE = 207685,
|
||||
SPELL_DH_SIGIL_OF_SILENCE = 204490,
|
||||
SPELL_DH_SIGIL_OF_SILENCE_AOE = 204490,
|
||||
SPELL_DH_SOUL_BARRIER = 227225,
|
||||
SPELL_DH_SOUL_CLEAVE = 228477,
|
||||
SPELL_DH_SOUL_CLEAVE_DMG = 228478,
|
||||
SPELL_DH_SOUL_FRAGMENT_COUNTER = 203981,
|
||||
SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF = 391172,
|
||||
SPELL_DH_SOUL_RENDING = 204909,
|
||||
SPELL_DH_SPIRIT_BOMB_DAMAGE = 218677,
|
||||
SPELL_DH_SPIRIT_BOMB_HEAL = 227255,
|
||||
SPELL_DH_SPIRIT_BOMB_VISUAL = 218678,
|
||||
SPELL_DH_THROW_GLAIVE = 185123,
|
||||
SPELL_DH_UNCONTAINED_FEL = 209261,
|
||||
SPELL_DH_VENGEFUL_RETREAT = 198813,
|
||||
SPELL_DH_VENGEFUL_RETREAT_TRIGGER = 198793,
|
||||
};
|
||||
|
||||
// 197125 - Chaos Strike
|
||||
class spell_dh_chaos_strike : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_CHAOS_STRIKE_ENERGIZE });
|
||||
}
|
||||
|
||||
void HandleEffectProc(AuraEffect* aurEff, ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
|
||||
args.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount());
|
||||
args.SetTriggeringAura(aurEff);
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_DH_CHAOS_STRIKE_ENERGIZE, args);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_dh_chaos_strike::HandleEffectProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 206416 - First Blood
|
||||
class spell_dh_first_blood : public AuraScript
|
||||
{
|
||||
public:
|
||||
ObjectGuid const& GetFirstTarget() const { return _firstTargetGUID; }
|
||||
void SetFirstTarget(ObjectGuid const& targetGuid) { _firstTargetGUID = targetGuid; }
|
||||
|
||||
private:
|
||||
void Register() override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _firstTargetGUID;
|
||||
};
|
||||
|
||||
// 188499 - Blade Dance
|
||||
// 210152 - Death Sweep
|
||||
class spell_dh_blade_dance : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_FIRST_BLOOD });
|
||||
}
|
||||
|
||||
void DecideFirstTarget(std::list<WorldObject*>& targetList)
|
||||
{
|
||||
if (targetList.empty())
|
||||
return;
|
||||
|
||||
Aura* aura = GetCaster()->GetAura(SPELL_DH_FIRST_BLOOD);
|
||||
if (!aura)
|
||||
return;
|
||||
|
||||
ObjectGuid firstTargetGUID = ObjectGuid::Empty;
|
||||
ObjectGuid selectedTarget = GetCaster()->GetTarget();
|
||||
|
||||
// Prefer the selected target if he is one of the enemies
|
||||
if (targetList.size() > 1 && !selectedTarget.IsEmpty())
|
||||
{
|
||||
auto it = std::find_if(targetList.begin(), targetList.end(), [selectedTarget](WorldObject* object)
|
||||
{
|
||||
return object->GetGUID() == selectedTarget;
|
||||
});
|
||||
if (it != targetList.end())
|
||||
firstTargetGUID = (*it)->GetGUID();
|
||||
}
|
||||
|
||||
if (firstTargetGUID.IsEmpty())
|
||||
firstTargetGUID = targetList.front()->GetGUID();
|
||||
|
||||
if (spell_dh_first_blood* script = aura->GetScript<spell_dh_first_blood>())
|
||||
script->SetFirstTarget(firstTargetGUID);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dh_blade_dance::DecideFirstTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 199552 - Blade Dance
|
||||
// 200685 - Blade Dance
|
||||
// 210153 - Death Sweep
|
||||
// 210155 - Death Sweep
|
||||
class spell_dh_blade_dance_damage : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_FIRST_BLOOD });
|
||||
}
|
||||
|
||||
void HandleHitTarget()
|
||||
{
|
||||
int32 damage = GetHitDamage();
|
||||
|
||||
if (AuraEffect* aurEff = GetCaster()->GetAuraEffect(SPELL_DH_FIRST_BLOOD, EFFECT_0))
|
||||
if (spell_dh_first_blood* script = aurEff->GetBase()->GetScript<spell_dh_first_blood>())
|
||||
if (GetHitUnit()->GetGUID() == script->GetFirstTarget())
|
||||
AddPct(damage, aurEff->GetAmount());
|
||||
|
||||
SetHitDamage(damage);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_dh_blade_dance_damage::HandleHitTarget);
|
||||
}
|
||||
};
|
||||
|
||||
// 204596 - Sigil of Flame
|
||||
// 207684 - Sigil of Misery
|
||||
// 202137 - Sigil of Silence
|
||||
template<uint32 TriggerSpellId>
|
||||
class areatrigger_dh_generic_sigil : public AreaTriggerEntityScript
|
||||
{
|
||||
public:
|
||||
areatrigger_dh_generic_sigil(char const* script) : AreaTriggerEntityScript(script) { }
|
||||
|
||||
template<uint32 Trigger>
|
||||
struct areatrigger_dh_generic_sigilAI : AreaTriggerAI
|
||||
{
|
||||
areatrigger_dh_generic_sigilAI(AreaTrigger* at) : AreaTriggerAI(at) { }
|
||||
|
||||
void OnRemove() override
|
||||
{
|
||||
if (Unit* caster = at->GetCaster())
|
||||
caster->CastSpell(at->GetPosition(), Trigger);
|
||||
}
|
||||
};
|
||||
|
||||
AreaTriggerAI* GetAI(AreaTrigger* at) const override
|
||||
{
|
||||
return new areatrigger_dh_generic_sigilAI<TriggerSpellId>(at);
|
||||
}
|
||||
};
|
||||
|
||||
// 208673 - Sigil of Chains
|
||||
class spell_dh_sigil_of_chains : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_SIGIL_OF_CHAINS_SLOW, SPELL_DH_SIGIL_OF_CHAINS_GRIP });
|
||||
}
|
||||
|
||||
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (WorldLocation const* loc = GetExplTargetDest())
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_DH_SIGIL_OF_CHAINS_SLOW, true);
|
||||
GetHitUnit()->CastSpell(loc->GetPosition(), SPELL_DH_SIGIL_OF_CHAINS_GRIP, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_dh_sigil_of_chains::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 202138 - Sigil of Chains
|
||||
struct areatrigger_dh_sigil_of_chains : AreaTriggerAI
|
||||
{
|
||||
areatrigger_dh_sigil_of_chains(AreaTrigger* at) : AreaTriggerAI(at) { }
|
||||
|
||||
void OnRemove() override
|
||||
{
|
||||
if (Unit* caster = at->GetCaster())
|
||||
{
|
||||
caster->CastSpell(at->GetPosition(), SPELL_DH_SIGIL_OF_CHAINS_VISUAL);
|
||||
caster->CastSpell(at->GetPosition(), SPELL_DH_SIGIL_OF_CHAINS_TARGET_SELECT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 131347 - Glide
|
||||
class spell_dh_glide : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_GLIDE_KNOCKBACK, SPELL_DH_GLIDE_DURATION, SPELL_DH_VENGEFUL_RETREAT_TRIGGER, SPELL_DH_FEL_RUSH });
|
||||
}
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (caster->IsMounted() || caster->GetVehicleBase())
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
|
||||
if (!caster->IsFalling())
|
||||
return SPELL_FAILED_NOT_ON_GROUND;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void HandleCast()
|
||||
{
|
||||
Player* caster = GetCaster()->ToPlayer();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
caster->CastSpell(caster, SPELL_DH_GLIDE_KNOCKBACK, true);
|
||||
caster->CastSpell(caster, SPELL_DH_GLIDE_DURATION, true);
|
||||
|
||||
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_DH_VENGEFUL_RETREAT_TRIGGER, GetCastDifficulty()), 0, nullptr, false, 250ms);
|
||||
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_DH_FEL_RUSH, GetCastDifficulty()), 0, nullptr, false, 250ms);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_dh_glide::CheckCast);
|
||||
BeforeCast += SpellCastFn(spell_dh_glide::HandleCast);
|
||||
}
|
||||
};
|
||||
|
||||
// 131347 - Glide
|
||||
class spell_dh_glide_AuraScript : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_GLIDE_DURATION });
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->RemoveAura(SPELL_DH_GLIDE_DURATION);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_glide_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_FEATHER_FALL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 197154 - Glide
|
||||
class spell_dh_glide_timer : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_GLIDE });
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->RemoveAura(SPELL_DH_GLIDE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_glide_timer::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 391166 - Soul Furnace
|
||||
class spell_dh_soul_furnace : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF });
|
||||
}
|
||||
|
||||
void CalculateSpellMod(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetStackAmount() == GetAura()->CalcMaxStackAmount())
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF, true);
|
||||
Remove();
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_dh_soul_furnace::CalculateSpellMod, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
// 339424 - Soul Furnace
|
||||
class spell_dh_soul_furnace_conduit : public AuraScript
|
||||
{
|
||||
void CalculateSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod)
|
||||
{
|
||||
if (aurEff->GetAmount() == 10)
|
||||
{
|
||||
if (!spellMod)
|
||||
{
|
||||
spellMod = new SpellModifierByClassMask(GetAura());
|
||||
spellMod->op = SpellModOp::HealingAndDamage;
|
||||
spellMod->type = SPELLMOD_PCT;
|
||||
spellMod->spellId = GetId();
|
||||
static_cast<SpellModifierByClassMask*>(spellMod)->mask = flag128(0x80000000);
|
||||
static_cast<SpellModifierByClassMask*>(spellMod)->value = GetEffect(EFFECT_1)->GetAmount() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_dh_soul_furnace_conduit::CalculateSpellMod, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_demon_hunter_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_dh_chaos_strike);
|
||||
|
||||
new areatrigger_dh_generic_sigil<SPELL_DH_SIGIL_OF_SILENCE_AOE>("areatrigger_dh_sigil_of_silence");
|
||||
new areatrigger_dh_generic_sigil<SPELL_DH_SIGIL_OF_MISERY_AOE>("areatrigger_dh_sigil_of_misery");
|
||||
new areatrigger_dh_generic_sigil<SPELL_DH_SIGIL_OF_FLAME_AOE>("areatrigger_dh_sigil_of_flame");
|
||||
RegisterAreaTriggerAI(areatrigger_dh_sigil_of_chains);
|
||||
RegisterSpellScript(spell_dh_sigil_of_chains);
|
||||
|
||||
// Havoc
|
||||
|
||||
/* Spells & Auras */
|
||||
|
||||
/* Auras */
|
||||
|
||||
RegisterSpellScript(spell_dh_first_blood);
|
||||
|
||||
/* AreaTrigger */
|
||||
|
||||
/* Spells */
|
||||
|
||||
RegisterSpellScript(spell_dh_blade_dance);
|
||||
RegisterSpellScript(spell_dh_blade_dance_damage);
|
||||
|
||||
// Vengeance
|
||||
RegisterSpellScript(spell_dh_soul_furnace);
|
||||
|
||||
// Vengeance & Havoc
|
||||
|
||||
RegisterSpellAndAuraScriptPair(spell_dh_glide, spell_dh_glide_AuraScript);
|
||||
RegisterSpellScript(spell_dh_glide_timer);
|
||||
|
||||
// Soulbind conduits
|
||||
RegisterSpellScript(spell_dh_soul_furnace_conduit);
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Scripts for spells with SPELLFAMILY_EVOKER and SPELLFAMILY_GENERIC spells used by evoker players.
|
||||
* Ordered alphabetically using scriptname.
|
||||
* Scriptnames of files in this file should be prefixed with "spell_evo_".
|
||||
*/
|
||||
|
||||
#include "Containers.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellHistory.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum EvokerSpells
|
||||
{
|
||||
SPELL_EVOKER_ENERGIZING_FLAME = 400006,
|
||||
SPELL_EVOKER_GLIDE_KNOCKBACK = 358736,
|
||||
SPELL_EVOKER_HOVER = 358267,
|
||||
SPELL_EVOKER_LIVING_FLAME = 361469,
|
||||
SPELL_EVOKER_LIVING_FLAME_DAMAGE = 361500,
|
||||
SPELL_EVOKER_LIVING_FLAME_HEAL = 361509,
|
||||
SPELL_EVOKER_PERMEATING_CHILL_TALENT = 370897,
|
||||
SPELL_EVOKER_PYRE_DAMAGE = 357212,
|
||||
SPELL_EVOKER_SOAR_RACIAL = 369536
|
||||
};
|
||||
|
||||
enum EvokerSpellLabels
|
||||
{
|
||||
SPELL_LABEL_EVOKER_BLUE = 1465,
|
||||
};
|
||||
|
||||
// 362969 - Azure Strike (blue)
|
||||
class spell_evo_azure_strike : public SpellScript
|
||||
{
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove(GetExplTargetUnit());
|
||||
Trinity::Containers::RandomResize(targets, GetEffectInfo(EFFECT_0).CalcValue(GetCaster()) - 1);
|
||||
targets.push_back(GetExplTargetUnit());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_evo_azure_strike::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 370455 - Charged Blast
|
||||
class spell_evo_charged_blast : public AuraScript
|
||||
{
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_EVOKER_BLUE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_evo_charged_blast::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 358733 - Glide (Racial)
|
||||
class spell_evo_glide : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_EVOKER_GLIDE_KNOCKBACK, SPELL_EVOKER_HOVER, SPELL_EVOKER_SOAR_RACIAL });
|
||||
}
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
if (!caster->IsFalling())
|
||||
return SPELL_FAILED_NOT_ON_GROUND;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void HandleCast()
|
||||
{
|
||||
Player* caster = GetCaster()->ToPlayer();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
caster->CastSpell(caster, SPELL_EVOKER_GLIDE_KNOCKBACK, true);
|
||||
|
||||
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_EVOKER_HOVER, GetCastDifficulty()), 0, nullptr, false, 250ms);
|
||||
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_EVOKER_SOAR_RACIAL, GetCastDifficulty()), 0, nullptr, false, 250ms);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_evo_glide::CheckCast);
|
||||
OnCast += SpellCastFn(spell_evo_glide::HandleCast);
|
||||
}
|
||||
};
|
||||
|
||||
// 361469 - Living Flame (Red)
|
||||
class spell_evo_living_flame : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo ({ SPELL_EVOKER_LIVING_FLAME_DAMAGE, SPELL_EVOKER_LIVING_FLAME_HEAL, SPELL_EVOKER_ENERGIZING_FLAME });
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* hitUnit = GetHitUnit();
|
||||
if (caster->IsFriendlyTo(hitUnit))
|
||||
caster->CastSpell(hitUnit, SPELL_EVOKER_LIVING_FLAME_HEAL, true);
|
||||
else
|
||||
caster->CastSpell(hitUnit, SPELL_EVOKER_LIVING_FLAME_DAMAGE, true);
|
||||
}
|
||||
|
||||
void HandleLaunchTarget(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (caster->IsFriendlyTo(GetHitUnit()))
|
||||
return;
|
||||
|
||||
if (AuraEffect* auraEffect = caster->GetAuraEffect(SPELL_EVOKER_ENERGIZING_FLAME, EFFECT_0))
|
||||
{
|
||||
int32 manaCost = GetSpell()->GetPowerTypeCostAmount(POWER_MANA).value_or(0);
|
||||
if (manaCost != 0)
|
||||
GetCaster()->ModifyPower(POWER_MANA, CalculatePct(manaCost, auraEffect->GetAmount()));
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_evo_living_flame::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnEffectLaunchTarget += SpellEffectFn(spell_evo_living_flame::HandleLaunchTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 381773 - Permeating Chill
|
||||
class spell_evo_permeating_chill : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_EVOKER_PERMEATING_CHILL_TALENT });
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
SpellInfo const* spellInfo = procInfo.GetSpellInfo();
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
if (!spellInfo->HasLabel(SPELL_LABEL_EVOKER_BLUE))
|
||||
return false;
|
||||
|
||||
if (!procInfo.GetActor()->HasAura(SPELL_EVOKER_PERMEATING_CHILL_TALENT))
|
||||
if (!spellInfo->IsAffected(SPELLFAMILY_EVOKER, { 0x40, 0, 0, 0 })) // disintegrate
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_evo_permeating_chill::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 393568 - Pyre
|
||||
class spell_evo_pyre : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo ({ SPELL_EVOKER_PYRE_DAMAGE });
|
||||
}
|
||||
|
||||
void HandleDamage(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit()->GetPosition(), SPELL_EVOKER_PYRE_DAMAGE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_evo_pyre::HandleDamage, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_evoker_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_evo_azure_strike);
|
||||
RegisterSpellScript(spell_evo_charged_blast);
|
||||
RegisterSpellScript(spell_evo_glide);
|
||||
RegisterSpellScript(spell_evo_living_flame);
|
||||
RegisterSpellScript(spell_evo_permeating_chill);
|
||||
RegisterSpellScript(spell_evo_pyre);
|
||||
}
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Scripts for spells with SPELLFAMILY_MONK and SPELLFAMILY_GENERIC spells used by monk players.
|
||||
* Scriptnames of files in this file should be prefixed with "spell_monk_".
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "Player.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum MonkSpells
|
||||
{
|
||||
SPELL_MONK_CALMING_COALESCENCE = 388220,
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHANNEL = 117952,
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC = 123333,
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK = 117962,
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD = 117953,
|
||||
SPELL_MONK_POWER_STRIKE_PROC = 129914,
|
||||
SPELL_MONK_POWER_STRIKE_ENERGIZE = 121283,
|
||||
SPELL_MONK_PROVOKE_SINGLE_TARGET = 116189,
|
||||
SPELL_MONK_PROVOKE_AOE = 118635,
|
||||
SPELL_MONK_NO_FEATHER_FALL = 79636,
|
||||
SPELL_MONK_OPEN_PALM_STRIKES_TALENT = 392970,
|
||||
SPELL_MONK_ROLL_BACKWARD = 109131,
|
||||
SPELL_MONK_ROLL_FORWARD = 107427,
|
||||
SPELL_MONK_SOOTHING_MIST = 115175,
|
||||
SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE = 154436,
|
||||
SPELL_MONK_STAGGER_DAMAGE_AURA = 124255,
|
||||
SPELL_MONK_STAGGER_HEAVY = 124273,
|
||||
SPELL_MONK_STAGGER_LIGHT = 124275,
|
||||
SPELL_MONK_STAGGER_MODERATE = 124274,
|
||||
SPELL_MONK_SURGING_MIST_HEAL = 116995,
|
||||
};
|
||||
|
||||
// 117952 - Crackling Jade Lightning
|
||||
class spell_monk_crackling_jade_lightning : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE,
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC
|
||||
});
|
||||
}
|
||||
|
||||
void OnTick(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (caster->HasAura(SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE))
|
||||
caster->CastSpell(caster, SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_monk_crackling_jade_lightning::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// 117959 - Crackling Jade Lightning
|
||||
class spell_monk_crackling_jade_lightning_knockback_proc_aura : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK,
|
||||
SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD
|
||||
});
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (GetTarget()->HasAura(SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD))
|
||||
return false;
|
||||
|
||||
if (eventInfo.GetActor()->HasAura(SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHANNEL, GetTarget()->GetGUID()))
|
||||
return false;
|
||||
|
||||
Spell* currentChanneledSpell = GetTarget()->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
|
||||
if (!currentChanneledSpell || currentChanneledSpell->GetSpellInfo()->Id != SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHANNEL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& eventInfo)
|
||||
{
|
||||
GetTarget()->CastSpell(eventInfo.GetActor(), SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK, TRIGGERED_FULL_MASK);
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_monk_crackling_jade_lightning_knockback_proc_aura::CheckProc);
|
||||
OnEffectProc += AuraEffectProcFn(spell_monk_crackling_jade_lightning_knockback_proc_aura::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 116849 - Life Cocoon
|
||||
class spell_monk_life_cocoon : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_CALMING_COALESCENCE });
|
||||
}
|
||||
|
||||
void CalculateAbsorb(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
int32 absorb = GetCaster()->CountPctFromMaxHealth(GetEffectValue());
|
||||
if (Player* player = GetCaster()->ToPlayer())
|
||||
AddPct(absorb, player->GetRatingBonusValue(CR_VERSATILITY_HEALING_DONE));
|
||||
|
||||
if (AuraEffect* calmingCoalescence = GetCaster()->GetAuraEffect(SPELL_MONK_CALMING_COALESCENCE, EFFECT_0, GetCaster()->GetGUID()))
|
||||
{
|
||||
AddPct(absorb, calmingCoalescence->GetAmount());
|
||||
calmingCoalescence->GetBase()->Remove();
|
||||
}
|
||||
|
||||
GetSpell()->SetSpellValue(SPELLVALUE_BASE_POINT0, absorb);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectLaunch += SpellEffectFn(spell_monk_life_cocoon::CalculateAbsorb, EFFECT_2, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 392972 - Open Palm Strikes
|
||||
class spell_monk_open_palm_strikes : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellEffect({ { SPELL_MONK_OPEN_PALM_STRIKES_TALENT, EFFECT_1} });
|
||||
}
|
||||
|
||||
bool CheckProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*procInfo*/)
|
||||
{
|
||||
AuraEffect const* talent = GetTarget()->GetAuraEffect(SPELL_MONK_OPEN_PALM_STRIKES_TALENT, EFFECT_1);
|
||||
return talent && roll_chance_i(talent->GetAmount());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckEffectProc += AuraCheckEffectProcFn(spell_monk_open_palm_strikes::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 121817 - Power Strike
|
||||
class spell_monk_power_strike_periodic : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_POWER_STRIKE_PROC });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_MONK_POWER_STRIKE_PROC, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_monk_power_strike_periodic::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 129914 - Power Strike Proc
|
||||
class spell_monk_power_strike_proc : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_POWER_STRIKE_ENERGIZE });
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_MONK_POWER_STRIKE_ENERGIZE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_monk_power_strike_proc::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 115546 - Provoke
|
||||
class spell_monk_provoke : public SpellScript
|
||||
{
|
||||
static uint32 const BlackOxStatusEntry = 61146;
|
||||
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (!(spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK)) // ensure GetExplTargetUnit() will return something meaningful during CheckCast
|
||||
return false;
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_MONK_PROVOKE_SINGLE_TARGET,
|
||||
SPELL_MONK_PROVOKE_AOE
|
||||
});
|
||||
}
|
||||
|
||||
SpellCastResult CheckExplicitTarget()
|
||||
{
|
||||
if (GetExplTargetUnit()->GetEntry() != BlackOxStatusEntry)
|
||||
{
|
||||
SpellInfo const* singleTarget = sSpellMgr->AssertSpellInfo(SPELL_MONK_PROVOKE_SINGLE_TARGET, GetCastDifficulty());
|
||||
SpellCastResult singleTargetExplicitResult = singleTarget->CheckExplicitTarget(GetCaster(), GetExplTargetUnit());
|
||||
if (singleTargetExplicitResult != SPELL_CAST_OK)
|
||||
return singleTargetExplicitResult;
|
||||
}
|
||||
else if (GetExplTargetUnit()->GetOwnerGUID() != GetCaster()->GetGUID())
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
if (GetHitUnit()->GetEntry() != BlackOxStatusEntry)
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_MONK_PROVOKE_SINGLE_TARGET, true);
|
||||
else
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_MONK_PROVOKE_AOE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_monk_provoke::CheckExplicitTarget);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_monk_provoke::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 109132 - Roll
|
||||
class spell_monk_roll : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_ROLL_BACKWARD, SPELL_MONK_ROLL_FORWARD, SPELL_MONK_NO_FEATHER_FALL });
|
||||
}
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
if (GetCaster()->HasUnitState(UNIT_STATE_ROOT))
|
||||
return SPELL_FAILED_ROOTED;
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetCaster(), GetCaster()->HasUnitMovementFlag(MOVEMENTFLAG_BACKWARD) ? SPELL_MONK_ROLL_BACKWARD : SPELL_MONK_ROLL_FORWARD,
|
||||
TRIGGERED_IGNORE_CAST_IN_PROGRESS);
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_MONK_NO_FEATHER_FALL, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_monk_roll::CheckCast);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_monk_roll::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 107427 - Roll
|
||||
// 109131 - Roll (backward)
|
||||
class spell_monk_roll_aura : public AuraScript
|
||||
{
|
||||
void CalcMovementAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
amount += 100;
|
||||
}
|
||||
|
||||
void CalcImmunityAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
amount -= 100;
|
||||
}
|
||||
|
||||
void ChangeRunBackSpeed(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->SetSpeed(MOVE_RUN_BACK, GetTarget()->GetSpeed(MOVE_RUN));
|
||||
}
|
||||
|
||||
void RestoreRunBackSpeed(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->UpdateSpeed(MOVE_RUN_BACK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
// Values need manual correction
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_monk_roll_aura::CalcMovementAmount, EFFECT_0, SPELL_AURA_MOD_SPEED_NO_CONTROL);
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_monk_roll_aura::CalcMovementAmount, EFFECT_2, SPELL_AURA_MOD_MINIMUM_SPEED);
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_monk_roll_aura::CalcImmunityAmount, EFFECT_5, SPELL_AURA_MECHANIC_IMMUNITY);
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_monk_roll_aura::CalcImmunityAmount, EFFECT_6, SPELL_AURA_MECHANIC_IMMUNITY);
|
||||
|
||||
// This is a special aura that sets backward run speed equal to forward speed
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_monk_roll_aura::ChangeRunBackSpeed, EFFECT_4, SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectApplyFn(spell_monk_roll_aura::RestoreRunBackSpeed, EFFECT_4, SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// Utility for stagger scripts
|
||||
Aura* FindExistingStaggerEffect(Unit* unit)
|
||||
{
|
||||
if (Aura* auraLight = unit->GetAura(SPELL_MONK_STAGGER_LIGHT))
|
||||
return auraLight;
|
||||
|
||||
if (Aura* auraModerate = unit->GetAura(SPELL_MONK_STAGGER_MODERATE))
|
||||
return auraModerate;
|
||||
|
||||
if (Aura* auraHeavy = unit->GetAura(SPELL_MONK_STAGGER_HEAVY))
|
||||
return auraHeavy;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static constexpr SpellEffIndex AuraStaggerEffectTick = EFFECT_0;
|
||||
static constexpr SpellEffIndex AuraStaggerEffectTotal = EFFECT_1;
|
||||
|
||||
// 115069 - Stagger
|
||||
class spell_monk_stagger : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_STAGGER_LIGHT, SPELL_MONK_STAGGER_MODERATE, SPELL_MONK_STAGGER_HEAVY });
|
||||
}
|
||||
|
||||
void AbsorbNormal(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
|
||||
{
|
||||
Absorb(dmgInfo, 1.0f);
|
||||
}
|
||||
|
||||
void AbsorbMagic(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
|
||||
{
|
||||
AuraEffect const* effect = GetEffect(EFFECT_4);
|
||||
if (!effect)
|
||||
return;
|
||||
|
||||
Absorb(dmgInfo, float(effect->GetAmount()) / 100.0f);
|
||||
}
|
||||
|
||||
void Absorb(DamageInfo& dmgInfo, float multiplier)
|
||||
{
|
||||
// Prevent default action (which would remove the aura)
|
||||
PreventDefaultAction();
|
||||
|
||||
// make sure damage doesn't come from stagger damage spell SPELL_MONK_STAGGER_DAMAGE_AURA
|
||||
if (SpellInfo const* dmgSpellInfo = dmgInfo.GetSpellInfo())
|
||||
if (dmgSpellInfo->Id == SPELL_MONK_STAGGER_DAMAGE_AURA)
|
||||
return;
|
||||
|
||||
AuraEffect const* effect = GetEffect(AuraStaggerEffectTick);
|
||||
if (!effect)
|
||||
return;
|
||||
|
||||
Unit* target = GetTarget();
|
||||
float agility = target->GetStat(STAT_AGILITY);
|
||||
float base = CalculatePct(agility, float(effect->GetAmount()));
|
||||
float K = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::ArmorConstant, target->GetLevel(), -2, 0, Classes(target->GetClass()), 0);
|
||||
|
||||
float newAmount = (base / (base + K));
|
||||
newAmount *= multiplier;
|
||||
|
||||
// Absorb X percentage of the damage
|
||||
float absorbAmount = float(dmgInfo.GetDamage()) * newAmount;
|
||||
if (absorbAmount > 0)
|
||||
{
|
||||
dmgInfo.AbsorbDamage(absorbAmount);
|
||||
|
||||
// Cast stagger and make it tick on each tick
|
||||
AddAndRefreshStagger(absorbAmount);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectAbsorb += AuraEffectAbsorbFn(spell_monk_stagger::AbsorbNormal, EFFECT_1);
|
||||
OnEffectAbsorb += AuraEffectAbsorbFn(spell_monk_stagger::AbsorbMagic, EFFECT_2);
|
||||
}
|
||||
|
||||
private:
|
||||
void AddAndRefreshStagger(float amount)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (Aura* auraStagger = FindExistingStaggerEffect(target))
|
||||
{
|
||||
AuraEffect* effStaggerRemaining = auraStagger->GetEffect(AuraStaggerEffectTotal);
|
||||
if (!effStaggerRemaining)
|
||||
return;
|
||||
|
||||
float newAmount = effStaggerRemaining->GetAmount() + amount;
|
||||
uint32 spellId = GetStaggerSpellId(target, newAmount);
|
||||
if (spellId == effStaggerRemaining->GetSpellInfo()->Id)
|
||||
{
|
||||
auraStagger->RefreshDuration();
|
||||
effStaggerRemaining->ChangeAmount(newAmount, false, true /* reapply */);
|
||||
}
|
||||
else
|
||||
{
|
||||
// amount changed the stagger type so we need to change the stagger amount (e.g. from medium to light)
|
||||
GetTarget()->RemoveAura(auraStagger);
|
||||
AddNewStagger(target, spellId, newAmount);
|
||||
}
|
||||
}
|
||||
else
|
||||
AddNewStagger(target, GetStaggerSpellId(target, amount), amount);
|
||||
}
|
||||
|
||||
uint32 GetStaggerSpellId(Unit* unit, float amount)
|
||||
{
|
||||
const float StaggerHeavy = 0.6f;
|
||||
const float StaggerModerate = 0.3f;
|
||||
|
||||
float staggerPct = amount / float(unit->GetMaxHealth());
|
||||
return (staggerPct >= StaggerHeavy) ? SPELL_MONK_STAGGER_HEAVY :
|
||||
(staggerPct >= StaggerModerate) ? SPELL_MONK_STAGGER_MODERATE :
|
||||
SPELL_MONK_STAGGER_LIGHT;
|
||||
}
|
||||
|
||||
void AddNewStagger(Unit* unit, uint32 staggerSpellId, float staggerAmount)
|
||||
{
|
||||
// We only set the total stagger amount. The amount per tick will be set by the stagger spell script
|
||||
unit->CastSpell(unit, staggerSpellId, CastSpellExtraArgs(SPELLVALUE_BASE_POINT1, staggerAmount).SetTriggerFlags(TRIGGERED_FULL_MASK));
|
||||
}
|
||||
};
|
||||
|
||||
// 124255 - Stagger - SPELL_MONK_STAGGER_DAMAGE_AURA
|
||||
class spell_monk_stagger_damage_aura : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_STAGGER_LIGHT, SPELL_MONK_STAGGER_MODERATE, SPELL_MONK_STAGGER_HEAVY });
|
||||
}
|
||||
|
||||
void OnPeriodicDamage(AuraEffect const* aurEff)
|
||||
{
|
||||
// Update our light/medium/heavy stagger with the correct stagger amount left
|
||||
if (Aura* auraStagger = FindExistingStaggerEffect(GetTarget()))
|
||||
{
|
||||
if (AuraEffect* auraEff = auraStagger->GetEffect(AuraStaggerEffectTotal))
|
||||
{
|
||||
float total = float(auraEff->GetAmount());
|
||||
float tickDamage = float(aurEff->GetAmount());
|
||||
auraEff->ChangeAmount(total - tickDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_monk_stagger_damage_aura::OnPeriodicDamage, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// 124273, 124274, 124275 - Light/Moderate/Heavy Stagger - SPELL_MONK_STAGGER_LIGHT / SPELL_MONK_STAGGER_MODERATE / SPELL_MONK_STAGGER_HEAVY
|
||||
class spell_monk_stagger_debuff_aura : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MONK_STAGGER_DAMAGE_AURA })
|
||||
&& ValidateSpellEffect({ { SPELL_MONK_STAGGER_DAMAGE_AURA, EFFECT_0 } });
|
||||
}
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
_period = float(sSpellMgr->AssertSpellInfo(SPELL_MONK_STAGGER_DAMAGE_AURA, GetCastDifficulty())->GetEffect(EFFECT_0).ApplyAuraPeriod);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnReapply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
// Calculate damage per tick
|
||||
float total = float(aurEff->GetAmount());
|
||||
float perTick = total * _period / float(GetDuration()); // should be same as GetMaxDuration() TODO: verify
|
||||
|
||||
// Set amount on effect for tooltip
|
||||
AuraEffect* effInfo = GetAura()->GetEffect(AuraStaggerEffectTick);
|
||||
if (effInfo)
|
||||
effInfo->ChangeAmount(perTick);
|
||||
|
||||
// Set amount on damage aura (or cast it if needed)
|
||||
CastOrChangeTickDamage(perTick);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes mode)
|
||||
{
|
||||
if (mode != AURA_EFFECT_HANDLE_REAL)
|
||||
return;
|
||||
|
||||
// Remove damage aura
|
||||
GetTarget()->RemoveAura(SPELL_MONK_STAGGER_DAMAGE_AURA);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectRemoveFn(spell_monk_stagger_debuff_aura::OnReapply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_monk_stagger_debuff_aura::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
|
||||
private:
|
||||
float _period = 0.0f;
|
||||
|
||||
void CastOrChangeTickDamage(float tickDamage)
|
||||
{
|
||||
Unit* unit = GetTarget();
|
||||
Aura* auraDamage = unit->GetAura(SPELL_MONK_STAGGER_DAMAGE_AURA);
|
||||
if (!auraDamage)
|
||||
{
|
||||
unit->CastSpell(unit, SPELL_MONK_STAGGER_DAMAGE_AURA, true);
|
||||
auraDamage = unit->GetAura(SPELL_MONK_STAGGER_DAMAGE_AURA);
|
||||
}
|
||||
|
||||
if (auraDamage)
|
||||
if (AuraEffect* eff = auraDamage->GetEffect(AuraStaggerEffectTick))
|
||||
eff->ChangeAmount(tickDamage);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_monk_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_monk_crackling_jade_lightning);
|
||||
RegisterSpellScript(spell_monk_crackling_jade_lightning_knockback_proc_aura);
|
||||
RegisterSpellScript(spell_monk_life_cocoon);
|
||||
RegisterSpellScript(spell_monk_open_palm_strikes);
|
||||
RegisterSpellScript(spell_monk_power_strike_periodic);
|
||||
RegisterSpellScript(spell_monk_power_strike_proc);
|
||||
RegisterSpellScript(spell_monk_provoke);
|
||||
RegisterSpellScript(spell_monk_roll);
|
||||
RegisterSpellScript(spell_monk_roll_aura);
|
||||
RegisterSpellScript(spell_monk_stagger);
|
||||
RegisterSpellScript(spell_monk_stagger_damage_aura);
|
||||
RegisterSpellScript(spell_monk_stagger_debuff_aura);
|
||||
}
|
||||
@@ -17,13 +17,10 @@
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_deathknight_spell_scripts();
|
||||
void AddSC_demon_hunter_spell_scripts();
|
||||
void AddSC_druid_spell_scripts();
|
||||
void AddSC_evoker_spell_scripts();
|
||||
void AddSC_generic_spell_scripts();
|
||||
void AddSC_hunter_spell_scripts();
|
||||
void AddSC_mage_spell_scripts();
|
||||
void AddSC_monk_spell_scripts();
|
||||
void AddSC_paladin_spell_scripts();
|
||||
void AddSC_priest_spell_scripts();
|
||||
void AddSC_rogue_spell_scripts();
|
||||
@@ -32,20 +29,16 @@ void AddSC_warlock_spell_scripts();
|
||||
void AddSC_warrior_spell_scripts();
|
||||
void AddSC_quest_spell_scripts();
|
||||
void AddSC_item_spell_scripts();
|
||||
void AddSC_azerite_item_spell_scripts();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddSpellsScripts()
|
||||
{
|
||||
AddSC_deathknight_spell_scripts();
|
||||
AddSC_demon_hunter_spell_scripts();
|
||||
AddSC_druid_spell_scripts();
|
||||
AddSC_evoker_spell_scripts();
|
||||
AddSC_generic_spell_scripts();
|
||||
AddSC_hunter_spell_scripts();
|
||||
AddSC_mage_spell_scripts();
|
||||
AddSC_monk_spell_scripts();
|
||||
AddSC_paladin_spell_scripts();
|
||||
AddSC_priest_spell_scripts();
|
||||
AddSC_rogue_spell_scripts();
|
||||
@@ -54,5 +47,4 @@ void AddSpellsScripts()
|
||||
AddSC_warrior_spell_scripts();
|
||||
AddSC_quest_spell_scripts();
|
||||
AddSC_item_spell_scripts();
|
||||
AddSC_azerite_item_spell_scripts();
|
||||
}
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "underrot.h"
|
||||
|
||||
enum CragmawSpells
|
||||
{
|
||||
// Cragmaw
|
||||
SPELL_CRAWG_EATING = 279156,
|
||||
SPELL_POWER_DISPLAY_TANTRUM = 271771,
|
||||
SPELL_POWER_ENERGIZE_TANTRUM = 271775,
|
||||
SPELL_CHARGE_SELECTOR = 260292,
|
||||
SPELL_INDIGESTION = 260793,
|
||||
SPELL_TANTRUM_INITIAL = 260333,
|
||||
|
||||
// Larva
|
||||
SPELL_DESTROY_LARVA = 260418,
|
||||
SPELL_METAMORPHOSIS_2 = 260766,
|
||||
SPELL_SUMMON_BLOOD_TICK = 260353,
|
||||
SPELL_SUMMON_BLOOD_TICK_VISUAL = 260496,
|
||||
|
||||
// Blood Tick
|
||||
SPELL_BLOOD_BURST_DAMAGE = 278637,
|
||||
SPELL_SERRATED_FANGS = 260455,
|
||||
|
||||
// Fetid Maggot
|
||||
SPELL_FEIGN_DEATH = 159474
|
||||
};
|
||||
|
||||
enum CragmawEvents
|
||||
{
|
||||
// Cragmaw
|
||||
EVENT_CHARGE_SELECTOR = 1,
|
||||
EVENT_INDIGESTION,
|
||||
EVENT_NORMAL_REQUEUE,
|
||||
EVENT_CHECK_ENERGY_TANTRUM,
|
||||
|
||||
// Blood Tick
|
||||
EVENT_SERRATED_FANGS = 1
|
||||
};
|
||||
|
||||
enum CragmawPoints
|
||||
{
|
||||
POINT_TANTRUM_START_RND_MOVEMENT = 0
|
||||
};
|
||||
|
||||
enum CragmawNPC
|
||||
{
|
||||
NPC_FETID_MAGGOT = 130909
|
||||
};
|
||||
|
||||
Position const FetidMaggotSpawn = { 857.864f, 984.981f, 39.231f, 4.68147f };
|
||||
|
||||
// 131817 - Cragmaw the Infested
|
||||
struct boss_cragmaw_the_infested : public BossAI
|
||||
{
|
||||
boss_cragmaw_the_infested(Creature* creature) : BossAI(creature, DATA_CRAGMAW_THE_INFESTED) { }
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
me->SetPowerType(POWER_ENERGY);
|
||||
DoCast(SPELL_POWER_DISPLAY_TANTRUM);
|
||||
|
||||
if (instance->GetData(DATA_CRAGMAW_CRAWG_EATING))
|
||||
return;
|
||||
|
||||
DoCastSelf(SPELL_CRAWG_EATING);
|
||||
me->SetEmoteState(EMOTE_STATE_EAT);
|
||||
if (TempSummon* summon = me->SummonCreature(NPC_FETID_MAGGOT, FetidMaggotSpawn))
|
||||
{
|
||||
_fetidMaggotGuid = summon->GetGUID();
|
||||
summon->CastSpell(nullptr, SPELL_FEIGN_DEATH, true);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
summons.DespawnAll();
|
||||
_EnterEvadeMode();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void ScheduleSpells()
|
||||
{
|
||||
events.Reset();
|
||||
|
||||
if (GetDifficulty() == DIFFICULTY_NORMAL)
|
||||
events.ScheduleEvent(EVENT_NORMAL_REQUEUE, 45s);
|
||||
|
||||
if (urand(0, 1) == 0)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_CHARGE_SELECTOR, 9s);
|
||||
events.ScheduleEvent(EVENT_INDIGESTION, 20s);
|
||||
events.ScheduleEvent(EVENT_CHARGE_SELECTOR, 33s);
|
||||
}
|
||||
else
|
||||
{
|
||||
events.ScheduleEvent(EVENT_INDIGESTION, 9s);
|
||||
events.ScheduleEvent(EVENT_CHARGE_SELECTOR, 21s);
|
||||
events.ScheduleEvent(EVENT_CHARGE_SELECTOR, 41s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
instance->SetData(DATA_CRAGMAW_CRAWG_EATING, 1);
|
||||
ScheduleSpells();
|
||||
events.ScheduleEvent(EVENT_CHECK_ENERGY_TANTRUM, 500ms);
|
||||
|
||||
if (Creature* fetidMaggot = ObjectAccessor::GetCreature(*me, _fetidMaggotGuid))
|
||||
fetidMaggot->DespawnOrUnsummon();
|
||||
|
||||
if (IsHeroicOrHigher())
|
||||
DoCast(SPELL_POWER_ENERGIZE_TANTRUM);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
if (id == POINT_TANTRUM_START_RND_MOVEMENT)
|
||||
me->GetMotionMaster()->MoveRandom(20.0f);
|
||||
}
|
||||
|
||||
void OnChannelFinished(SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TANTRUM_INITIAL)
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
};
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHARGE_SELECTOR:
|
||||
DoCast(SPELL_CHARGE_SELECTOR);
|
||||
break;
|
||||
case EVENT_INDIGESTION:
|
||||
DoCast(SPELL_INDIGESTION);
|
||||
break;
|
||||
case EVENT_NORMAL_REQUEUE:
|
||||
ScheduleSpells();
|
||||
break;
|
||||
case EVENT_CHECK_ENERGY_TANTRUM:
|
||||
if (me->GetPower(POWER_ENERGY) >= 100)
|
||||
{
|
||||
ScheduleSpells();
|
||||
DoCast(SPELL_TANTRUM_INITIAL);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->MovePoint(POINT_TANTRUM_START_RND_MOVEMENT, me->GetHomePosition());
|
||||
}
|
||||
events.Repeat(500ms);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
ObjectGuid _fetidMaggotGuid;
|
||||
};
|
||||
|
||||
// 132051 - Blood Tick
|
||||
struct npc_cragmaw_blood_tick : public ScriptedAI
|
||||
{
|
||||
npc_cragmaw_blood_tick(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
Creature* cragmaw = me->GetInstanceScript()->GetCreature(DATA_CRAGMAW_THE_INFESTED);
|
||||
if (!cragmaw || !cragmaw->IsAIEnabled())
|
||||
return;
|
||||
|
||||
cragmaw->AI()->JustSummoned(me);
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_SERRATED_FANGS, 1s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasUnitState(UNIT_STATE_STUNNED))
|
||||
return;
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SERRATED_FANGS:
|
||||
DoCastVictim(SPELL_SERRATED_FANGS);
|
||||
_events.ScheduleEvent(EVENT_SERRATED_FANGS, 6s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
// 271775 - Tantrum Energy Bar (periodic)
|
||||
class spell_cragmaw_power_energize_tantrum : public AuraScript
|
||||
{
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
target->SetPower(POWER_ENERGY, target->GetPower(POWER_ENERGY) + 2);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_cragmaw_power_energize_tantrum::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 260411 - Summon Larva
|
||||
class spell_cragmaw_summon_larva : public AuraScript
|
||||
{
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Creature* creature = GetTarget()->ToCreature())
|
||||
creature->DespawnOrUnsummon(300ms);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_cragmaw_summon_larva::OnRemove, EFFECT_0, SPELL_AURA_AREA_TRIGGER, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 260418 - Destroy Larva
|
||||
struct at_cragmaw_destroy_larva : AreaTriggerAI
|
||||
{
|
||||
at_cragmaw_destroy_larva(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (!unit->IsPlayer())
|
||||
return;
|
||||
|
||||
at->GetCaster()->CastSpell(nullptr, SPELL_DESTROY_LARVA, true);
|
||||
}
|
||||
};
|
||||
|
||||
// 260416 - Metamorphosis
|
||||
class spell_cragmaw_larva_metamorphosis : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_SUMMON_BLOOD_TICK,
|
||||
SPELL_SUMMON_BLOOD_TICK_VISUAL,
|
||||
SPELL_METAMORPHOSIS_2
|
||||
});
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (aurEff->GetTickNumber() == aurEff->GetTotalTicks() - 2)
|
||||
GetTarget()->CastSpell(nullptr, SPELL_METAMORPHOSIS_2, true);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
|
||||
return;
|
||||
|
||||
Unit* target = GetTarget();
|
||||
target->CastSpell(nullptr, SPELL_SUMMON_BLOOD_TICK_VISUAL, true);
|
||||
target->CastSpell(target->GetPosition(), SPELL_SUMMON_BLOOD_TICK, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_cragmaw_larva_metamorphosis::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_cragmaw_larva_metamorphosis::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 278641 - Blood Burst
|
||||
class spell_cragmaw_blood_burst : public AuraScript
|
||||
{
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
target->CastSpell(target, SPELL_BLOOD_BURST_DAMAGE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_cragmaw_blood_burst::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_cragmaw_the_infested()
|
||||
{
|
||||
// Creature
|
||||
RegisterUnderrotCreatureAI(boss_cragmaw_the_infested);
|
||||
RegisterUnderrotCreatureAI(npc_cragmaw_blood_tick);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_cragmaw_power_energize_tantrum);
|
||||
RegisterSpellScript(spell_cragmaw_larva_metamorphosis);
|
||||
RegisterSpellScript(spell_cragmaw_blood_burst);
|
||||
RegisterSpellScript(spell_cragmaw_summon_larva);
|
||||
|
||||
// AreaTrigger
|
||||
RegisterAreaTriggerAI(at_cragmaw_destroy_larva);
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "Containers.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "underrot.h"
|
||||
|
||||
enum LeaxaSpells
|
||||
{
|
||||
SPELL_TAINT_OF_GHUUN = 260685,
|
||||
SPELL_BLOOD_BOLT = 260879,
|
||||
SPELL_SANGUINE_FEAST = 264747,
|
||||
SPELL_CREEPING_ROT_SELECTOR = 260889,
|
||||
SPELL_CREEPING_ROT_SUMMON = 260894,
|
||||
SPELL_CREEPING_ROT_SPAWN_VISUAL = 260891,
|
||||
SPELL_CREEPING_ROT_AURA = 261496,
|
||||
SPELL_CREEPING_ROT_PERIODIC_DMG = 261498,
|
||||
SPELL_BLOOD_MIRROR_SELECTOR = 264603,
|
||||
SPELL_BLOOD_MIRROR_MISSILE = 264609
|
||||
};
|
||||
|
||||
enum LeaxaEvents
|
||||
{
|
||||
EVENT_BLOOD_BOLT = 1,
|
||||
EVENT_CREEPING_ROT,
|
||||
EVENT_SANGUINE_FEAST,
|
||||
EVENT_BLOOD_MIRROR
|
||||
};
|
||||
|
||||
enum LeaxaTexts
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SANGUINE_FEAST = 1,
|
||||
SAY_ROT_AND_WITHER = 2,
|
||||
SAY_BLOOD_MIRROR = 3,
|
||||
SAY_ANNOUNCE_BLOOD_MIRROR = 4,
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
|
||||
enum LeaxaAnimKits
|
||||
{
|
||||
ANIMKIT_BLOOD_EFFIGY_DEATH = 9798
|
||||
};
|
||||
|
||||
// 131318 - Elder Leaxa
|
||||
struct boss_elder_leaxa : public BossAI
|
||||
{
|
||||
boss_elder_leaxa(Creature* creature) : BossAI(creature, DATA_ELDER_LEAXA) { }
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
summons.DespawnAll();
|
||||
_EnterEvadeMode();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
me->SetAIAnimKitId(0);
|
||||
events.ScheduleEvent(EVENT_BLOOD_BOLT, 1s);
|
||||
if (IsHeroicOrHigher())
|
||||
events.ScheduleEvent(EVENT_SANGUINE_FEAST, 8s);
|
||||
events.ScheduleEvent(EVENT_CREEPING_ROT, 12s);
|
||||
events.ScheduleEvent(EVENT_BLOOD_MIRROR, 17s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BLOOD_BOLT:
|
||||
DoCastVictim(SPELL_BLOOD_BOLT);
|
||||
events.ScheduleEvent(EVENT_BLOOD_BOLT, 6s);
|
||||
break;
|
||||
case EVENT_SANGUINE_FEAST:
|
||||
Talk(SAY_SANGUINE_FEAST);
|
||||
DoCastAOE(SPELL_SANGUINE_FEAST);
|
||||
events.ScheduleEvent(EVENT_SANGUINE_FEAST, 30s);
|
||||
break;
|
||||
case EVENT_CREEPING_ROT:
|
||||
Talk(SAY_ROT_AND_WITHER);
|
||||
DoCastAOE(SPELL_CREEPING_ROT_SELECTOR);
|
||||
events.ScheduleEvent(EVENT_CREEPING_ROT, 16s);
|
||||
break;
|
||||
case EVENT_BLOOD_MIRROR:
|
||||
Talk(SAY_BLOOD_MIRROR);
|
||||
Talk(SAY_ANNOUNCE_BLOOD_MIRROR);
|
||||
DoCastSelf(SPELL_BLOOD_MIRROR_SELECTOR);
|
||||
events.ScheduleEvent(EVENT_BLOOD_MIRROR, 47s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 134701 - Blood Effigy
|
||||
struct npc_blood_effigy : public ScriptedAI
|
||||
{
|
||||
npc_blood_effigy(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_BLOOD_BOLT, 1s);
|
||||
_events.ScheduleEvent(EVENT_SANGUINE_FEAST, 8s);
|
||||
_events.ScheduleEvent(EVENT_CREEPING_ROT, 12s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->SetAIAnimKitId(ANIMKIT_BLOOD_EFFIGY_DEATH);
|
||||
me->DespawnOrUnsummon(3s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BLOOD_BOLT:
|
||||
DoCastVictim(SPELL_BLOOD_BOLT);
|
||||
_events.ScheduleEvent(EVENT_BLOOD_BOLT, 2s);
|
||||
break;
|
||||
case EVENT_SANGUINE_FEAST:
|
||||
DoCastAOE(SPELL_SANGUINE_FEAST);
|
||||
_events.ScheduleEvent(EVENT_SANGUINE_FEAST, 30s);
|
||||
break;
|
||||
case EVENT_CREEPING_ROT:
|
||||
DoCastAOE(SPELL_CREEPING_ROT_SELECTOR);
|
||||
_events.ScheduleEvent(EVENT_CREEPING_ROT, 16s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
// 132398 - Blood Wave Stalker
|
||||
struct npc_blood_wave_stalker : public ScriptedAI
|
||||
{
|
||||
npc_blood_wave_stalker(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
static constexpr float WALK_DISTANCE = 58.0f;
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCast(SPELL_CREEPING_ROT_AURA);
|
||||
|
||||
float angle = me->GetOrientation();
|
||||
float destX = me->GetPositionX() + WALK_DISTANCE * std::cos(angle);
|
||||
float destY = me->GetPositionY() + WALK_DISTANCE * std::sin(angle);
|
||||
float destZ = me->GetPositionZ();
|
||||
Position walkDest(destX, destY, destZ);
|
||||
|
||||
me->GetMotionMaster()->MovePoint(0, walkDest);
|
||||
}
|
||||
};
|
||||
|
||||
// 264747 - Sanguine Feast
|
||||
class spell_sanguine_feast_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
caster->CastSpell(GetHitUnit(), uint32(GetEffectInfo().CalcValue(caster)));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_sanguine_feast_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 260889 - Creeping Rot
|
||||
class spell_creeping_rot_selector : public SpellScript
|
||||
{
|
||||
static constexpr float SPAWN_DISTANCE = 5.0f;
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
|
||||
// make sure spell is cast towards target and caster looks towards target
|
||||
caster->SetInFront(target);
|
||||
caster->SetFacingToObject(target);
|
||||
|
||||
caster->CastSpell(target, SPELL_CREEPING_ROT_SUMMON);
|
||||
|
||||
float angle = caster->GetOrientation();
|
||||
float destX = caster->GetPositionX() + SPAWN_DISTANCE * std::cos(angle);
|
||||
float destY = caster->GetPositionY() + SPAWN_DISTANCE * std::sin(angle);
|
||||
float destZ = caster->GetPositionZ();
|
||||
Position spawnVisualDest(destX, destY, destZ);
|
||||
caster->CastSpell(spawnVisualDest, SPELL_CREEPING_ROT_SPAWN_VISUAL, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_creeping_rot_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 261496 - Creeping Rot (Aura)
|
||||
class spell_creeping_rot_aura : public AuraScript
|
||||
{
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
|
||||
return;
|
||||
|
||||
Creature* creature = GetTarget()->ToCreature();
|
||||
if (!creature)
|
||||
return;
|
||||
|
||||
creature->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_creeping_rot_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
static Position const MirrorSpawnPositions[] =
|
||||
{
|
||||
{ 879.79865f, 1222.6233f, 56.47815f },
|
||||
{ 856.184f, 1232.5435f, 56.52007f },
|
||||
{ 859.34204f, 1238.0243f, 56.520065f },
|
||||
{ 857.8333f, 1220.6545f, 56.468567f },
|
||||
{ 876.17365f, 1240.2848f, 56.409615f },
|
||||
{ 864.25867f, 1240.5903f, 56.520065f },
|
||||
{ 863.1042f, 1218.0591f, 56.468765f }
|
||||
};
|
||||
|
||||
// 264603 - Blood Mirror
|
||||
class spell_blood_mirror_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_BLOOD_MIRROR_MISSILE });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Position spawnPos = Trinity::Containers::SelectRandomContainerElement(MirrorSpawnPositions);
|
||||
GetCaster()->CastSpell(spawnPos, SPELL_BLOOD_MIRROR_MISSILE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_blood_mirror_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 260879 - Blood Bolt
|
||||
// 264757 - Sanguine Feast
|
||||
// 261498 - Creeping Rot
|
||||
class spell_taint_of_ghuun : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_TAINT_OF_GHUUN });
|
||||
}
|
||||
|
||||
void HandleHit()
|
||||
{
|
||||
InstanceScript* instance = GetHitUnit()->GetInstanceScript();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
Creature* leaxa = instance->GetCreature(DATA_ELDER_LEAXA);
|
||||
if (!leaxa)
|
||||
return;
|
||||
|
||||
leaxa->CastSpell(GetHitUnit(), SPELL_TAINT_OF_GHUUN, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_taint_of_ghuun::HandleHit);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_elder_leaxa()
|
||||
{
|
||||
// Creature
|
||||
RegisterUnderrotCreatureAI(boss_elder_leaxa);
|
||||
RegisterUnderrotCreatureAI(npc_blood_wave_stalker);
|
||||
RegisterUnderrotCreatureAI(npc_blood_effigy);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_sanguine_feast_selector);
|
||||
RegisterSpellScript(spell_creeping_rot_selector);
|
||||
RegisterSpellScript(spell_creeping_rot_aura);
|
||||
RegisterSpellScript(spell_blood_mirror_selector);
|
||||
RegisterSpellScript(spell_taint_of_ghuun);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "AreaBoundary.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "underrot.h"
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ DATA_ELDER_LEAXA, new CircleBoundary(Position(869.502014f, 1230.199951f), 58.0f) },
|
||||
{ DATA_CRAGMAW_THE_INFESTED, new CircleBoundary(Position(852.797974f, 982.133545f), 90.0f) }
|
||||
};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_ELDER_LEAXA, DATA_ELDER_LEAXA },
|
||||
{ BOSS_SPORECALLER_ZANCHA, DATA_SPORECALLER_ZANCHA },
|
||||
{ BOSS_CRAGMAW_THE_INFESTED, DATA_CRAGMAW_THE_INFESTED },
|
||||
{ BOSS_UNBOUND_ABOMINATION, DATA_UNBOUND_ABOMINATION },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_WALL_DOOR_SHORTCUT_ENTRANCE, DATA_SPORECALLER_ZANCHA, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_ELDER_LEAXA, {{ 2111 }} },
|
||||
{ DATA_CRAGMAW_THE_INFESTED, {{ 2112 }} },
|
||||
{ DATA_SPORECALLER_ZANCHA, {{ 2118 }} },
|
||||
{ DATA_UNBOUND_ABOMINATION, {{ 2123 }} },
|
||||
};
|
||||
|
||||
class instance_underrot : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_underrot() : InstanceMapScript(UnderrotScriptName, 1841) { }
|
||||
|
||||
struct instance_underrot_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_underrot_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
LoadBossBoundaries(boundaries);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
|
||||
_cragmawCrawgEating = false;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 dataId) const override
|
||||
{
|
||||
switch (dataId)
|
||||
{
|
||||
case DATA_CRAGMAW_CRAWG_EATING:
|
||||
return _cragmawCrawgEating ? 1 : 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 dataId, uint32 /*value*/) override
|
||||
{
|
||||
switch (dataId)
|
||||
{
|
||||
case DATA_CRAGMAW_CRAWG_EATING:
|
||||
_cragmawCrawgEating = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _cragmawCrawgEating;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_underrot_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_underrot()
|
||||
{
|
||||
new instance_underrot();
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_UNDERROT_H_
|
||||
#define DEF_UNDERROT_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "Underrot"
|
||||
#define UnderrotScriptName "instance_underrot"
|
||||
|
||||
uint32 const EncounterCount = 4;
|
||||
|
||||
enum UnderrotDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_ELDER_LEAXA = 0,
|
||||
DATA_SPORECALLER_ZANCHA,
|
||||
DATA_CRAGMAW_THE_INFESTED,
|
||||
DATA_UNBOUND_ABOMINATION,
|
||||
|
||||
DATA_CRAGMAW_CRAWG_EATING
|
||||
};
|
||||
|
||||
enum UnderrotCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_ELDER_LEAXA = 131318,
|
||||
BOSS_SPORECALLER_ZANCHA = 131383,
|
||||
BOSS_CRAGMAW_THE_INFESTED = 131817,
|
||||
BOSS_UNBOUND_ABOMINATION = 133007
|
||||
};
|
||||
|
||||
enum UnderrotGameObjectIds
|
||||
{
|
||||
GO_PYRAMID_DOOR_UNBOUND_ABOMINATION_ENTRANCE = 296385,
|
||||
GO_WALL_DOOR_SHORTCUT_ENTRANCE = 295356
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetUnderrotAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, UnderrotScriptName);
|
||||
}
|
||||
|
||||
#define RegisterUnderrotCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetUnderrotAI)
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is where scripts' loading functions should be declared:
|
||||
|
||||
// Underrot
|
||||
void AddSC_instance_underrot();
|
||||
void AddSC_boss_elder_leaxa();
|
||||
void AddSC_boss_cragmaw_the_infested();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddZandalarScripts()
|
||||
{
|
||||
// Underrot
|
||||
AddSC_instance_underrot();
|
||||
AddSC_boss_elder_leaxa();
|
||||
AddSC_boss_cragmaw_the_infested();
|
||||
}
|
||||
Reference in New Issue
Block a user