Tombe de Sargeras : module complet 9/9 boss porte depuis DestinyCoreNew (mudyx)

AVANT : 4 boss etaient des coquilles vides de 28-33 lignes (Hote affige, Jeune fille
de vigilance, Sassz ine, KIL JAEDEN le boss final) et AUCUN boss n etait binde en DB
(ScriptName vides sauf Goroth) -> le raid entier etait decoratif malgre 978 spawns.

APRES : module lignee uwow complet (12 161 lignes, 12 fichiers) transcrit vers nos
APIs en 7 passes de compatibilite (~880 erreurs de compilation resorbees) :
instance script complet (portes, frames, graveyards), 9 encounters scriptes,
trash/evenements, 74 bindings de sorts, ~60 ScriptName de creatures, ATs.

Ajouts CORE reutilisables (compat DestinyCoreNew, prepareront le futur port Antorus) :
- UnitAI : DoCastTopAggro, GetObjectData, hooks no-op (SpellFinishCast,
  OnApplyOrRemoveAura, OnRemoveAuraTarget, OnAreaTriggerDespawn/Cast, OnInterruptCast,
  IsDisableGenerateLoot, GetModifyedData)
- CreatureAI : Talk(guid), Talk(liste aleatoire), ZoneTalk
- ScriptedAI : CheckHomeDistToEvade + alias IsHeroicRaid/IsMythicRaid/IsLfrRaid/
  IsNormalRaid/IsHeroicPlusRaid ; SummonList::GetCreature
- Unit : GetAnyOwner, CastSpellDelay x2 ; Creature : SetReactState(delay), StopAttack
- Map : ApplyOnEveryPlayer, IsHeroicPlusRaid ; GameObject : AddDelayedEvent (m_Events)
- Position : SimplePosXYRelocationByAngle, GenerateNonDuplicatePoints, IsLinesCross
  (reecrit sans G3D::LineSegment2D, absent de notre g3dlite)
- MotionMaster : MoveSmoothFlyPath x2 ; AreaTrigger : GetRadius/SetSphereScale(no-op)/
  isMoving/Despawn/GetProgressCompat ; AreaTriggerAI : IsValidTarget/CalculateSpline

Degradations douces assumees (documentees en commentaire dans le code) :
filtrage de cibles des ATs (IsValidTarget jamais appele par notre moteur), scale
dynamique des zones de Kil jaeden, conversations cinematiques, distribution de loot
personnelle, hooks d interruption/notification d aura, quelques approximations de
roles (SoloQ->ROLE_TANK) et de type de degats.

