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:
Gustavo
2017-10-16 23:32:30 -02:00
committed by funjoker
parent f2a4cf99e6
commit f34ee9b737
4 changed files with 178 additions and 279 deletions

View File

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

View File

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

View File

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

View File

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