mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-18 00:18:43 +01:00
Core/Scripts: Update boss Toravon the Ice Watcher (#20395)
* Core/Scripts: Update boss Toravon the Ice Watcher
Frozen Orbs: Fixed summon delay, removed old hack, aggro behavior implemented(every 10sec they reset threat and change target)
Remove no longer needed script for the orb stalker
All timers adjusted
Update instance model
Update script register model
Fix Frostbite proc
(cherry picked from commit 5a90251ea2)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
-- Update boss Toravon the Ice Watcher
|
||||
UPDATE `creature_template` SET `InhabitType`=11, `ScriptName`='' WHERE `entry`=38461;
|
||||
-- UPDATE `spell_dbc` SET `Effect1`=3, `EffectImplicitTargetA1`=22, `EffectImplicitTargetB1`=15, `EffectRadiusIndex1`=28, `MaxAffectedTargets`=1 WHERE `Id`=46523;
|
||||
DELETE FROM `spelleffect_dbc` WHERE `Id`=155917;
|
||||
INSERT INTO `spelleffect_dbc` (`Id`, `Effect`, `EffectValueMultiplier`, `EffectApplyAuraName`, `EffectAmplitude`, `EffectBasePoints`, `EffectBonusMultiplier`, `EffectDamageMultiplier`, `EffectChainTarget`, `EffectDieSides`, `EffectItemType`, `EffectMechanic`, `EffectMiscValue`, `EffectMiscValueB`, `EffectRadiusIndex`, `EffectRadiusIndexMax`, `EffectRealPointsPerLevel`, `EffectSpellClassMaskA`, `EffectSpellClassMaskB`, `EffectSpellClassMaskC`, `EffectTriggerSpell`, `EffectImplicitTargetA`, `EffectImplicitTargetB`, `EffectSpellId`, `EffectIndex`) VALUES
|
||||
(155917, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 15, 46523, 0);
|
||||
UPDATE `spell_dbc` SET `SpellTargetRestrictionsId`=872 WHERE `Id`=46523;
|
||||
|
||||
DELETE FROM `creature_template_addon` WHERE `entry`=38461;
|
||||
INSERT INTO `creature_template_addon` (`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES
|
||||
(38461,0,0,0,1,0,72094);
|
||||
|
||||
DELETE FROM `spell_proc` WHERE `SpellId`=71993;
|
||||
INSERT INTO `spell_proc` (`SpellId`,`ProcFlags`,`HitMask`,`Cooldown`) VALUES
|
||||
(71993,4,12287,4000);
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_toravon_random_aggro';
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(46523,'spell_toravon_random_aggro');
|
||||
@@ -17,28 +17,26 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "vault_of_archavon.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Toravon
|
||||
SPELL_FREEZING_GROUND = 72090, // don't know cd... using 20 secs.
|
||||
SPELL_FREEZING_GROUND = 72090,
|
||||
SPELL_FROZEN_ORB = 72091,
|
||||
SPELL_WHITEOUT = 72034, // Every 38 sec. cast. (after SPELL_FROZEN_ORB)
|
||||
SPELL_WHITEOUT = 72034,
|
||||
SPELL_FROZEN_MALLET = 71993,
|
||||
|
||||
// Frozen Orb
|
||||
SPELL_FROZEN_ORB_DMG = 72081,
|
||||
SPELL_FROZEN_ORB_AURA = 72067,
|
||||
SPELL_RANDOM_AGGRO = 72084,
|
||||
|
||||
// Frost Warder
|
||||
SPELL_FROST_BLAST = 72123, // don't know cd... using 20 secs.
|
||||
SPELL_FROZEN_MALLET_2 = 72122,
|
||||
|
||||
// Frozen Orb
|
||||
SPELL_FROZEN_ORB_DMG = 72081, // priodic dmg aura
|
||||
SPELL_FROZEN_ORB_AURA = 72067, // make visible
|
||||
|
||||
// Frozen Orb Stalker
|
||||
SPELL_FROZEN_ORB_SUMMON = 72093, // summon orb
|
||||
SPELL_FROZEN_MALLET_2 = 72122
|
||||
};
|
||||
|
||||
enum Events
|
||||
@@ -47,256 +45,159 @@ enum Events
|
||||
EVENT_FROZEN_ORB = 2,
|
||||
EVENT_WHITEOUT = 3,
|
||||
|
||||
EVENT_FROST_BLAST = 4,
|
||||
EVENT_FROST_BLAST = 4
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
struct boss_toravon : public BossAI
|
||||
{
|
||||
NPC_FROZEN_ORB = 38456 // 1 in 10 mode and 3 in 25 mode
|
||||
boss_toravon(Creature* creature) : BossAI(creature, DATA_TORAVON) { }
|
||||
|
||||
};
|
||||
|
||||
class boss_toravon : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_toravon() : CreatureScript("boss_toravon") { }
|
||||
|
||||
struct boss_toravonAI : public BossAI
|
||||
{
|
||||
boss_toravonAI(Creature* creature) : BossAI(creature, DATA_TORAVON)
|
||||
{
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoCast(me, SPELL_FROZEN_MALLET);
|
||||
|
||||
events.ScheduleEvent(EVENT_FROZEN_ORB, 11000);
|
||||
events.ScheduleEvent(EVENT_WHITEOUT, 13000);
|
||||
events.ScheduleEvent(EVENT_FREEZING_GROUND, 15000);
|
||||
|
||||
_EnterCombat();
|
||||
}
|
||||
|
||||
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_FROZEN_ORB:
|
||||
me->CastCustomSpell(SPELL_FROZEN_ORB, SPELLVALUE_MAX_TARGETS, 1, me);
|
||||
events.ScheduleEvent(EVENT_FROZEN_ORB, 38000);
|
||||
break;
|
||||
case EVENT_WHITEOUT:
|
||||
DoCast(me, SPELL_WHITEOUT);
|
||||
events.ScheduleEvent(EVENT_WHITEOUT, 38000);
|
||||
break;
|
||||
case EVENT_FREEZING_GROUND:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
|
||||
DoCast(target, SPELL_FREEZING_GROUND);
|
||||
events.ScheduleEvent(EVENT_FREEZING_GROUND, 20000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVaultOfArchavonAI<boss_toravonAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## Mob Frost Warder
|
||||
######*/
|
||||
class npc_frost_warder : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_frost_warder() : CreatureScript("npc_frost_warder") { }
|
||||
|
||||
struct npc_frost_warderAI : public ScriptedAI
|
||||
{
|
||||
npc_frost_warderAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
|
||||
DoCast(me, SPELL_FROZEN_MALLET_2);
|
||||
|
||||
events.ScheduleEvent(EVENT_FROST_BLAST, 5000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (events.ExecuteEvent() == EVENT_FROST_BLAST)
|
||||
{
|
||||
DoCastVictim(SPELL_FROST_BLAST);
|
||||
events.ScheduleEvent(EVENT_FROST_BLAST, 20000);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVaultOfArchavonAI<npc_frost_warderAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## Mob Frozen Orb
|
||||
######*/
|
||||
class npc_frozen_orb : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_frozen_orb() : CreatureScript("npc_frozen_orb") { }
|
||||
|
||||
struct npc_frozen_orbAI : public ScriptedAI
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
npc_frozen_orbAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
DoCastSelf(SPELL_FROZEN_MALLET);
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
done = false;
|
||||
killTimer = 60000; // if after this time there is no victim -> destroy!
|
||||
}
|
||||
events.ScheduleEvent(EVENT_FROZEN_ORB, Seconds(12));
|
||||
events.ScheduleEvent(EVENT_WHITEOUT, Seconds(25));
|
||||
events.ScheduleEvent(EVENT_FREEZING_GROUND, Seconds(7));
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
_EnterCombat();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!done)
|
||||
{
|
||||
DoCast(me, SPELL_FROZEN_ORB_AURA, true);
|
||||
DoCast(me, SPELL_FROZEN_ORB_DMG, true);
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (killTimer <= diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
me->DespawnOrUnsummon();
|
||||
killTimer = 10000;
|
||||
}
|
||||
else
|
||||
killTimer -= diff;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 killTimer;
|
||||
bool done;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
return GetVaultOfArchavonAI<npc_frozen_orbAI>(creature);
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FROZEN_ORB:
|
||||
me->CastCustomSpell(SPELL_FROZEN_ORB, SPELLVALUE_MAX_TARGETS, RAID_MODE(1, 3), me);
|
||||
events.Repeat(Seconds(32));
|
||||
break;
|
||||
case EVENT_WHITEOUT:
|
||||
DoCastSelf(SPELL_WHITEOUT);
|
||||
events.Repeat(Seconds(38));
|
||||
break;
|
||||
case EVENT_FREEZING_GROUND:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
|
||||
DoCast(target, SPELL_FREEZING_GROUND);
|
||||
events.Repeat(Seconds(38));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## Mob Frozen Orb Stalker
|
||||
######*/
|
||||
class npc_frozen_orb_stalker : public CreatureScript
|
||||
struct npc_frost_warder : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_frozen_orb_stalker() : CreatureScript("npc_frozen_orb_stalker") { }
|
||||
npc_frost_warder(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
struct npc_frozen_orb_stalkerAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
_events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
|
||||
DoCastSelf(SPELL_FROZEN_MALLET_2);
|
||||
|
||||
_events.ScheduleEvent(EVENT_FROST_BLAST, 5000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (_events.ExecuteEvent() == EVENT_FROST_BLAST)
|
||||
{
|
||||
npc_frozen_orb_stalkerAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
creature->SetVisible(false);
|
||||
creature->AddUnitFlag(UnitFlags(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE));
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
|
||||
instance = creature->GetInstanceScript();
|
||||
spawned = false;
|
||||
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (spawned)
|
||||
return;
|
||||
|
||||
spawned = true;
|
||||
Unit* toravon = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_TORAVON));
|
||||
if (!toravon)
|
||||
return;
|
||||
|
||||
uint8 num_orbs = RAID_MODE(1, 3);
|
||||
for (uint8 i = 0; i < num_orbs; ++i)
|
||||
{
|
||||
Position pos;
|
||||
me->GetNearPoint(toravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f);
|
||||
me->UpdatePosition(pos);
|
||||
DoCast(me, SPELL_FROZEN_ORB_SUMMON);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
bool spawned;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVaultOfArchavonAI<npc_frozen_orb_stalkerAI>(creature);
|
||||
DoCastVictim(SPELL_FROST_BLAST);
|
||||
_events.ScheduleEvent(EVENT_FROST_BLAST, 20000);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
struct npc_frozen_orb : public ScriptedAI
|
||||
{
|
||||
npc_frozen_orb(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void IsSummonedBy(Unit* /*summoner*/) override
|
||||
{
|
||||
DoCastSelf(SPELL_FROZEN_ORB_AURA, true);
|
||||
DoCastSelf(SPELL_FROZEN_ORB_DMG, true);
|
||||
DoCastSelf(SPELL_RANDOM_AGGRO, true);
|
||||
|
||||
if (Creature* toravon = me->GetInstanceScript()->GetCreature(DATA_TORAVON))
|
||||
{
|
||||
if (toravon->IsInCombat())
|
||||
{
|
||||
toravon->AI()->JustSummoned(me);
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
else
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 46523 - Random Aggro
|
||||
class spell_toravon_random_aggro : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_toravon_random_aggro);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetCaster()->GetTypeId() == TYPEID_UNIT;
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* caster = GetCaster()->ToCreature();
|
||||
if (!caster->IsAIEnabled)
|
||||
return;
|
||||
|
||||
caster->GetThreatManager().resetAllAggro();
|
||||
|
||||
if (Unit* target = caster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1))
|
||||
caster->GetThreatManager().AddThreat(target, 1000000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_toravon_random_aggro::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_toravon()
|
||||
{
|
||||
new boss_toravon();
|
||||
new npc_frost_warder();
|
||||
new npc_frozen_orb();
|
||||
new npc_frozen_orb_stalker();
|
||||
RegisterVaultOfArchavonCreatureAI(boss_toravon);
|
||||
RegisterVaultOfArchavonCreatureAI(npc_frost_warder);
|
||||
RegisterVaultOfArchavonCreatureAI(npc_frozen_orb);
|
||||
RegisterSpellScript(spell_toravon_random_aggro);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Creature.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "vault_of_archavon.h"
|
||||
|
||||
@@ -27,6 +26,15 @@
|
||||
4 - Toravon the Ice Watcher event
|
||||
*/
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_ARCHAVON, DATA_ARCHAVON },
|
||||
{ NPC_EMALON, DATA_EMALON },
|
||||
{ NPC_KORALON, DATA_KORALON },
|
||||
{ NPC_TORAVON, DATA_TORAVON },
|
||||
{ 0, 0, }
|
||||
};
|
||||
|
||||
class instance_vault_of_archavon : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -38,42 +46,13 @@ class instance_vault_of_archavon : public InstanceMapScript
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
|
||||
ArchavonDeath = 0;
|
||||
EmalonDeath = 0;
|
||||
KoralonDeath = 0;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_EMALON:
|
||||
EmalonGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_TORAVON:
|
||||
ToravonGUID = creature->GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 identifier) const override
|
||||
{
|
||||
switch (identifier)
|
||||
{
|
||||
case DATA_EMALON:
|
||||
return EmalonGUID;
|
||||
case DATA_TORAVON:
|
||||
return ToravonGUID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
@@ -126,8 +105,6 @@ class instance_vault_of_archavon : public InstanceMapScript
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid EmalonGUID;
|
||||
ObjectGuid ToravonGUID;
|
||||
time_t ArchavonDeath;
|
||||
time_t EmalonDeath;
|
||||
time_t KoralonDeath;
|
||||
|
||||
@@ -30,7 +30,7 @@ enum VAData
|
||||
DATA_ARCHAVON = 0,
|
||||
DATA_EMALON = 1,
|
||||
DATA_KORALON = 2,
|
||||
DATA_TORAVON = 3,
|
||||
DATA_TORAVON = 3
|
||||
};
|
||||
|
||||
enum VACreatureIds
|
||||
@@ -44,12 +44,12 @@ enum VACreatureIds
|
||||
enum VAAchievementCriteriaIds
|
||||
{
|
||||
CRITERIA_EARTH_WIND_FIRE_10 = 12018,
|
||||
CRITERIA_EARTH_WIND_FIRE_25 = 12019,
|
||||
CRITERIA_EARTH_WIND_FIRE_25 = 12019
|
||||
};
|
||||
|
||||
enum VAAchievementSpells
|
||||
{
|
||||
SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK = 68308,
|
||||
SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK = 68308
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
@@ -58,4 +58,6 @@ inline AI* GetVaultOfArchavonAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, VoAScriptName);
|
||||
}
|
||||
|
||||
#define RegisterVaultOfArchavonCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetVaultOfArchavonAI)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user