SQL : sql/sylvania/tomb_of_sargeras_bindings.sql (applique en DB).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-01 22:21:27 +00:00
parent b4b14b591c
commit 69dbb2e657
43 changed files with 12835 additions and 3398 deletions
+17
View File
@@ -23,6 +23,21 @@
class AreaTrigger;
class Unit;
// Moments d action des areatriggers (compat scripts DestinyCoreNew ; notre moteur
// n appelle PAS IsValidTarget : le filtrage de cibles de ces scripts est inactif)
enum AreaTriggerActionMoment
{
AT_ACTION_MOMENT_ENTER = 0x0001,
AT_ACTION_MOMENT_LEAVE = 0x0002,
AT_ACTION_MOMENT_UPDATE_TARGET = 0x0004,
AT_ACTION_MOMENT_DESPAWN = 0x0008,
AT_ACTION_MOMENT_SPAWN = 0x0010,
AT_ACTION_MOMENT_REMOVE = 0x0020,
AT_ACTION_MOMENT_ON_THE_WAY = 0x0040,
AT_ACTION_MOMENT_ON_STOP_MOVE = 0x0080,
};
class TC_GAME_API AreaTriggerAI
{
protected:
@@ -63,6 +78,8 @@ class TC_GAME_API AreaTriggerAI
// Called when the AreaTrigger is update target
virtual void ActionOnUpdate(GuidList& affectedPlayers) {}
virtual bool IsValidTarget(Unit* /*caster*/, Unit* /*target*/, AreaTriggerActionMoment /*actionM*/) { return true; }
virtual bool CalculateSpline(Position const* /*pos*/, Position& /*startPos*/, Position& /*endPos*/, std::vector<Position>& /*path*/) { return false; }
};
class NullAreaTriggerAI : public AreaTriggerAI
+6
View File
@@ -194,6 +194,12 @@ void UnitAI::DoCastVictim(uint32 spellId, bool triggered)
me->CastSpell(me->GetVictim(), spellId, triggered);
}
void UnitAI::DoCastTopAggro(uint32 spellId, bool triggered, bool onlyPlayer /*= true*/)
{
if (Unit* victim = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 100.0f, onlyPlayer))
me->CastSpell(victim, spellId, triggered);
}
void UnitAI::DoCastAOE(uint32 spellId, bool triggered)
{
if (!triggered && me->HasUnitState(UNIT_STATE_CASTING))
+13
View File
@@ -23,6 +23,7 @@
#include "EventMap.h"
#include "ObjectGuid.h"
#include "ThreatManager.h"
#include "SpellAuraDefines.h"
#define CAST_AI(a, b) (dynamic_cast<a*>(b))
#define ENSURE_AI(a,b) (EnsureAI<a>(b))
@@ -224,6 +225,17 @@ class TC_GAME_API UnitAI
// Note: it for recalculation damage or special reaction at damage
// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
virtual void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) { }
// Hook generique guid->bool utilise par les scripts portes de DestinyCoreNew (uwow)
virtual bool GetObjectData(ObjectGuid const& /*guid*/, uint32 /*type*/) { return false; }
// Hooks de notification uwow : notre moteur ne les appelle pas (code mort tolere)
virtual void SpellFinishCast(SpellInfo const* /*spell*/) { }
virtual void OnApplyOrRemoveAura(uint32 /*spellId*/, AuraRemoveMode /*mode*/, bool /*apply*/) { }
virtual void OnRemoveAuraTarget(Unit* /*target*/, uint32 /*spellId*/, AuraRemoveMode /*mode*/) { }
virtual bool IsDisableGenerateLoot() { return false; }
virtual uint32 GetModifyedData(uint32 /*type*/) { return 0; }
virtual void OnAreaTriggerDespawn(uint32 /*spellId*/, Position /*pos*/, bool /*duration*/) { }
virtual void OnAreaTriggerCast(Unit* /*caster*/, Unit* /*target*/, uint32 /*spellId*/, uint32 /*atEntry*/) { }
virtual void OnInterruptCast(Unit* /*caster*/, uint32 /*spellId*/, uint32 /*curSpellID*/, uint32 /*schoolMask*/) { }
// Called when the creature receives heal
virtual void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) { }
@@ -242,6 +254,7 @@ class TC_GAME_API UnitAI
void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false);
void DoCastSelf(uint32 spellId, bool triggered = false) { DoCast(me, spellId, triggered); }
void DoCastVictim(uint32 spellId, bool triggered = false);
void DoCastTopAggro(uint32 spellId, bool triggered = false, bool onlyPlayer = true);
void DoCastAOE(uint32 spellId, bool triggered = false);
void DoCastRandom(uint32 spellId, float dist, bool triggered = false, int32 aura = 0, uint32 position = 0);
+21
View File
@@ -439,3 +439,24 @@ void CreatureAI::SetFlyMode(bool fly)
else
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);
}
void CreatureAI::Talk(uint8 id, ObjectGuid whisperGuid)
{
WorldObject const* target = nullptr;
if (!whisperGuid.IsEmpty())
target = ObjectAccessor::GetUnit(*me, whisperGuid);
Talk(id, target);
}
void CreatureAI::Talk(std::initializer_list<uint8> ids, ObjectGuid whisperGuid /*= ObjectGuid::Empty*/)
{
if (ids.size() == 0)
return;
uint8 id = *(ids.begin() + urand(0, uint32(ids.size()) - 1));
Talk(id, whisperGuid);
}
void CreatureAI::ZoneTalk(uint8 id)
{
sCreatureTextMgr->SendChat(me, id, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE);
}
+4
View File
@@ -19,6 +19,7 @@
#define CREATUREAI_H
#include "UnitAI.h"
#include <initializer_list>
#include "Common.h"
#include "ObjectDefines.h"
@@ -100,6 +101,9 @@ class TC_GAME_API CreatureAI : public UnitAI
virtual ~CreatureAI();
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr);
void Talk(uint8 id, ObjectGuid whisperGuid); // compat DestinyCoreNew
void ZoneTalk(uint8 id); // texte a toute la zone
void Talk(std::initializer_list<uint8> ids, ObjectGuid whisperGuid = ObjectGuid::Empty); // choix aleatoire
void AddDelayedEvent(uint64 timeOffset, std::function<void()>&& function);
void KillAllDelayedEvents();
@@ -1641,3 +1641,48 @@ void ScriptedAI::GetTalkData(uint32 eventId)
}
}
bool ScriptedAI::CheckHomeDistToEvade(uint32 diff, float dist, float x, float y, float z, bool onlyZ)
{
if (!me->IsInCombat())
return false;
bool evade = false;
if (_checkHomeTimer <= diff)
{
_checkHomeTimer = 1500;
if (onlyZ)
{
if ((me->GetPositionZ() > z + dist) || (me->GetPositionZ() < z - dist))
evade = true;
}
else if (x != 0.0f || y != 0.0f || z != 0.0f)
{
if (me->GetDistance(x, y, z) >= dist)
evade = true;
}
else if (me->GetDistance(me->GetHomePosition()) >= dist)
evade = true;
if (evade)
{
EnterEvadeMode();
return true;
}
}
else
_checkHomeTimer -= diff;
return false;
}
Creature* SummonList::GetCreature(uint32 entry)
{
for (auto const& guid : *this)
if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
if (summon->GetEntry() == entry)
return summon;
return nullptr;
}
@@ -86,6 +86,7 @@ public:
void Summon(Creature const* summon);
void Despawn(Creature const* summon);
Creature* GetCreature(uint32 entry);
void DespawnEntry(uint32 entry);
void DespawnAll();
@@ -347,6 +348,14 @@ struct TC_GAME_API ScriptedAI : public CreatureAI
// - for raid in mode 25-heroic
// DO NOT USE to check raid in mode 25-normal.
bool IsHeroic() const { return _isHeroic; }
bool IsHeroicRaid() const { return IsHeroic(); }
bool IsHeroicPlusRaid() const { return IsHeroic() || me->GetMap()->IsMythic(); }
bool IsMythicRaid() const { return me->GetMap()->IsMythic(); }
bool IsLfrRaid() const { return _difficulty == DIFFICULTY_LFR || _difficulty == DIFFICULTY_LFR_NEW; }
bool IsNormalRaid() const { return _difficulty == DIFFICULTY_NORMAL_RAID; }
// Evade si trop loin du point d ancrage (helper des scripts portes de DestinyCoreNew)
bool CheckHomeDistToEvade(uint32 diff, float dist = 0.0f, float x = 0.0f, float y = 0.0f, float z = 0.0f, bool onlyZ = false);
uint32 _checkHomeTimer = 1500;
// return the dungeon or raid difficulty
Difficulty GetDifficulty() const { return _difficulty; }
@@ -1001,3 +1001,10 @@ void AreaTrigger::AI_Destroy()
{
_ai.reset();
}
float AreaTrigger::GetRadius() const
{
if (AreaTriggerTemplate const* t = GetTemplate())
return t->MaxSearchRadius;
return 0.0f;
}
@@ -80,6 +80,13 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
AreaTriggerMiscTemplate const* GetMiscTemplate() const { return _areaTriggerMiscTemplate; }
AreaTriggerTemplate const* GetTemplate() const;
// compat DestinyCoreNew : rayon courant approxime par le rayon du template ;
// l animation de scale dynamique n est pas supportee par notre moteur (no-op)
float GetRadius() const;
void SetSphereScale(float /*scale*/, uint32 /*time*/ = 0, bool /*grow*/ = false) { }
bool isMoving() const { return false; } // compat : pas de suivi spline expose
void Despawn() { Remove(); }
float GetProgressCompat() const { return GetProgress(); }
ObjectGuid::LowType GetSpawnId() const { return _spawnId; }
uint32 GetScriptId() const;
@@ -3327,3 +3327,23 @@ void Creature::ReLoad(bool skipDB)
TC_LOG_DEBUG("sql.sql", "Creature SpawnID (" SI64FMTD ") reloaded.", GetSpawnId());
}
void Creature::SetReactState(ReactStates st, uint32 delay)
{
if (!delay)
{
SetReactState(st);
return;
}
AddDelayedEvent(delay, [this, st]() -> void { SetReactState(st); });
}
void Creature::StopAttack(bool clearMove /*= false*/, bool interruptSpells /*= false*/)
{
SetReactState(REACT_PASSIVE);
AttackStop();
if (clearMove)
GetMotionMaster()->Clear();
if (interruptSpells)
InterruptNonMeleeSpells(false);
}
@@ -106,6 +106,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool CanFly() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_AIR) != 0; }
void SetReactState(ReactStates st) { m_reactState = st; }
void SetReactState(ReactStates st, uint32 delay); // variante differee (compat DestinyCoreNew)
void StopAttack(bool clearMove = false, bool interruptSpells = false);
ReactStates GetReactState() const { return m_reactState; }
bool HasReactState(ReactStates state) const { return (m_reactState == state); }
void InitializeReactState();
@@ -300,6 +300,18 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
/// Event handler
EventProcessor m_Events;
// compat DestinyCoreNew : evenement differe via m_Events (mis a jour dans GameObject::Update)
void AddDelayedEvent(uint64 timeOffset, std::function<void()>&& function)
{
class LambdaEvent : public BasicEvent
{
std::function<void()> _fn;
public:
explicit LambdaEvent(std::function<void()>&& fn) : _fn(std::move(fn)) { }
bool Execute(uint64, uint32) override { _fn(); return true; }
};
m_Events.AddEvent(new LambdaEvent(std::move(function)), m_Events.CalculateTime(timeOffset));
}
uint32 GetWorldEffectID() const { return _worldEffectID; }
void SetWorldEffectID(uint32 worldEffectID) { _worldEffectID = worldEffectID; }
@@ -16,6 +16,7 @@
*/
#include "Position.h"
#include <cmath>
#include "ByteBuffer.h"
#include "GridDefines.h"
#include "Random.h"
@@ -279,3 +280,73 @@ ByteBuffer& operator<<(ByteBuffer& buf, Position::ConstStreamer<Position::Packed
buf.appendPackXYZ(streamer.Pos->GetPositionX(), streamer.Pos->GetPositionY(), streamer.Pos->GetPositionZ());
return buf;
}
void Position::SimplePosXYRelocationByAngle(Position& pos, float dist, float angle, bool relative /*= false*/) const
{
if (!relative)
angle += GetOrientation();
pos.m_positionX = m_positionX + dist * std::cos(angle);
pos.m_positionY = m_positionY + dist * std::sin(angle);
pos.m_positionZ = m_positionZ;
if (!Trinity::IsValidMapCoord(pos.m_positionX, pos.m_positionY))
{
pos.Relocate(this);
return;
}
Trinity::NormalizeMapCoord(pos.m_positionX);
Trinity::NormalizeMapCoord(pos.m_positionY);
pos.SetOrientation(GetOrientation());
}
void Position::GenerateNonDuplicatePoints(std::list<Position>& randPosList, Position const& centerPos, uint8 maxPoint, float randMin, float randMax, float minDist) const
{
Position pos;
uint8 traiCount = 0;
while (randPosList.size() < maxPoint)
{
bool badPos = false;
centerPos.SimplePosXYRelocationByAngle(pos, frand(randMin, randMax), frand(0.0f, 6.28f));
++traiCount;
for (auto const& _pos : randPosList)
{
if (pos.GetExactDist(&_pos) <= minDist)
{
badPos = true;
break;
}
}
if (!badPos || traiCount > uint8(maxPoint * 10))
randPosList.push_back(pos);
}
}
bool Position::IsLinesCross(Position const& pos11, Position const& pos12, Position const& pos21, Position const& pos22, Position* dest /*= nullptr*/) const
{
// intersection parametrique de deux segments 2D (sans G3D::LineSegment2D, absent de notre g3dlite)
float x1 = pos11.GetPositionX(), y1 = pos11.GetPositionY();
float x2 = pos12.GetPositionX(), y2 = pos12.GetPositionY();
float x3 = pos21.GetPositionX(), y3 = pos21.GetPositionY();
float x4 = pos22.GetPositionX(), y4 = pos22.GetPositionY();
float denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (std::fabs(denom) < 1e-6f)
return false; // paralleles ou colineaires
float t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
float u = ((x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2)) / denom;
if (t < 0.0f || t > 1.0f || u < 0.0f || u > 1.0f)
return false; // intersection hors des segments
if (dest)
{
dest->m_positionX = x1 + t * (x2 - x1);
dest->m_positionY = y1 + t * (y2 - y1);
}
return true;
}
@@ -19,6 +19,7 @@
#define Trinity_game_Position_h__
#include "Define.h"
#include <list>
#include <string>
#include <cmath>
#include <G3D/Vector3.h>
@@ -103,6 +104,9 @@ public:
float GetPositionY() const { return m_positionY; }
float GetPositionZ() const { return m_positionZ; }
float GetOrientation() const { return m_orientation; }
void SimplePosXYRelocationByAngle(Position& pos, float dist, float angle, bool relative = false) const;
void GenerateNonDuplicatePoints(std::list<Position>& randPosList, Position const& centerPos, uint8 maxPoint, float randMin, float randMax, float minDist) const;
bool IsLinesCross(Position const& pos11, Position const& pos12, Position const& pos21, Position const& pos22, Position* dest = nullptr) const;
void GetPosition(float &x, float &y) const
{
+42
View File
@@ -15214,3 +15214,45 @@ void Unit::EmoteWithDelay(uint32 Delay, uint8 Id)
m_Events.AddEvent(new EmoteWithDelay(this, Id, Delay), m_Events.CalculateTime(Delay));
}
void Unit::CastSpellDelay(Unit* victim, uint32 spellId, bool triggered, uint32 delay, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
{
if (m_cleanupDone)
return;
ObjectGuid targetGUID = victim->GetGUID();
AddDelayedCombat(delay, [this, spellId, triggered, castItem, triggeredByAura, originalCaster, targetGUID]() -> void
{
Unit* target = ObjectAccessor::GetUnit(*this, targetGUID);
if (!target)
return;
CastSpell(target, spellId, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
});
}
void Unit::CastSpellDelay(Position pos, uint32 spellId, bool triggered, uint32 delay)
{
if (m_cleanupDone)
return;
if (!delay)
CastSpell(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), spellId, triggered);
else
AddDelayedCombat(delay, [this, pos, spellId, triggered]() -> void
{
CastSpell(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), spellId, triggered);
});
}
Unit* Unit::GetAnyOwner() const
{
if (GetCharmerGUID())
return GetCharmer();
if (ToTempSummon())
return ToTempSummon()->GetSummoner();
if (GetOwner())
return GetOwner();
return nullptr;
}
+4
View File
@@ -1426,6 +1426,7 @@ class TC_GAME_API Unit : public WorldObject
BrawlersGuild* GetBrawlerGuild();
Unit* GetOwner() const;
Unit* GetAnyOwner() const; // charmeur > summoner > owner (compat DestinyCoreNew)
Guardian* GetGuardianPet() const;
Minion* GetFirstMinion() const;
Unit* GetCharmer() const;
@@ -1702,6 +1703,9 @@ class TC_GAME_API Unit : public WorldObject
m_Functions.KillAllFunctions();
}
// Cast differe (helpers des scripts portes de DestinyCoreNew)
void CastSpellDelay(Unit* victim, uint32 spellId, bool triggered, uint32 delay, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
void CastSpellDelay(Position pos, uint32 spellId, bool triggered, uint32 delay);
void AddDelayedCombat(uint64 timeOffset, std::function<void()>&& function)
{
m_CombatFunctions.AddDelayedEvent(timeOffset, std::move(function));
+12
View File
@@ -4702,3 +4702,15 @@ void Map::UpdateAreaDependentAuras()
if (player->IsInWorld())
player->UpdateAreaDependentAuras();
}
void Map::ApplyOnEveryPlayer(std::function<void(Player*)> function)
{
auto const& players = GetPlayers();
if (players.isEmpty())
return;
for (auto const& itr : players)
if (Player* player = itr.GetSource())
if (player->IsInWorld() && player->GetMap() == this)
function(player);
}
+3
View File
@@ -32,6 +32,7 @@
#include <bitset>
#include <list>
#include <memory>
#include <functional>
#include <mutex>
#include <set>
#include <unordered_set>
@@ -416,6 +417,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
bool IsMythic() const;
bool Is25ManRaid() const;
bool IsLFR() const;
bool IsHeroicPlusRaid() const { return IsHeroic() || IsMythic(); }
bool IsChallengeMode() const;
bool IsBattleground() const;
bool IsBattleArena() const;
@@ -443,6 +445,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
void ApplyOnEveryPlayer(std::function<void(Player*)> function);
//per-map script storage
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target);
+25
View File
@@ -942,3 +942,28 @@ void MotionMaster::DelayedDelete(MovementGenerator* curr)
_expireList = new ExpireList();
_expireList->push_back(curr);
}
void MotionMaster::MoveSmoothFlyPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize)
{
Movement::MoveSplineInit init(_owner);
init.SetSmooth();
init.SetFly();
init.SetUncompressed();
Movement::PointsArray path(pathPoints, pathPoints + pathSize);
init.MovebyPath(path);
init.Launch();
Mutate(new EffectMovementGenerator(pointId), MOTION_SLOT_ACTIVE);
}
void MotionMaster::MoveSmoothFlyPath(uint32 pointId, Position const position, float flightSpeed /*= 0.0f*/)
{
Movement::MoveSplineInit init(_owner);
init.SetSmooth();
init.SetFly();
init.SetUncompressed();
init.MoveTo(position.m_positionX, position.m_positionY, position.m_positionZ, false, false);
if (flightSpeed > 0.0f)
init.SetVelocity(flightSpeed);
init.Launch();
Mutate(new EffectMovementGenerator(pointId), MOTION_SLOT_ACTIVE);
}
+2
View File
@@ -180,6 +180,8 @@ class TC_GAME_API MotionMaster
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
void MoveSmoothPath(uint32 pointId, Position const* pathPoints, size_t pathSize, bool walk = false, bool fly = false);
void MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk);
void MoveSmoothFlyPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize);
void MoveSmoothFlyPath(uint32 pointId, Position const position, float flightSpeed = 0.0f);
void MoveSmoothPath(uint32 pointId, Movement::PointsArray const& points, bool walk);
// Walk along spline chain stored in DB (script_spline_chain_meta and script_spline_chain_waypoints)
void MoveAlongSplineChain(uint32 pointId, uint16 dbChainId, bool walk);
@@ -0,0 +1,632 @@
/*
https://uwow.biz/
To-DO: Conversation 5002/5003 when near. Now it don't work =C
*/
#include "tomb_of_sargeras.h"
enum Spells
{
// 116689
SPELL_BONE_SCYTHE = 233423, // aura
SPELL_SCYTHE_SWEEP = 233426,
SPELL_BONE_SAW = 233441, // 100% energy
SPELL_BONE_SAW_ENERGY = 234550, // proc
SPELL_DEBUFF_OVERRIDE = 233103, // 233652
SPELL_DEBUFF_OVER_AURA = 233104,
SPELL_DEBUFF_OVER_AURA1 = 234364,
SPELL_DEBUFF_UNBEAR_TOR = 233430,
// not normal
SPELL_CALCIFIED_QUILS = 233431, // 233432(233435)
// 116691
SPELL_GET_ENERGY = 246454,
SPELL_ECHOING_ANGUISH = 233983, // 22
SPELL_FEL_SQUAL = 235230, // 100%
SPELL_FEL_SQUAL_ENERGY = 235237,
SPELL_TORMENTING_BURST = 234015, // 17
SPELL_PANGS_OF_GUILT = 239401, // 10
// not normal
SPELL_SUFFOCATING_DARK = 233894, // 24
SPELL_AOE_SILENCE = 250306, // ????
SPELL_REGENERATE_ENERGY = 246455,
SPELL_ENRAGE = 248671, // 720 secs
SPELL_BELAC_PRISONER = 236283,
SPELL_SOUL_CORRUPTION = 248713,
};
enum eEvents
{
EVENT_SCYTHE_SWEEP = 1,
EVENT_CALCIFIED_QUILS,
EVENT_ECHOING_ANGUISH,
EVENT_PANGS_OF_GUILT,
EVENT_TORMENTING_BURST,
EVENT_SUFFOCATING_DARK,
EVENT_CHECK_ENERGY,
EVENT_ENRAGE,
EVENT_SUMMON_ADD,
};
std::map<uint32, uint32> hitSpells
{
{ SPELL_BONE_SAW , SPELL_BONE_SAW_ENERGY},
{ SPELL_FEL_SQUAL , SPELL_FEL_SQUAL_ENERGY}
};
// 116689, 116691
class boss_demonic_inquisition : public CreatureScript
{
public:
boss_demonic_inquisition() : CreatureScript("boss_demonic_inquisition") {}
struct boss_demonic_inquisitionAI : BossAI
{
boss_demonic_inquisitionAI(Creature* creature) : BossAI(creature, DATA_DEMONIC_INQUISITION)
{
if (me->GetEntry() == NPC_BELAK)
SetCombatMovement(false);
}
std::unordered_map<ObjectGuid, std::array<bool, 2>> calcifiedQuilsTargets{};
void Reset() override
{
if (me->IsAlive())
_Reset();
me->RemoveAurasDueToSpell(SPELL_DEBUFF_OVERRIDE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DEBUFF_OVER_AURA);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DEBUFF_OVER_AURA1);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ECHOING_ANGUISH);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BELAC_PRISONER);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SOUL_CORRUPTION);
me->KillAllDelayedEvents();
me->RemoveAllAreaTriggers();
if (me->IsAlive())
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DEBUFF_UNBEAR_TOR);
}
void EnterCombat(Unit* who) override
{
_EnterCombat();
events.Reset();
me->SetPower(me->GetPowerType(), 0);
switch (me->GetEntry())
{
case NPC_ATRIGAN:
DoCast(me, SPELL_DEBUFF_OVERRIDE);
events.RescheduleEvent(EVENT_SCYTHE_SWEEP, 5200);
if (IsHeroicRaid() || IsMythicRaid())
events.RescheduleEvent(EVENT_CALCIFIED_QUILS, 8500);
Talk(0);
events.RescheduleEvent(EVENT_SUMMON_ADD, 1000);
break;
case NPC_BELAK:
DoCast(me, SPELL_GET_ENERGY);
events.RescheduleEvent(EVENT_PANGS_OF_GUILT, 100);
events.RescheduleEvent(EVENT_ECHOING_ANGUISH, 5000);
events.RescheduleEvent(EVENT_TORMENTING_BURST, 9000);
if (IsHeroicRaid() || IsMythicRaid())
events.RescheduleEvent(EVENT_SUFFOCATING_DARK, 10000);
me->AddDelayedEvent(6500, [this]() -> void
{
Talk(0);
});
break;
}
DoCast(me, SPELL_REGENERATE_ENERGY);
events.RescheduleEvent(EVENT_CHECK_ENERGY, 100); // both
if (!IsLfrRaid())
events.RescheduleEvent(EVENT_ENRAGE, 720000);
if (Creature* other = instance->instance->GetCreature(instance->GetGuidData(me->GetEntry() == NPC_BELAK ? NPC_ATRIGAN : NPC_BELAK)))
{
other->AddDelayedEvent(100, [other,who]() -> void
{
if (who)
if(!other->IsInCombat())
other->AI()->EnterCombat(who);
});
}
}
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override
{
BossAI::EnterEvadeMode();
Reset();
me->NearTeleportTo(me->GetHomePosition());
if (Creature* other = instance->instance->GetCreature(instance->GetGuidData(me->GetEntry() == NPC_BELAK ? NPC_ATRIGAN : NPC_BELAK)))
{
other->AddDelayedEvent(100, [other]() -> void
{
if (other->IsInCombat())
other->AI()->EnterEvadeMode();
});
}
}
void DamageTaken(Unit* attacker, uint32& damage) override
{
if (attacker == me)
return;
if (Creature* other = instance->instance->GetCreature(instance->GetGuidData(me->GetEntry() == NPC_BELAK ? NPC_ATRIGAN : NPC_BELAK)))
{
if (damage >= me->GetHealth())
other->Kill(other, true);
else
other->DealDamage(other, damage);
}
// approximation : notre DamageTaken n expose pas le type de degats,
// le renvoi d epines se declenche donc sur tout degat (l original excluait DoT/split)
for (const auto& pair : hitSpells)
if (me->HasAura(pair.first))
attacker->CastSpell(attacker, pair.second, true);
}
void JustDied(Unit* killer) override
{
//Talk(SAY_DEATH);
if (me->GetEntry() == NPC_ATRIGAN)
DoCast(240053);
_JustDied();
if (me->GetEntry() == NPC_ATRIGAN)
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->HasAura(SPELL_DEBUFF_UNBEAR_TOR))
{
instance->DoUpdateAchievementCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, 243355);
break;
}
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DEBUFF_UNBEAR_TOR);
}
Reset();
}
bool GetObjectData(ObjectGuid const& guid, uint32 type) override
{
if (calcifiedQuilsTargets[guid][type])
return true;
calcifiedQuilsTargets[guid][type] = true;
return false;
}
void UpdateAI(uint32 diff) override
{
if (CheckHomeDistToEvade(diff, 50.0f))
return;
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_CALCIFIED_QUILS) || me->HasAura(SPELL_BONE_SAW) || me->HasAura(SPELL_FEL_SQUAL))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SCYTHE_SWEEP:
DoCast(SPELL_SCYTHE_SWEEP);
events.RescheduleEvent(EVENT_SCYTHE_SWEEP, 24500);
break;
case EVENT_CHECK_ENERGY:
if (me->GetPower(me->GetPowerType()) >= 100)
{
DoCast(me->GetEntry() == NPC_ATRIGAN ? SPELL_BONE_SAW : SPELL_FEL_SQUAL);
Talk(1);
}
events.RescheduleEvent(EVENT_CHECK_ENERGY, 100);
break;
case EVENT_CALCIFIED_QUILS:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
{
calcifiedQuilsTargets.clear();
DoCast(target, SPELL_CALCIFIED_QUILS);
me->AddDelayedEvent(5000, [this, target]()
{
if (!target)
return;
Position pos = target->GetPosition();
float diff_x = pos.GetPositionX() - me->GetPositionX();
float diff_y = pos.GetPositionY() - me->GetPositionY();
float dist = sqrt(diff_x * diff_x + diff_y * diff_y);
for (float mod = 2 / dist, time = 0; mod < 60.0f / dist; mod += (2 / dist), time++)
{
for (float i = -0.5f; i <= 0.5f; i += 0.2f)
{
if (urand(1, 5) == 5)
continue;
float new_x = mod*diff_x*sqrt(3) / 2 - i * mod *diff_y / 2;
float new_y = i * mod *diff_x / 2 + mod* diff_y * sqrt(3) / 2;
me->AddDelayedEvent(1 + time * 50, [=]()
{
me->CastSpell({ me->GetPositionX() + new_x + frand(-2, 2), me->GetPositionY() + new_y + frand(-2, 2), me->GetPositionZ(), 0 }, 233435, true);
});
}
}
});
}
events.RescheduleEvent(EVENT_CALCIFIED_QUILS, 20000);
break;
case EVENT_PANGS_OF_GUILT:
DoCast(SPELL_PANGS_OF_GUILT);
events.RescheduleEvent(EVENT_PANGS_OF_GUILT, 10000);
break;
case EVENT_ECHOING_ANGUISH:
DoCast(SPELL_ECHOING_ANGUISH);
events.RescheduleEvent(EVENT_ECHOING_ANGUISH, 22000);
break;
case EVENT_TORMENTING_BURST:
DoCast(SPELL_TORMENTING_BURST);
events.RescheduleEvent(EVENT_TORMENTING_BURST, 17000);
break;
case EVENT_SUFFOCATING_DARK:
{
std::list<HostileReference*> threatlist = me->getThreatManager().getThreatList();
threatlist.remove_if([this](HostileReference* ref)
{
if (!ref->getTarget()->IsPlayer())
return true;
return me->GetDistance(ref->getTarget()) >= 60.0f;
});
std::list<HostileReference*> threatListTemp = threatlist;
threatListTemp.remove_if([this](HostileReference* ref)
{
return ref->getTarget()->ToPlayer()->GetRoleForGroup() == ROLE_TANK; // approximation : on ecarte seulement les tanks
});
uint8 count = std::min(3, int32(ceil(float(threatlist.size()) / 5.0f)));
if (threatListTemp.size() >= count)
threatlist = threatListTemp;
Trinity::Containers::RandomResize(threatlist, count);
for (const auto& target : threatlist)
if (Unit* targ = target->getTarget())
me->CastSpell(targ->GetPositionX(), targ->GetPositionY(), 3011.62f, SPELL_SUFFOCATING_DARK, true);
events.RescheduleEvent(EVENT_SUFFOCATING_DARK, 24000);
break;
}
case EVENT_ENRAGE:
DoCast(SPELL_ENRAGE);
break;
case EVENT_SUMMON_ADD:
me->SummonCreature(NPC_TORMENTED_SOUL, 6403.00f, -935.00f, 3037.16f);
break;
}
}
if (me->GetEntry() != NPC_BELAK)
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new boss_demonic_inquisitionAI (creature);
}
};
// 117957
class npc_tos_tormented_soul : public CreatureScript
{
public:
npc_tos_tormented_soul() : CreatureScript("npc_tos_tormented_soul") {}
struct npc_tos_tormented_soulAI : public ScriptedAI
{
npc_tos_tormented_soulAI(Creature* creature) : ScriptedAI(creature), summons(me)
{
me->m_SightDistance = 20;
}
EventMap events;
SummonList summons;
void Reset() override
{
events.Reset();
summons.DespawnAll();
me->SetControlled(true, UNIT_STATE_ROOT);
me->RemoveAurasDueToSpell(239135);
}
void EnterCombat(Unit* /*who*/) override
{
events.RescheduleEvent(EVENT_1, 6000);
events.RescheduleEvent(EVENT_2, 5000);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void DamageTaken(Unit* attacker, uint32& damage) override
{
if (urand(1, 3) == 2)
DoCast(attacker, 235301);
}
void UpdateAI(uint32 diff) override
{
if (CheckHomeDistToEvade(diff, 17.0f))
return;
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_1:
DoCast(SPELL_SOUL_CORRUPTION);
events.RescheduleEvent(EVENT_1, 6000);
break;
case EVENT_2:
DoCast(239135);
events.RescheduleEvent(EVENT_2, urand(16000, 19000));
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_tos_tormented_soulAI(creature);
}
};
// 233652
class spell_tos_confess : public SpellScriptLoader
{
public:
spell_tos_confess() : SpellScriptLoader("spell_tos_confess") { }
class spell_tos_confess_AuraScript : public AuraScript
{
PrepareAuraScript(spell_tos_confess_AuraScript);
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetTarget())
{
if (!caster->IsPlayer())
return;
caster->GetMotionMaster()->MoveSmoothFlyPath(0, { caster->GetPositionX() + frand(-3, 3), caster->GetPositionY() + frand(-3, 3), caster->GetPositionZ() + 10.0f, caster->GetOrientation() });
caster->AddDelayedEvent(1500, [caster]() -> void {
caster->RemoveAurasDueToSpell(233652);
caster->GetMotionMaster()->Clear();
caster->ToPlayer()->TeleportTo(caster->GetMapId(), 6403.13f, -935.55f, 3060.23f, caster->GetOrientation(),TELE_TO_SEAMLESS);
});
}
}
void Register()
{
OnEffectApply += AuraEffectApplyFn(spell_tos_confess_AuraScript::OnApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_tos_confess_AuraScript();
}
};
// 233104
class spell_tos_torment : public SpellScriptLoader
{
public:
spell_tos_torment() : SpellScriptLoader("spell_tos_torment") { }
class spell_tos_torment_AuraScript : public AuraScript
{
PrepareAuraScript(spell_tos_torment_AuraScript);
void OnTick(AuraEffect const* /*aurEff*/)
{
Unit* target = GetTarget();
if (!target)
return;
if (target->GetPower(POWER_ALTERNATE_POWER) >= 100)
target->CastSpell(target, SPELL_DEBUFF_UNBEAR_TOR, true);
else if (target->GetPower(POWER_ALTERNATE_POWER) == 0)
if (target->GetDistance2d(6403.13f, -935.55f) <= 30.0f)
target->CastSpell(target, 243560, true); // 235293
if (target->GetDistance2d(6403.13f, -935.55f) > 40.0f && target->HasAura(SPELL_BELAC_PRISONER))
{
target->RemoveAurasDueToSpell(SPELL_BELAC_PRISONER);
target->RemoveAurasDueToSpell(SPELL_DEBUFF_OVER_AURA1); // clear
target->CastSpell(target, SPELL_DEBUFF_OVER_AURA1, true);
}
}
void OnRemove(AuraEffect const* /*auraEffect*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (!target || !target->IsPlayer())
return;
if (target->GetDistance2d(6403.13f, -935.55f) <= 30.0f)
if (target->IsAlive())
target->ToPlayer()->TeleportTo(target->GetMapId(), 6401.96f, -795.64f, 3020.17f, 0.01f, TELE_TO_SEAMLESS);
else
target->NearTeleportTo(6401.96f, -795.64f, 3020.17f, 0.01f);
target->RemoveAurasDueToSpell(SPELL_BELAC_PRISONER);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tos_torment_AuraScript::OnTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
AfterEffectRemove += AuraEffectRemoveFn(spell_tos_torment_AuraScript::OnRemove, SpellEffIndex::EFFECT_1, SPELL_AURA_PERIODIC_DUMMY, AuraEffectHandleModes::AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_tos_torment_AuraScript();
}
};
// 235305
class spell_tos_prisoner : public SpellScriptLoader
{
public:
spell_tos_prisoner() : SpellScriptLoader("spell_tos_prisoner") { }
class spell_tos_prisoner_AuraScript : public AuraScript
{
PrepareAuraScript(spell_tos_prisoner_AuraScript);
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool & /*canBeRecalculated*/)
{
amount = -1;
}
void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32& absorbAmount)
{
absorbAmount = dmgInfo.GetDamage();
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_tos_prisoner_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_tos_prisoner_AuraScript();
}
};
// 233435
class spell_tos_calcified_quils : public SpellScript
{
PrepareSpellScript(spell_tos_calcified_quils);
void HandleDamage(SpellEffIndex /*effectIndex*/)
{
if (GetCaster() && GetHitUnit())
if (GetCaster()->GetEntry() == NPC_ATRIGAN)
if (GetCaster()->ToCreature()->AI()->GetObjectData(GetHitUnit()->GetGUID(), 0))
SetHitDamage(0);
}
void RecalculateDamage(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (GetCaster() && GetHitUnit())
if (GetCaster()->GetEntry() == NPC_ATRIGAN)
if (!GetCaster()->ToCreature()->AI()->GetObjectData(GetHitUnit()->GetGUID(), 1))
GetHitUnit()->SetPower(POWER_ALTERNATE_POWER, GetHitUnit()->GetPower(POWER_ALTERNATE_POWER) + 10);
}
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_tos_calcified_quils::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
OnEffectHitTarget += SpellEffectFn(spell_tos_calcified_quils::RecalculateDamage, EFFECT_2, SPELL_EFFECT_ENERGIZE);
}
};
// 235295
class spell_tos_adherent_fragment : public SpellScript
{
PrepareSpellScript(spell_tos_adherent_fragment);
void HandleAfterCast()
{
if (Unit* caster = GetCaster())
if (InstanceScript* instance = caster->GetInstanceScript())
if (instance->instance->IsMythic())
caster->CastSpellDelay(caster, 241505, true, 1000);
}
void Register() override
{
AfterCast += SpellCastFn(spell_tos_adherent_fragment::HandleAfterCast);
}
};
class achievement_grin_and_bear_it : public AchievementCriteriaScript
{
public:
achievement_grin_and_bear_it() : AchievementCriteriaScript("achievement_grin_and_bear_it") { }
bool OnCheck(Player* source, Unit* /*target*/) override
{
if (source->IsAlive() && source->HasAura(233430))
return true;
return false;
}
};
void AddSC_boss_demonic_inquisition()
{
new boss_demonic_inquisition();
new npc_tos_tormented_soul();
new spell_tos_confess();
new spell_tos_torment();
new spell_tos_prisoner();
RegisterSpellScript(spell_tos_calcified_quils);
RegisterSpellScript(spell_tos_adherent_fragment);
new achievement_grin_and_bear_it();
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,755 @@
/*
https://uwow.biz/
*/
#include "AreaTriggerAI.h"
#include "tomb_of_sargeras.h"
enum Spells
{
SPELL_GOROTH_ENERGIZE = 237333,
SPELL_BURNING_ARMOR = 231363,
SPELL_BURNING_ERUPTION = 231395,
SPELL_BURNING_ERUPTION_DUMMY = 233025,
SPELL_CRASHING_COMET_FILTER = 232249, //Caster Boss
SPELL_CRASHING_COMET_LFR_FILTER = 244548, //Caster Boss. Only LFR
SPELL_CRASHING_COMET_FILTER2 = 232254, //Caster Ember Stalker - 115892
SPELL_CRASHING_COMET_LFR_FILTER2 = 244580, //Caster Ember Stalker - 115892. Only LFR
SPELL_CRASHING_COMET_MISSILE = 230339,
SPELL_CRASHING_COMET_LFR_MISSILE = 244581,
SPELL_INFERNAL_SPIKE_FILTER = 233050,
SPELL_INFERNAL_SPIKE_SUMMON = 233055,
SPELL_INFERNAL_SPIKE_AT = 233019,
SPELL_INFERNAL_SPIKE_PROTECTION = 234475,
SPELL_SHATTERING_STAR_FILTER = 233269,
SPELL_SHATTERING_STAR_MARK = 233272,
SPELL_SHATTERING_STAR_AURA = 233289, //unk
SPELL_SHATTERING_STAR_SPEED = 233290,
SPELL_SHATTERING_STAR_HIT = 233274,
SPELL_SHATTERING_STAR_AT = 233279,
SPELL_SHATTERING_NOVA = 233283,
SPELL_STAR_BURN = 236329,
SPELL_INFERNAL_BURNING = 233062,
SPELL_INFERNAL_DETONATION = 233900, //Mythic
SPELL_RAIN_OF_BRIMSTONE_DUMMY = 233285, //Mythic
SPELL_RAIN_OF_BRIMSTONE_MISSILE = 238587, //Mythic
SPELL_RAIN_OF_BRIMSTONE_SUMMON = 233266, //Mythic
SPELL_RAIN_OF_BRIMSTONE_SPIKE_DESTROY = 238659, //Mythic
//Lava Stalker
SPELL_FEL_PERIODIC_TRIGGER = 234386,
SPELL_FEL_ERUPTION_TELEGRAPH = 234366,
SPELL_FEL_ERUPTION_DUMMY = 234368,
SPELL_FEL_ERUPTION_MISSILE = 234387,
SPELL_FEL_ERUPTION_AT = 234330,
//Brimstone Infernal
SPELL_FEL_FIRE = 241455,
};
enum eEvents
{
EVENT_BURNING_ARMOR = 1,
EVENT_CRASHING_COMET = 2,
EVENT_INFERNAL_SPIKE = 3,
EVENT_SHATTERING_STAR = 4,
EVENT_RAIN_OF_BRIMSTONE = 5,
};
enum Misc
{
SPELLVISUAL_INFERNAL_SPIKE_DESTROY = 66119,
DATA_SPIKES_COUNTER,
};
Position const centrPos = {6101.30f, -795.72f, 2971.72f};
//115844
struct boss_goroth : BossAI
{
explicit boss_goroth(Creature* creature) : BossAI(creature, DATA_GOROTH) {}
uint8 spiketouched = 0;
uint8 felRand = 0;
uint8 shatteringCounter = 0;
uint8 rainBrimstoneCounter = 0;
uint32 felEruptionTimer = 0;
uint32 shatteringTimer = 0;
uint32 rainBrimstoneTimer = 0;
ObjectGuid shatteringTargetGUID;
void Reset() override
{
_Reset();
spiketouched = 0;
shatteringCounter = 0;
rainBrimstoneCounter = 0;
shatteringTimer = 60000;
rainBrimstoneTimer = 60000;
me->RemoveAurasDueToSpell(SPELL_GOROTH_ENERGIZE);
me->SetMaxPower(POWER_ENERGY, 100);
me->SetPower(POWER_ENERGY, 0);
me->SetReactState(REACT_DEFENSIVE);
me->SummonCreature(NPC_EMBER_STALKER, 6194.41f, -842.93f, 3042.72f, 0.0f);
if (IsHeroicPlusRaid())
{
felRand = 0;
felEruptionTimer = 30000;
}
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
DoCast(me, SPELL_GOROTH_ENERGIZE, true);
events.RescheduleEvent(EVENT_BURNING_ARMOR, 10000);
events.RescheduleEvent(EVENT_CRASHING_COMET, 8000);
events.RescheduleEvent(EVENT_INFERNAL_SPIKE, 4000);
events.RescheduleEvent(EVENT_SHATTERING_STAR, IsMythicRaid() ? 34000 : 24000);
if (IsMythicRaid())
events.RescheduleEvent(EVENT_RAIN_OF_BRIMSTONE, 12000);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_INFERNAL_SPIKE_PROTECTION);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(12);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_INFERNAL_SPIKE_PROTECTION);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_STAR_BURN);
}
void KilledUnit(Unit* who) override
{
if (!who->IsPlayer())
return;
Talk({ 7, 9, 10 });
}
void DoAction(int32 const action) override
{
switch (action)
{
case ACTION_1:
if (auto player = ObjectAccessor::GetPlayer(*me, shatteringTargetGUID))
DoCast(player, SPELL_STAR_BURN, true);
break;
case ACTION_2:
++spiketouched;
break;
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_SPIKES_COUNTER)
return spiketouched;
return 0;
}
void OnRemoveAuraTarget(Unit* target, uint32 spellId, AuraRemoveMode mode) override
{
if (!me->IsInCombat() || !target || mode != AURA_REMOVE_BY_EXPIRE)
return;
switch (spellId)
{
case SPELL_BURNING_ARMOR:
target->CastSpell(target, SPELL_BURNING_ERUPTION, true);
me->CastSpell(target, SPELL_BURNING_ERUPTION_DUMMY, true);
break;
}
}
void SpellFinishCast(const SpellInfo* spell) override
{
switch (spell->Id)
{
case SPELL_INFERNAL_BURNING:
{
me->SetPower(POWER_ENERGY, 0);
EntryCheckPredicate pred(NPC_INFERNAL_SPIKE);
summons.DoAction(ACTION_1, pred);
break;
}
case SPELL_RAIN_OF_BRIMSTONE_DUMMY:
{
Position pos;
std::list<Position> randPosList;
bool badPos = false;
uint16 traiCount = 0;
while (randPosList.size() < 3)
{
badPos = false;
centrPos.SimplePosXYRelocationByAngle(pos, frand(25.0f, 35.0f), frand(0.0f, 6.28f));
++traiCount;
for (auto _pos : randPosList)
{
if (pos.GetExactDist(&_pos) <= 10.0f)
{
badPos = true;
break;
}
}
if (!badPos || traiCount > 15)
randPosList.push_back(pos);
}
for (auto _pos : randPosList)
me->CastSpell(_pos, SPELL_RAIN_OF_BRIMSTONE_MISSILE, true);
break;
}
}
}
void SpellHit(Unit* target, SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_SHATTERING_STAR_HIT:
if (me->IsInCombat())
DoCast(target, SPELL_SHATTERING_STAR_AT, true);
break;
}
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_INFERNAL_SPIKE_FILTER:
DoCast(target, SPELL_INFERNAL_SPIKE_SUMMON, true);
break;
case SPELL_SHATTERING_STAR_FILTER:
shatteringTargetGUID = target->GetGUID();
DoCast(target, SPELL_SHATTERING_STAR_MARK, true);
DoCast(target, SPELL_SHATTERING_STAR_SPEED, true);
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (CheckHomeDistToEvade(diff, 62.0f, 6100.85f, -795.70f, 2971.72f))
return;
if (felEruptionTimer)
{
if (felEruptionTimer <= diff)
{
felEruptionTimer = 30000;
uint8 felRandOld = felRand;
while (felRandOld == felRand)
{
felRand = urand(2, 5);
}
; // SummonCreatureGroupDespawn : groupes d invocation uwow, non porte
me->SummonCreatureGroup(felRand);
}
else
felEruptionTimer -= diff;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BURNING_ARMOR:
DoCastTopAggro(SPELL_BURNING_ARMOR);
events.RescheduleEvent(EVENT_BURNING_ARMOR, 24000);
break;
case EVENT_CRASHING_COMET:
{
if (IsLfrRaid())
DoCast(SPELL_CRASHING_COMET_LFR_FILTER);
else
DoCast(SPELL_CRASHING_COMET_FILTER);
EntryCheckPredicate pred(NPC_EMBER_STALKER);
summons.DoAction(ACTION_1, pred);
events.RescheduleEvent(EVENT_CRASHING_COMET, 18000);
break;
}
case EVENT_INFERNAL_SPIKE:
DoCast(SPELL_INFERNAL_SPIKE_FILTER);
events.RescheduleEvent(EVENT_INFERNAL_SPIKE, 16000);
break;
case EVENT_SHATTERING_STAR:
if (++shatteringCounter == 4)
shatteringTimer = IsMythicRaid() ? 30000 : 50000;
shatteringTargetGUID.Clear();
DoCast(SPELL_SHATTERING_STAR_FILTER);
events.RescheduleEvent(EVENT_SHATTERING_STAR, shatteringTimer);
break;
case EVENT_RAIN_OF_BRIMSTONE:
if (++rainBrimstoneCounter == 4)
{
rainBrimstoneCounter = 0;
rainBrimstoneTimer = 68000;
}
else
rainBrimstoneTimer = 60000;
DoCast(SPELL_RAIN_OF_BRIMSTONE_DUMMY);
events.RescheduleEvent(EVENT_RAIN_OF_BRIMSTONE, rainBrimstoneTimer);
break;
}
}
DoMeleeAttackIfReady();
}
};
//115892
struct npc_goroth_ember_stalker : public ScriptedAI
{
npc_goroth_ember_stalker(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
me->SetDisplayId(11686);
}
void Reset() {}
void DoAction(int32 const action) override
{
if (IsLfrRaid())
me->CastSpellDelay(me, SPELL_CRASHING_COMET_LFR_FILTER2, true, 500);
else
me->CastSpellDelay(me, SPELL_CRASHING_COMET_FILTER2, true, 500);
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
auto owner = me->GetAnyOwner();
if (!owner)
return;
switch (spell->Id)
{
case SPELL_CRASHING_COMET_LFR_FILTER2:
me->CastSpell(target, SPELL_CRASHING_COMET_LFR_MISSILE, true, nullptr, nullptr, owner->GetGUID());
break;
case SPELL_CRASHING_COMET_FILTER2:
me->CastSpell(target, SPELL_CRASHING_COMET_MISSILE, true, nullptr, nullptr, owner->GetGUID());
break;
}
}
void UpdateAI(uint32 diff) {}
};
//116976
struct npc_goroth_infernal_spike : public ScriptedAI
{
npc_goroth_infernal_spike(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
}
bool despawn = false;
void IsSummonedBy(Unit* summoner) override
{
me->CastSpellDelay(me, SPELL_INFERNAL_SPIKE_AT, false, 500);
}
void Reset() {}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (despawn || caster->GetEntry() != NPC_GOROTH)
return;
if (spell->Id == SPELL_BURNING_ERUPTION_DUMMY || spell->Id == SPELL_RAIN_OF_BRIMSTONE_SPIKE_DESTROY)
DoAction(true);
}
void OnAreaTriggerDespawn(uint32 spellId, Position pos, bool duration) override
{
if (despawn)
return;
if (spellId == SPELL_INFERNAL_SPIKE_AT)
DoAction(true);
}
void DoAction(int32 const action) override
{
if (despawn)
return;
despawn = true;
if (IsMythicRaid())
{
if (auto owner = me->GetAnyOwner())
owner->CastSpell(me, SPELL_INFERNAL_DETONATION, true);
}
; // (PlaySpellVisual positionnel : cosmetique uwow, non porte)
me->DespawnOrUnsummon(1000);
}
void UpdateAI(uint32 diff) {}
};
//117931
struct npc_goroth_lava_stalker : public ScriptedAI
{
npc_goroth_lava_stalker(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
}
void IsSummonedBy(Unit* summoner) override
{
me->CastSpellDelay(me, SPELL_FEL_ERUPTION_TELEGRAPH, true, 500);
me->CastSpellDelay(me, SPELL_FEL_PERIODIC_TRIGGER, true, 7000);
}
void Reset() {}
void UpdateAI(uint32 diff) {}
};
//119950
struct npc_goroth_brimstone_infernal : public ScriptedAI
{
npc_goroth_brimstone_infernal(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
instance = me->GetInstanceScript();
}
InstanceScript* instance;
uint32 felTimer = 0;
void IsSummonedBy(Unit* summoner) override
{
me->SetReactState(REACT_AGGRESSIVE, 2000);
felTimer = 12000; //Need correct time!
}
void Reset() {}
void EnterCombat(Unit* /*who*/)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
}
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (felTimer)
{
if (felTimer <= diff)
{
felTimer = 15000; //Need correct time!
DoCast(SPELL_FEL_FIRE);
}
else
felTimer -= diff;
}
DoMeleeAttackIfReady();
}
};
//233024
class spell_tos_goroth_crashing_comet : public SpellScript
{
PrepareSpellScript(spell_tos_goroth_crashing_comet);
void FilterTargets(std::list<WorldObject*>& targets)
{
std::list<WorldObject*> infernalSpikes;
for (auto target : targets)
{
if (target->GetEntry() == NPC_INFERNAL_SPIKE)
infernalSpikes.push_back(target);
}
for (auto infernalSpike : infernalSpikes)
{
if (auto spike = ObjectAccessor::GetCreature(*GetCaster(), infernalSpike->GetGUID()))
spike->GetAI()->DoAction(true);
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_tos_goroth_crashing_comet::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY);
}
};
//234368
class spell_tos_goroth_fel_eruption_dummy : public SpellScript
{
PrepareSpellScript(spell_tos_goroth_fel_eruption_dummy);
void HandleScript(SpellEffIndex /*effectIndex*/)
{
if (!GetCaster() || !GetHitDest())
return;
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* goroth = instance->instance->GetCreature(instance->GetGuidData(DATA_GOROTH)))
goroth->CastSpell(GetHitDest()->GetPositionX(), GetHitDest()->GetPositionY(), GetHitDest()->GetPositionZ(), SPELL_FEL_ERUPTION_AT, true);
}
void Register() override
{
OnEffectLaunch += SpellEffectFn(spell_tos_goroth_fel_eruption_dummy::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
//238588
class spell_tos_goroth_rain_of_brimstone : public SpellScript
{
PrepareSpellScript(spell_tos_goroth_rain_of_brimstone);
uint8 targetCount = 0;
void FilterTargets(std::list<WorldObject*>& targets)
{
if (!GetCaster() || !GetExplTargetDest())
return;
GetCaster()->CastSpell(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY(), GetExplTargetDest()->GetPositionZ(), SPELL_RAIN_OF_BRIMSTONE_SPIKE_DESTROY, true);
if (targets.empty())
GetCaster()->CastSpell(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY(), GetExplTargetDest()->GetPositionZ(), SPELL_RAIN_OF_BRIMSTONE_SUMMON, true);
else
targetCount = targets.size();
}
void HandleDamage(SpellEffIndex /*effectIndex*/)
{
if (targetCount)
SetHitDamage(GetHitDamage() / targetCount);
}
void Register()
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_tos_goroth_rain_of_brimstone::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_tos_goroth_rain_of_brimstone::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
//237333
class spell_tos_goroth_energy_tracker : public AuraScript
{
PrepareAuraScript(spell_tos_goroth_energy_tracker);
uint8 powerTick = 0;
void OnTick(AuraEffect const* aurEff)
{
auto caster = GetCaster()->ToCreature();
if (!caster || !caster->IsInCombat())
return;
auto powerCount = caster->GetPower(POWER_ENERGY);
if (powerCount < 100)
{
if (powerTick < 8)
{
++powerTick;
if (aurEff->GetTickNumber() == 1)
caster->SetPower(POWER_ENERGY, powerCount + 1);
else
caster->SetPower(POWER_ENERGY, powerCount + 2);
}
else
{
powerTick = 0;
caster->SetPower(POWER_ENERGY, powerCount + 1);
}
}
else if (!caster->HasUnitState(UNIT_STATE_CASTING))
{
caster->CastSpell(caster, SPELL_INFERNAL_BURNING, false);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tos_goroth_energy_tracker::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
//234386
class spell_tos_goroth_fel_periodic_trigger : public AuraScript
{
PrepareAuraScript(spell_tos_goroth_fel_periodic_trigger);
void OnTick(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (auto caster = GetCaster())
{
Position pos;
float angle = caster->GetRelativeAngle(centrPos.GetPositionX(), centrPos.GetPositionY()) + frand(-1.0f, 1.0f);
pos = caster->GetNearPosition(frand(35.0f, 45.0f), angle);
caster->CastSpell(pos, SPELL_FEL_ERUPTION_MISSILE, true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tos_goroth_fel_periodic_trigger::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
//955600
struct at_goroth_infernal_spike_los_blocker : AreaTriggerAI
{
at_goroth_infernal_spike_los_blocker(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) {}
bool IsValidTarget(Unit* caster, Unit* target, AreaTriggerActionMoment actionM) override
{
if (caster && target && target->IsPlayer())
{
if (auto instance = target->GetInstanceScript())
{
if (auto goroth = ObjectAccessor::GetCreature(*target, instance->GetGuidData(DATA_GOROTH)))
{
if (at->IsInBetween(target, goroth, 2.5f))
{
if (!target->HasAura(SPELL_INFERNAL_SPIKE_PROTECTION))
target->CastSpell(target, SPELL_INFERNAL_SPIKE_PROTECTION, true, nullptr, nullptr, caster->GetGUID());
}
else if (auto aura = target->GetAura(SPELL_INFERNAL_SPIKE_PROTECTION, caster->GetGUID()))
aura->Remove();
}
}
}
return true;
}
};
//13412
struct at_goroth_shattering_star : AreaTriggerAI
{
explicit at_goroth_shattering_star(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) {}
uint8 infernalSpikeTouched = 1;
void OnUnitEnter(Unit* unit) override
{
auto caster = at->GetCaster();
if (unit->GetEntry() == NPC_INFERNAL_SPIKE)
{
++infernalSpikeTouched;
if (unit->IsAIEnabled)
unit->GetAI()->DoAction(true);
//Achievement
if (caster->IsAIEnabled)
caster->GetAI()->DoAction(ACTION_2);
}
}
void OnDestinationReached() override
{
auto caster = at->GetCaster();
if (!caster)
{
at->Remove();
return;
}
if (auto spellInfo = sSpellMgr->GetSpellInfo(SPELL_SHATTERING_NOVA))
{
if (auto effInfo = spellInfo->GetEffect(EFFECT_0, caster->GetMap()->GetDifficultyID()))
{
float damage = effInfo->BasePoints / std::max(infernalSpikeTouched, uint8(1));
SpellCastTargets targets;
; // (SetCaster : le caster est fourni au CastSpell, inutile chez nous)
targets.SetDst(at->GetPosition());
CustomSpellValues values;
values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
caster->CastSpell(targets, spellInfo, &values, TriggerCastFlags(TRIGGERED_FULL_MASK));
}
}
if (infernalSpikeTouched < 2 && caster->IsAIEnabled)
caster->GetAI()->DoAction(ACTION_1);
}
};
//13526
struct at_goroth_fel_pool : AreaTriggerAI
{
explicit at_goroth_fel_pool(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) {}
void OnUnitEnter(Unit* unit) override
{
if (unit->GetEntry() == NPC_INFERNAL_SPIKE)
unit->GetAI()->DoAction(true);
}
};
//36337
class achievement_fel_turkey : public AchievementCriteriaScript
{
public:
achievement_fel_turkey() : AchievementCriteriaScript("achievement_fel_turkey") {}
bool OnCheck(Player* /*player*/, Unit* target) override
{
if (!target)
return false;
if (auto boss = target->ToCreature())
if (boss->IsAIEnabled && boss->AI()->GetData(DATA_SPIKES_COUNTER) >= 30)
return true;
return false;
}
};
void AddSC_boss_goroth()
{
RegisterCreatureAI(boss_goroth);
RegisterCreatureAI(npc_goroth_ember_stalker);
RegisterCreatureAI(npc_goroth_infernal_spike);
RegisterCreatureAI(npc_goroth_lava_stalker);
RegisterCreatureAI(npc_goroth_brimstone_infernal);
RegisterSpellScript(spell_tos_goroth_crashing_comet);
RegisterSpellScript(spell_tos_goroth_fel_eruption_dummy);
RegisterSpellScript(spell_tos_goroth_rain_of_brimstone);
RegisterAuraScript(spell_tos_goroth_energy_tracker);
RegisterAuraScript(spell_tos_goroth_fel_periodic_trigger);
RegisterAreaTriggerAI(at_goroth_infernal_spike_los_blocker);
RegisterAreaTriggerAI(at_goroth_shattering_star);
RegisterAreaTriggerAI(at_goroth_fel_pool);
new achievement_fel_turkey();
}
@@ -0,0 +1,766 @@
/*
https://uwow.biz/
*/
#include "tomb_of_sargeras.h"
enum Says
{
SAY_AGGRO = 0,
SAY_CALL = 1,
SAY_DRAW_IN = 2,
SAY_DEATH = 3,
};
enum Spells
{
SPELL_DRAW_IN = 232061, //
SPELL_FRIGID_BLOWS = 233429, //
SPELL_DRENCHING_SLOUGH = 233526, // dummy
SPELL_FROSTY_DISCHARGE = 232174, // at end link
SPELL_UNCHECKED_RAGE = 231854, // 100%
SPELL_UNCHECKED_RAGE_VICTIM = 247403, //
SPELL_CALL_ADDS = 232192, //
SPELL_CANCEL_DRENCHED = 239926, // link
SPELL_CHANGE_ENERGY = 241486, //
SPELL_REGENERATE_ENERGY = 232379, //
SPELL_ENQUBATION = 240347,
SPELL_HARDENED_SHELL = 240315,
SPELL_ENQUBATION_RED = 242027,
SPELL_ENQUBATION_BLUE = 242030,
SPELL_ENQUBATION_GREEN = 242031,
SPELL_ENRAGE = 64238, //
SPELL_JAGGED_ABRASION = 231998,
//achievement npc spells
SPELL_SONIC_WAVE = 241436,
SPELL_SPLASH = 241393,
SPELL_ELDERS_RAGE = 241416,
};
enum eEvents
{
EVENT_CHECK_ENERGY = 1,
EVENT_CALL_ADDS,
EVENT_DRAW_IN,
EVENT_HATCHING,
EVENT_HATCHING_CLEAN_UP,
EVENT_ENRAGE,
EVENT_ELDER1,
EVENT_ELDER2,
EVENT_ELDER3,
};
enum Misc
{
DATA_COMPLETE,
};
enum Action
{
ACTION_COMPLETE,
};
Position const addsPos[4]
{
{5877.17f, -906.50f, 2920.25f, 6.20f},
{5880.17f, -896.95f, 2920.35f, 5.73f},
{5889.86f, -886.83f, 2920.35f, 5.42f},
{5946.16f, -919.47f, 2919.52f, 2.62f}
};
Position const eggsPos[4]
{
{5915.40f, -876.02f, 2919.83f, 0.0f},
{5944.42f, -900.28f, 2919.46f, 0.0f},
{5918.47f, -945.27f, 2919.86f, 0.0f},
{5882.26f, -920.99f, 2920.99f, 0.0f}
};
uint32 const eggsCasts[3]
{
SPELL_ENQUBATION_BLUE,
SPELL_ENQUBATION_RED,
SPELL_ENQUBATION_GREEN
};
// 116407
class boss_harjatan : public CreatureScript
{
public:
boss_harjatan() : CreatureScript("boss_harjatan") {}
struct boss_harjatanAI : BossAI
{
boss_harjatanAI(Creature* creature) : BossAI(creature, DATA_HARJATAN), achievecomplete(false)
{
me->SetReactState(REACT_DEFENSIVE);
achievecomplete = false;
}
std::map<uint8, std::vector<ObjectGuid>> eggs{};
bool achievecomplete;
void Reset() override
{
if (me->IsAlive())
{
_Reset();
achievecomplete = false;
if (Creature* elder = instance->instance->GetCreature(instance->GetGuidData(NPC_ELDER)))
if (!elder->IsAlive())
elder->Respawn();
}
eggs.clear();
instance->DoRemoveAurasDueToSpellOnPlayers(231770);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_JAGGED_ABRASION);
std::list<AreaTrigger*> list;
me->GetAreatriggerListInRange(list, 80.0f);
list.remove_if([](AreaTrigger* at1) { AreaTriggerTemplate const* t1 = at1->GetTemplate(); return !t1 || t1->Id != 13251; });
for (std::list<AreaTrigger*>::const_iterator itr = list.begin(); itr != list.end(); itr++)
(*itr)->RemoveFromWorld();
if (IsMythicRaid())
{
for (uint8 j = 0; j < 4; ++j)
{
const auto& pos = eggsPos[j];
for (uint8 i = 0; i < 5; ++i)
if (Creature* add = me->SummonCreature(NPC_EGGS, pos.GetPositionX() + frand(-4, 4), pos.GetPositionY() + frand(-4, 4), pos.GetPositionZ(), 0.0f))
{
add->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_ATTACKABLE_1);
add->CastSpell(add, SPELL_HARDENED_SHELL);
eggs[j].push_back(add->GetGUID());
}
}
}
}
void DoAction(int32 const action)
{
if (action == ACTION_COMPLETE)
achievecomplete = true;
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_COMPLETE:
return achievecomplete ? 1 : 0;
}
return 0;
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
me->SetPower(POWER_ENERGY, 0);
DoCast(SPELL_REGENERATE_ENERGY);
events.RescheduleEvent(EVENT_CHECK_ENERGY, 500);
events.RescheduleEvent(EVENT_ENRAGE, IsMythicRaid() ? 360000 : 480000);
events.RescheduleEvent(EVENT_DRAW_IN, 58000);
events.RescheduleEvent(EVENT_CALL_ADDS, 17000);
if (IsMythicRaid())
events.RescheduleEvent(EVENT_HATCHING, 30000);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
Reset();
}
void JustSummoned(Creature* creature) override
{
switch(creature->GetEntry())
{
case NPC_EGGS:
creature->SetReactState(REACT_ATTACK_OFF);
creature->SetControlled(true, UNIT_STATE_ROOT);
break;
case NPC_TADPOLE_3:
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
{
creature->SetTarget(target->GetGUID());
creature->AI()->DoAction(true);
}
break;
}
}
BossAI::JustSummoned(creature);
}
void SpellFinishCast(SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_UNCHECKED_RAGE:
DoCastVictim(SPELL_UNCHECKED_RAGE_VICTIM, true);
for (const auto& vector : eggs)
for (const auto& guid : vector.second)
if (Creature* egg = instance->instance->GetCreature(guid))
if (me->isInFront(egg) && me->GetDistance(egg) <= 20.0f)
egg->RemoveAurasDueToSpell(SPELL_HARDENED_SHELL);
break;
case SPELL_CALL_ADDS:
for (uint8 i = 0; i < 4; ++i)
me->SummonCreature(i < 2 ? 117596 : 116569, addsPos[i]);
break;
case SPELL_FROSTY_DISCHARGE:
events.RescheduleEvent(EVENT_DRAW_IN, 59000);
events.RescheduleEvent(EVENT_CALL_ADDS, 17000);
if (IsMythicRaid())
events.RescheduleEvent(EVENT_HATCHING, 30000);
break;
}
}
void OnApplyOrRemoveAura(uint32 spellId, AuraRemoveMode /*mode*/, bool apply) override
{
switch (spellId)
{
case SPELL_FRIGID_BLOWS:
if (apply)
return;
me->SetPower(me->GetPowerType(), 0);
DoCast(SPELL_FROSTY_DISCHARGE);
break;
case SPELL_DRAW_IN:
if (apply)
return;
if (!me->HasAura(SPELL_FRIGID_BLOWS))
{
DoCast(SPELL_FROSTY_DISCHARGE);
me->SetPower(me->GetPowerType(), 0);
}
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (CheckHomeDistToEvade(diff, 50.0f))
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CHECK_ENERGY:
if (me->GetPower(POWER_ENERGY) >= 100)
DoCast(SPELL_UNCHECKED_RAGE);
events.RescheduleEvent(EVENT_CHECK_ENERGY, 500);
break;
case EVENT_CALL_ADDS:
Talk(SAY_CALL);
DoCast(SPELL_CALL_ADDS);
events.RescheduleEvent(EVENT_CALL_ADDS, 36000);
break;
case EVENT_DRAW_IN:
Talk(SAY_DRAW_IN);
DoCast(SPELL_DRAW_IN);
break;
case EVENT_HATCHING:
{
DoCast(SPELL_ENQUBATION);
std::vector<uint8> eggsIndexes{ 0, 1, 2, 3 };
std::list<uint8> eggsColors{ 0, 1, 2 };
Trinity::Containers::RandomResize(eggsIndexes, 2);
Trinity::Containers::RandomResize(eggsColors, 2);
for (auto i : eggsIndexes)
{
uint8 color = eggsColors.front();
eggsColors.pop_front();
if (eggsCasts[color] == SPELL_ENQUBATION_GREEN)
{
for (const auto& guid : eggs[i])
if (Creature* egg = instance->instance->GetCreature(guid))
{
if (!egg->IsAlive())
egg->Respawn(true);
egg->AI()->EnterCombat(me->GetVictim());
egg->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_ATTACKABLE_1);
egg->CastSpell(egg, SPELL_HARDENED_SHELL);
egg->CastSpellDelay(egg, eggsCasts[color], false, 100);
}
}
else
if (Creature* egg = instance->instance->GetCreature(eggs[i][urand(0, eggs[i].size())]))
{
if (!egg->IsAlive())
egg->Respawn(true);
egg->AI()->EnterCombat(me->GetVictim());
egg->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_ATTACKABLE_1);
egg->CastSpell(egg, SPELL_HARDENED_SHELL);
egg->CastSpellDelay(egg, eggsCasts[color], false, 100);
}
}
events.RescheduleEvent(EVENT_HATCHING_CLEAN_UP, 28000);
break;
}
case EVENT_HATCHING_CLEAN_UP:
{
for (const auto& vector : eggs)
for (const auto& guid : vector.second)
if (Creature* egg = instance->instance->GetCreature(guid))
{
if (!egg->IsAlive())
egg->Respawn(true);
else
egg->SetHealth(egg->GetMaxHealth());
for (const auto& spell : eggsCasts)
egg->RemoveAurasDueToSpell(spell);
egg->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_ATTACKABLE_1);
}
break;
}
case EVENT_ENRAGE:
DoCast(SPELL_ENRAGE);
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new boss_harjatanAI(creature);
}
};
// 121184
class npc_mistress_sasszine : public CreatureScript
{
public:
npc_mistress_sasszine() : CreatureScript("npc_mistress_sasszine") {}
struct npc_mistress_sasszineAI : ScriptedAI
{
npc_mistress_sasszineAI(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
SetCanSeeEvenInPassiveMode(true);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
}
bool _introDone = false;
uint32 introAdds = 0;
void DoAction(const int32) override
{
if (!introAdds)
introAdds = 1;
switch (--introAdds)
{
case 1:
Talk(2);
break;
case 0:
me->CastSpell(me, 241744);
me->CastSpellDelay(me, 241680, false, 11000);
me->DespawnOrUnsummon(13500);
break;
}
}
void MoveInLineOfSight(Unit* who) override
{
if (!who->IsPlayer())
return;
if (me->GetDistance(who) < 100.0f && !_introDone)
{
_introDone = true;
InstanceScript* instance = me->GetInstanceScript();
if (!instance)
return;
if (instance->GetBossState(DATA_HARJATAN) != NOT_STARTED)
{
me->DespawnOrUnsummon();
return;
}
Talk(0);
for (auto id : { NPC_EVENT_1, NPC_EVENT_2 })
if (Creature* add = instance->instance->GetCreature(instance->GetGuidData(id)))
if (add->IsAlive())
++introAdds;
if (introAdds)
return;
me->CastSpellDelay(me, 241744, false, 11000);
me->CastSpellDelay(me, 241680, false, 21000);
me->DespawnOrUnsummon(23500);
}
}
void UpdateAI(uint32 diff) override {}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_mistress_sasszineAI(creature);
}
};
// 121155
struct npc_tos_tadpole : ScriptedAI
{
npc_tos_tadpole(Creature* creature) : ScriptedAI(creature) {}
uint32 timer;
bool canDoEvent = false;
void DoAction(const int32) override
{
me->SetReactState(REACT_PASSIVE);
me->AddDelayedEvent(1500, [this]()-> void
{
if (Unit* target = me->GetVictim())
{
me->GetMotionMaster()->MoveFollow(target, 0, 0);
me->CastSpell(target, 241600);
}
timer = 1000;
canDoEvent = true;
});
}
void JustDied(Unit*) override
{
DoCast(me, 241587, true);
}
void UpdateAI(uint32 diff) override
{
if (canDoEvent)
{
if (timer <= diff)
{
if (Unit* target = me->GetVictim())
{
if (me->GetDistance2d(target) <= 2.2f)
{
DoCast(241603);
me->DespawnOrUnsummon(100);
}
else
me->GetMotionMaster()->MoveFollow(target, 0, 0);
}
else
me->DespawnOrUnsummon();
timer = 1000;
}
else
timer -= diff;
}
}
};
// 121071 achievement npc
class npc_elder_murk_eye : public CreatureScript
{
public:
npc_elder_murk_eye() : CreatureScript("npc_elder_murk_eye") {}
struct npc_elder_murk_eyeAI : ScriptedAI
{
npc_elder_murk_eyeAI(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
instance = me->GetInstanceScript();
}
EventMap events;
InstanceScript* instance;
uint32 CheckTimer;
uint32 EvadeTimer;
Position const jumppoint = { 5892.11f, -898.21f, 2919.83f, 5.7f };
void Initialize()
{
CheckTimer = 2000;
EvadeTimer = 5000;
}
void Reset() override
{
events.Reset();
me->SetReactState(REACT_PASSIVE);
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->RemoveAura(241416);
me->RemoveAura(241393);
}
void EnterCombat(Unit* /*who*/) override
{
events.RescheduleEvent(EVENT_ELDER1, 6000); //wave
events.RescheduleEvent(EVENT_ELDER2, 8000); //splash
events.RescheduleEvent(EVENT_ELDER3, 25000); //rage
}
void UpdateAI(uint32 diff) override
{
if ((!me->IsInCombat()) && (instance->GetBossState(DATA_HARJATAN) == FAIL) || (!me->IsInCombat()) && (instance->GetBossState(DATA_HARJATAN) == NOT_STARTED))
{
if (EvadeTimer <= diff)
{
EnterEvadeMode();
EvadeTimer = 5000;
}
else EvadeTimer -= diff;
}
if ((!me->IsInCombat()) && (instance->GetBossState(DATA_HARJATAN) == IN_PROGRESS))
{
if (CheckTimer <= diff)
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->HasAura(232454))
{
me->SetVisible(true);
me->GetMotionMaster()->MoveJump(jumppoint, 10.0f, 10.0f);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_AGGRESSIVE);
break;
}
CheckTimer = 2000;
}
else CheckTimer -= diff;
}
if (!UpdateVictim())
return;
events.Update(diff);
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ELDER1:
DoCast(SPELL_SONIC_WAVE);
events.RescheduleEvent(EVENT_ELDER1, 6000);
break;
case EVENT_ELDER2:
DoCast(SPELL_SPLASH);
events.RescheduleEvent(EVENT_ELDER2, 20000);
break;
case EVENT_ELDER3:
DoCast(SPELL_ELDERS_RAGE);
events.RescheduleEvent(EVENT_ELDER3, 45000);
break;
}
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* Harjatan = instance->instance->GetCreature(instance->GetGuidData(NPC_HARJATAN)))
{
Harjatan->AI()->DoAction(ACTION_COMPLETE);
}
instance->DoRemoveAurasDueToSpellOnPlayers(231770);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_elder_murk_eyeAI(creature);
}
};
// 231854
class spell_tos_unchecked_rage : public SpellScriptLoader
{
public:
spell_tos_unchecked_rage() : SpellScriptLoader("spell_tos_unchecked_rage") { }
class spell_tos_unchecked_rage_SpellScript : public SpellScript
{
PrepareSpellScript(spell_tos_unchecked_rage_SpellScript);
void CorrectTargets(std::list<WorldObject*>& targets)
{
if (!GetCaster())
return;
auto caster = GetCaster();
if (targets.size() < 5)
caster->CastSpell(caster, 247782, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_tos_unchecked_rage_SpellScript::CorrectTargets, SpellEffIndex::EFFECT_0, Targets::TARGET_UNIT_CONE_ENEMY_104);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_tos_unchecked_rage_SpellScript();
};
};
// 234016
class spell_tos_fixate : public AuraScript
{
PrepareAuraScript(spell_tos_fixate);
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
Unit* caster = GetCaster();
if (!target || !caster)
return;
caster->AddAura(234128, caster);
caster->AddThreat(target, std::numeric_limits<float>::max());
caster->TauntApply(target);
}
void OnRemove(AuraEffect const* /*auraEffect*/, AuraEffectHandleModes /*mode*/)
{
if (GetCaster() && GetTarget())
GetCaster()->TauntFadeOut(GetTarget());
}
void Register()
{
OnEffectApply += AuraEffectApplyFn(spell_tos_fixate::OnApply, EFFECT_0, SPELL_AURA_FIXATE, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_tos_fixate::OnRemove, SpellEffIndex::EFFECT_0, SPELL_AURA_FIXATE, AuraEffectHandleModes::AURA_EFFECT_HANDLE_REAL);
}
};
// 232061
class spell_tos_draw_in : public AuraScript
{
PrepareAuraScript(spell_tos_draw_in);
uint8 counter = 0;
void OnTick(AuraEffect const* /*aurEff*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
std::list<AreaTrigger*> list;
caster->GetAreatriggerListInRange(list, 80.0f);
list.remove_if([](AreaTrigger* at1) { AreaTriggerTemplate const* t1 = at1->GetTemplate(); return !t1 || t1->Id != 13251; });
uint8 realCount = 0;
for (std::list<AreaTrigger*>::const_iterator itr = list.begin(); itr != list.end(); itr++)
{
if ((*itr)->GetDuration() <= 9000)
continue;
// adaptation : notre API de creation manuelle d AT differe, on recaste le sort
// createur (231754) a la meme position pour regenerer la zone avec sa duree fraiche
caster->CastSpell((*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), 231754, true);
(*itr)->RemoveFromWorld();
++realCount;
}
for (uint8 i = 0; i < realCount; ++i)
caster->CastSpellDelay(caster, SPELL_FRIGID_BLOWS, true, (1 + i) * GetDuration() / realCount);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tos_draw_in::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
class achievement_grand_fin_ale : public AchievementCriteriaScript
{
public:
achievement_grand_fin_ale() : AchievementCriteriaScript("achievement_grand_fin_ale") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
if (!target)
return false;
if (Creature* boss = target->ToCreature())
if (boss->AI()->GetData(DATA_COMPLETE))
return true;
return false;
}
};
void AddSC_boss_harjatan()
{
new boss_harjatan();
new npc_mistress_sasszine();
new npc_elder_murk_eye();
new achievement_grand_fin_ale();
RegisterCreatureAI(npc_tos_tadpole);
new spell_tos_unchecked_rage();
RegisterAuraScript(spell_tos_fixate);
RegisterAuraScript(spell_tos_draw_in);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,785 @@
/*
* This file is part of the DestinyCore 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 "tomb_of_sargeras.h"
enum Says
{
SAY_AGGRO = 0,
SAY_INFUSION_START = 1,
SAY_INFUSION_END = 2,
SAY_SECOND_PHASE = 3,
SAY_SECOND_PHASE_LATER = 4,
SAY_BEFORE_DEATH = 5, // ????????????
SAY_DEATH = 6,
};
enum Spells
{
// Global
SPELL_INFUSION = 235271, //
SPELL_MASS_INSTABILITY = 235267, // real cast aura (235117) + 8 //
SPELL_UNSTABLE_SOUL = 235117, // maybe need it late 243275 //
// Light Side
SPELL_LIGHT_INFUSION = 235213, // dmg 235214 //
SPELL_HAMMER_OF_CREATION = 241635, // Aoe 235569 and tank dmg 241624 //
SPELL_HAMMER_OF_CREATION_AOE = 235569, //
SPELL_HAMMER_OF_CREATION_VICT = 241624, //
SPELL_LIGHT_REMANENCE = 237994, // 119825
SPELL_LIGHT_REMANENCE_SMALL = 238311, // myth
// Fel side
SPELL_FEL_INFUSION = 235240, // dmg 235253 //
SPELL_HAMMER_OF_OBLITERATION = 241636, // aoe dmg 235573 and tank dmg 241634 + 17 //
SPELL_HAMMER_OF_OBLITERATION_AOE = 235573, //
SPELL_HAMMER_OF_OBLITERATION_VICT = 241634, //
SPELL_FEL_REMANENCE = 238316, // 119826
SPELL_FEL_REMANENCE_SMALL = 238416, // myth
// Phase two
SPELL_MOVE_TO_ANOTHER = 235630,
SPELL_BLOWBACK = 248812, // by links; can find auras //
SPELL_TITANIC_BULWARK = 235028, // by links //
SPELL_WRATH_OF_THE_CREATORS = 234891, // dmg 234896 (holy) and 236432(fel)
SPELL_WRATH_OF_THE_CREATORS_TICK = 235014, //
SPELL_WRATH_OF_THE_CREATORS_TICK_LIGHT = 234917, //
SPELL_WRATH_OF_THE_CREATORS_TICK_FEL = 236433, //
SPELL_WRATH_OF_THE_CREATORS_TICK_LIGHT_DMG = 234896, //
SPELL_WRATH_OF_THE_CREATORS_TICK_FEL_DMG = 236432, //
SPELL_WRATH_OF_THE_CREATORS_BUFF = 237339, //
SPELL_EXTINGUISH_LIFE = 238475, //
SPELL_ESSENCE_FRAGMENTS = 236061, //
SPELL_ESSENCE_FRAGMENTS_TICK = 235859, //
SPELL_CREATE_AT_VISUAL_FEL = 236708, //
SPELL_CREATE_AT_VISUAL_LIGHT = 236690, //
SPELL_ESSENCE_HIT_LIGHT = 235554, // visual
SPELL_ESSENCE_BUFF_LIGHT = 235534, //
SPELL_ESSENCE_HIT_FEL = 235555, // visual
SPELL_ESSENCE_BUFF_FEL = 235538, //
// myth
SPELL_FRAGMENT_BURST = 239069,
SPELL_FRAGMENT_BURST_DEBUFF = 241729,
SPELL_FRAGMENTING = 239153,
SPELL_LIGHT_FRAGMENT = 241697,
SPELL_LIGHT_FRAGMENT_FOCUS = 241713,
SPELL_FEL_FRAGMENT = 241728,
SPELL_FEL_FRAGMENT_FOCUS = 241727,
SPELL_ENRAGE = 64238, //
SPELL_SHIELD = 241593,
SPELL_UNKWN = 237856, // also 235859
};
enum eEvents
{
EVENT_INFUSION = 1,
EVENT_LIGHT_HAMMER,
EVENT_FEL_HAMMER,
EVENT_MASS_INSTABILITY,
EVENT_SECOND_PHASE,
EVENT_FRAGMENTS,
};
Position const fragmentsPos[6]
{
{6375.67f, -789.47f, 2887.84f, 0.0f}, // original right 1
{6384.21f, -788.24f, 2887.84f, 0.0f}, // original right 2
{6394.00f, -786.70f, 2887.84f, 0.0f}, // original right 3
{6376.05f, -799.67f, 2887.84f, 0.0f}, // original left 1
{6384.74f, -801.70f, 2887.84f, 0.0f}, // original left 2
{6393.59f, -803.61f, 2887.84f, 0.0f} // original left 3
//6319.85 other side
};
// 118289
struct boss_maiden_of_vigilance : BossAI
{
boss_maiden_of_vigilance(Creature* creature) : BossAI(creature, DATA_MAIDEN_OF_VIGILANCE) {}
uint32 wrathOfCreatorsCasts;
uint32 countOfTeleports;
bool empoweredPhase;
bool isFelNeed = true;
void Reset() override
{
if (me->IsAlive())
_Reset();
me->KillAllDelayedEvents();
wrathOfCreatorsCasts = 0;
countOfTeleports = 0;
empoweredPhase = false; // set true on 3 phase (second 1 phase)
SetCombatMovement(true);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_LIGHT_INFUSION);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FEL_INFUSION);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SHIELD);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FRAGMENT_BURST_DEBUFF);
me->SetReactState(REACT_DEFENSIVE);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, false);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_EnterCombat();
me->AddDelayedEvent(480000, [this]() -> void
{
DoCast(me, SPELL_ENRAGE, true);
});
if (!IsLfrRaid())
{
events.RescheduleEvent(EVENT_INFUSION, 2000);
events.RescheduleEvent(EVENT_LIGHT_HAMMER, 12000);
events.RescheduleEvent(EVENT_MASS_INSTABILITY, 21000);
events.RescheduleEvent(EVENT_SECOND_PHASE, 40000);
if (IsMythicRaid())
events.RescheduleEvent(EVENT_FRAGMENTS, 10000);
}
else
{
events.RescheduleEvent(EVENT_MASS_INSTABILITY, 6000);
events.RescheduleEvent(EVENT_INFUSION, 40000);
events.RescheduleEvent(EVENT_SECOND_PHASE, 47000);
}
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
Reset();
}
void JustSummoned(Creature* creature) override
{
BossAI::JustSummoned(creature);
switch (creature->GetEntry())
{
case NPC_REMANENCE_LIGHT:
if (IsHeroicPlusRaid())
creature->CastSpell(creature, SPELL_LIGHT_REMANENCE_SMALL);
break;
case NPC_REMANENCE_FEL:
if (IsHeroicPlusRaid())
creature->CastSpell(creature, SPELL_FEL_REMANENCE_SMALL);
break;
}
}
void SummonedCreatureDespawn(Creature* creature) override
{
if (!IsMythicRaid())
return;
switch (creature->GetEntry())
{
case NPC_ESSENCE_FEL:
case NPC_ESSENCE_LIGHT:
me->CastSpell(me, SPELL_FRAGMENT_BURST, true);
break;
}
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_HAMMER_OF_CREATION_AOE:
case SPELL_HAMMER_OF_CREATION_VICT:
if (target->HasAura(SPELL_FEL_INFUSION))
DoCast(target, SPELL_UNSTABLE_SOUL, true);
break;
case SPELL_HAMMER_OF_OBLITERATION_AOE:
case SPELL_HAMMER_OF_OBLITERATION_VICT:
if (target->HasAura(SPELL_LIGHT_INFUSION))
DoCast(target, SPELL_UNSTABLE_SOUL, true);
break;
}
}
void SpellFinishCast(SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_MASS_INSTABILITY:
{
uint32 spell = isFelNeed ? SPELL_FEL_INFUSION : SPELL_LIGHT_INFUSION;
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0,
[spell](Unit* targett)
{
if (!targett->IsPlayer() || !targett->IsAlive() || !targett->ToPlayer()->isInTankSpec())
return false;
return targett->HasAura(spell);
}))
me->CastSpell(target, SPELL_UNSTABLE_SOUL, false);
for (uint32 spell : {SPELL_LIGHT_INFUSION, SPELL_FEL_INFUSION})
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0,
[spell](Unit* targett)
{
if (!targett->IsPlayer() || !targett->IsAlive() || targett->ToPlayer()->isInTankSpec())
return false;
return targett->HasAura(spell);
}))
me->CastSpell(target, SPELL_UNSTABLE_SOUL, false);
break;
}
case SPELL_WRATH_OF_THE_CREATORS_TICK:
{
bool lightOrFel = wrathOfCreatorsCasts++ % 2 == 0;
me->CastSpell(me, lightOrFel ? SPELL_WRATH_OF_THE_CREATORS_TICK_LIGHT : SPELL_WRATH_OF_THE_CREATORS_TICK_FEL, true);
instance->instance->ApplyOnEveryPlayer([this, lightOrFel](Player* player)
{
me->CastSpell(player, lightOrFel ? SPELL_WRATH_OF_THE_CREATORS_TICK_LIGHT_DMG : SPELL_WRATH_OF_THE_CREATORS_TICK_FEL_DMG, true);
});
if (me->GetAuraCount(SPELL_WRATH_OF_THE_CREATORS_BUFF) >= 30)
{
// me->CastStop();
instance->instance->ApplyOnEveryPlayer([this](Player* player)
{
me->CastSpell(player, SPELL_EXTINGUISH_LIFE, true);
});
// OnInterruptCast(me, NULL, SPELL_WRATH_OF_THE_CREATORS, NULL);
}
break;
}
case SPELL_ESSENCE_FRAGMENTS_TICK:
// countOfTeleports % 2 == 1 - other side, == 0 - original side
for (uint8 i =0;i < 6;++i)
{
const auto& pos = fragmentsPos[i];
uint32 spellid = (urand(1, 2) == 1 ? SPELL_CREATE_AT_VISUAL_FEL : SPELL_CREATE_AT_VISUAL_LIGHT);
me->CastSpell(pos.GetPositionX() - (countOfTeleports % 2 == 1 ? 73.2f : 0), pos.GetPositionY(), pos.GetPositionZ(), spellid, true);
if (Creature* add = me->SummonCreature((spellid == SPELL_CREATE_AT_VISUAL_FEL ? NPC_ESSENCE_FEL : NPC_ESSENCE_LIGHT), pos.GetPositionX() - (countOfTeleports % 2 == 1 ? 73.2f : 0), pos.GetPositionY(), pos.GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 12000))
{
float change_speed = 1.2f * M_PI*add->GetDistance2d(6348.20f, -795.95f) / 45;
add->SetSpeed(MOVE_WALK, change_speed);
add->GetMotionMaster()->MoveCirclePath(6348.20f, -795.95f, add->GetPositionZ(), add->GetDistance2d(6348.20f, -795.95f), (countOfTeleports % 2 == 0 ? i > 2 : i <= 2), 24);
}
}
break;
case SPELL_HAMMER_OF_CREATION:
case SPELL_HAMMER_OF_OBLITERATION:
DoCastTopAggro(spell->Id == SPELL_HAMMER_OF_OBLITERATION ? SPELL_HAMMER_OF_OBLITERATION_VICT : SPELL_HAMMER_OF_CREATION_VICT, true);
DoCastTopAggro(spell->Id == SPELL_HAMMER_OF_OBLITERATION ? SPELL_HAMMER_OF_OBLITERATION_AOE : SPELL_HAMMER_OF_CREATION_AOE, true);
if (IsHeroicPlusRaid())
{
uint32 spellid = spell->Id == SPELL_HAMMER_OF_CREATION ? SPELL_FEL_INFUSION : SPELL_LIGHT_INFUSION;
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0,
[spellid](Unit* targett)
{
if (!targett->IsPlayer() || !targett->IsAlive())
return false;
return targett->HasAura(spellid);
}))
me->CastSpell(target, spell->Id == SPELL_HAMMER_OF_OBLITERATION ? SPELL_FEL_REMANENCE : SPELL_LIGHT_REMANENCE, true);
}
break;
}
}
void OnApplyOrRemoveAura(uint32 spellId, AuraRemoveMode /*mode*/, bool apply) override
{
if (spellId != SPELL_BLOWBACK || !me->IsInCombat() || !me->IsAlive())
return;
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, apply);
}
void OnInterruptCast(Unit* /*caster*/, uint32 spellId, uint32 curSpellID, uint32 /*schoolMask*/) override
{
if (curSpellID == SPELL_WRATH_OF_THE_CREATORS)
{
empoweredPhase = true;
me->SetReactState(REACT_DEFENSIVE);
if (!IsLfrRaid())
{
events.RescheduleEvent(EVENT_INFUSION, 3000);
events.RescheduleEvent(EVENT_LIGHT_HAMMER, 12000);
events.RescheduleEvent(EVENT_MASS_INSTABILITY, 21000);
events.RescheduleEvent(EVENT_SECOND_PHASE, 82000);
if (IsMythicRaid())
events.RescheduleEvent(EVENT_FRAGMENTS, 8000);
}
else
{
events.RescheduleEvent(EVENT_MASS_INSTABILITY, 8000);
events.RescheduleEvent(EVENT_INFUSION, 21000);
events.RescheduleEvent(EVENT_SECOND_PHASE, 67000);
}
}
}
void UpdateAI(uint32 diff) override
{
if (me->HasAura(SPELL_WRATH_OF_THE_CREATORS))
{
bool needEvade = true;
auto list = me->getThreatManager().getThreatList();
for (auto& itr: list)
if (Unit* target = itr->getTarget())
if (target->IsPlayer() && target->IsAlive())
{
needEvade = false;
break;
}
if (needEvade)
EnterEvadeMode();
return;
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_INFUSION:
me->CastSpell(me, SPELL_INFUSION);
if (!empoweredPhase)
Talk(SAY_INFUSION_START);
if (empoweredPhase)
events.RescheduleEvent(EVENT_INFUSION, 38000);
break;
case EVENT_LIGHT_HAMMER:
DoCast(SPELL_HAMMER_OF_CREATION);
isFelNeed = false;
events.RescheduleEvent(EVENT_FEL_HAMMER, 19000);
break;
case EVENT_FEL_HAMMER:
DoCast(SPELL_HAMMER_OF_OBLITERATION);
isFelNeed = true;
if (empoweredPhase)
events.RescheduleEvent(EVENT_LIGHT_HAMMER, 19000);
break;
case EVENT_MASS_INSTABILITY:
DoCast(SPELL_MASS_INSTABILITY);
if (empoweredPhase)
events.RescheduleEvent(EVENT_MASS_INSTABILITY, 36000);
break;
case EVENT_SECOND_PHASE:
events.Reset();
Talk(SAY_SECOND_PHASE);
me->AddDelayedEvent(8000, [this]()
{
Talk(SAY_SECOND_PHASE_LATER);
});
wrathOfCreatorsCasts = 0;
if (++countOfTeleports % 2)
me->CastSpell(6310.30f, -795.36f, 2887.84f, SPELL_MOVE_TO_ANOTHER);
else
me->CastSpell(me->GetHomePosition(), SPELL_MOVE_TO_ANOTHER,false);
SetCombatMovement(false);
me->SetReactState(REACT_PASSIVE);
break;
case EVENT_FRAGMENTS:
{
Unit* target = nullptr;
for (int8 i = 2; i >= 0; i--)
if (target = SelectTarget(SELECT_TARGET_RANDOM, i))
break;
if (!target)
break;
DoCast(SPELL_FRAGMENTING);
bool isFelFragment = target->HasAura(SPELL_LIGHT_INFUSION);
me->CastSpell(target, (isFelFragment ? SPELL_FEL_FRAGMENT : SPELL_LIGHT_FRAGMENT));
Position pos(target->GetPosition());
ObjectGuid guid = target->GetGUID();
me->AddDelayedEvent(3000, [this, guid, isFelFragment, pos]() -> void
{
me->SummonCreature((isFelFragment ? NPC_ESSENCE_FEL : NPC_ESSENCE_LIGHT), pos, TEMPSUMMON_TIMED_DESPAWN, 10000);
});
break;
}
}
}
DoMeleeAttackIfReady();
}
};
// 118640 light 118643 fel
struct npc_tos_essences : ScriptedAI
{
npc_tos_essences(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
SetCanSeeEvenInPassiveMode(true);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
; // (m_RateUpdateTimer : optimisation de cadence uwow, non portee)
}
bool justDoIt = false;
uint32 updateTimer = 200;
void IsSummonedBy(Unit* cre) override
{
if (me->GetTarget().IsEmpty())
return;
Unit* unit = me->GetVictim();
if (!unit || !unit->IsAlive())
unit = me->FindNearestPlayer(60, true);
if (unit)
me->GetMotionMaster()->MoveFollow(unit, 0, 0);
}
void UpdateAI(uint32 diff) override
{
if (justDoIt)
return;
if (updateTimer <= diff)
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (const auto& itr : players)
{
Player* who = itr.GetSource();
if (!who->IsAlive())
continue;
if (me->GetDistance(who) < 0.22f && !justDoIt)
{
justDoIt = true;
me->CastSpell(who, me->GetEntry() == NPC_ESSENCE_FEL ? SPELL_ESSENCE_HIT_FEL : SPELL_ESSENCE_HIT_LIGHT);
if (who->HasAura(SPELL_LIGHT_INFUSION) && me->GetEntry() == NPC_ESSENCE_LIGHT)
{
for (const auto& itr : players)
if (Player* temp = itr.GetSource())
if ((temp == who || temp->GetDistance(who) <= 10.0f) && temp->HasAura(SPELL_LIGHT_INFUSION))
temp->CastSpell(temp, SPELL_ESSENCE_BUFF_LIGHT);
}
else if (who->HasAura(SPELL_FEL_INFUSION) && me->GetEntry() == NPC_ESSENCE_FEL)
{
for (const auto& itr : players)
if (Player* temp = itr.GetSource())
if ((temp == who || temp->GetDistance(who) <= 10.0f) && temp->HasAura(SPELL_FEL_INFUSION))
temp->CastSpell(temp, SPELL_ESSENCE_BUFF_FEL);
}
else
who->CastSpell(who, SPELL_UNSTABLE_SOUL);
if (TempSummon* tempSum = me->ToTempSummon()) // we need it for disabling call SummonedCreatureDespawn
; // (SetSummonerGUID : detachement du summoner, non porte)
me->DespawnOrUnsummon(100);
break;
}
}
updateTimer = 200;
}
else
updateTimer -= diff;
}
};
// 120132, 120131
struct npc_tos_essences_intro : ScriptedAI
{
npc_tos_essences_intro(Creature* creature) : ScriptedAI(creature)
{
SetCanSeeEvenInPassiveMode(true);
}
std::set<ObjectGuid> players{};
uint32 timer = 500;
void UpdateAI(uint32 diff) override
{
if (timer <= diff)
{
Map::PlayerList const& pPlayers = me->GetMap()->GetPlayers();
for (const auto& itr : pPlayers)
{
Player* who = itr.GetSource();
if (me->GetDistance(who) < 1.0f)
{
if (players.find(who->GetGUID()) != players.end())
return;
players.insert(who->GetGUID());
uint32 enemySpell = (me->GetEntry() == 120132 ? 239408 : 239407);
if (who->HasAura(enemySpell))
who->CastSpell(who, 239409);
else
who->CastSpell(who, (me->GetEntry() != 120132 ? 239408 : 239407));
}
}
timer = 500;
}
else
timer -= diff;
}
};
// 235271
class spell_tos_infusion : public SpellScript
{
PrepareSpellScript(spell_tos_infusion);
std::vector<uint32> spellsForTank{ SPELL_LIGHT_INFUSION, SPELL_FEL_INFUSION };
void CorrectTargets(std::list<WorldObject*>& targets)
{
if (!GetCaster())
return;
auto caster = GetCaster();
if (caster->IsCreature())
caster->ToCreature()->AI()->Talk(SAY_INFUSION_END);
targets.remove_if([](WorldObject* target)
{
return !target->IsPlayer();
});
for (auto itr = targets.begin(); itr != targets.end(); )
{
Unit* target = (*itr)->ToUnit();
if (!target->IsPlayer())
{
++itr;
continue;
}
for (auto spell : { SPELL_LIGHT_INFUSION, SPELL_FEL_INFUSION })
target->ToUnit()->RemoveAurasDueToSpell(spell);
if (Player* player = target->ToPlayer())
if (ROLE_TANK == player->GetRoleForGroup() && !spellsForTank.empty()) // tanks have are different buffs
{
caster->CastSpell(player, spellsForTank.back(), true);
spellsForTank.pop_back();
itr = targets.erase(itr);
continue;
}
++itr;
}
uint8 i = 0;
for (auto target : targets)
{
if (!target->IsPlayer())
continue;
for (auto spell : { SPELL_LIGHT_INFUSION, SPELL_FEL_INFUSION })
target->ToUnit()->RemoveAurasDueToSpell(spell);
if (++i <= (targets.size() / 2))
caster->CastSpell(target->ToUnit(), SPELL_LIGHT_INFUSION, true);
else
caster->CastSpell(target->ToUnit(), SPELL_FEL_INFUSION, true);
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_tos_infusion::CorrectTargets, SpellEffIndex::EFFECT_0, Targets::TARGET_UNIT_DEST_AREA_ENEMY);
}
};
// 248812
class spell_tos_blowback : public AuraScript
{
PrepareAuraScript(spell_tos_blowback);
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (!GetCaster() || !GetTarget())
return;
if (GetCaster()->GetDistance2d(GetTarget()) >= 60.0f)
SetDuration(10);
else
SetDuration(1000*(60-GetCaster()->GetDistance2d(GetTarget())) * 12.0f / 60.0f);
}
void Register()
{
OnEffectApply += AuraEffectApplyFn(spell_tos_blowback::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
}
};
// 234896, 236432
class spell_tos_wrath_of_the_creators : public SpellScript
{
PrepareSpellScript(spell_tos_wrath_of_the_creators);
void HandleDamage(SpellEffIndex /*effectIndex*/)
{
if (!GetCaster())
return;
if (auto caster = GetCaster())
{
uint32 count = caster->GetAuraCount(SPELL_WRATH_OF_THE_CREATORS_BUFF);
SetHitDamage(GetHitDamage() * (1 + 0.05*count));
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_tos_wrath_of_the_creators::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 235117
class spell_tos_unstable_soul : public AuraScript
{
PrepareAuraScript(spell_tos_unstable_soul);
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (!GetTarget())
return;
Unit* target = GetTarget();
if (target->GetAuraCount(235117) <= 1)
{
target->CastSpell(target, 249912);
return;
}
Aura* aura = GetAura();
if (target->GetMap()->IsMythic())
{
target->RemoveAppliedAuras(235117, [aura](AuraApplication const* aplication) -> bool
{
Aura const* curAura = aplication->GetBase();
return curAura != aura;
});
target->CastSpell(target, 249912);
}
else
target->RemoveAura(aura);
}
void Register()
{
OnEffectApply += AuraEffectApplyFn(spell_tos_unstable_soul::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
// 235213 235240
class spell_tos_infusions : public AuraScript
{
PrepareAuraScript(spell_tos_infusions);
bool isFirstTick = true;
void OnTick(AuraEffect const* /*aurEff*/)
{
Unit* target = GetTarget();
if (!target)
return;
if (isFirstTick)
{
isFirstTick = false;
return;
}
else
{
target->RemoveAurasDueToSpell(GetSpellInfo()->Id == SPELL_FEL_INFUSION ? 241316 : 241315);
if (target->IsAlive())
target->CastSpell(target, GetSpellInfo()->Id == SPELL_FEL_INFUSION ? 241316 : 241315, true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tos_infusions::OnTick, EFFECT_0, SPELL_AURA_ANY);
}
};
// 241593
class spell_egvin_levitation : public AuraScript
{
PrepareAuraScript(spell_egvin_levitation);
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (!GetTarget())
return;
Unit* target = GetTarget();
if (!target->GetMap()->IsHeroicPlusRaid())
target->CastSpell(target, 241565, true);
}
void Register()
{
OnEffectApply += AuraEffectApplyFn(spell_egvin_levitation::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_maiden_of_vigilance()
{
RegisterCreatureAI(boss_maiden_of_vigilance);
RegisterCreatureAI(npc_tos_essences);
RegisterCreatureAI(npc_tos_essences_intro);
RegisterSpellScript(spell_tos_infusion);
RegisterAuraScript(spell_tos_blowback);
RegisterSpellScript(spell_tos_wrath_of_the_creators);
RegisterAuraScript(spell_tos_unstable_soul);
RegisterAuraScript(spell_tos_infusions);
RegisterAuraScript(spell_egvin_levitation);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,391 +0,0 @@
/*
* Copyright (C) 2016-2019 MagicStaorm
*
* Este codigo es de uso exclusivo y privado para la red de gaming
* ColossusWoW está totalmente prohibida su distribución y
* uso en proyectos ajenos, si has obtenido o encontrado este codigo
* publicamente envianos un email a administracion@colossuswow.com
* indicandonos como y donde has obtenido este codigo
*
* Recuerda, no distribuyas, no compartas y no subas este codigo a ningun
* lugar publico, usa siempre nuestros repositorios Git!
*/
#include "tomb_of_sargeras.h"
enum atriganSpells
{
SPELL_TORMENT = 233104,
SPELL_BONE_SCYTHE = 233423,
SPELL_SCYTHE_SWIP = 233426,
SPELL_BONE_SAW = 233441,
SPELL_UNBEARABLE_TORMENT = 233430,
};
enum atriganEvents
{
EVENT_TORMENT = 1,
EVENT_BONE_SCYTHE,
EVENT_SCYTHE_SWIP,
EVENT_BONE_SAW,
EVENT_CHECK_FOR_PLAYERS,
};
class boss_atrigan : public CreatureScript
{
public:
boss_atrigan() : CreatureScript("boss_atrigan") {}
struct boss_atriganAI : public BossAI
{
boss_atriganAI(Creature* creature) : BossAI(creature, DATA_ATRIGAN)
{
instance->SetBossState(DATA_ATRIGAN, NOT_STARTED);
}
Vehicle* vehicle;
bool isCasting;
int8 count = 0;
void Reset() override
{
_Reset();
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->SetBossState(DATA_ATRIGAN, FAIL);
}
events.Reset();
}
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
me->GetMotionMaster()->MoveTargetedHome();
_DespawnAtEvade(0, nullptr);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
//Talk(SAY_COMBAT);
me->SetPower(POWER_ENERGY, 0);
me->setActive(true);
DoZoneInCombat();
SetPlayersInCombat(true);
}
void JustDied(Unit* /*killer*/) override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustDied();
instance->SetBossState(DATA_ATRIGAN, DONE);
}
//Talk(SAY_DIED);
}
void KilledUnit(Unit* victim) override
{
//if (victim->GetTypeId() == TYPEID_PLAYER)
// Talk(SAY_KILL);
}
void JustReachedHome() override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(DATA_ATRIGAN, FAIL);
}
}
void DespawnGameObjects(uint32 entry)
{
std::list<GameObject*> gameObjects;
GetGameObjectListWithEntryInGrid(gameObjects, me, entry, 1000.0f);
if (gameObjects.empty())
return;
for (std::list<GameObject*>::iterator iter = gameObjects.begin(); iter != gameObjects.end(); ++iter)
(*iter)->Delete();
}
void DespawnCreatures(uint32 entry)
{
std::list<Creature*> creatures;
GetCreatureListWithEntryInGrid(creatures, me, entry, 1000.0f);
if (creatures.empty())
return;
for (std::list<Creature*>::iterator iter = creatures.begin(); iter != creatures.end(); ++iter)
(*iter)->DespawnOrUnsummon();
}
void SetPlayersInCombat(bool evade)
{
uint8 players = 0;
Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (Player *player = i->GetSource())
{
if (player->IsAlive() && player->GetDistance(me) <= 150.0f && !player->IsGameMaster())
{
++players;
player->SetInCombatWith(me->ToUnit());
}
}
}
if (players == 0 && evade == true)
_EnterEvadeMode();
}
}
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_TORMENT:
break;
case EVENT_BONE_SCYTHE:
break;
case EVENT_SCYTHE_SWIP:
break;
case EVENT_BONE_SAW:
break;
case EVENT_CHECK_FOR_PLAYERS:
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetTombOfSargerasAI<boss_atriganAI>(creature);
}
};
enum belacSpells
{
SPELL_PANGS_OF_GUILT = 239401,
SPELL_CONFESS = 233652,
SPELL_TORMENTING_BURST = 234015,
SPELL_ECHOING_ANGUIS = 233983,
SPELL_FEL_SQUAL = 235230,
};
enum belacEvents
{
EVENT_PANGS_OF_GUILT = 1,
EVENT_CONFESS,
EVENT_TORMENTING_BURST,
EVENT_ECHOING_ANGUIS,
EVENT_FEL_SQUAL,
};
class boss_belac : public CreatureScript
{
public:
boss_belac() : CreatureScript("boss_belac") {}
struct boss_belacAI : public BossAI
{
boss_belacAI(Creature* creature) : BossAI(creature, DATA_BELAC)
{
instance->SetBossState(DATA_BELAC, NOT_STARTED);
}
void Reset() override
{
_Reset();
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->SetBossState(DATA_BELAC, FAIL);
}
}
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
me->GetMotionMaster()->MoveTargetedHome();
_DespawnAtEvade(0, nullptr);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
//Talk(SAY_COMBAT);
me->SetPower(POWER_ENERGY, 0);
me->setActive(true);
DoZoneInCombat();
SetPlayersInCombat(true);
}
void JustDied(Unit* /*killer*/) override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustDied();
instance->SetBossState(DATA_BELAC, DONE);
}
//Talk(SAY_DIED);
}
void KilledUnit(Unit* victim) override
{
//if (victim->GetTypeId() == TYPEID_PLAYER)
// Talk(SAY_KILL);
}
void JustReachedHome() override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(DATA_BELAC, FAIL);
}
}
void DespawnGameObjects(uint32 entry)
{
std::list<GameObject*> gameObjects;
GetGameObjectListWithEntryInGrid(gameObjects, me, entry, 1000.0f);
if (gameObjects.empty())
return;
for (std::list<GameObject*>::iterator iter = gameObjects.begin(); iter != gameObjects.end(); ++iter)
(*iter)->Delete();
}
void DespawnCreatures(uint32 entry)
{
std::list<Creature*> creatures;
GetCreatureListWithEntryInGrid(creatures, me, entry, 1000.0f);
if (creatures.empty())
return;
for (std::list<Creature*>::iterator iter = creatures.begin(); iter != creatures.end(); ++iter)
(*iter)->DespawnOrUnsummon();
}
void SetPlayersInCombat(bool evade)
{
uint8 players = 0;
Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (Player *player = i->GetSource())
{
if (player->IsAlive() && player->GetDistance(me) <= 150.0f && !player->IsGameMaster())
{
++players;
player->SetInCombatWith(me->ToUnit());
}
}
}
if (players == 0 && evade == true)
_EnterEvadeMode();
}
}
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_PANGS_OF_GUILT:
break;
case EVENT_CONFESS:
break;
case EVENT_TORMENTING_BURST:
break;
case EVENT_ECHOING_ANGUIS:
break;
case EVENT_FEL_SQUAL:
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetTombOfSargerasAI<boss_belacAI>(creature);
}
};
void AddSC_boss_demonic_inquisition()
{
new boss_atrigan();
new boss_belac();
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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 "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "tomb_of_sargeras.h"
enum Spells
{
SPELL_SPIRIT_WORLD = 235621
};
void AddSC_boss_desolate_host()
{
}
@@ -1,392 +0,0 @@
/*
lyosky
*/
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "InstanceScript.h"
#include "GameObject.h"
#include "PhaseShift.h"
#include "PhasingHandler.h"
#include "tomb_of_sargeras.h"
enum Spells
{
//Stage One: A Slumber Disturbed
SPELL_TOUCH_OF_SARGERAS = 239207,//?????? 14s 42s mythic 60
SPELL_TOUCH_OF_SARGERAS_VISUAL = 234012,//239057 summon
SPELL_RUPTURE_REALITIES = 239132,//???? to do 31s 60s phase2 every 37s
//SPELL_RUPTURE_REALITIES = 239132,235572
//SPELL_RUPTURE_REALITIES = 239152, //???? 236419 dmg 234090 visual
SPELL_UNBOUND_CHAOS = 234059, //7s 35-60 s
SPELL_UNBOUND_CHAOS_MARK = 239482,
SPELL_SHADOWY_BLADES = 236571,//27s 30-46 236591/???? 241588
SPELL_SHADOWY_BLADES_MOVETO = 236591,
SPELL_SHADOWY_BLADES_DMG = 241588,
SPELL_DESOLATE = 236494,//?? 13s-19s 11.4s
//Maiden of Valor
NPC_MAIDEN_OF_VALOR = 120437,
SPELL_CORRUPTED_MATRIX = 233556,// 10s 40s
SPELL_MATRIX_EMPOWERMENT = 233961,// add
SPELL_CLEANSING_PROTOCOL = 233856,
SPELL_MALFUNCTION = 233739,// on 233856 remove ,damage 25%hp
//Stage Two: An Avatar Awakened
SPELL_DARK_MARK = 239739,//???? mythic 31.6 ,21 every mythic 25 34s
SPELL_RAIN_OF_THE_DESTROYER = 240396, //only mythic 15s 35s
SPELL_RIPPLE_OF_DARKNESS = 236528,// on no one in range AOE
SPELL_SEAR = 234179, //aura
SPELL_INTRO = 239847,//????
SPELL_ANNIHILATION = 235597,//PHASE_2 ??
SPELL_CONSUME = 240594,//??
GO_GROUND = 267934,
NPC_CORRUPTED_BLADE = 119158,
};
enum Events
{
EVENT_INTRO = 1,
EVENT_ATTACK_RANGE = 2000,
};
struct boss_fallen_avatar : public BossAI
{
boss_fallen_avatar(Creature* creature) : BossAI(creature, DATA_FALLEN_AVATAR) { Initialize(); }
void Initialize()
{
PhaseStatus = PHASE_01;
SetCombatMovement(false);
//me->SetDisableGravity(true);
IsLock = false;
}
void Reset() override
{
_Reset();
Initialize();
if (Creature* maidenofvalor = me->FindNearestCreature(NPC_MAIDEN_OF_VALOR, 150.0f, true))
maidenofvalor->DespawnOrUnsummon();
//if (!me->FindNearestGameObject(GO_GROUND, 500.0f))
// me->SummonGameObject(GO_GROUND, Position(5825.93f, -1216.87f, 2787.37f, 0.872664f), QuaternionData(), WEEK);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
instance->DoDelayedConversation(5000, 4955);
}
void DoAction(int32 param)
{
switch (param)
{
case 1:
SwitchPhase();
break;
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (me->HealthWillBeBelowPctDamaged(20, damage))
SwitchPhase();
}
void SwitchPhase()
{
if(PhaseStatus == PHASE_01)
{
PhaseStatus = PHASE_02;
SetCombatMovement(true);
//me->SetDisableGravity(false);
if (GameObject* ground = me->FindNearestGameObject(GO_GROUND, 150.0f))
ground->Delete();
events.Reset();
DoCastSelf(SPELL_ANNIHILATION);
AddTimedDelayedOperation(3500, [this]() -> void
{
me->NearTeleportTo(Position(6621.16f, -794.8966f, 1519.918f, 2.9986f));
instance->DoNearTeleportPlayers(Position(6561.1f, -791.82f, 1509.91f, 6.2429f));
DoCastSelf(SPELL_ANNIHILATION);
});
AddTimedDelayedOperation(5000, [this]() -> void
{
//me->GetMotionMaster()->Clear();
//me->GetMotionMaster()->MovePoint(0, Position(6561.1f, -791.82f, 1509.91f, 6.2429f), true);
//me->GetMotionMaster()->MoveChase(me->SelectNearestPlayer());
DoCastSelf(SPELL_SEAR);
events.ScheduleEvent(SPELL_RUPTURE_REALITIES, 37s);
events.ScheduleEvent(SPELL_DESOLATE, 19s);
if (IsMythic())
events.ScheduleEvent(SPELL_DARK_MARK, 31s, 32s);
else
events.ScheduleEvent(SPELL_DARK_MARK, 21s);
if (IsMythic())
events.ScheduleEvent(SPELL_RAIN_OF_THE_DESTROYER, 15s);
});
}
}
void ScheduleTasks() override
{
PhaseStatus = PHASE_01;
me->RemoveAurasDueToSpell(SPELL_INTRO);
events.ScheduleEvent(SPELL_TOUCH_OF_SARGERAS, 14s, 15s);
events.ScheduleEvent(SPELL_RUPTURE_REALITIES, 31s);
events.ScheduleEvent(SPELL_UNBOUND_CHAOS, 7s);
events.ScheduleEvent(SPELL_SHADOWY_BLADES, 27s);
events.ScheduleEvent(SPELL_DESOLATE, 13s);
events.ScheduleEvent(NPC_MAIDEN_OF_VALOR, 4s);
//events.ScheduleEvent(SPELL_ANNIHILATION, 120s);
//events.ScheduleEvent(SPELL_FEL_INFUSION, 5s);
//events.ScheduleEvent(SPELL_CONSUME, 5s);
}
void ExecuteEvent(uint32 eventId) override
{
/*
for (auto threat : me->getThreatManager().getThreatList())
if (me->IsWithinCombatRange(threat->getTarget(), me->GetCombatReach()))
me->RemoveAurasDueToSpell(SPELL_RIPPLE_OF_DARKNESS);
*/
switch (eventId)
{
case SPELL_TOUCH_OF_SARGERAS:
{
if (Unit* target1 = SelectTarget(SELECT_TARGET_RANDOM, 0.0, 0.0, true))
{
me->CastSpell(target1, SPELL_TOUCH_OF_SARGERAS, false);
AddTimedDelayedOperation(2500, [this, target1]() -> void
{
me->CastSpell(target1, SPELL_TOUCH_OF_SARGERAS_VISUAL, false);
});
}
if(IsMythic())
events.Repeat(60s);
else
events.Repeat(42s);
break;
}
case SPELL_RUPTURE_REALITIES:
{
if (Unit* target1 = SelectTarget(SELECT_TARGET_RANDOM, 0.0, 0.0, true))
me->CastSpell(target1, SPELL_RUPTURE_REALITIES, false);
for (uint8 i = 0; i < 5; ++i)
me->SummonCreature(NPC_CORRUPTED_BLADE, me->GetRandomNearPosition(10.0f), TEMPSUMMON_MANUAL_DESPAWN, WEEK);
if (PhaseStatus == PHASE_01)
events.Repeat(60s);
else
events.Repeat(37s);
break;
}
case SPELL_UNBOUND_CHAOS:
{
if (Unit* target1 = SelectTarget(SELECT_TARGET_RANDOM, 0.0, 0.0, true))
{
me->CastSpell(target1, SPELL_UNBOUND_CHAOS, false);
AddTimedDelayedOperation(500, [this, target1]() -> void
{
me->CastSpell(target1, SPELL_UNBOUND_CHAOS_MARK, false);
});
AddTimedDelayedOperation(1000, [this, target1]() -> void
{
me->CastSpell(target1, SPELL_UNBOUND_CHAOS_MARK, false);
});
AddTimedDelayedOperation(1500, [this, target1]() -> void
{
me->CastSpell(target1, SPELL_UNBOUND_CHAOS_MARK, false);
});
}
events.Repeat(35s);
break;
}
case SPELL_SHADOWY_BLADES:
{
DoCast(SPELL_SHADOWY_BLADES);
events.Repeat(30s);
break;
}
case SPELL_DESOLATE:
{
DoCast(SPELL_DESOLATE);
events.Repeat(11s, 12s);
break;
}
case NPC_MAIDEN_OF_VALOR:
{
me->SummonCreature(NPC_MAIDEN_OF_VALOR, me->GetPositionWithDistInFront(25.0f), TEMPSUMMON_MANUAL_DESPAWN, WEEK);
break;
}
case SPELL_DARK_MARK:
{
if (Unit* target1 = SelectTarget(SELECT_TARGET_RANDOM, 0.0, 0.0, true))
me->CastSpell(target1, SPELL_DARK_MARK, false);
if (Unit* target1 = SelectTarget(SELECT_TARGET_RANDOM, 0.0, 0.0, true))
me->CastSpell(target1, SPELL_DARK_MARK, false);
if (IsMythic())
events.Repeat(25s);
else
events.Repeat(34s);
break;
}
case SPELL_RAIN_OF_THE_DESTROYER:
{
DoCast(SPELL_RAIN_OF_THE_DESTROYER);
events.Repeat(35s);
break;
}
default:
if (me->GetDistance2d(me->SelectNearestPlayer())>me->GetCombatReach())
me->CastSpell(me, SPELL_RIPPLE_OF_DARKNESS, false);
break;
}
}
void MoveInLineOfSight(Unit* who) override
{
if (who->IsPlayer() && me->IsWithinDist(who, 25.0f, false) && !IsLock)
{
IsLock = true;
instance->DoConversation(4899);
if (Creature* jidan = me->FindNearestCreature(120867, 50.0f, true))
{
AddTimedDelayedOperation(25000, [this, jidan]() -> void
{
jidan->CastSpell(me, 240897, true);
me->RemoveAurasDueToSpell(SPELL_INTRO);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->NearTeleportTo(me->GetPositionWithDistInFront(20.0f));
});
AddTimedDelayedOperation(30000, [this, jidan]() -> void
{
PhasingHandler::AddPhase(jidan, 180, true);
});
//jidan->DespawnOrUnsummon(30000);
}
}
}
void JustSummoned(Creature* summon) override
{
switch (summon->GetEntry())
{
case NPC_MAIDEN_OF_VALOR:
{
summon->setFaction(me->getFaction());
uint64 health = (uint64)(me->GetMaxHealth()*0.5f);
summon->SetMaxHealth(health);
summon->SetHealth(health);
break;
}
case NPC_CORRUPTED_BLADE:
{
summon->setFaction(me->getFaction());
if (Unit* target1 = SelectTarget(SELECT_TARGET_RANDOM, 0.0, 0.0, true))
{
AddTimedDelayedOperation(3000, [this, summon, target1]() -> void
{
summon->CastSpell(target1, SPELL_SHADOWY_BLADES_MOVETO, false);
});
AddTimedDelayedOperation(5500, [this, summon, target1]() -> void
{
summon->CastSpell(target1, SPELL_SHADOWY_BLADES_DMG, false);
summon->DespawnOrUnsummon();
});
}
break;
}
}
}
/*
*/
uint8 PhaseStatus;
uint8 PHASE_01;
uint8 PHASE_02;
bool IsLock;
};
struct npc_maiden_of_valor_120437 : public ScriptedAI
{
npc_maiden_of_valor_120437(Creature* creature) : ScriptedAI(creature) { }
void JustDied(Unit* /*killer*/) override
{
if (Creature* boss = me->FindNearestCreature(NPC_FALLEN_AVATAR, 150.0f, true))
boss->AI()->DoAction(1);
}
/*
SPELL_CORRUPTED_MATRIX = 233556,// 10s 40s
SPELL_MATRIX_EMPOWERMENT = 233961,// add
SPELL_CLEANSING_PROTOCOL = 233856,
SPELL_MALFUNCTION = 233739,// on 233856 remove ,damage 25%hp
*/
void EnterCombat(Unit* /*victim*/)
{
events.ScheduleEvent(SPELL_CORRUPTED_MATRIX, 10s);
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (!UpdateVictim())
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_CORRUPTED_MATRIX:
{
DoCast(SPELL_CORRUPTED_MATRIX);
events.Repeat(40s);
break;
}
}
}
DoMeleeAttackIfReady();
}
int8 IsLock;
void MoveInLineOfSight(Unit* who) override
{
if (who->IsPlayer() && me->IsWithinDist(who, 25.0f, false) && !IsLock)
{
IsLock = true;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
}
}
};
struct npc_corrupted_blade_119158 : public ScriptedAI
{
npc_corrupted_blade_119158(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
SetCombatMovement(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
}
void UpdateAI(uint32 diff) override { }
};
void AddSC_boss_fallen_avatar()
{
RegisterCreatureAI(boss_fallen_avatar);
RegisterCreatureAI(npc_maiden_of_valor_120437);
RegisterCreatureAI(npc_corrupted_blade_119158);
}
@@ -1,428 +0,0 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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 "AreaTriggerTemplate.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "tomb_of_sargeras.h"
enum Spells
{
// Goroth
SPELL_BURNING_ARMOR = 231363,
SPELL_BURNING_ERUPTION = 231395, // Casted at SPELL_BURNING_ARMOR end
SPELL_CRASHING_COMET = 232249,
SPELL_CRASHING_COMET_DAMAGE = 230345,
SPELL_INFERNAL_SPIKE_SUMMON = 233055,
SPELL_INFERNAL_SPIKE = 233019,
SPELL_INFERNAL_SPIKE_PROTECTION = 234475,
SPELL_SHATTERING_STAR = 233272,
SPELL_SHATTERING_STAR_AT = 233279,
SPELL_SHATTERING_STAR_DAMAGE = 233281,
SPELL_SHATTERING_STAR_FINAL_DAMAGE = 233283,
SPELL_INFERNAL_BURNING = 233062,
SPELL_INFERNAL_BURNING_REMOVE_SPIKES = 233078,
// Infernal chaosbringer
SPELL_MASSIVE_ERUPTION = 242909
};
enum Misc
{
NPC_INFERNAL_SPIKE = 116976,
SPELLVISUAL_INFERNAL_SPIKE_DESTROY = 66119,
AT_SHATTERING_STAR = 13412
};
enum Texts
{
SAY_AGGRO = 1,
SAY_KILL = 2,
SAY_WIPE = 3,
SAY_DEATH = 4,
SAY_INFERNAL_BURNING = 5,
SAY_SHATTERING_STAR = 6,
SAY_INFERNAL_SPIKE = 7
};
enum Events
{
EVENT_MASSIVE_ERUPTION = 1
};
struct boss_goroth : public BossAI
{
boss_goroth(Creature* creature) : BossAI(creature, DATA_GOROTH) { }
void EnterCombat(Unit* /*attacker*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
instance->SetBossState(DATA_GOROTH, IN_PROGRESS);
events.ScheduleEvent(SPELL_BURNING_ARMOR, 16s);
events.ScheduleEvent(SPELL_CRASHING_COMET, 10s, 20s);
events.ScheduleEvent(SPELL_INFERNAL_SPIKE_SUMMON, 12s);
events.ScheduleEvent(SPELL_SHATTERING_STAR, 10s, 20s);
events.ScheduleEvent(SPELL_INFERNAL_BURNING, 55s);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_GOROTH, DONE);
}
void JustReachedHome() override
{
Talk(SAY_WIPE);
instance->SetBossState(DATA_GOROTH, FAIL);
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case SPELL_BURNING_ARMOR:
{
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO))
DoCast(target, SPELL_BURNING_ARMOR);
events.Repeat(16s);
break;
}
case SPELL_CRASHING_COMET:
{
UnitList targetList;
SelectTargetList(targetList, 3, SELECT_TARGET_RANDOM, 200.0f, true);
for (Unit* target : targetList)
DoCast(target, SPELL_CRASHING_COMET, true);
events.Repeat(10s, 20s);
break;
}
case SPELL_INFERNAL_SPIKE_SUMMON:
{
Talk(SAY_INFERNAL_SPIKE);
UnitList targetList;
SelectTargetList(targetList, 3, SELECT_TARGET_RANDOM, 200.0f, true);
for (Unit* target : targetList)
DoCast(target, SPELL_INFERNAL_SPIKE_SUMMON);
events.Repeat(12s);
break;
}
case SPELL_SHATTERING_STAR:
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 2))
{
Talk(SAY_SHATTERING_STAR);
_shatteringStarTargetGUID = target->GetGUID();
DoCast(target, SPELL_SHATTERING_STAR);
}
events.Repeat(10s, 20s);
break;
}
case SPELL_INFERNAL_BURNING:
{
Talk(SAY_INFERNAL_BURNING);
DoCast(SPELL_INFERNAL_BURNING);
events.Repeat(55s);
break;
}
default:
break;
}
}
void JustSummoned(Creature* summon) override
{
BossAI::JustSummoned(summon);
if (summon->GetEntry() == NPC_INFERNAL_SPIKE)
summon->CastSpell(summon, SPELL_INFERNAL_SPIKE, false);
}
ObjectGuid GetGUID(int32 /*id*/ = 0) const override
{
return _shatteringStarTargetGUID;
}
private:
ObjectGuid _shatteringStarTargetGUID;
};
struct infernal_chaosbringer : public ScriptedAI
{
infernal_chaosbringer(Creature* creature) : ScriptedAI(creature), Summons(me) { }
void Reset() override
{
_events.Reset();
me->CombatStop(true);
}
void EnterCombat(Unit* /*who*/) override
{
_events.ScheduleEvent(EVENT_MASSIVE_ERUPTION, 15s);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MASSIVE_ERUPTION:
DoCastAOE(SPELL_MASSIVE_ERUPTION);
_events.Repeat(15s);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
SummonList Summons;
};
// 231363
class spell_burning_armor : public AuraScript
{
PrepareAuraScript(spell_burning_armor);
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->CastSpell(nullptr, SPELL_BURNING_ERUPTION, true);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_burning_armor::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 232249
class aura_crashing_comet : public AuraScript
{
PrepareAuraScript(aura_crashing_comet);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
caster->CastSpell(GetTarget(), SPELL_CRASHING_COMET_DAMAGE, true);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(aura_crashing_comet::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 230345
class spell_crashing_comet_damage : public SpellScript
{
PrepareSpellScript(spell_crashing_comet_damage);
void HandleHit(SpellEffIndex /*effIndex*/)
{
Unit* target = GetHitUnit();
if (!target)
return;
CreatureList infernalSpikes;
target->GetCreatureListWithEntryInGrid(infernalSpikes, NPC_INFERNAL_SPIKE, GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius());
for (Creature* infernalSpike : infernalSpikes)
{
infernalSpike->SendPlaySpellVisual(infernalSpike->GetGUID(), SPELLVISUAL_INFERNAL_SPIKE_DESTROY);
infernalSpike->DespawnOrUnsummon();
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_crashing_comet_damage::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 233062
class spell_infernal_burning : public SpellScript
{
PrepareSpellScript(spell_infernal_burning);
void BeforeCastHandler()
{
Creature* caster = GetCaster()->ToCreature();
if (!caster)
return;
CreatureList infernalSpikes;
caster->GetCreatureListWithEntryInGrid(infernalSpikes, NPC_INFERNAL_SPIKE, 200.0f);
for (auto reference : caster->getThreatManager().getThreatList())
for (Creature* spike : infernalSpikes)
if (spike->IsInBetween(GetCaster(), reference->getTarget(), 2.0f))
reference->getTarget()->AddAura(SPELL_INFERNAL_SPIKE_PROTECTION);
}
void AfterCastHandler()
{
if (Creature* caster = GetCaster()->ToCreature())
for (auto reference : caster->getThreatManager().getThreatList())
reference->getTarget()->RemoveAurasDueToSpell(SPELL_INFERNAL_SPIKE_PROTECTION);
}
void Register() override
{
BeforeCast += SpellCastFn(spell_infernal_burning::BeforeCastHandler);
AfterCast += SpellCastFn(spell_infernal_burning::AfterCastHandler);
}
};
// 233078
class spell_infernal_burning_remove_spikes : public SpellScript
{
PrepareSpellScript(spell_infernal_burning_remove_spikes);
void HandleOnCast()
{
CreatureList infernalSpikes;
GetCaster()->GetCreatureListWithEntryInGrid(infernalSpikes, NPC_INFERNAL_SPIKE, GetSpellInfo()->GetMaxRange());
for (Creature* infernalSpike : infernalSpikes)
{
infernalSpike->SendPlaySpellVisual(GetCaster()->GetGUID(), SPELLVISUAL_INFERNAL_SPIKE_DESTROY);
infernalSpike->DespawnOrUnsummon();
}
}
void Register() override
{
OnCast += SpellCastFn(spell_infernal_burning_remove_spikes::HandleOnCast);
}
};
// 233274
class spell_shattering_star_dummy : public SpellScript
{
PrepareSpellScript(spell_shattering_star_dummy);
void HandleHit(SpellEffIndex /*effIndex*/)
{
if (Creature* goroth = GetHitUnit()->ToCreature())
if (goroth->AI())
goroth->CastSpell(GetCaster(), SPELL_SHATTERING_STAR_AT, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_shattering_star_dummy::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
//AT : 13412
//Spell : 233279
struct at_goroth_shattering_star : AreaTriggerAI
{
at_goroth_shattering_star(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
if (Creature* creCaster = caster->ToCreature())
if (creCaster->IsAIEnabled)
if (Unit* target = ObjectAccessor::GetUnit(*creCaster, creCaster->AI()->GetGUID()))
at->SetDestination(*target, 1000);
}
void OnUnitEnter(Unit* unit) override
{
if (unit->GetEntry() == NPC_INFERNAL_SPIKE)
{
++_infernalSpikeTouched;
unit->SendPlaySpellVisual(unit->GetGUID(), SPELLVISUAL_INFERNAL_SPIKE_DESTROY);
unit->ToCreature()->DespawnOrUnsummon();
}
else if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit))
caster->CastSpell(unit, SPELL_SHATTERING_STAR_DAMAGE, true);
}
}
void OnDestinationReached() override
{
if (Unit* caster = at->GetCaster())
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_SHATTERING_STAR_FINAL_DAMAGE))
if (SpellEffectInfo const* spellEffectInfo = spellInfo->GetEffect(caster->GetMap()->GetDifficultyID(), EFFECT_0))
caster->CastCustomSpell(SPELL_SHATTERING_STAR_FINAL_DAMAGE, SPELLVALUE_BASE_POINT0, spellEffectInfo->BasePoints / std::max(_infernalSpikeTouched, uint8(1)), nullptr, TRIGGERED_FULL_MASK);
// TODO : Deal damage to target if _infernalSpikeTouched == 0
at->Remove();
}
uint8 _infernalSpikeTouched = 0;
};
void AddSC_boss_goroth()
{
RegisterCreatureAI(boss_goroth);
RegisterCreatureAI(infernal_chaosbringer);
RegisterAuraScript(spell_burning_armor);
RegisterAuraScript(aura_crashing_comet);
RegisterSpellScript(spell_crashing_comet_damage);
RegisterSpellScript(spell_infernal_burning);
RegisterSpellScript(spell_infernal_burning_remove_spikes);
RegisterSpellScript(spell_shattering_star_dummy);
RegisterAreaTriggerAI(at_goroth_shattering_star);
}
@@ -1,640 +0,0 @@
/*
* Copyright (C) 2016-2019 MagicStorm
*
* Este codigo es de uso exclusivo y privado para la red de gaming
* ColossusWoW est? totalmente prohibida su distribuci?n y
* uso en proyectos ajenos, si has obtenido o encontrado este codigo
* publicamente envianos un email a administracion@colossuswow.com
* indicandonos como y donde has obtenido este codigo
*
* Recuerda, no distribuyas, no compartas y no subas este codigo a ningun
* lugar publico, usa siempre nuestros repositorios Git!
*/
#include "AreaTriggerTemplate.h"
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "SpellAuraEffects.h"
#include "ScriptMgr.h"
#include "GameObject.h"
#include "ScriptedCreature.h"
#include "tomb_of_sargeras.h"
#include "SpellMgr.h"
enum harjatanSpells
{
SPELL_ABRASIVE_ARMOR = 233071,
SPELL_JAGGED_ABRASION = 231998,
SPELL_UNCHECKED_RAGE = 231854,
SPELL_COMMANDING_ROAR = 232192,
SPELL_DRENCHED = 231770,
SPELL_WATERY_SPLASH = 233371,
SPELL_AQUEOUS_BURST = 231729,
SPELL_AQUEOUS_BURST_DMG = 231754,
SPELL_DRIPPING_BLADE = 239907,
SPELL_DRIVEN_ASSAULT = 234128,
SPELL_SPLASHY_CLEAVE = 234129,
SPELL_DRENCHING_WATERS = 231768,
SPELL_DRAW_IN = 232061,
SPELL_FRIGID_BLOWS = 233429,
SPELL_GATHER_ENERGY = 232379,
SPELL_ENRAGED = 241587,
SPELL_FROSTY_DISCHARGE = 232174,
};
enum harjatanEvents
{
EVENT_UNCHECKED_RAGE = 1,
EVENT_COMMANDING_ROAR,
EVENT_WATERY_SPLASH,
EVENT_AQUEOUS_BURST,
EVENT_DRIVEN_ASSAULT,
EVENT_SPLASHY_CLEAVE,
EVENT_DRENCHING_WATERS,
EVENT_DRAW_IN,
EVENT_CHECK_FOR_PLAYERS,
};
class boss_harjatan : public CreatureScript
{
public:
boss_harjatan() : CreatureScript("boss_harjatan") {}
struct boss_harjatanAI : public BossAI
{
boss_harjatanAI(Creature* creature) : BossAI(creature, DATA_HARJATAN)
{
instance->SetBossState(DATA_HARJATAN, NOT_STARTED);
//me->setPowerType(POWER_ENERGY);
me->SetMaxPower(POWER_ENERGY, 100);
me->SetPower(POWER_ENERGY, 100);
}
bool isCasting;
std::list<Creature*> waveMender;
std::list<Creature*> gladiator;
void Reset() override
{
_Reset();
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->SetBossState(DATA_HARJATAN, FAIL);
}
if (GameObject* go = me->FindNearestGameObject(269192, 500.0f))
go->SetLootState(GO_READY);
isCasting = false;
me->RemoveAurasDueToSpell(SPELL_GATHER_ENERGY);
//me->setPowerType(POWER_ENERGY);
me->SetMaxPower(POWER_ENERGY, 100);
me->SetPower(POWER_ENERGY, 0);
events.Reset();
}
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
me->GetMotionMaster()->MoveTargetedHome();
_DespawnAtEvade(0, nullptr);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
DoCast(SPELL_ABRASIVE_ARMOR);
//Talk(SAY_COMBAT);
me->SetPower(POWER_ENERGY, 0);
events.ScheduleEvent(EVENT_COMMANDING_ROAR, 17.3 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_DRAW_IN, 59 * IN_MILLISECONDS);
if (GameObject* go = me->FindNearestGameObject(269192, 500.0f))
go->UseDoorOrButton(1000000, true);
if (Creature* creature = me->FindNearestCreature(121184, 150.0f))
creature->SetVisible(false);
me->setActive(true);
DoZoneInCombat();
DoCast(SPELL_GATHER_ENERGY);
SetPlayersInCombat(true);
}
void JustDied(Unit* /*killer*/) override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustDied();
instance->SetBossState(DATA_HARJATAN, DONE);
}
if (GameObject* go = me->FindNearestGameObject(269192, 500.0f))
go->SetLootState(GO_READY);
if (GameObject* go = me->FindNearestGameObject(269120, 500.0f))
go->UseDoorOrButton(1000000, true);
//Talk(SAY_DIED);
}
void KilledUnit(Unit* victim) override
{
//if (victim->GetTypeId() == TYPEID_PLAYER)
// Talk(SAY_KILL);
}
void JustReachedHome() override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(DATA_HARJATAN, FAIL);
}
}
void DespawnGameObjects(uint32 entry)
{
std::list<GameObject*> gameObjects;
GetGameObjectListWithEntryInGrid(gameObjects, me, entry, 1000.0f);
if (gameObjects.empty())
return;
for (std::list<GameObject*>::iterator iter = gameObjects.begin(); iter != gameObjects.end(); ++iter)
(*iter)->Delete();
}
void DespawnCreatures(uint32 entry)
{
std::list<Creature*> creatures;
GetCreatureListWithEntryInGrid(creatures, me, entry, 1000.0f);
if (creatures.empty())
return;
for (std::list<Creature*>::iterator iter = creatures.begin(); iter != creatures.end(); ++iter)
(*iter)->DespawnOrUnsummon();
}
void SetPlayersInCombat(bool evade)
{
uint8 players = 0;
Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (Player *player = i->GetSource())
{
if (player->IsAlive() && player->GetDistance(me) <= 150.0f && !player->IsGameMaster())
{
++players;
player->SetInCombatWith(me->ToUnit());
}
}
}
if (players == 0 && evade == true)
_EnterEvadeMode();
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
events.Update(diff);
if (uint32 power = me->GetPower(POWER_ENERGY))
if (power == 100)
if (!isCasting)
{
events.ScheduleEvent(EVENT_UNCHECKED_RAGE, 1 * IN_MILLISECONDS);
isCasting = true;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_UNCHECKED_RAGE:
DoCast(SPELL_UNCHECKED_RAGE);
isCasting = false;
break;
case EVENT_COMMANDING_ROAR:
DoCast(SPELL_COMMANDING_ROAR);
for (uint8 i = 0; i < 2; ++i)
{
me->SummonCreature(NPC_RAZORJAW_WAVEMENDER, 5898.825f, -879.8507f, 2941.018f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
me->SummonCreature(NPC_RAZORJAW_GLADIATOR, 5876.136f, -887.0951f, 2933.093f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
}
events.ScheduleEvent(EVENT_COMMANDING_ROAR, 31.8 * IN_MILLISECONDS);
break;
case EVENT_DRAW_IN:
DoCast(SPELL_DRAW_IN);
events.ScheduleEvent(EVENT_DRAW_IN, 59 * IN_MILLISECONDS);
break;
case EVENT_CHECK_FOR_PLAYERS:
SetPlayersInCombat(true);
events.ScheduleEvent(EVENT_CHECK_FOR_PLAYERS, 1 * IN_MILLISECONDS);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetTombOfSargerasAI<boss_harjatanAI>(creature);
}
};
// 116569 - Razorjaw Wavemender
class npc_razorjaw_wavemender : public CreatureScript
{
public:
npc_razorjaw_wavemender() : CreatureScript("npc_razorjaw_wavemender") { }
struct npc_razorjaw_wavemenderAI : public ScriptedAI
{
npc_razorjaw_wavemenderAI(Creature* creature) : ScriptedAI(creature)
{
}
void Reset() override
{
events.Reset();
}
void EnterCombat(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_WATERY_SPLASH, 10 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_AQUEOUS_BURST, 12 * IN_MILLISECONDS);
}
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_WATERY_SPLASH:
if (Unit* target = me->GetVictim())
me->CastSpell(target, SPELL_WATERY_SPLASH, true);
events.ScheduleEvent(EVENT_WATERY_SPLASH, 10 * IN_MILLISECONDS);
break;
case EVENT_AQUEOUS_BURST:
if (Unit* target = me->GetVictim()/*SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f, true)*/)
me->CastSpell(target, SPELL_AQUEOUS_BURST, true);
events.ScheduleEvent(EVENT_AQUEOUS_BURST, 16 * IN_MILLISECONDS);
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetTombOfSargerasAI<npc_razorjaw_wavemenderAI>(creature);
}
};
// 117596 - Razorjaw Gladiator
class npc_razorjaw_gladiator : public CreatureScript
{
public:
npc_razorjaw_gladiator() : CreatureScript("npc_razorjaw_gladiator") { }
struct npc_razorjaw_gladiatorAI : public ScriptedAI
{
npc_razorjaw_gladiatorAI(Creature* creature) : ScriptedAI(creature)
{
}
std::list<AreaTrigger*> areaTriggerList;
void Reset() override
{
events.Reset();
me->RemoveAllAreaTriggers();
}
void EnterCombat(Unit* /*who*/) override
{
DoCast(SPELL_DRIPPING_BLADE);
events.ScheduleEvent(EVENT_DRIVEN_ASSAULT, 10 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_SPLASHY_CLEAVE, 12 * IN_MILLISECONDS);
}
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_DRIVEN_ASSAULT:
if (Unit* target = me->GetVictim()/*SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f, true)*/)
{
if (!target->HasAura(240792))
{
me->CastSpell(target, 234016, true);
me->CastSpell(me, SPELL_DRIVEN_ASSAULT, true);
}
else
events.ScheduleEvent(EVENT_DRIVEN_ASSAULT, 1 * IN_MILLISECONDS);
}
events.ScheduleEvent(EVENT_DRIVEN_ASSAULT, 10 * IN_MILLISECONDS);
break;
case EVENT_SPLASHY_CLEAVE:
DoCast(SPELL_SPLASHY_CLEAVE);
events.ScheduleEvent(EVENT_SPLASHY_CLEAVE, 12 * IN_MILLISECONDS);
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetTombOfSargerasAI<npc_razorjaw_gladiatorAI>(creature);
}
};
// 233429 - frigid blows
class spell_harjatan_frigid_blows : public SpellScriptLoader
{
public:
spell_harjatan_frigid_blows() : SpellScriptLoader("spell_harjatan_frigid_blows") { }
class spell_harjatan_frigid_blows_AuraScript : public AuraScript
{
PrepareAuraScript(spell_harjatan_frigid_blows_AuraScript);
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* target = GetTarget())
if (Aura* aura = target->GetAura(GetId()))
if (aura->GetStackAmount() <= 1)
target->CastSpell(target, SPELL_FROSTY_DISCHARGE, true);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_harjatan_frigid_blows_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_harjatan_frigid_blows_AuraScript();
}
};
// 231729 - Aqueous Burst
class spell_harjatan_aqueous_burst : public SpellScriptLoader
{
public:
spell_harjatan_aqueous_burst() : SpellScriptLoader("spell_harjatan_aqueous_burst") { }
class spell_harjatan_aqueous_burst_AuraScript : public AuraScript
{
PrepareAuraScript(spell_harjatan_aqueous_burst_AuraScript);
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* target = GetTarget())
target->CastSpell(target, SPELL_AQUEOUS_BURST_DMG, true);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_harjatan_aqueous_burst_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_harjatan_aqueous_burst_AuraScript();
}
};
// 13251 - Drenching waters
class areatrigger_drenching_waters : public AreaTriggerEntityScript
{
public:
areatrigger_drenching_waters() : AreaTriggerEntityScript("areatrigger_drenching_waters") { }
struct areatrigger_drenching_watersAI : AreaTriggerAI
{
areatrigger_drenching_watersAI(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
bool isCasting = false;
uint32 checkTime;
uint8 count;
void OnInitialize() override
{
checkTime = 1000;
count = 0;
}
void OnUpdate(uint32 diff) override
{
if (checkTime <= diff)
{
if (Creature* boss = at->FindNearestCreature(BOSS_HARJATAN, 500.0f))
if (boss->HasAura(SPELL_DRAW_IN))
{
Position pos = at->GetNearPosition(float(-count), at->GetAngle(*boss));
at->GetMap()->AreaTriggerRelocation(at, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
}
if (Creature* boss = at->FindNearestCreature(BOSS_HARJATAN, 5.0f))
if (boss->HasAura(SPELL_DRAW_IN))
{
boss->CastSpell(boss, SPELL_FRIGID_BLOWS, true);
at->RemoveFromWorld();
}
if (Creature* boss = at->FindNearestCreature(BOSS_HARJATAN, 500.0f, false))
at->RemoveFromWorld();
checkTime = 1000;
}
else
checkTime -= diff;
}
void OnUnitEnter(Unit* target) override
{
if (!target)
return;
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (Unit* caster = at->GetCaster())
caster->CastSpell(target, SPELL_DRENCHING_WATERS, true);
}
void OnUnitExit(Unit* target) override
{
if (!target)
return;
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (target->HasAura(SPELL_DRENCHING_WATERS))
target->RemoveAurasDueToSpell(SPELL_DRENCHING_WATERS);
}
};
AreaTriggerAI* GetAI(AreaTrigger* areatrigger) const override
{
return new areatrigger_drenching_watersAI(areatrigger);
}
};
// 231854 - Unchecked Rage
class spell_harjatan_unchecked_rage : public SpellScriptLoader
{
public:
spell_harjatan_unchecked_rage() : SpellScriptLoader("spell_harjatan_unchecked_rage") { }
class spell_harjatan_unchecked_rage_SpellScript : public SpellScript
{
PrepareSpellScript(spell_harjatan_unchecked_rage_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
uint8 count = 0;
for (auto target : targets)
++count;
if (count < 5)
if (Unit* caster = GetCaster())
caster->CastSpell(caster, SPELL_ENRAGED, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_harjatan_unchecked_rage_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CONE_ENEMY_104);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_harjatan_unchecked_rage_SpellScript();
}
};
// 232174 - Frosty Discharge
class spell_harjatan_frosty_discharge : public SpellScriptLoader
{
public:
spell_harjatan_frosty_discharge() : SpellScriptLoader("spell_harjatan_frosty_discharge") { }
class spell_harjatan_frosty_discharge_SpellScript : public SpellScript
{
PrepareSpellScript(spell_harjatan_frosty_discharge_SpellScript);
void HandleDummy()
{
if (Unit* caster = GetCaster())
caster->CastSpell(caster, GetSpellInfo()->GetEffect(EFFECT_0)->BasePoints, true);
}
void Register() override
{
OnCast += SpellCastFn(spell_harjatan_frosty_discharge_SpellScript::HandleDummy);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_harjatan_frosty_discharge_SpellScript();
}
};
void AddSC_boss_harjatan()
{
new boss_harjatan();
new npc_razorjaw_wavemender();
new npc_razorjaw_gladiator();
new spell_harjatan_frigid_blows();
new spell_harjatan_aqueous_burst();
new areatrigger_drenching_waters();
new spell_harjatan_unchecked_rage();
new spell_harjatan_frosty_discharge();
}
@@ -1,28 +0,0 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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 "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "tomb_of_sargeras.h"
void AddSC_boss_tos_kiljaeden()
{
}
@@ -1,28 +0,0 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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 "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "tomb_of_sargeras.h"
void AddSC_boss_maiden_of_vigilance()
{
}
@@ -1,28 +0,0 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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 "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "tomb_of_sargeras.h"
void AddSC_boss_sasszine()
{
}
@@ -1,901 +0,0 @@
/*
* Copyright (C) 2017-2019 AshamaneProject <https://github.com/AshamaneProject>
*
* 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 "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "SpellScript.h"
#include "tomb_of_sargeras.h"
//constant positions about teleports and Kasparian Jumps
Position const LunaspyreTeleports[5] =
{
{},
{},
{},
{},
{},
};
Position const CenterCombat[1] =
{
{},
};
Position const YathaeTeleports[5] =
{
{},
{},
{},
{},
{},
};
Position const KasparianJumps[5] =
{
{},
{},
{},
{},
{},
};
enum Says
{
// Sisters
SAY_SISTERS_AGGRO = 1,
SAY_SISTERS_DEATH = 2,
SAY_SISTERS_EVADE = 3,
SAY_SISTER_KILLS = 4,
// Kasparian
SAY_KASPARIAN_AGGRO = 1,
SAY_SPELL_GLAIVE = 2,
SAY_KASPARIAN_KILLS = 3,
SAY_KASPARIAN_EVADE = 4,
SAY_KASPARIAN_DIED = 5,
// Yathae
SAY_YATHAE_AGGRO = 6,
SAY_PHASE_COMBAT = 7,
SAY_SPELLS_ARROW = 8,
SAY_SPELL_AOE = 9,
SAY_YATHAE_KILLS = 10,
SAY_YATHAE_EVADE = 11,
SAY_YATHAE_DIED = 12,
// Lunaspyre
SAY_LUNASPYRE_AGGRO = 13,
SAY_SPELL = 14,
SAY_FOUNTAIN_OF_ELUNE = 15,
SAY_LUNASPYRE_KILLS = 16,
SAY_LUNASPYRE_EVADE = 17,
SAY_LUNASPYRE_DIED = 18
};
enum SistersSpells
{
// Generic
SPELL_QUIET_SUICIDE = 3617, // Serverside spell
SPELL_INCORPOREAL_TELEPORT = 236115, // Cast
SPELL_INCORPOREAL_TELEPORT_2 = 236224, // Not sure if this is the teleport or need script. Instant cast. These two teleport spells are the same for Lunaspyre
SPELL_COOLDOWN_CREATURE_SPECIAL = 61207, // To block other spells from interfering with their special
SPELL_GHOST_AURA = 235268, // Cosmetic for Sisters
SPELL_ELUNE_FOUNTAIN = 236357, // Create AT 11284
SPELL_LUNAR_SUFFUSION = 234995, // Add the aura every 3 seconds on the bright side
SPELL_UMBRA_SUFFUSION = 234996, // Add the aura every 3 seconds on the dark side
SPELL_ASTRAL_PURGE = 234998, // Will trigger on change side in Fountain of Elune, and reset Suffusion marks.
// Generic Talk
// Kasparian
SPELL_KASPARIAN_KILL_CONVERSATION_A = 243051, // When unactive sister kills a player
SPELL_KASPARIAN_KILL_CONVERSATION_B = 243052, // When unactive sister kills a player
SPELL_KASPARIAN_KILL_CONVERSATION_C = 243053, // When unactive sister kills a player
// Yathae
SPELL_YATHAE_BECOMES_ACTIVE_CONVERSATION = 243044, // Probably at Start Combat in Active Phase
// Lunaspyre
SPELL_LUNASPYRE_BECOMES_ACTIVE_CONVERSATION = 243047, // Probably at Start Combat in Active Phase
SPELL_LUNASPYRE_KILL_CONVERSATION_A = 243059, // When unactive sister kills a player
SPELL_LUNASPYPE_KILL_CONVERSATION_B = 243060, // When unactive sister kills a player
SPELL_LUNASPYRE_KILL_CONVERSATION_C = 243061, // When unactive sister kills a player
// Kasparian
SPELL_TWILIGHT_GLAIVE_AT = 236529, // AT 9785 and add aura to bunny + make bunny got target,then return
SPELL_TWILIGHT_GLAIVE_DAMAGE = 236541,
SPELL_TWILIGHT_GLAIVE_DUMMY = 237561,
SPELL_MOON_GLAIVE = 236547,
SPELL_DISCORPORATE = 236550, // Astral Purge will remove it
SPELL_GLAIVE_STORM = 239379, // Only used in Elune's Fountain Phase 3 (normal), phase 2 and 3 heroic and mythic
// Yathae
SPELL_SHADOW_SHOT = 237630,
SPELL_INCORPOREAL_SHOT_CAST = 236305, // Only used in Elune's Fountain Phase 2 (normal), phase 1 and 3 heroic and mythic
SPELL_INCORPOREAL_SHOT_DAMAGE = 236306,
SPELL_CALL_MOONTALON = 236694,
SPELL_TWILIGHT_VOLLEY_AT = 236442, // AT 9777
SPELL_TWILIGHT_VOLLEY_DAMAGE = 236516, // Apply this aura OnUnitEnter();
SPELL_RAPID_SHOT = 236598,
SPELL_RAPID_SHOT_AURA = 236596,
// Lunaspyre
SPELL_EMBRACE_OF_THE_ECLIPSE_HEAL = 233263, // Shields Heal
SPELL_EMBRACE_OF_THE_ECLIPSE_BOSS = 233264, // Shield Boss
SPELL_LUNAR_BEACON = 236712, // OnRemove(); actives Lunar barrage.
SPELL_LUNAR_FIRE = 239264, // Only on current target,active.
SPELL_LUNAR_STRIKE = 237632,
SPELL_MOON_BURN = 236518, // Astral Purge will remove this.
SPELL_LUNAR_BARRAGE_AT = 236726, // AT 9807
SPELL_LUNAR_BARRAGE_DAMAGE = 237351
};
enum SistersEvents
{
// General
EVENT_INCORPOREAL_TELEPORT = 1,
EVENT_TELEPORT_CENTER_COMBAT,
EVENT_BACK_TO_GHOST,
EVENT_BERSERKER,
// Kasparian
EVENT_TWILIGHT_GLAIVE,
EVENT_MOON_GLAIVE,
EVENT_GLAIVE_STORM,
EVENT_JUMP_TIGER,
EVENT_KASPARIAN_JUST_DIED,
EVENT_KASPARIAN_AGGRO,
// Yathae
EVENT_SHADOW_SHOT,
EVENT_INCORPOREAL_SHOT,
EVENT_CALL_MOONTALON,
EVENT_TWILIGHT_VOLLEY,
EVENT_RAPID_SHOT,
EVENT_YATHAE_JUST_DIED,
EVENT_YATHAE_AGGRO,
// Lunaspyre
EVENT_EMBRACE_OF_THE_ECLIPSE,
EVENT_LUNAR_BEACON,
EVENT_LUNAR_FIRE,
EVENT_LUNAR_STRIKE,
EVENT_MOON_BURN,
EVENT_LUNASPYRE_JUST_DIED,
EVENT_LUNASPYRE_AGGRO
};
enum Actions
{
ACTION_RETURN_PHASE1 = 1,
ACTION_RETURN = 2,
ACTION_SAY_SISTERS_AGGRO = 3,
ACTION_EVADE = 4,
ACTION_PHASE_2 = 5,
ACTION_PHASE_3 = 6,
ACTION_SISTERS_DEAD = 7
};
enum Phases
{
THE_HUNTRESS = 1,
THE_CAPTAIN = 2,
THE_PRIESTESS = 3,
SISTER_GHOST = 4
};
enum Objects
{
DATA_HUNTRESS_KASPARIAN,
DATA_CAPTAIN_YATHAE_MOONSTRIKE,
DATA_PRIESTESS_LUNASPYRE,
};
class boss_sisters_of_the_moon : public CreatureScript
{
public:
boss_sisters_of_the_moon() : CreatureScript("boss_sisters_of_the_moon") { }
struct boss_sisters_of_the_moon_AI : public BossAI
{
boss_sisters_of_the_moon_AI(Creature* creature) : BossAI(creature, DATA_SISTERS_OF_THE_MOON)
{
creature->GetInstanceScript();
Creature* kasparian = instance->GetCreature(NPC_HUNTRESS_KASPARIAN);
Creature* yathae = instance->GetCreature(NPC_CAPTAIN_YATHAE_MOONSTRIKE);
Creature* lunaspyre = instance->GetCreature(NPC_PRIESTESS_LUNASPYRE);
if (instance)
{
EncounterState bossState = instance->GetBossState(DATA_SISTERS_OF_THE_MOON);
if (bossState != DONE && bossState != NOT_STARTED)
instance->SetBossState(DATA_SISTERS_OF_THE_MOON, NOT_STARTED);
}
}
void Reset() override
{
me->RemoveAllAreaTriggers();
events.Reset();
if (instance)
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
switch (me->GetEntry())
{
case NPC_HUNTRESS_KASPARIAN:
DoAction(ACTION_RETURN_PHASE1);
break;
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
case NPC_PRIESTESS_LUNASPYRE:
DoAction(ACTION_RETURN);
break;
default:
break;
}
}
void EnterCombat(Unit* /*attacker*/) override
{
if (instance)
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
instance->SetBossState(DATA_SISTERS_OF_THE_MOON, IN_PROGRESS);
}
events.AddPhase(THE_HUNTRESS);
DoAction(ACTION_SAY_SISTERS_AGGRO);
DoZoneInCombat();
switch (me->GetEntry())
{
case NPC_HUNTRESS_KASPARIAN:
events.ScheduleEvent(EVENT_MOON_GLAIVE, 17s, THE_HUNTRESS);
events.ScheduleEvent(EVENT_TWILIGHT_GLAIVE, 22s);
break;
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
events.ScheduleEvent(EVENT_TWILIGHT_VOLLEY, 15s);
events.ScheduleEvent(EVENT_CALL_MOONTALON, 40s, 0, THE_CAPTAIN);
events.ScheduleEvent(EVENT_INCORPOREAL_TELEPORT, 30s, 38s, 0, ((THE_HUNTRESS), (THE_PRIESTESS)));
events.ScheduleEvent(EVENT_RAPID_SHOT, 25s, 0, THE_CAPTAIN);
events.ScheduleEvent(EVENT_SHADOW_SHOT, 10s, 0, THE_CAPTAIN);
break;
case NPC_PRIESTESS_LUNASPYRE:
events.ScheduleEvent(EVENT_LUNAR_FIRE, 12s);
events.ScheduleEvent(EVENT_LUNAR_BEACON, 17s, 0 , THE_PRIESTESS);
events.ScheduleEvent(EVENT_MOON_BURN, 10s, 0 , THE_PRIESTESS);
events.ScheduleEvent(EVENT_INCORPOREAL_TELEPORT, 30s, 38s, ((THE_HUNTRESS), (THE_CAPTAIN)));
break;
}
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_DespawnAtEvade();
me->RemoveAllAreaTriggers();
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MOON_BURN);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_RAPID_SHOT);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MOON_GLAIVE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_LUNAR_BARRAGE_DAMAGE);
switch (me->GetEntry())
{
case NPC_HUNTRESS_KASPARIAN:
{
if (events.IsInPhase(THE_HUNTRESS))
Talk(SAY_KASPARIAN_EVADE);
break;
}
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
{
if (events.IsInPhase(THE_CAPTAIN))
Talk(SAY_YATHAE_EVADE);
break;
}
case NPC_PRIESTESS_LUNASPYRE:
{
if (events.IsInPhase(THE_PRIESTESS))
Talk(SAY_LUNASPYRE_EVADE);
break;
}
default:
break;
}
}
void DoAction(const int32 action) override
{
switch (action)
{
case ACTION_EVADE:
{
switch (me->GetEntry())
{
case NPC_HUNTRESS_KASPARIAN:
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAurasDueToSpell(SPELL_GHOST_AURA);
break;
}
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
case NPC_PRIESTESS_LUNASPYRE:
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->AddAura(SPELL_GHOST_AURA, me);
break;
}
default:
break;
}
break;
}
case ACTION_PHASE_2:
{
events.SetPhase(THE_CAPTAIN);
switch (me->GetEntry())
{
case NPC_HUNTRESS_KASPARIAN:
{
me->AddAura(SPELL_GHOST_AURA, me);
// Disable Movement
break;
}
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_TELEPORT_CENTER_COMBAT, 0s);
//Enable Movement
break;
}
case NPC_PRIESTESS_LUNASPYRE:
break;
default:
break;
}
break;
}
case ACTION_PHASE_3:
{
events.SetPhase(THE_PRIESTESS);
switch (me->GetEntry())
{
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->AddAura(SPELL_GHOST_AURA, me);
events.ScheduleEvent(EVENT_BACK_TO_GHOST, 0s);
// Disable Movement
break;
}
case NPC_PRIESTESS_LUNASPYRE:
{
me->RemoveAurasDueToSpell(SPELL_GHOST_AURA);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_TELEPORT_CENTER_COMBAT, 0s);
// Enable Movement
break;
}
default:
break;
}
break;
}
case ACTION_SISTERS_DEAD:
{
events.ScheduleEvent(EVENT_LUNASPYRE_JUST_DIED, 0s);
events.ScheduleEvent(EVENT_YATHAE_JUST_DIED, 8s);
events.ScheduleEvent(EVENT_KASPARIAN_JUST_DIED, 16s);
break;
}
case ACTION_SAY_SISTERS_AGGRO:
{
events.ScheduleEvent(EVENT_KASPARIAN_AGGRO, 0s);
events.ScheduleEvent(EVENT_LUNASPYRE_AGGRO, 4s);
events.ScheduleEvent(EVENT_YATHAE_AGGRO, 9s);
break;
}
default:
break;
}
}
void DamageTaken(Unit* attacker, uint32 &damage) override
{
if (me->GetEntry() == NPC_HUNTRESS_KASPARIAN)
{
if (me->HealthBelowPctDamaged(70, damage))
{
DoAction(ACTION_PHASE_2);
}
}
if (me->GetEntry() == NPC_CAPTAIN_YATHAE_MOONSTRIKE)
{
if (me->HealthBelowPctDamaged(40, damage))
{
DoAction(ACTION_PHASE_3);
}
}
}
void JustDied(Unit* /*killer*/) override
{
DoAction(ACTION_SISTERS_DEAD);
}
void KilledUnit(Unit* killer) override
{
if (killer->GetTypeId() == TYPEID_PLAYER && !me->IsInEvadeMode())
{
/*switch (killer)
{
case NPC_HUNTRESS_KASPARIAN:
{
if (events.IsInPhase(THE_HUNTRESS))
killer->Talk(SAY_KASPARIAN_KILLS);
else if (events.IsInPhase(THE_CAPTAIN))
yathae->AI()->Talk(SAY_SISTER_KILLS);
else if (events.IsInPhase(THE_PRIESTESS))
lunaspyre->AI()->Talk(SAY_SISTER_KILLS);
break;
}
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
{
if (events.IsInPhase(THE_HUNTRESS))
kasparian->AI()->Talk(SAY_SISTER_KILLS);
else if (events.IsInPhase(THE_CAPTAIN))
killer->Talk(SAY_YATHAE_KILLS);
else if (events.IsInPhase(THE_PRIESTESS))
lunaspyre->AI()->Talk(SAY_SISTER_KILLS);
break;
}
case NPC_PRIESTESS_LUNASPYRE:
{
if (events.IsInPhase(THE_HUNTRESS))
kasparian->AI()->Talk(SAY_SISTER_KILLS);
else if (events.IsInPhase(THE_CAPTAIN))
yathae->AI()->Talk(SAY_YATHAE_KILLS);
else if (events.IsInPhase(THE_PRIESTESS))
killer->Talk(SAY_LUNASPYRE_KILLS);
break;
}
default:
break;
}*/
}
}
void UpdateAI(const uint32 diff) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
// Kasparian
case EVENT_KASPARIAN_AGGRO:
Talk(SAY_KASPARIAN_AGGRO);
break;
case EVENT_MOON_GLAIVE:
{
DoCastVictim(SPELL_MOON_GLAIVE);
events.Repeat(17s);
}
break;
case EVENT_TWILIGHT_GLAIVE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_TWILIGHT_GLAIVE_AT);
events.Repeat(22s);
break;
case EVENT_GLAIVE_STORM:
// TODO
break;
case EVENT_KASPARIAN_JUST_DIED:
Talk(SAY_KASPARIAN_DIED);
break;
// Yathae
case EVENT_YATHAE_AGGRO:
Talk(SAY_YATHAE_AGGRO);
break;
case EVENT_CALL_MOONTALON:
DoCast(me, SPELL_CALL_MOONTALON);
events.Repeat(40s);
break;
case EVENT_TWILIGHT_VOLLEY:
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_TWILIGHT_VOLLEY_AT);
events.Repeat(15s);
}
break;
case EVENT_RAPID_SHOT:
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_RAPID_SHOT);
DoCast(me, SPELL_COOLDOWN_CREATURE_SPECIAL, true);
}
events.Repeat(17s);
}
break;
case EVENT_SHADOW_SHOT:
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_SHADOW_SHOT);
}
events.Repeat(20s);
}
break;
case EVENT_YATHAE_JUST_DIED:
Talk(SAY_YATHAE_DIED);
break;
// Lunaspyre
case EVENT_LUNASPYRE_AGGRO:
Talk(SAY_LUNASPYRE_AGGRO);
break;
case EVENT_LUNAR_BEACON:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_LUNAR_BEACON);
events.Repeat(12s);
break;
case EVENT_LUNAR_FIRE:
DoCastVictim(SPELL_LUNAR_FIRE);
events.Repeat(25s);
break;
case EVENT_MOON_BURN:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_MOON_BURN);
events.Repeat(14s);
break;
case EVENT_LUNAR_STRIKE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_LUNAR_STRIKE);
events.Repeat(16s);
break;
case EVENT_EMBRACE_OF_THE_ECLIPSE:
// TODO
break;
case EVENT_LUNASPYRE_JUST_DIED:
Talk(SAY_LUNASPYRE_DIED);
break;
default:
break;
}
}
switch (me->GetEntry())
{
case NPC_HUNTRESS_KASPARIAN:
{
if (events.IsInPhase(THE_HUNTRESS))
DoMeleeAttackIfReady();
else
DoSpellAttackIfReady(SPELL_MOON_GLAIVE);
break;
}
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
{
if (events.IsInPhase(THE_CAPTAIN))
DoMeleeAttackIfReady();
else
DoSpellAttackIfReady(SPELL_SHADOW_SHOT);
break;
}
case NPC_PRIESTESS_LUNASPYRE:
{
if (events.IsInPhase(THE_PRIESTESS))
DoMeleeAttackIfReady();
else
DoSpellAttackIfReady(SPELL_LUNAR_STRIKE);
break;
}
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new boss_sisters_of_the_moon_AI(creature);
}
};
// Kasparian Spells & ATs
struct at_twilight_glaive : AreaTriggerAI
{
at_twilight_glaive(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
if (Creature* creCaster = caster->ToCreature())
if (creCaster->IsAIEnabled)
if (Unit* target = ObjectAccessor::GetUnit(*creCaster, creCaster->AI()->GetGUID()))
{
Position targetPos = target->GetPosition();
float targetDist = caster->GetDistance(target);
float targetAngle = caster->GetAngle(target);
at->MovePosition(targetPos, targetDist, targetAngle);
}
}
void OnUnitEnter(Unit* /*unit*/) override
{
if (Unit* caster = at->GetCaster())
if (Unit* target = at->GetTarget())
if (caster->IsValidAttackTarget(target))
caster->CastSpell(target, SPELL_TWILIGHT_GLAIVE_DAMAGE, true);
}
void OnDestinationReached() override
{
if (Unit* caster = at->GetCaster())
{
Position casterPos = caster->GetPosition();
float casterDist = at->GetDistance(caster);
float casterAngle = at->GetAngle(caster);
at->MovePosition(casterPos, casterDist, casterAngle);
}
at->Remove();
}
};
// Yathae Spells & AT
struct at_twilight_volley : AreaTriggerAI
{
at_twilight_volley(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnInitialize() override
{
/*if (Unit* caster = at->GetCaster())
if (Creature* creCaster = caster->ToCreature())
if (creCaster->IsAIEnabled)
if (Unit* target = ObjectAccessor::GetUnit(*creCaster, creCaster->AI()->GetGUID()))
at->SetPosition(*target);*/
}
void OnUnitEnter(Unit* /*unit*/) override
{
if (Unit* caster = at->GetCaster())
if (Unit* target = at->GetTarget())
if (caster->IsValidAttackTarget(target))
caster->CastSpell(target, SPELL_TWILIGHT_VOLLEY_DAMAGE, true);
}
void OnUnitExit(Unit* /*unit*/) override
{
if (Unit* caster = at->GetCaster())
if (Unit* target = at->GetTarget())
if (caster->IsValidAttackTarget(target))
target->RemoveAurasDueToSpell(SPELL_TWILIGHT_VOLLEY_DAMAGE);
}
};
// Lunasypre Spells & AT
/*class spell_embrace_of_the_eclipse : public SpellScriptLoader
{
public:
spell_embrace_of_the_eclipse() : SpellScriptLoader("spell_embrace_of_the_eclipse") { }
class spell_embrace_of_the_eclipse_SpellScript : public SpellScript
{
PrepareSpellScript(spell_embrace_of_the_eclipse_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*//*) override
{
return ValidateSpellInfo({ SPELL_EMBRACE_OF_THE_ECLIPSE_HEAL, SPELL_EMBRACE_OF_THE_ECLIPSE_BOSS });
}
void HandleAfterCast()
{
Unit* caster = GetCaster();
Creature* kasparian = instance->GetCreature(NPC_HUNTRESS_KASPARIAN);
Creature* yathae = instance->GetCreature(NPC_CAPTAIN_YATHAE_MOONSTRIKE);
if (!caster)
return;
std::list<Player*> playerList;
GetPlayerListInGrid(playerList, me, 200.0f);
for (auto itr : playerList)
itr->RemoveAura(SPELL_EMBRACE_OF_THE_ECLIPSE_HEAL);
}
void Register() override
{
AfterCast += SpellCastFn(spell_embrace_of_the_eclipse_SpellScript::HandleAfterCast);
}
};
class spell_embrace_of_the_eclipse_AuraScript : public AuraScript
{
PrepareAuraScript(spell_embrace_of_the_eclipse_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*//*) override
{
return ValidateSpellInfo({ SPELL_EMBRACE_OF_THE_ECLIPSE_BOSS, SPELL_EMBRACE_OF_THE_ECLIPSE_HEAL });
}
void HandleRemove(AuraEffect const* aurEff, uint32 &shieldType, AuraEffectHandleModes /*mode*//*)
{
AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
if (removeMode == AURA_REMOVE_BY_EXPIRE)
{
switch (shieldType)
{
case SPELL_EMBRACE_OF_THE_ECLIPSE_BOSS:
break;
case SPELL_EMBRACE_OF_THE_ECLIPSE_HEAL:
break;
default:
break;
}
}
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_embrace_of_the_eclipse_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_ABSORB, AURA_EFFECT_HANDLE_REAL);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_embrace_of_the_eclipse_SpellScript();
}
AuraScript* GetAuraScript() const override
{
return new spell_embrace_of_the_eclipse_AuraScript();
}
};*/
class spell_lunar_beacon : public SpellScriptLoader
{
public:
spell_lunar_beacon() : SpellScriptLoader("spell_lunar_beacon") { }
class spell_lunar_beacon_AuraScript : public AuraScript
{
PrepareAuraScript(spell_lunar_beacon_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_LUNAR_BARRAGE_AT });
}
void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (GetCaster())
{
AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
if (removeMode == AURA_REMOVE_BY_EXPIRE)
GetCaster()->CastSpell(GetTarget(), SPELL_LUNAR_BARRAGE_AT, true);
}
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_lunar_beacon_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_lunar_beacon_AuraScript();
}
};
struct at_lunar_barrage : AreaTriggerAI
{
at_lunar_barrage(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
if (Creature* creCaster = caster->ToCreature())
if (creCaster->IsAIEnabled)
if (Unit* target = ObjectAccessor::GetUnit(*creCaster, creCaster->AI()->GetGUID()))
at->SetDestination(*target, 1000);
}
void OnUnitEnter(Unit* /*unit*/) override
{
if (Unit* caster = at->GetCaster())
if (Unit* target = at->GetTarget())
if (caster->IsValidAttackTarget(target))
caster->CastSpell(target, SPELL_LUNAR_BARRAGE_DAMAGE, true);
}
void OnUnitExit(Unit* /*unit*/) override
{
if (Unit* caster = at->GetCaster())
if (Unit* target = at->GetTarget())
if (caster->IsValidAttackTarget(target))
target->RemoveAurasDueToSpell(SPELL_LUNAR_BARRAGE_DAMAGE);
}
};
void AddSC_boss_sisters_of_the_moon_debug()
{
// Boss
new boss_sisters_of_the_moon();
// Kasparian ATs & Spells
RegisterAreaTriggerAI(at_twilight_glaive);
// Yathae ATs & Spells
RegisterAreaTriggerAI(at_twilight_volley);
// Lunaspyre ATs & Spells
new spell_lunar_beacon();
//new spell_embrace_of_the_eclipse();
RegisterAreaTriggerAI(at_lunar_barrage);
}
@@ -1,164 +1,605 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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/>.
*/
https://uwow.biz/
*/
#include "Creature.h"
#include "tomb_of_sargeras.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
DoorData const doorData[] =
{
{ GO_DOOR_ROOM_GOROTH_S, DATA_GOROTH, DOOR_TYPE_ROOM },
{ GO_DOOR_ROOM_GOROTH_N, DATA_GOROTH, DOOR_TYPE_PASSAGE },
{ GO_DOOR_ROOM_GOROTH_E, DATA_GOROTH, DOOR_TYPE_PASSAGE },
//{269164, DATA_GOROTH, DOOR_TYPE_PASSAGE},
{268514, DATA_GOROTH, DOOR_TYPE_PASSAGE},
{268580, DATA_GOROTH, DOOR_TYPE_PASSAGE},
{GO_GOROTH_GATES, DATA_GOROTH, DOOR_TYPE_PASSAGE},
{269975, DATA_GOROTH, DOOR_TYPE_ROOM},
{269974, DATA_GOROTH, DOOR_TYPE_ROOM},
{269973, DATA_GOROTH, DOOR_TYPE_ROOM},
{ GO_INTRODESTROY_2, DATA_GOROTH, DOOR_TYPE_PASSAGE},
{269120, DATA_HARJATAN, DOOR_TYPE_PASSAGE},
{269192, DATA_HARJATAN, DOOR_TYPE_ROOM},
{GO_SASSZINE_DOOR, DATA_MISTRESS_SASSZINE, DOOR_TYPE_ROOM},
{GO_INQUISITION_DOOR, DATA_DEMONIC_INQUISITION, DOOR_TYPE_ROOM},
{GO_HAMMER_THRONE, DATA_DEMONIC_INQUISITION, DOOR_TYPE_PASSAGE},
{GO_ELUNES_THRONE, DATA_THE_DESOLATE_HOST, DOOR_TYPE_PASSAGE},
{GO_GOLGANETH_THRONE, DATA_MISTRESS_SASSZINE, DOOR_TYPE_PASSAGE},
{GO_MAIDEN_DOOR, DATA_MAIDEN_OF_VIGILANCE, DOOR_TYPE_ROOM},
{GO_SISTERS_MOON_DOOR, DATA_SISTERS_OF_THEMOON, DOOR_TYPE_ROOM},
{GO_AVATARA_DOOR, DATA_FALLEN_AVATAR, DOOR_TYPE_ROOM},
{GO_DESOLATE_HOST_DOOR_1, DATA_THE_DESOLATE_HOST, DOOR_TYPE_ROOM},
{GO_DESOLATE_HOST_DOOR_2, DATA_THE_DESOLATE_HOST, DOOR_TYPE_ROOM},
{0, 0, DOOR_TYPE_ROOM} // END
};
ObjectData const creatureData[] =
{
{NPC_BREACH_IN_WINDOW, NPC_BREACH_IN_WINDOW},
{NPC_KHADGAR, NPC_KHADGAR},
{NPC_VELEN, NPC_VELEN},
{NPC_ILLIDAN, NPC_ILLIDAN},
{NPC_MAEIV, NPC_MAEIV},
{NPC_DURGAN, NPC_DURGAN},
{NPC_ATRIGAN_MISC, NPC_ATRIGAN_MISC},
{NPC_EVENT_1, NPC_EVENT_1},
{NPC_EVENT_2, NPC_EVENT_2},
{NPC_SASSZINE_MISC, NPC_SASSZINE_MISC},
{NPC_GOROTH, DATA_GOROTH},
{NPC_SASSZINE, DATA_MISTRESS_SASSZINE},
{NPC_MOON_STALKER, DATA_SISTERS_OF_THEMOON},
{NPC_HUNTRESS_KASPARIAN, NPC_HUNTRESS_KASPARIAN},
{NPC_PRIESTESS_LUNASPYRE, NPC_PRIESTESS_LUNASPYRE},
{NPC_CAPTAIN_YATHAE, NPC_CAPTAIN_YATHAE},
{NPC_KILJAEDEN, DATA_KILJAEDEN},
{NPC_HAMMER_1, NPC_HAMMER_1},
{NPC_HAMMER_2, NPC_HAMMER_2},
{NPC_ELUNES_1, NPC_ELUNES_1},
{NPC_ELUNES_2, NPC_ELUNES_2},
{NPC_GOLGANETH_1, NPC_GOLGANETH_1},
{NPC_GOLGANETH_2, NPC_GOLGANETH_2},
{NPC_SASSZINE_NPC_OUTRO, NPC_SASSZINE_NPC_OUTRO},
{NPC_KILDJEDAN_AVATARA, NPC_KILDJEDAN_AVATARA},
{NPC_ATRIGAN, NPC_ATRIGAN},
{NPC_BELAK, NPC_BELAK},
{NPC_HARJATAN, NPC_HARJATAN},
{NPC_ELDER, NPC_ELDER},
{NPC_AVATARA_MAIDEN , NPC_AVATARA_MAIDEN},
{NPC_SISTERS_ACH_ADD, NPC_SISTERS_ACH_ADD},
{0, 0} // END
};
ObjectData const gobjectData[] =
{
{GO_GOROTH_GATES, GO_GOROTH_GATES},
{GO_INTRODESTROY_1, GO_INTRODESTROY_1},
{GO_INTRODESTROY_2, GO_INTRODESTROY_2},
{GO_INTRODESTROY_3, GO_INTRODESTROY_3},
{GO_ELEVATOR, GO_ELEVATOR},
{GO_KILJAEDEN_BRIDGE_1, GO_KILJAEDEN_BRIDGE_1},
{GO_KILJAEDEN_BRIDGE_2, GO_KILJAEDEN_BRIDGE_2},
{GO_KILJAEDEN_CHEST, GO_KILJAEDEN_CHEST},
{269164, 269164},
{268580, 268580},
{GO_AVATARA_FLOOR , GO_AVATARA_FLOOR},
// Avataras floor blocks
{267700, 267700},
{267701, 267701},
{267702, 267702},
{267703, 267703},
{267704, 267704},
{267705, 267705},
{267706, 267706},
{267707, 267707},
{267708, 267708},
{267709, 267709},
{267710, 267710},
{267711, 267711},
{267712, 267712},
{267713, 267713},
{267714, 267714},
{267715, 267715},
{267716, 267716},
{267717, 267717},
{267718, 267718},
{267719, 267719},
{267720, 267720},
{267721, 267721},
{267722, 267722},
{267723, 267723},
{267724, 267724},
// end Avatara bloks
{0, 0 } // END
};
class instance_tomb_of_sargeras : public InstanceMapScript
{
public:
instance_tomb_of_sargeras() : InstanceMapScript("instance_tomb_of_sargeras", 1676) { }
public:
instance_tomb_of_sargeras() : InstanceMapScript(ToSScriptName, 1676) {}
struct instance_tomb_of_sargeras_InstanceMapScript : public InstanceScript
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_tomb_of_sargeras_InstanceMapScript(map);
}
struct instance_tomb_of_sargeras_InstanceMapScript : InstanceScript
{
instance_tomb_of_sargeras_InstanceMapScript(Map* map) : InstanceScript(map->ToInstanceMap())
{
instance_tomb_of_sargeras_InstanceMapScript(InstanceMap* map) : InstanceScript(map) { }
SetBossNumber(MAX_ENCOUNTER);
}
void Initialize() override
{
SetBossNumber(ENCOUNTER_COUNT);
LoadDoorData(doorData);
}
std::vector<ObjectGuid> addsIntro{};
std::set<ObjectGuid> lunarArchersEvent{};
WorldLocation loc_res_pla{};
void OnCreatureCreate(Creature* creature) override
std::vector<ObjectGuid> avatarasFloors{};
uint32 checkTimer = 1000;
uint32 checkPlayersFallTimer = 1000;
void Initialize() override
{
LoadDoorData(doorData);
LoadObjectData(creatureData, gobjectData);
}
void OnPlayerEnter(Player* player) override {}
void OnCreatureCreate(Creature* creature) override
{
InstanceScript::OnCreatureCreate(creature);
switch (creature->GetEntry())
{
switch (creature->GetEntry())
{
case BOSS_GOROTH:
case 121024:
case 121023:
if (creature->GetPositionX() >= 6019.0f && creature->GetPositionZ() <= 2972.0f)
{
if (!creature->HasAura(35356) && !false /* flag3 feign death non porte */)
{
creature->AddDelayedEvent(1000, [creature] () -> void {creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK1H);});
addsIntro.push_back(creature->GetGUID());
}
}
break;
case NPC_GOROTH:
creature->SetVisible(false);
creature->setActive(false);
GorothGUID = creature->GetGUID();
creature->SetReactState(REACT_PASSIVE);
break;
case BOSS_ATRIGAN:
AtriganGUID = creature->GetGUID();
case NPC_MAEIV:
case NPC_ILLIDAN:
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK1H);
break;
case BOSS_BELAC:
BelacGUID = creature->GetGUID();
case NPC_VELEN:
creature->CastSpell(creature, 241186); // he don't want use it like aura =C
break;
case BOSS_HARJATAN:
case NPC_HUNTRESS_KASPARIAN:
case NPC_CAPTAIN_YATHAE_MOONSTRIKE:
case NPC_PRIESTESS_LUNASPYRE:
case NPC_SASSZINE:
case NPC_ENGINE_OF_SOULS:
case NPC_SOUL_QUEEN_DEJAHNA:
case NPC_DESOLATE_HOST:
case NPC_MAIDEN_OF_VIGILANCE:
case NPC_FALLEN_AVATAR:
case NPC_KILJAEDEN:
AddObject(creature, true);
break;
default:
break;
}
case NPC_ATRIGAN_MISC:
creature->SetReactState(REACT_PASSIVE);
if (GetBossState(DATA_GOROTH) != NOT_STARTED)
creature->SetVisible(false);
break;
case NPC_HAMMER_1:
case NPC_HAMMER_2:
if (GetBossState(DATA_DEMONIC_INQUISITION) != DONE)
creature->SetVisible(false);
break;
case NPC_ELUNES_1:
case NPC_ELUNES_2:
if (GetBossState(DATA_THE_DESOLATE_HOST) != DONE)
creature->SetVisible(false);
break;
case NPC_GOLGANETH_1:
case NPC_GOLGANETH_2:
if (GetBossState(DATA_MISTRESS_SASSZINE) != DONE)
creature->SetVisible(false);
break;
case NPC_LUNAR_ARCHER:
if (creature->GetDistance(6088.19f, -1030.07f, 2896.31f) <= 10.0f)
lunarArchersEvent.insert(creature->GetGUID());
break;
case NPC_KILDJEDAN_AVATARA:
if (GetBossState(DATA_FALLEN_AVATAR) == DONE)
creature->SetVisible(false);
break;
case NPC_TADPOLE_1:
case NPC_TADPOLE_2:
case NPC_TADPOLE_3:
if (Creature* harjatan = instance->GetCreature(GetGuidData(NPC_HARJATAN)))
harjatan->AI()->JustSummoned(creature);
break;
case NPC_FRAGMENT_SOUL:
if (!instance->IsMythic())
creature->DespawnOrUnsummon(100);
else if (Creature* atrigan = instance->GetCreature(GetGuidData(NPC_ATRIGAN)))
{
atrigan->AI()->JustSummoned(creature);
creature->CastSpell(creature, 241521);
}
break;
default:
break;
}
}
void OnGameObjectCreate(GameObject* go) override
void OnGameObjectCreate(GameObject* go) override
{
InstanceScript::OnGameObjectCreate(go);
switch (go->GetEntry())
{
switch (go->GetEntry())
{
case GO_DESTRUCTIBLE_1:
DestructibleGUID[0] = go->GetGUID();
if (GetBossState(DATA_GOROTH) == DONE)
go->UseDoorOrButton(1000000, true);
case GO_ELEVATOR:
if (GetBossState(DATA_MAIDEN_OF_VIGILANCE) != DONE)
// (SetPhaseMask 2 : phasing legacy uwow, non porte)
break;
case GO_DESTRUCTIBLE_2:
DestructibleGUID[1] = go->GetGUID();
if (GetBossState(DATA_GOROTH) == DONE)
go->UseDoorOrButton(1000000, true);
case 267700:
case 267701:
case 267702:
case 267703:
case 267704:
case 267705:
case 267706:
case 267707:
case 267708:
case 267709:
case 267710:
case 267711:
case 267712:
case 267713:
case 267714:
case 267715:
case 267716:
case 267717:
case 267718:
case 267719:
case 267720:
case 267721:
case 267722:
case 267723:
case 267724:
avatarasFloors.push_back(go->GetGUID());
break;
case GO_DESTRUCTIBLE_3:
DestructibleGUID[2] = go->GetGUID();
if (GetBossState(DATA_GOROTH) == DONE)
go->UseDoorOrButton(1000000, true);
break;
case GO_DOOR_TO_MISTRESS:
case GO_DOOR_TO_MISTRESS2:
if (GetBossState(DATA_HARJATAN) == DONE)
go->UseDoorOrButton(1000000, true);
break;
case GO_DOOR_ROOM_GOROTH_S:
case GO_DOOR_ROOM_GOROTH_N:
case GO_DOOR_ROOM_GOROTH_E:
AddDoor(go, true);
break;
default:
break;
}
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case DATA_GOROTH:
return GorothGUID;
case DATA_ATRIGAN:
return AtriganGUID;
case DATA_BELAC:
return BelacGUID;
default:
break;
}
return ObjectGuid::Empty;
}
protected:
EventMap events;
ObjectGuid GorothGUID;
ObjectGuid AtriganGUID;
ObjectGuid BelacGUID;
ObjectGuid DestructibleGUID[3];
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_tomb_of_sargeras_InstanceMapScript(map);
}
}
void OnGameObjectRemove(GameObject* go) override
{
InstanceScript::OnGameObjectRemove(go);
}
void OnUnitDeath(Unit* creature) override
{
switch (creature->GetEntry())
{
case NPC_LUNAR_ARCHER:
if (lunarArchersEvent.find(creature->GetGUID()) != lunarArchersEvent.end())
{
lunarArchersEvent.erase(creature->GetGUID());
if (lunarArchersEvent.empty())
instance->SummonCreature(NPC_GUARDIAN_SENTRY, { 6088.50f, -1027.06f, 2896.43f, 4.23f });
}
break;
case NPC_EVENT_1:
case NPC_EVENT_2:
if (Creature* event = instance->GetCreature(GetGuidData(NPC_SASSZINE_MISC)))
if (event->IsAlive() && event->IsInWorld())
event->AI()->DoAction(1);
break;
default:
break;
}
}
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
if (type != DATA_MAIDEN_OF_VIGILANCE && type != DATA_FALLEN_AVATAR && type != DATA_KILJAEDEN)
if (GameObject* go = instance->GetGameObject(GetGuidData(269164)))
HandleGameObject(go->GetGUID(), CheckRequiredBosses(DATA_MAIDEN_OF_VIGILANCE), go);
switch (state)
{
case DONE:
{
switch (type)
{
case DATA_GOROTH:
if (auto khadgar = instance->GetCreature(GetGuidData(NPC_KHADGAR)))
khadgar->AI()->DoAction(true);
break;
case DATA_DEMONIC_INQUISITION:
for (auto id : {NPC_HAMMER_1, NPC_HAMMER_2})
if (auto hammer = instance->GetCreature(GetGuidData(id)))
hammer->SetVisible(true);
break;
case DATA_HARJATAN:
if (auto sivash = instance->GetCreature(GetGuidData(NPC_SASSZINE_NPC_OUTRO)))
sivash->AddDelayedEvent(2000, [sivash] {sivash->AI()->ZoneTalk(0); });
break;
case DATA_THE_DESOLATE_HOST:
for (auto id : { NPC_ELUNES_1, NPC_ELUNES_2 })
if (auto elunes = instance->GetCreature(GetGuidData(id)))
elunes->SetVisible(true);
break;
case DATA_MISTRESS_SASSZINE:
for (auto id : { NPC_GOLGANETH_1, NPC_GOLGANETH_2 })
if (auto golganeth = instance->GetCreature(GetGuidData(id)))
golganeth->SetVisible(true);
break;
case DATA_MAIDEN_OF_VIGILANCE:
if (auto go = instance->GetGameObject(GetGuidData(GO_ELEVATOR)))
// (SetPhaseMask 1 : phasing legacy uwow, non porte)
break;
default:
break;
}
break;
}
case NOT_STARTED:
{
switch (type)
{
case DATA_FALLEN_AVATAR:
if (GameObject* go = instance->GetGameObject(GetGuidData(GO_AVATARA_FLOOR)))
go->SetDestructibleState(GO_DESTRUCTIBLE_INTACT);
for (auto i : avatarasFloors)
if (GameObject* go = instance->GetGameObject(i))
go->SetDestructibleState(GO_DESTRUCTIBLE_INTACT);
break;
}
break;
}
default:
break;
case IN_PROGRESS:
// TODO: handle IN_PROGRESS if needed
break;
case FAIL:
// TODO: handle FAIL if needed
break;
case SPECIAL:
// TODO: handle SPECIAL if needed
break;
case TO_BE_DECIDED:
// TODO: handle TO_BE_DECIDED if needed
break;
}
if (type == DATA_KILJAEDEN)
{
if (state == IN_PROGRESS)
{
HandleGameObject(GetGuidData(GO_KILJAEDEN_BRIDGE_1), true);
HandleGameObject(GetGuidData(GO_KILJAEDEN_BRIDGE_2), true);
}
else
{
HandleGameObject(GetGuidData(GO_KILJAEDEN_BRIDGE_1), false);
HandleGameObject(GetGuidData(GO_KILJAEDEN_BRIDGE_2), false);
}
}
return true;
}
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case 1: // intro
for (auto guid : addsIntro)
if (auto creature = instance->GetCreature(guid))
{
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
creature->CombatStop();
creature->CastSpell(creature, 35356);
}
break;
default:
break;
}
}
uint32 GetData(uint32 type) const override
{
//switch (type)
//{
//default:
return 0;
//}
}
ObjectGuid GetGuidData(uint32 type) const override
{
//switch (type)
//{
//default:
return InstanceScript::GetGuidData(type);
//}
}
bool CheckRequiredBosses(uint32 bossId, Player const* /*player*/ = nullptr) const override
{
if (false)
return true;
switch (bossId)
{
case DATA_MAIDEN_OF_VIGILANCE:
for (uint32 i = DATA_GOROTH; i < DATA_MAIDEN_OF_VIGILANCE; ++i)
if (GetBossState(i) != DONE)
return false;
return true;
default:
return true;
}
}
WorldLocation* GetClosestGraveYard(float x, float y, float z) /* signature uwow, la table graveyard_zone fait foi */
{
Position playerPosition(x, y, z);
uint32 graveyardId = 5889;
std::vector<uint32> availableGravs{ 6014, 6017, 6019, 5889 };
if (GetBossState(DATA_GOROTH) == DONE)
availableGravs.push_back(6015);
if (CheckRequiredBosses(DATA_MAIDEN_OF_VIGILANCE))
availableGravs.push_back(6016);
if (GetBossState(DATA_HARJATAN) == DONE)
availableGravs.push_back(6018);
if (GetBossState(DATA_MAIDEN_OF_VIGILANCE) == DONE)
availableGravs.push_back(6020);
if (GetBossState(DATA_FALLEN_AVATAR) == DONE)
availableGravs.push_back(6210);
if (GetBossState(DATA_KILJAEDEN) == DONE)
availableGravs.push_back(6117);
for (auto gravYard : availableGravs)
{
WorldSafeLocsEntry const* temp = sWorldSafeLocsStore.LookupEntry(gravYard);
WorldSafeLocsEntry const* saved = sWorldSafeLocsStore.LookupEntry(graveyardId);
if (!temp)
continue;
if (!saved)
graveyardId = gravYard;
Position pos1(temp->Loc.X, temp->Loc.Y, temp->Loc.Z);
Position pos2(saved->Loc.X, saved->Loc.Y, saved->Loc.Z);
if (playerPosition.GetExactDist(&pos1) < playerPosition.GetExactDist(&pos2))
graveyardId = gravYard;
}
if (GetBossState(DATA_GOROTH) != DONE)
{
WorldSafeLocsEntry const* temp = sWorldSafeLocsStore.LookupEntry(6015);
WorldSafeLocsEntry const* saved = sWorldSafeLocsStore.LookupEntry(graveyardId);
if (temp)
{
Position pos1(temp->Loc.X, temp->Loc.Y, temp->Loc.Z);
Position pos2(saved->Loc.X, saved->Loc.Y, saved->Loc.Z);
if (playerPosition.GetExactDist(&pos1) < playerPosition.GetExactDist(&pos2))
graveyardId = 6015;
}
}
if (WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(graveyardId))
{
loc_res_pla.Relocate(gy->Loc.X, gy->Loc.Y, gy->Loc.Z);
loc_res_pla.m_mapId = gy->MapID;
}
return &loc_res_pla;
}
std::string GetSaveData() override
{
std::ostringstream saveStream;
saveStream << "T O S " << GetSaveData();
return saveStream.str();
}
void Load(const char* data) override
{
if (!data)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(data);
char dataHead1, dataHead2, dataHead3;
std::istringstream loadStream(data);
loadStream >> dataHead1 >> dataHead2 >> dataHead3;
if (dataHead1 == 'T' && dataHead2 == 'O' && dataHead3 == 'S')
{
for (uint32 i = 0; i < MAX_ENCOUNTER; ++i)
{
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
tmpState = NOT_STARTED;
SetBossState(i, EncounterState(tmpState));
}
}
else
OUT_LOAD_INST_DATA_FAIL;
OUT_LOAD_INST_DATA_COMPLETE;
}
void Update(uint32 diff) override
{
if (checkTimer <= diff)
{
checkTimer = 1000;
instance->ApplyOnEveryPlayer([&](Player* player)
{
if (GetBossState(DATA_FALLEN_AVATAR) == IN_PROGRESS &&
(player->GetPositionZ() <= 1509.50f || (player->GetPositionX() >= 6667.59f && player->GetPositionZ() <= 1540.68f)))
{
if (!player->HasAura(240249))
player->CastSpell(player, 240249, true);
}
else if (player->HasAura(240249))
player->RemoveAurasDueToSpell(240249);
if (player->IsAlive())
if (GetBossState(DATA_MAIDEN_OF_VIGILANCE) == IN_PROGRESS || GetBossState(DATA_MAIDEN_OF_VIGILANCE) == NOT_STARTED)
if (player->GetDistance2d(6348.49f, -796.72f) <= 21.0f)
if (player->GetPositionZ() <= 2855.0f)
player->Kill(player);
});
}
else
checkTimer -= diff;
if (checkPlayersFallTimer <= diff)
{
checkPlayersFallTimer = 500;
instance->ApplyOnEveryPlayer([&](Player* player)
{
if (player->IsFalling())
{
if (player->IsWithinBox({ 4500.0f, -1510.0f, 5330.0f }, 200.0f, 200.0f, 20.0f))
{
if (player->IsAlive())
player->Kill(player);
player->NearTeleportTo(4500.18f, -1484.60f, 5385.64f, player->GetOrientation());
}
if (player->GetDistance(6437.81f, -1089.29f, 2881.52f) < 100.0f && player->GetPositionZ() < 2870.0f)
{
if (player->IsAlive())
player->Kill(player);
player->NearTeleportTo(6402.37f, -1064.89f, 2881.05f, player->GetOrientation());
}
}
});
}
else
checkPlayersFallTimer -= diff;
}
};
};
void AddSC_instance_tomb_of_sargeras()
@@ -1,312 +1,542 @@
/*
* Copyright (C) 2016-2019 MagicStorm
*
* Este codigo es de uso exclusivo y privado para la red de gaming
* ColossusWoW est? totalmente prohibida su distribuci?n y
* uso en proyectos ajenos, si has obtenido o encontrado este codigo
* publicamente envianos un email a administracion@colossuswow.com
* indicandonos como y donde has obtenido este codigo
*
* Recuerda, no distribuyas, no compartas y no subas este codigo a ningun
* lugar publico, usa siempre nuestros repositorios Git!
https://uwow.biz/
*/
#include "GameObject.h"
#include "tomb_of_sargeras.h"
#include "WaypointManager.h"
#include "GameObjectAI.h"
const Position infernalChaosbringer[4] =
Position const InfernalsPos[3] =
{
{ 6130.221f, -801.1302f, 2971.884f, 2.807055f },
{ 6086.503f, -816.4011f, 2971.987f, 2.965497f },
{ 6064.199f, -782.8004f, 2971.644f, 2.827615f },
{ 6131.155f, -773.0943f, 2971.543f, 0.0f },
{ 6130.221f, -801.1302f, 2971.544f, 2.807055f },
{ 6086.503f, -816.4011f, 2971.721f, 2.965497f },
{ 6064.199f, -782.8004f, 2971.544f, 2.827615f },
};
// 119726 - Archimage Khadgar
class npc_archimage_khadgar_tos : public CreatureScript
// 121605
struct npc_tos_breach : ScriptedAI
{
public:
npc_archimage_khadgar_tos() : CreatureScript("npc_archimage_khadgar_tos") { }
explicit npc_tos_breach(Creature* creature) : ScriptedAI(creature) { }
enum velenEvents
void DoAction(int32 const actionID) override
{
EVENT_FALL_BACK = 1,
EVENT_IMPACT,
EVENT_CHECK_FOR_EVENT_START,
EVENT_ILLIDAN_TALK,
EVENT_TALK_ATRIGAN1,
EVENT_CAST_SCENE,
EVENT_SUMMONS,
};
enum velenSay
{
SAY_INTRO = 0,
};
struct npc_archimage_khadgar_tosAI : public ScriptedAI
{
npc_archimage_khadgar_tosAI(Creature* creature) : ScriptedAI(creature)
me->SetVisible(true);
switch (actionID)
{
//me->SummonGameObject(GO_DESTRUCTIBLE_2, 6146.56f, -762.025f, 2970.9f, 3.14159f, QuaternionData(-0.0f, -0.0f, -0.284929f, -0.958549f), 100000);
}
uint32 startTimer;
bool eventStarted;
void Reset() override
{
events.Reset();
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
if (Creature* creature = me->FindNearestCreature(NPC_VELEN, 1000.0f))
case 1:
for (uint8 i = 0; i < 3; ++i)
{
creature->SetReactState(REACT_PASSIVE);
creature->AttackStop();
}
if (Creature* creature = me->FindNearestCreature(117931, 1000.0f))
{
creature->SetReactState(REACT_PASSIVE);
creature->AttackStop();
creature->setFaction(35);
}
std::list<Unit*> unitList;
//me->GetAnyUnitListInRange(unitList, 1000.0f);
if (!unitList.empty())
{
for (auto unit : unitList)
me->AddDelayedEvent(100 + 600 * i, [this, i]() -> void
{
if (unit->GetTypeId() != TYPEID_UNIT)
continue;
unit->ToCreature()->Respawn();
}
me->CastSpell(InfernalsPos[i], 242915, false);
});
}
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
DoZoneInCombat();
events.ScheduleEvent(EVENT_CHECK_FOR_EVENT_START, 1 * IN_MILLISECONDS);
eventStarted = false;
break;
default:
break;
}
void CheckForStartEvent()
{
if (!eventStarted)
{
Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player *player = i->GetSource())
if (player->IsAlive() && player->GetDistance2d(5967.10f, -795.73f) <= 3.0f)
{
if (eventStarted)
continue;
me->Yell("Quickly, bolster our ranks! We must push through!", LANG_UNIVERSAL, NULL);
events.ScheduleEvent(EVENT_ILLIDAN_TALK, 6 * IN_MILLISECONDS);
events.CancelEvent(EVENT_CHECK_FOR_EVENT_START);
eventStarted = true;
}
}
}
void CastSceneToPlayers()
{
Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player *player = i->GetSource())
if (player->IsAlive())
player->CastSpell(player, SPELL_GOROTH_INTRO, true);
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_IMPACT:
if (Creature* creature = me->FindNearestCreature(NPC_VELEN, 1000.0f))
creature->DespawnOrUnsummon();
if (Creature* creature = me->FindNearestCreature(NPC_ILLIDAN, 1000.0f))
creature->DespawnOrUnsummon();
DoCast(SPELL_IMPACT);
me->DespawnCreaturesInArea(121024, 1000.0f);
me->DespawnCreaturesInArea(119742, 1000.0f);
me->DespawnCreaturesInArea(119768, 1000.0f);
me->DespawnCreaturesInArea(121005, 1000.0f);
me->DespawnCreaturesInArea(119730, 1000.0f);
me->DespawnCreaturesInArea(117931, 1000.0f);
me->DespawnCreaturesInArea(119777, 1000.0f);
if (Creature* creature = me->FindNearestCreature(NPC_ATRIGAN, 1000.0f))
{
creature->SummonCreature(NPC_INFERNAL_CHAOSBRINGER, 6130.221f, -801.1302f, 2971.884f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
creature->SummonCreature(NPC_INFERNAL_CHAOSBRINGER, 6086.503f, -816.4011f, 2971.987f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
creature->SummonCreature(NPC_INFERNAL_CHAOSBRINGER, 6064.199f, -782.8004f, 2971.644f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
creature->DespawnOrUnsummon(5000);
}
me->DespawnOrUnsummon();
break;
case EVENT_FALL_BACK:
Talk(SAY_INTRO);
events.ScheduleEvent(EVENT_IMPACT, 100);
break;
case EVENT_ILLIDAN_TALK:
if (Creature* creature = me->FindNearestCreature(NPC_ILLIDAN, 1000.0f))
creature->Yell("Leave none standing! If we fall here, Azeroth burns.", LANG_UNIVERSAL, NULL);
events.ScheduleEvent(EVENT_TALK_ATRIGAN1, 6 * IN_MILLISECONDS);
break;
case EVENT_TALK_ATRIGAN1:
if (Creature* creature = me->FindNearestCreature(NPC_ATRIGAN, 1000.0f))
{
creature->Yell("Yes! Let them come! Their bodies will fuel the flames or their burning world!", LANG_UNIVERSAL, NULL);
CastSceneToPlayers();
if (GameObject* go = me->FindNearestGameObject(GO_DESTRUCTIBLE_1, 5000.0f))
{
/*if (Creature* boss = me->FindNearestCreature(BOSS_GOROTH, 1000.0f))
go->CastSpell(boss, SPELL_SUMMON, true);*/
go->SetLootState(GO_READY);
go->UseDoorOrButton(1000000, true);
}
}
events.ScheduleEvent(EVENT_CAST_SCENE, 1 * IN_MILLISECONDS);
break;
case EVENT_CHECK_FOR_EVENT_START:
CheckForStartEvent();
events.ScheduleEvent(EVENT_CHECK_FOR_EVENT_START, 1 * IN_MILLISECONDS);
break;
case EVENT_CAST_SCENE:
if (GameObject* go = me->FindNearestGameObject(GO_DESTRUCTIBLE_2, 1000.0f))
{
go->SetLootState(GO_READY);
go->UseDoorOrButton(1000000, false);
}
if (GameObject* go = me->FindNearestGameObject(GO_DESTRUCTIBLE_3, 1000.0f))
{
go->SetLootState(GO_READY);
go->UseDoorOrButton(1000000, false);
}
events.ScheduleEvent(EVENT_SUMMONS, 3 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_FALL_BACK, 5 * IN_MILLISECONDS);
break;
case EVENT_SUMMONS:
if (Creature* creature = me->FindNearestCreature(BOSS_GOROTH, 1000.0f))
{
creature->SetVisible(true);
creature->SetAIAnimKitId(8801);
creature->PlayOneShotAnimKitId(8801);
creature->CastSpell(creature, 233081, true);
creature->CastSpell(creature, SPELL_IMPACT, true);
}
break;
}
}
}
private:
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetTombOfSargerasAI<npc_archimage_khadgar_tosAI>(creature);
}
};
// 241227 - Summon
class spell_goroth_summon : public SpellScriptLoader
uint32 const introEntries[4]
{
NPC_VELEN,
NPC_ILLIDAN,
NPC_MAEIV,
NPC_DURGAN
};
Position const introPositions[5]
{
{ 5986.409f, -795.8195f, 2978.126f, 6.269365f },
{ 5978.724f, -801.1215f, 2978.127f, 0.1859942f },
{ 5993.796f, -789.9375f, 2976.677f, 5.799626f },
{ 5990.001f, -801.5347f, 2977.88f, 0.3382317f },
{ 5980.707f, -790.559f, 2978.127f, 6.063946f }
};
// 119726
struct npc_tos_kadghar_1 : ScriptedAI
{
explicit npc_tos_kadghar_1(Creature* creature) : ScriptedAI(creature)
{
if (me->GetMapId() == 1676)
{
instance = me->GetInstanceScript();
IntroDone = false;
outroDone = false;
}
else
{
IntroDone = true;
outroDone = false;
}
SetCanSeeEvenInPassiveMode(true);
}
InstanceScript* instance;
bool IntroDone, outroDone;
void DoAction(int32 const actionID) override
{
me->GetMotionMaster()->MovePoint(0, 6087.42f, -796.14f, 2971.72f);
for (uint8 i = 0; i < 4; ++i)
if (auto add = me->GetMap()->GetCreature(instance->GetGuidData(introEntries[i])))
add->GetMotionMaster()->MovePoint(0, 6087.42f, -796.14f, 2971.72f);
me->AddDelayedEvent(8500, [this]() -> void
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(0, introPositions[0].GetPositionX() + 217.0f, introPositions[0].GetPositionY(), introPositions[0].GetPositionZ());
for (uint8 i = 0; i < 4; ++i)
if (auto add = me->GetMap()->GetCreature(instance->GetGuidData(introEntries[i])))
{
add->GetMotionMaster()->Clear();
add->GetMotionMaster()->MovePoint(0, introPositions[i + 1].GetPositionX() + 217.0f, introPositions[i + 1].GetPositionY(), introPositions[i + 1].GetPositionZ());
}
});
me->AddDelayedEvent(25000, [this]() -> void
{
if (Creature* egvin = me->SummonCreature(NPC_EGVIN, 6213.44f, -795.67f, 2975.00, 3.18f))
{
egvin->CastSpell(egvin, 241351);
egvin->CastSpell(me, 245480); // me->CreateConversation(4951);
egvin->AddDelayedEvent(600, [egvin] {
egvin->SetWalk(true);
egvin->GetMotionMaster()->MovePoint(0, 6209.66f, -795.69f, 2974.36f);
});
}
});
}
void MoveInLineOfSight(Unit* who) override
{
if (!who->IsPlayer())
return;
if (!IntroDone && instance->GetBossState(DATA_GOROTH) == DONE)
{
IntroDone = true;
me->CastStop();
me->CastSpell(introPositions[0], SPELL_INTRO_TELEPORT, false);
me->AddDelayedEvent(1000, [this] {me->SetFacingTo(6.25f); });
for (uint8 i = 0; i < 4; ++i)
if (auto add = me->GetMap()->GetCreature(instance->GetGuidData(introEntries[i])))
{
if (i == 0)
{
add->RemoveAurasDueToSpell(241186);
add->CastStop();
}
add->CombatStop();
add->CastSpell(introPositions[i + 1], SPELL_INTRO_TELEPORT, false);
add->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
add->AddDelayedEvent(1000, [add] {add->SetFacingTo(6.25f); });
}
if (auto visual_boss = me->GetMap()->GetCreature(instance->GetGuidData(NPC_ATRIGAN_MISC)))
visual_boss->DespawnOrUnsummon();
}
if(IntroDone)
return;
if (!instance)
return;
if (me->GetDistance(who) < 100.0f && !IntroDone)
{
IntroDone = true;
for (auto goid : { GO_INTRODESTROY_1, GO_INTRODESTROY_2, GO_INTRODESTROY_3})
if (GameObject* go = me->GetMap()->GetGameObject(instance->GetGuidData(goid)))
go->SetByteValue(GAMEOBJECT_BYTES_1, 0, 0);
if (GameObject* go = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GOROTH_GATES)))
go->SetByteValue(GAMEOBJECT_BYTES_1, 0, 1);
me->AddDelayedEvent(2000, [this] () -> void
{
Talk(1);
me->CastStop();
me->CastSpell(introPositions[0], SPELL_INTRO_TELEPORT, false);
me->AddDelayedEvent(1000, [this] {me->SetFacingTo(6.25f); });
for (uint8 i =0; i < 4; ++i)
if (auto add = me->GetMap()->GetCreature(instance->GetGuidData(introEntries[i])))
{
if (i == 0)
{
add->RemoveAurasDueToSpell(241186);
add->CastStop();
}
add->CombatStop();
add->CastSpell(introPositions[i + 1], SPELL_INTRO_TELEPORT, false);
add->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
add->AddDelayedEvent(1000, [add] {add->SetFacingTo(6.25f); });
}
instance->SetData(1, 1);
if (GameObject* go = me->GetMap()->GetGameObject(instance->GetGuidData(GO_INQUISITION_DOOR_INTRO)))
{
go->SetByteValue(GAMEOBJECT_BYTES_1, 0, 0);
go->AddDelayedEvent(4000, [go] {
go->SetByteValue(GAMEOBJECT_BYTES_1, 0, 1);
});
}
if (auto visual_boss = me->GetMap()->GetCreature(instance->GetGuidData(NPC_ATRIGAN_MISC)))
{
visual_boss->RemoveAllAuras();
visual_boss->GetMotionMaster()->MovePoint(0, 6370.82f, -795.00f, 3011.62f);
visual_boss->DespawnOrUnsummon(5000);
}
});
me->AddDelayedEvent(7000, [this]() -> void
{
if (auto boss = me->GetMap()->GetCreature(instance->GetGuidData(DATA_GOROTH)))
{
boss->SetVisible(true);
boss->SetReactState(REACT_DEFENSIVE);
boss->GetMotionMaster()->MovePath(25759848, false);
boss->AI()->Talk(10);
boss->AddDelayedEvent(4000, [boss]() -> void
{
boss->AI()->Talk(0);
boss->SetHomePosition(boss->GetPosition());
});
}
me->AddDelayedEvent(1000, [this]() -> void {
if (auto summoner = me->GetMap()->GetCreature(instance->GetGuidData(NPC_BREACH_IN_WINDOW)))
summoner->AI()->DoAction(1);
});
});
}
if (me->GetDistance(who) < 20.0f && !outroDone)
{
bool canUseIt = true;
for (uint8 i = 0; i < DATA_MAIDEN_OF_VIGILANCE; ++i)
if (instance->GetBossState(i) != DONE)
canUseIt = false;
if (!canUseIt)
return;
outroDone = true;
Creature* egvin = me->FindNearestCreature(NPC_EGVIN, 40.0f, true);
if (!egvin)
egvin = me->SummonCreature(NPC_EGVIN, 6213.44f, -795.67f, 2975.00, 3.18f);
if (!egvin)
return; // it's unreal
egvin->CastSpell(egvin, 240060);
}
}
};
// 269783
struct go_tos_tele_to_kiljedan : GameObjectAI
{
explicit go_tos_tele_to_kiljedan(GameObject* gameobject) : GameObjectAI(gameobject)
{
instance = go->GetInstanceScript();
}
InstanceScript* instance;
uint32 timer = 1000;
void UpdateAI(uint32 diff) override
{
if (timer <= diff)
{
if (!instance || instance->GetBossState(DATA_FALLEN_AVATAR) != DONE)
return;
const auto& players = instance->instance->GetPlayers();
for (auto& pitr : players)
{
Player* who = pitr.GetSource();
if (who->IsBeingTeleported())
return;
if (go->GetDistance(who) < 13)
who->NearTeleportTo(4499.94f, -1072.47f, 5335.96f, 4.70f);
}
timer = 1000;
}
else
timer -= diff;
}
};
class spell_vantus_rune_tomb_of_sargeras : public SpellScriptLoader
{
public:
spell_goroth_summon() : SpellScriptLoader("spell_goroth_summon") { }
spell_vantus_rune_tomb_of_sargeras() : SpellScriptLoader("spell_vantus_rune_tomb_of_sargeras") {}
class spell_goroth_summon_SpellScript : public SpellScript
class spell_vantus_rune_tomb_of_sargeras_AuraScript : public AuraScript
{
PrepareSpellScript(spell_goroth_summon_SpellScript);
PrepareAuraScript(spell_vantus_rune_tomb_of_sargeras_AuraScript);
void HandleDummy(SpellEffIndex effIndex)
uint16 checkOnProc;
uint16 checkOnRemove;
bool Load()
{
/*if (Unit* caster = GetCaster())
checkOnProc = 1000;
checkOnRemove = 1000;
return true;
}
void OnUpdate(uint32 diff, AuraEffect* /*aurEff*/)
{
Unit* player = GetCaster();
if (!player)
return;
InstanceScript* instance = player->GetInstanceScript();
if (!instance)
return;
if (checkOnProc <= diff)
{
if (GameObject* go = caster->FindNearestGameObject(269839, 1000.0f))
if (instance->GetBossState(DATA_FALLEN_AVATAR) == IN_PROGRESS)
{
go->setActive(true);
go->SetLootState(GO_ACTIVATED);
if (!player->HasAura(237795) && player->HasAura(237820))
{
player->CastSpell(player, 237795, false);
}
}
if (GameObject* go = caster->FindNearestGameObject(269838, 1000.0f))
if (instance->GetBossState(DATA_GOROTH) == IN_PROGRESS)
{
go->setActive(true);
go->SetLootState(GO_ACTIVATED);
if (!player->HasAura(237796) && player->HasAura(237821))
{
player->CastSpell(player, 237796, false);
}
}
if (Creature* creature = caster->FindNearestCreature(BOSS_GOROTH, 1000.0f))
if (instance->GetBossState(DATA_SISTERS_OF_THEMOON) == IN_PROGRESS)
{
creature->SetVisible(true);
creature->AddAura(233081, creature);
if (!player->HasAura(237797) && player->HasAura(237822))
{
player->CastSpell(player, 237797, false);
}
}
if (instance->GetBossState(DATA_MAIDEN_OF_VIGILANCE) == IN_PROGRESS)
{
if (!player->HasAura(237798) && player->HasAura(237823))
{
player->CastSpell(player, 237798, false);
}
}
if (instance->GetBossState(DATA_HARJATAN) == IN_PROGRESS)
{
if (!player->HasAura(237799) && player->HasAura(237824))
{
player->CastSpell(player, 237799, false);
}
}
if (instance->GetBossState(DATA_KILJAEDEN) == IN_PROGRESS)
{
if (!player->HasAura(237800) && player->HasAura(237825))
{
player->CastSpell(player, 237800, false);
}
}
if (instance->GetBossState(DATA_MISTRESS_SASSZINE) == IN_PROGRESS)
{
if (!player->HasAura(237801) && player->HasAura(237826))
{
player->CastSpell(player, 237801, false);
}
}
if (instance->GetBossState(DATA_THE_DESOLATE_HOST) == IN_PROGRESS)
{
if (!player->HasAura(237802) && player->HasAura(237827))
{
player->CastSpell(player, 237802, false);
}
}
if (instance->GetBossState(DATA_DEMONIC_INQUISITION) == IN_PROGRESS)
{
if (!player->HasAura(237803) && player->HasAura(237828))
{
player->CastSpell(player, 237803, false);
}
}
}
else checkOnProc -= diff;
for (uint8 i = 0; i < 4; ++i)
caster->SummonCreature(NPC_INFERNAL_CHAOSBRINGER, infernalChaosbringer[i], TEMPSUMMON_CORPSE_DESPAWN);
caster->ToCreature()->DespawnOrUnsummon();
}*/
if (checkOnRemove <= diff)
{
if (player->HasAura(237795) && player->HasAura(237820))
{
if (instance->GetBossState(DATA_FALLEN_AVATAR) == DONE || instance->GetBossState(DATA_FALLEN_AVATAR) == NOT_STARTED)
{
player->RemoveAura(237795);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237796) && player->HasAura(237821))
{
if (instance->GetBossState(DATA_GOROTH) == DONE || instance->GetBossState(DATA_GOROTH) == NOT_STARTED)
{
player->RemoveAura(237796);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237797) && player->HasAura(237822))
{
if (instance->GetBossState(DATA_SISTERS_OF_THEMOON) == DONE || instance->GetBossState(DATA_SISTERS_OF_THEMOON) == NOT_STARTED)
{
player->RemoveAura(237797);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237798) && player->HasAura(237823))
{
if (instance->GetBossState(DATA_MAIDEN_OF_VIGILANCE) == DONE || instance->GetBossState(DATA_MAIDEN_OF_VIGILANCE) == NOT_STARTED)
{
player->RemoveAura(237798);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237799) && player->HasAura(237824))
{
if (instance->GetBossState(DATA_HARJATAN) == DONE || instance->GetBossState(DATA_HARJATAN) == NOT_STARTED)
{
player->RemoveAura(237799);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237800) && player->HasAura(237825))
{
if (instance->GetBossState(DATA_KILJAEDEN) == DONE || instance->GetBossState(DATA_KILJAEDEN) == NOT_STARTED)
{
player->RemoveAura(237800);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237801) && player->HasAura(237826))
{
if (instance->GetBossState(DATA_MISTRESS_SASSZINE) == DONE || instance->GetBossState(DATA_MISTRESS_SASSZINE) == NOT_STARTED)
{
player->RemoveAura(237801);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237802) && player->HasAura(237827))
{
if (instance->GetBossState(DATA_THE_DESOLATE_HOST) == DONE || instance->GetBossState(DATA_THE_DESOLATE_HOST) == NOT_STARTED)
{
player->RemoveAura(237802);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
if (player->HasAura(237803) && player->HasAura(237828))
{
if (instance->GetBossState(DATA_DEMONIC_INQUISITION) == DONE || instance->GetBossState(DATA_DEMONIC_INQUISITION) == NOT_STARTED)
{
player->RemoveAura(237803);
checkOnProc = 1000;
checkOnRemove = 1000;
}
}
}
else checkOnRemove -= diff;
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_goroth_summon_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
/* hook EffectUpdate (tick par diff) non supporte par notre AuraScript */;
}
};
AuraScript* GetAuraScript() const override
{
return new spell_vantus_rune_tomb_of_sargeras_AuraScript();
}
class spell_vantus_rune_tomb_of_sargeras_SpellScript : public SpellScript
{
PrepareSpellScript(spell_vantus_rune_tomb_of_sargeras_SpellScript);
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
if (Player* player = caster->ToPlayer())
{
if (!player->GetQuestRewardStatus(39695))
return SPELL_CAST_OK;
}
SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_YOU_ALREADY_USED_VANTUS_RUNE);
return SPELL_FAILED_CUSTOM_ERROR;
}
void HandleOnHit()
{
if (!GetCaster())
return;
if (Player* player = GetCaster()->ToPlayer())
{
uint32 questId = 39695;
if (questId)
{
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
if (!quest)
return;
if (player->CanTakeQuest(quest, false))
player->CompleteQuest(questId);
}
}
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_vantus_rune_tomb_of_sargeras_SpellScript::CheckCast);
OnHit += SpellHitFn(spell_vantus_rune_tomb_of_sargeras_SpellScript::HandleOnHit);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_goroth_summon_SpellScript();
return new spell_vantus_rune_tomb_of_sargeras_SpellScript();
}
};
void AddSC_tomb_of_sargeras()
{
new npc_archimage_khadgar_tos();
new spell_goroth_summon();
}
RegisterCreatureAI(npc_tos_breach);
RegisterCreatureAI(npc_tos_kadghar_1);
RegisterGameObjectAI(go_tos_tele_to_kiljedan);
new spell_vantus_rune_tomb_of_sargeras();
}
@@ -1,161 +1,323 @@
/*
* Copyright (C) 2017-2018 AshamaneProject <https://github.com/AshamaneProject>
*
* 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/>.
*/
https://uwow.biz/
*/
#ifndef TOMB_OF_SARGERAS_H
#define TOMB_OF_SARGERAS_H
#ifndef TombOsSargeasH_
#define TombOsSargeasH_
#define DataHeader "TOS"
#define TombOfSargerasScriptName "instance_tomb_of_sargeras"
#include "InstanceScript.h"
#include "AreaTriggerTemplate.h"
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "EventMap.h"
#include "SpellAuras.h"
#include "Unit.h"
#include "GameObject.h"
#include "ScriptedCreature.h"
#include "Vehicle.h"
#include "VehicleDefines.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "TemporarySummon.h"
#include "Player.h"
#include "Map.h"
#include "GameObjectAI.h"
#include "MapManager.h"
#include "GridNotifiers.h"
#include "InstanceSaveMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "TemporarySummon.h"
#include "MotionMaster.h"
#include "Player.h"
uint32 const EncounterCount = 10;
#include "Spell.h"
#include "SpellMgr.h"
#include "SpellAuraEffects.h"
enum tosDataTypes
// Constantes uwow absentes de notre core (valeurs = SharedDefines de DestinyCoreNew).
// Les hooks references sur ces valeurs ne matchent simplement pas si le client n a pas l effet.
#define SPELL_AURA_FIXATE AuraType(128)
#define SPELL_EFFECT_TELEPORT_L SpellEffectName(252)
#define TARGET_UNIT_ENEMY_BETWEEN_DEST Targets(129)
#define TARGET_UNIT_BETWEEN_ENEMY Targets(134)
#define REACT_ATTACK_OFF REACT_PASSIVE
#define UNIT_DYNFLAG_NOT_SELECTABLE_MODEL 0x0002
#define CREATURE_SUMMON_GROUP_RESET 0
enum eData
{
DATA_GOROTH,
DATA_HARJATAN,
DATA_MISTRESS_SASSZINE,
DATA_ATRIGAN,
DATA_BELAC,
DATA_SISTERS_OF_THE_MOON,
DATA_THE_DESOLATE_HOST,
DATA_MAIDEN_OF_VIGILANCE,
DATA_FALLEN_AVATAR,
DATA_KILJAEDEN,
DATA_GOROTH = 0,
DATA_HARJATAN = 1,
DATA_MISTRESS_SASSZINE = 2,
ENCOUNTER_COUNT,
DATA_DEMONIC_INQUISITION = 3,
DATA_THE_DESOLATE_HOST = 4,
DATA_SISTERS_OF_THEMOON = 5,
DATA_MAIDEN_OF_VIGILANCE = 6,
DATA_FALLEN_AVATAR = 7,
DATA_KILJAEDEN = 8,
MAX_ENCOUNTER
};
enum Creatures
enum eCreatures
{
BOSS_GOROTH = 115844,
BOSS_ATRIGAN = 120996,
NPC_BREACH_IN_WINDOW = 121605,
// Demonic Inquisition
BOSS_BELAC = 116691,
BOSS_HARJATAN = 116407,
// Sisters of the Moon
NPC_HUNTRESS_KASPARIAN = 118523,
NPC_CAPTAIN_YATHAE_MOONSTRIKE = 118374,
NPC_PRIESTESS_LUNASPYRE = 118518,
NPC_SASSZINE = 115767,
// Desolate Host
NPC_ENGINE_OF_SOULS = 118460,
NPC_SOUL_QUEEN_DEJAHNA = 118462,
NPC_DESOLATE_HOST = 119072,
NPC_MAIDEN_OF_VIGILANCE = 118289,
NPC_FALLEN_AVATAR = 120436,
NPC_KILJAEDEN = 117269,
NPC_RAZORJAW_WAVEMENDER = 116569,
NPC_RAZORJAW_GLADIATOR = 117596,
NPC_INFERNAL_CHAOSBRINGER = 118022,
NPC_BRIMSTONE_INFERNAL = 119950,
NPC_KHADGAR = 119726,
NPC_VELEN = 119728,
NPC_ILLIDAN = 119729,
NPC_ATRIGAN = 120996,
NPC_MAEIV = 119730,
NPC_DURGAN = 119777,
NPC_EGIDA = 121630,
NPC_HAMMER_1 = 121494,
NPC_HAMMER_2 = 121111,
NPC_ELUNES_1 = 121495,
NPC_ELUNES_2 = 121110,
NPC_GOLGANETH_1 = 121496,
NPC_GOLGANETH_2 = 121105,
NPC_EGVIN = 119723,
NPC_ATRIGAN_MISC = 120996, //Not boss
NPC_SASSZINE_NPC_OUTRO = 121190,
NPC_SASSZINE_MISC = 121184,
NPC_LUNAR_ARCHER = 120721,
NPC_GUARDIAN_SENTRY = 120777,
NPC_TORMENTED_SOUL = 117957,
NPC_FRAGMENT_SOUL = 121138,
NPC_KILDJEDAN_AVATARA = 120867,
//! BOSSES
//Goroth
NPC_GOROTH = 115844,
NPC_EMBER_STALKER = 115892,
NPC_INFERNAL_SPIKE = 116976,
NPC_LAVA_STALKER = 117931, //Heroic+
NPC_BRIMSTONE_INFERNAL = 119950,
//Harajatan
NPC_HARJATAN = 116407,
NPC_EGGS = 120545,
NPC_ELDER = 121071,
NPC_TADPOLE_1 = 120574,
NPC_TADPOLE_2 = 121156,
NPC_TADPOLE_3 = 121155,
NPC_EVENT_1 = 121011,
NPC_EVENT_2 = 117123,
//Mistress Sassz'ine
NPC_SASSZINE = 115767,
NPC_ABYSS_STALKER = 115795,
NPC_TORNADO_TRIGGER = 118286,
NPC_ELECTRIFYING_JELLYFISH = 115896,
NPC_RAZORJAW_WAVERUNNER = 115902,
NPC_SARUKEL_TRIGGER = 116843,
NPC_OSSUNET_TRIGGER = 116881,
NPC_PIRANHADO_TRIGGER = 116841,
NPC_DELICIOUS_BUFFERFISH = 119791, //Mythic
NPC_TIDESTONE_GOLGANNETH = 121105, //Spawn after death boss
//Demonic Inquisitor
NPC_ATRIGAN = 116689,
NPC_BELAK = 116691,
NPC_ESSENCE_LIGHT = 118640,
NPC_ESSENCE_FEL = 118643,
NPC_REMANENCE_LIGHT = 119825,
NPC_REMANENCE_FEL = 119826,
//Sisters of the Moon
NPC_MOON_STALKER = 118182,
NPC_HUNTRESS_KASPARIAN = 118523,
NPC_PRIESTESS_LUNASPYRE = 118518,
NPC_CAPTAIN_YATHAE = 118374,
NPC_MOONTALON = 119205,
NPC_GLAIVE_TARGET = 119054,
NPC_SISTERS_ACH_ADD = 121498,
//The Desolate Host
NPC_SWIRLING_SOULS_TRIG = 120988, //Event Manager
NPC_DESOLATE_HOST = 119072, //!Real world
NPC_ENGINE_OF_SOULS = 118460,
NPC_REANIMATED_TEMPLAR = 118715,
NPC_REANIMATED_TEMPLAR_MIRROR = 119938, //Mythic
NPC_GHASTLY_BONEWARDEN = 118728,
NPC_GHASTLY_BONEWARDEN_MIRROR = 119939, //Mythic
NPC_TORMENTED_CRIES_TRIG = 118924,
NPC_SOUL_QUEEN_DEJAHNA = 118462, //!Spirit world
NPC_FALLEN_PRIESTESS = 118729,
NPC_FALLEN_PRIESTESS_MIRROR = 119940, //Mythic
NPC_SOUL_RESIDUE = 118730,
NPC_SOUL_RESIDUE_MIRROR = 119941, //Mythic
NPC_SPIRITUAL_FONT = 118701, //!Other
NPC_SPIRITUAL_BARRIER_TRIG = 118727,
NPC_TEARS_OF_ELUNE = 121110, //Spawn After Dies Boss
//Avatara
NPC_FALLEN_AVATAR = 116939,
NPC_CORRUPTED_BLADE = 119158,
NPC_PILONES = 117279,
NPC_AVATARA_MAIDEN = 117264,
NPC_BLACK_WINDS = 121294,
NPC_TOUCH_OF_SARGERAS = 120838,
//Maiden of Vigilance
NPC_MAIDEN_OF_VIGILANCE = 118289,
//Kil'jaeden <The Deceiver>
NPC_KILJAEDEN = 117269,
NPC_ARMAGEDDON_STALKER = 120839,
NPC_ERUPTING_REFLECTION = 119206,
NPC_WAILING_REFLECTION = 119107, //Mythic
NPC_HOPELESS_REFLECTION = 119663, //Mythic
NPC_SHADOWSOUL = 121193,
NPC_STAGE4_ILLIDAN_STORMRAGE = 121227,
NPC_DEMONIC_OBELISK = 120270,
NPC_NETHER_RIFT = 120390,
NPC_FLAMING_ORB = 120082, //Heroic+
};
enum CosmeticSpells
enum eGameObjects
{
SPELL_COSMETIC_TELEPORT = 240923, // Used by Kil'jaeden after Fallen Avatar activation
SPELL_AWAKEN = 240897, // Kil'jaeden activate Fallen Avatar spell.
SPELL_FEL_INFUSION = 236682, // Used by Maiden of Valor.
GO_INTRODESTROY_1 = 269839,
GO_INTRODESTROY_2 = 269838,
GO_INTRODESTROY_3 = 269842,
GO_GOROTH_GATES = 272802,
GO_GOROTH_INFERNAL_SPIKE = 266938, //LOS_BLOCKER
GO_SASSZINE_DOOR = 269976,
GO_INQUISITION_DOOR = 268579,
GO_INQUISITION_DOOR_INTRO = 268580,
GO_SISTERS_MOON_DOOR = 269045,
GO_HAMMER_THRONE = 269780,
GO_ELUNES_THRONE = 269779,
GO_GOLGANETH_THRONE = 269782,
GO_MAIDEN_DOOR = 269988,
GO_ELEVATOR = 268574,
GO_AVATARA_FLOOR = 267934,
GO_AVATARA_DOOR = 269262,
GO_DESOLATE_HOST_DOOR_1 = 268749,
GO_DESOLATE_HOST_DOOR_2 = 269781,
GO_KILJAEDEN_BRIDGE_1 = 271126,
GO_KILJAEDEN_BRIDGE_2 = 271127,
GO_KILJAEDEN_CHEST = 271099,
};
enum tosSpells
enum eSpells
{
SPELL_SUMMON = 241227,
SPELL_IMPACT = 242924,
SPELL_PILLAR_COSMETIC = 243149,
SPELL_GOROTH_INTRO = 247931,
SPELL_INTRO_TELEPORT = 241303,
};
enum tosSounds
enum TosGenericActions
{
SOUND_INTRO = 81787,
SOUND_GOROTH2 = 81789,
ACTION_NONE = 0,
ACTION_1 = 1,
ACTION_2,
ACTION_3,
ACTION_4,
ACTION_5,
ACTION_6,
ACTION_7,
ACTION_8,
ACTION_9,
ACTION_10,
ACTION_11,
ACTION_12,
ACTION_13,
ACTION_14,
ACTION_15,
ACTION_16,
ACTION_17,
ACTION_18,
ACTION_19,
ACTION_20,
ACTION_21,
ACTION_22,
ACTION_23,
ACTION_24,
ACTION_25,
ACTION_26,
ACTION_27,
ACTION_28,
ACTION_29,
ACTION_30,
ACTION_31,
ACTION_32,
ACTION_33,
ACTION_34,
ACTION_35,
ACTION_36,
ACTION_37,
ACTION_38,
ACTION_39,
ACTION_40,
ACTION_41,
ACTION_42,
ACTION_43,
ACTION_44,
ACTION_45,
ACTION_46,
ACTION_47,
ACTION_48,
ACTION_49,
ACTION_50,
};
enum Gameobjects
// Enum generique d evenements (present dans l EventMap.h de DestinyCoreNew, module-local ici)
enum TosGenericEvents
{
GO_MOON_CHAMBER_WINDOW = 269842,
GO_DOOR_ROOM_GOROTH_S = 269974,
GO_DOOR_ROOM_GOROTH_N = 269975,
GO_DOOR_ROOM_GOROTH_E = 269973,
GO_DOOR_ROOM_GOROTH_4 = 268580,
GO_DOOR_HARJATAN_1 = 269120,
GO_DOOR_HARJATAN_2 = 269192,
GO_DOOR_AFTER_SASSZINE_1 = 268752,
GO_DOOR_SISTERS_OF_THE_MOON_1 = 268750,
GO_DOOR_SISTERS_OF_THE_MOON_2 = 268514,
GO_DOOR_SISTERS_OF_THE_MOON_3 = 268751,
GO_DOOR_SISTERS_OF_THE_MOON_4 = 268749,
GO_DOOR_DEMONIC_INQUISITION_1 = 268579,
GO_DOOR_MAIDEN_OF_VIGILANCE_1 = 269164,
GO_DOOR_MAIDEN_OF_VIGILANCE_2 = 269261,
GO_DOOR_MAIDEN_OF_VIGILANCE_3 = 269262,
GO_DOOR_FALLEN_AVATAR = 267934,
GO_DOOR_FELSTORM_COLLISION_01 = 269987,
GO_DESTRUCTIBLE_1 = 269842,
GO_DESTRUCTIBLE_2 = 269839,
GO_DESTRUCTIBLE_3 = 269838,
GO_DOOR_TO_MISTRESS = 269120,
GO_DOOR_TO_MISTRESS2 = 270940,
EVENT_1 = 1,
EVENT_2,
EVENT_3,
EVENT_4,
EVENT_5,
EVENT_6,
EVENT_7,
EVENT_8,
EVENT_9,
EVENT_10,
EVENT_11,
EVENT_12,
EVENT_13,
EVENT_14,
EVENT_15,
EVENT_16,
EVENT_17,
EVENT_18,
EVENT_19,
EVENT_20,
EVENT_21,
EVENT_22,
EVENT_23,
EVENT_24,
EVENT_25,
EVENT_26,
EVENT_27,
EVENT_28,
EVENT_29,
EVENT_30,
EVENT_31,
EVENT_32,
EVENT_33,
EVENT_34,
EVENT_35,
EVENT_36,
EVENT_37,
EVENT_38,
EVENT_39,
EVENT_40,
EVENT_41,
EVENT_42,
EVENT_43,
EVENT_44,
EVENT_45,
EVENT_46,
EVENT_47,
EVENT_48,
EVENT_49,
EVENT_50,
};
template<class AI>
CreatureAI* GetTombOfSargerasAI(Creature* creature)
{
if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
if (instance->GetInstanceScript())
if (instance->GetScriptId() == sObjectMgr->GetScriptId(TombOfSargerasScriptName))
return new AI(creature);
return NULL;
}
#define ToSScriptName "instance_tomb_of_sargeras"
#endif
@@ -175,14 +175,15 @@ void AddSC_instance_emerald_nightmare();
// Tomb of Sargeras
void AddSC_boss_demonic_inquisition();
void AddSC_boss_desolate_host();
void AddSC_boss_the_desolate_host();
void AddSC_boss_fallen_avatar();
void AddSC_boss_goroth();
void AddSC_boss_sisters_of_the_moon();
void AddSC_boss_shiwar();
void AddSC_boss_harjatan();
void AddSC_boss_tos_kiljaeden();
void AddSC_boss_maiden_of_vigilance();
void AddSC_boss_sasszine();
void AddSC_boss_mistress_sasszine();
void AddSC_tomb_of_sargeras();
void AddSC_instance_tomb_of_sargeras();
@@ -376,14 +377,15 @@ void AddBrokenIslesScripts()
// Tomb of Sargeras
AddSC_boss_demonic_inquisition();
AddSC_boss_desolate_host();
AddSC_boss_the_desolate_host();
AddSC_boss_fallen_avatar();
AddSC_boss_goroth();
AddSC_boss_sisters_of_the_moon();
AddSC_boss_shiwar();
AddSC_boss_harjatan();
AddSC_boss_tos_kiljaeden();
AddSC_boss_maiden_of_vigilance();
AddSC_boss_sasszine();
AddSC_boss_mistress_sasszine();
AddSC_tomb_of_sargeras();
AddSC_instance_tomb_of_sargeras();