Scripts: dropped most post Cataclysm PvE scripts

This commit is contained in:
Ovahlord
2024-03-13 12:25:37 +01:00
parent 4c5ed71edd
commit 51daca7cbf
51 changed files with 0 additions and 24341 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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");
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
};

View File

@@ -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);
};

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();
}