Scripts/LCT: implement Lockmaw and Augh

This commit is contained in:
Ovalord
2017-12-18 22:27:57 +01:00
parent d36619e44a
commit e43a015b83
5 changed files with 862 additions and 31 deletions

View File

@@ -0,0 +1,41 @@
-- Lockmaw
UPDATE `creature_template` SET `difficulty_entry_1`= 49043, `mechanic_immune_mask`= 667893759, `scriptname`= 'boss_lockmaw' WHERE `entry`= 43614;
UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `faction`= 16, `exp`= 3, `mechanic_immune_mask`= 667893759 WHERE `entry`= 49043;
-- Dust Flail Front
UPDATE `creature_template` SET `minlevel`= 80, `maxlevel`= 80, `faction`= 14, `unit_flags`= 33554944, `flags_extra`= 128 WHERE `entry`= 43655;
-- Dust Flail Back
UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 14, `unit_flags`= 33554944, `flags_extra`= 128 WHERE `entry`= 43650;
-- Frenzied Crocolisk
UPDATE `creature_template` SET `minlevel`= 84, `maxlevel`= 84, `difficulty_entry_1`= 49311, `flags_extra`= 256, `scriptname`= 'npc_lockmaw_frenzied_crocolisk' WHERE `entry`= 43658;
UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 16, `exp`= 3, `flags_extra`= 256 WHERE `entry`= 49311;
-- Augh 1 and 2
UPDATE `creature_template` SET `unit_flags`= 32832, `mechanic_immune_mask`= 667893759, `scriptname`= 'npc_lockmaw_augh' WHERE `entry` IN (45379, 45378);
-- Augh
UPDATE `creature_template` SET `mechanic_immune_mask`= 667893759, `scriptname`= 'boss_augh' WHERE `entry`= 49045;
-- Add Stalker
UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 131 WHERE `entry`= 45124;
DELETE FROM `spell_script_names` WHERE `ScriptName` IN
('spell_lockmaw_paralytic_blow_dart',
'spell_lockmaw_scent_of_blood',
'spell_lockmaw_random_aggro_taunt');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(84799, 'spell_lockmaw_paralytic_blow_dart'),
(89989, 'spell_lockmaw_paralytic_blow_dart'),
(81690, 'spell_lockmaw_scent_of_blood'),
(89998, 'spell_lockmaw_scent_of_blood'),
(50230, 'spell_lockmaw_random_aggro_taunt');
DELETE FROM `creature_template_addon` WHERE `entry`= 43650;
INSERT INTO `creature_template_addon` (`entry`, `Auras`) VALUES
(43650, '81646');
DELETE FROM `creature_text` WHERE `CreatureID`= 49045;
INSERT INTO `creature_text` (`CreatureID`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `comment`) VALUES
(49045, 0, 0, 'Augh appears from the distance!', 41, 0, 0, 0, 0, 0, 50638, 'Augh - Intro 1'),
(49045, 1, 0, 'GAAAH! How you kill croc?!', 12, 0, 0, 53, 0, 0, 49169, 'Augh - Intro 2'),
(49045, 2, 0, 'Augh smart! Augh already steal treasure while you no looking!', 12, 0, 0, 1, 0, 0, 49170, 'Augh - Intro 3'),
(49045, 3, 0, 'Augh da boss! Oh yeah!', 12, 0, 0, 0, 0, 0, 49171, 'Augh Taunt'),
(49045, 4, 0, 'Augh steal your treasure. Uhn uhn uhnnn!', 12, 0, 0, 0, 0, 0, 49173, 'Augh Taunt'),
(49045, 5, 0, 'Who bad?! Augh bad!! Ugn!', 12, 0, 0, 0, 0, 0, 49172, 'Augh Taunt');

View File

@@ -4130,7 +4130,11 @@ void SpellMgr::LoadSpellInfoCorrections()
// Aura is refreshed at 3 seconds, and the tick should happen at the fourth.
spellInfo->AttributesEx8 |= SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER;
});
// END OF HALLS OF ORIGINATION SPELLS
//
// THE LOST CITY OF THE TOL'VIR SPELLS
//
// Solar Fire
ApplySpellFix({ 89133, 89878 }, [](SpellInfo* spellInfo)
{
@@ -4173,7 +4177,8 @@ void SpellMgr::LoadSpellInfoCorrections()
{
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS);
});
// ENDOF HALLS OF ORIGINATION SPELLS
// END OF THE LOST CITY OF THE TOL'VIR SPELLS
// Threatening Gaze
ApplySpellFix({ 24314 }, [](SpellInfo* spellInfo)

View File

@@ -0,0 +1,619 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "lost_city_of_the_tolvir.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
enum Texts
{
// Augh Boss
SAY_ANNOUNCE_AUGH_APPEAR = 0,
SAY_AUGH_INTRO_1 = 1,
SAY_AUGH_INTRO_2 = 2,
SAY_AUGH_TAUNT_1 = 3,
SAY_AUGH_TAUNT_2 = 4,
SAY_AUGH_TAUNT_3 = 5
};
enum Spells
{
// Lockmaw
SPELL_VISCOUS_POISON = 81630,
SPELL_SCENT_OF_BLOOD = 81690,
SPELL_SCENT_OF_BLOOD_HC = 89998,
SPELL_DUST_FLAIL_DUMMY = 81652,
SPELL_DUST_FLAIL = 81642,
SPELL_VENOMOUS_RAGE = 81706,
// Frenzied Crocolisk
SPELL_STEALTHED = 84244,
// Augh (Combat Assistance)
SPELL_PARALYTIC_BLOW_DART = 84799,
SPELL_SMOKE_BOMB = 84768,
SPELL_RANDOM_AGGRO_TAUNT = 50230,
SPELL_WHIRLWIND = 84784,
// Augh (Heroic Boss)
SPELL_DRAGONS_BREATH = 83776,
SPELL_FRENZY = 91415,
SPELL_WHIRLWIND_BOSS = 91408
};
enum Events
{
// Lockmaw
EVENT_VISCOUS_POISON = 1,
EVENT_SCENT_OF_BLOOD,
EVENT_DUST_FLAIL,
EVENT_MAKE_AGGRESSIVE,
EVENT_SUMMON_CROCOLISK,
EVENT_SUMMON_AUGH,
// Frenzied Crocolisk
EVENT_FIND_PLAYER_TARGET,
// Augh (Assistance)
EVENT_ROAR_EMOTE,
EVENT_PARALYTIC_BLOW_DART,
EVENT_SMOKE_BOMB,
EVENT_WHIRLWIND,
EVENT_RANDOM_AGGRO,
EVENT_ATTACK_STOP,
// Augh Boss
EVENT_MOVE_HOME_POS,
EVENT_TALK_INTRO_1,
EVENT_TALK_INTRO_2,
EVENT_PLAY_EMOTE,
EVENT_MAKE_ATTACKABLE,
EVENT_TALK_TAUNT_1,
EVENT_TALK_TAUNT_2,
EVENT_TALK_TAUNT_3,
EVENT_DRAGONS_BREATH
};
enum Phases
{
PHASE_INTRO = 1,
PHASE_COMBAT
};
enum Actions
{
ACTION_AUGH_INTRO = 1,
ACTION_AUGH_ATTACKABLE = 2
};
Position const AughMovePoint = { -11062.5f, -1662.39f, 0.7606202f, 0.8028514f };
class ScentOfBloodTargetSelector : public std::unary_function<Unit*, bool>
{
public:
ScentOfBloodTargetSelector() { }
bool operator()(Unit* unit) const
{
return (!unit->HasAura(SPELL_SCENT_OF_BLOOD) || !unit->HasAura(SPELL_SCENT_OF_BLOOD_HC));
}
};
class boss_lockmaw : public CreatureScript
{
public:
boss_lockmaw() : CreatureScript("boss_lockmaw") { }
struct boss_lockmawAI : public BossAI
{
boss_lockmawAI(Creature* creature) : BossAI(creature, DATA_LOCKMAW)
{
Initialize();
}
void Initialize()
{
_enraged = false;
_lastSpellID = 0;
}
void Reset() override
{
instance->SetBossState(DATA_LOCKMAW_AND_AUGH, NOT_STARTED);
instance->SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_NONE);
_Reset();
Initialize();
}
void EnterCombat(Unit* /*victim*/) override
{
_EnterCombat();
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
events.ScheduleEvent(EVENT_VISCOUS_POISON, Seconds(6));
events.ScheduleEvent(EVENT_SCENT_OF_BLOOD, Seconds(6));
events.ScheduleEvent(EVENT_DUST_FLAIL, Seconds(8));
events.ScheduleEvent(EVENT_SUMMON_AUGH, Seconds(6));
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_DespawnAtEvade();
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() == NPC_DUST_FLAIL_FRONT_STALKER)
{
me->SetReactState(REACT_PASSIVE);
me->StopMoving();
me->AttackStop();
me->SetFacingToObject(summon);
DoCastSelf(SPELL_DUST_FLAIL);
events.ScheduleEvent(EVENT_MAKE_AGGRESSIVE, Seconds(5));
}
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
{
if (me->HealthBelowPct(30) && !_enraged)
{
DoCastSelf(SPELL_VENOMOUS_RAGE, true);
_enraged = true;
}
}
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_VISCOUS_POISON:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true, 0))
DoCast(target, SPELL_VISCOUS_POISON);
events.Repeat(Seconds(26));
break;
case EVENT_SCENT_OF_BLOOD:
DoCastAOE(SPELL_SCENT_OF_BLOOD, true);
events.ScheduleEvent(EVENT_SCENT_OF_BLOOD, Seconds(30));
events.ScheduleEvent(EVENT_SUMMON_CROCOLISK, Milliseconds(100));
break;
case EVENT_SUMMON_CROCOLISK:
instance->SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_SUMMON_CROCOLISKS);
break;
case EVENT_DUST_FLAIL:
DoCastAOE(SPELL_DUST_FLAIL_DUMMY, true);
events.Repeat(Seconds(39));
break;
case EVENT_MAKE_AGGRESSIVE:
me->SetReactState(REACT_AGGRESSIVE);
break;
case EVENT_SUMMON_AUGH:
if (_lastSpellID != SPELL_SUMMON_AUGH_DART)
{
_lastSpellID = SPELL_SUMMON_AUGH_DART;
instance->SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_SUMMON_AUGH_DART);
events.Repeat(Seconds(20));
}
else
{
_lastSpellID = SPELL_SUMMON_AUGH_WHIRLWIND;
instance->SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_SUMMON_AUGH_WHIRLWIND);
events.Repeat(Seconds(40));
}
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
bool _enraged;
uint32 _lastSpellID;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetLostCityOfTheTolvirAI<boss_lockmawAI>(creature);
}
};
class boss_augh : public CreatureScript
{
public:
boss_augh() : CreatureScript("boss_augh") { }
struct boss_aughAI : public BossAI
{
boss_aughAI(Creature* creature) : BossAI(creature, DATA_AUGH) { }
void EnterCombat(Unit* /*victim*/) override
{
_EnterCombat();
me->HandleEmoteCommand(EMOTE_ONESHOT_NONE);
events.SetPhase(PHASE_COMBAT);
DoCastSelf(SPELL_FRENZY);
events.ScheduleEvent(EVENT_PARALYTIC_BLOW_DART, Seconds(8));
events.ScheduleEvent(EVENT_WHIRLWIND, Seconds(9));
events.ScheduleEvent(EVENT_DRAGONS_BREATH, Seconds(6));
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
instance->SetBossState(DATA_AUGH, FAIL);
_DespawnAtEvade();
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_AUGH_INTRO:
me->SetReactState(REACT_PASSIVE);
Talk(SAY_ANNOUNCE_AUGH_APPEAR);
events.SetPhase(PHASE_INTRO);
events.ScheduleEvent(EVENT_MOVE_HOME_POS, Seconds(1));
break;
case ACTION_AUGH_ATTACKABLE:
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MOVE_HOME_POS:
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(0, AughMovePoint, true);
events.ScheduleEvent(EVENT_TALK_INTRO_1, Seconds(10) + Milliseconds(500), 0, PHASE_INTRO);
break;
case EVENT_TALK_INTRO_1:
me->SetFacingTo(AughMovePoint.GetOrientation());
Talk(SAY_AUGH_INTRO_1);
events.ScheduleEvent(EVENT_TALK_INTRO_2, Seconds(4), 0, PHASE_INTRO);
break;
case EVENT_TALK_INTRO_2:
Talk(SAY_AUGH_INTRO_2);
events.ScheduleEvent(EVENT_PLAY_EMOTE, Seconds(3), 0, PHASE_INTRO);
break;
case EVENT_PLAY_EMOTE:
me->HandleEmoteCommand(EMOTE_STATE_SPELL_CHANNEL_OMNI);
events.ScheduleEvent(EVENT_MAKE_ATTACKABLE, Seconds(4), 0, PHASE_INTRO);
events.ScheduleEvent(EVENT_TALK_TAUNT_1, Seconds(5), PHASE_INTRO);
break;
case EVENT_MAKE_ATTACKABLE:
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
break;
case EVENT_TALK_TAUNT_1:
Talk(SAY_AUGH_TAUNT_1);
events.ScheduleEvent(EVENT_TALK_TAUNT_2, Seconds(5), 0, PHASE_INTRO);
break;
case EVENT_TALK_TAUNT_2:
Talk(SAY_AUGH_TAUNT_2);
events.ScheduleEvent(EVENT_TALK_TAUNT_3, Seconds(5), 0, PHASE_INTRO);
break;
case EVENT_TALK_TAUNT_3:
Talk(SAY_AUGH_TAUNT_3);
break;
case EVENT_PARALYTIC_BLOW_DART:
DoCastAOE(SPELL_PARALYTIC_BLOW_DART);
events.Repeat(Seconds(10), Seconds(15));
break;
case EVENT_WHIRLWIND:
DoCastAOE(SPELL_RANDOM_AGGRO_TAUNT, true);
DoCastSelf(SPELL_WHIRLWIND_BOSS);
events.Repeat(Seconds(29));
break;
case EVENT_DRAGONS_BREATH:
DoCastAOE(SPELL_DRAGONS_BREATH);
events.Repeat(Seconds(28));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetLostCityOfTheTolvirAI<boss_aughAI>(creature);
}
};
class npc_lockmaw_frenzied_crocolisk : public CreatureScript
{
public:
npc_lockmaw_frenzied_crocolisk() : CreatureScript("npc_lockmaw_frenzied_crocolisk") { }
struct npc_lockmaw_frenzied_crocoliskAI : public ScriptedAI
{
npc_lockmaw_frenzied_crocoliskAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon(Seconds(5));
}
void IsSummonedBy(Unit* summoner) override
{
if (Creature* lockmaw = _instance->GetCreature(DATA_LOCKMAW))
lockmaw->AI()->JustSummoned(me);
me->SetReactState(REACT_PASSIVE);
DoZoneInCombat();
_events.ScheduleEvent(EVENT_FIND_PLAYER_TARGET, Seconds(1));
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_FIND_PLAYER_TARGET:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, ScentOfBloodTargetSelector()))
{
DoCastSelf(SPELL_STEALTHED);
me->AI()->AttackStart(target);
me->AddThreat(target, 50000000.0f);
}
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetLostCityOfTheTolvirAI<npc_lockmaw_frenzied_crocoliskAI>(creature);
}
};
class npc_lockmaw_augh : public CreatureScript
{
public:
npc_lockmaw_augh() : CreatureScript("npc_lockmaw_augh") { }
struct npc_lockmaw_aughAI : public ScriptedAI
{
npc_lockmaw_aughAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void IsSummonedBy(Unit* /*summoner*/) override
{
if (Creature* lockmaw = _instance->GetCreature(DATA_LOCKMAW))
lockmaw->AI()->JustSummoned(me);
DoCastSelf(SPELL_STEALTHED, true);
if (me->GetEntry() == NPC_AUGH_DART)
{
me->SetReactState(REACT_PASSIVE);
_events.ScheduleEvent(EVENT_ROAR_EMOTE, Seconds(7));
_events.ScheduleEvent(EVENT_PARALYTIC_BLOW_DART, Seconds(8));
_events.ScheduleEvent(EVENT_SMOKE_BOMB, Seconds(12));
}
else
_events.ScheduleEvent(EVENT_WHIRLWIND, Seconds(4));
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
// There is indeed now immunity aura...
damage = 0;
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ROAR_EMOTE:
me->HandleEmoteCommand(EMOTE_ONESHOT_BATTLE_ROAR);
break;
case EVENT_PARALYTIC_BLOW_DART:
DoCastAOE(SPELL_PARALYTIC_BLOW_DART);
break;
case EVENT_SMOKE_BOMB:
DoCastSelf(SPELL_SMOKE_BOMB);
me->DespawnOrUnsummon(Seconds(3));
break;
case EVENT_WHIRLWIND:
DoCastAOE(SPELL_RANDOM_AGGRO_TAUNT, true);
DoCastSelf(SPELL_WHIRLWIND);
_events.ScheduleEvent(EVENT_RANDOM_AGGRO, Seconds(10));
break;
case EVENT_RANDOM_AGGRO:
DoCastAOE(SPELL_RANDOM_AGGRO_TAUNT, true);
_events.ScheduleEvent(EVENT_ATTACK_STOP, Seconds(10));
break;
case EVENT_ATTACK_STOP:
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
me->DespawnOrUnsummon(Seconds(6));
break;
default:
break;
}
}
}
private:
EventMap _events;
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetLostCityOfTheTolvirAI<npc_lockmaw_aughAI>(creature);
}
};
class spell_lockmaw_scent_of_blood : public SpellScriptLoader
{
public:
spell_lockmaw_scent_of_blood() : SpellScriptLoader("spell_lockmaw_scent_of_blood") { }
class spell_lockmaw_scent_of_blood_SpellScript : public SpellScript
{
PrepareSpellScript(spell_lockmaw_scent_of_blood_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_lockmaw_scent_of_blood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const
{
return new spell_lockmaw_scent_of_blood_SpellScript();
}
};
class spell_lockmaw_paralytic_blow_dart : public SpellScriptLoader
{
public:
spell_lockmaw_paralytic_blow_dart() : SpellScriptLoader("spell_lockmaw_paralytic_blow_dart") { }
class spell_lockmaw_paralytic_blow_dart_SpellScript : public SpellScript
{
PrepareSpellScript(spell_lockmaw_paralytic_blow_dart_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_lockmaw_paralytic_blow_dart_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const
{
return new spell_lockmaw_paralytic_blow_dart_SpellScript();
}
};
class spell_lockmaw_random_aggro_taunt : public SpellScriptLoader
{
public:
spell_lockmaw_random_aggro_taunt() : SpellScriptLoader("spell_lockmaw_random_aggro_taunt") { }
class spell_lockmaw_random_aggro_taunt_SpellScript : public SpellScript
{
PrepareSpellScript(spell_lockmaw_random_aggro_taunt_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void EffectScriptEffect(SpellEffIndex /*effIndex*/)
{
GetHitPlayer()->CastSpell(GetCaster(), GetSpellInfo()->Effects[EFFECT_0].BasePoints, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_lockmaw_random_aggro_taunt_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_lockmaw_random_aggro_taunt_SpellScript::EffectScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const
{
return new spell_lockmaw_random_aggro_taunt_SpellScript();
}
};
void AddSC_boss_lockmaw_and_augh()
{
new boss_lockmaw();
new boss_augh();
new npc_lockmaw_frenzied_crocolisk();
new npc_lockmaw_augh();
new spell_lockmaw_scent_of_blood();
new spell_lockmaw_paralytic_blow_dart();
new spell_lockmaw_random_aggro_taunt();
}

View File

@@ -19,6 +19,26 @@
#include "InstanceScript.h"
#include "lost_city_of_the_tolvir.h"
enum TimedEvents
{
EVENT_SPAWN_AUGH = 1
};
enum SummonGroups
{
SUMMON_GROUP_WIND_TUNNEL = 0
};
enum Actions
{
// Lockmaw and Augh
ACTION_AUGH_INTRO = 1,
ACTION_AUGH_ATTACKABLE = 2
};
Position const AughSpawnPos = { -11058.91f, -1625.342f, -0.1304993f, 4.782202f };
Position const AughHomePos = { -11062.5f, -1662.39f, 0.7606202f, 0.8028514f };
ObjectData const creatureData[] =
{
{ BOSS_GENERAL_HUSAM, DATA_GENERAL_HUSAM },
@@ -28,7 +48,7 @@ ObjectData const creatureData[] =
{ BOSS_SIAMAT, DATA_SIAMAT },
{ NPC_BLAZE_OF_THE_HEAVENS, DATA_BLAZE_OF_THE_HEAVENS },
{ NPC_HARBINGER_OF_DARKNESS, DATA_HARBINGER_OF_DARKNESS },
{ 0, 0 } // End
{ 0, 0 } // End
};
ObjectData const gameObjectData[] =
@@ -39,31 +59,155 @@ ObjectData const gameObjectData[] =
class instance_lost_city_of_the_tolvir : public InstanceMapScript
{
public:
instance_lost_city_of_the_tolvir() : InstanceMapScript(LCTScriptName, 755) { }
public:
instance_lost_city_of_the_tolvir() : InstanceMapScript(LCTScriptName, 755) { }
struct instance_lost_city_of_the_tolvir_InstanceMapScript : public InstanceScript
{
instance_lost_city_of_the_tolvir_InstanceMapScript(Map* map) : InstanceScript(map)
struct instance_lost_city_of_the_tolvir_InstanceMapScript : public InstanceScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, gameObjectData);
}
instance_lost_city_of_the_tolvir_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, gameObjectData);
Initialize();
}
bool SetBossState(uint32 type, EncounterState state) override
void Initialize()
{
_heroicAughSpawned = false;
}
void OnCreatureCreate(Creature* creature) override
{
InstanceScript::OnCreatureCreate(creature);
if (creature->GetEntry() == NPC_ADD_STALKER)
addStalkerGUIDs.push_back(creature->GetGUID());
}
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
switch (type)
{
case DATA_LOCKMAW:
if (!instance->IsHeroic() && state == DONE)
SetBossState(DATA_LOCKMAW_AND_AUGH, DONE);
else if (instance->IsHeroic() && state == DONE && !_heroicAughSpawned)
_events.ScheduleEvent(EVENT_SPAWN_AUGH, Seconds(4));
break;
case DATA_AUGH: // Since Augh is summoned, we need to handle his respawn here
if (state == DONE)
SetBossState(DATA_LOCKMAW_AND_AUGH, DONE);
else if (state == FAIL)
_events.ScheduleEvent(EVENT_SPAWN_AUGH, Seconds(30));
break;
case DATA_GENERAL_HUSAM:
case DATA_LOCKMAW_AND_AUGH:
case DATA_HIGH_PROPHET_BARIM:
if (state == DONE && CheckSiamatsPlatform())
{
if (GameObject* platform = GetGameObject(DATA_SIAMAT_PLATFORM))
{
platform->setActive(true);
platform->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED);
platform->EnableCollision(true);
}
instance->SetZoneWeather(ZONE_ID_LOST_CITY, WEATHER_STATE_HEAVY_RAIN, 1.0f);
instance->SummonCreatureGroup(SUMMON_GROUP_WIND_TUNNEL);
}
break;
default:
break;
}
return true;
}
void SetData(uint32 data, uint32 value) override
{
switch (data)
{
case DATA_LOCKMAW_COMBAT_ASSISTANCE:
switch (value)
{
case ASSISTANCE_SUMMON_AUGH_DART:
if (Unit* stalker = instance->GetCreature(Trinity::Containers::SelectRandomContainerElement(addStalkerGUIDs)))
stalker->CastSpell(stalker, SPELL_SUMMON_AUGH_DART);
SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_NONE);
break;
case ASSISTANCE_SUMMON_AUGH_WHIRLWIND:
if (Unit* stalker = instance->GetCreature(Trinity::Containers::SelectRandomContainerElement(addStalkerGUIDs)))
stalker->CastSpell(stalker, SPELL_SUMMON_AUGH_WHIRLWIND);
SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_NONE);
break;
case ASSISTANCE_SUMMON_CROCOLISKS:
{
GuidVector tempList = addStalkerGUIDs;
if (!tempList.empty())
{
Trinity::Containers::RandomResize(tempList, 4);
for (auto itr = tempList.begin(); itr != tempList.end(); itr++)
if (Unit* stalker = instance->GetCreature(*itr))
stalker->CastSpell(stalker, SPELL_SUMMON_CROCOLISK);
}
SetData(DATA_LOCKMAW_COMBAT_ASSISTANCE, ASSISTANCE_NONE);
break;
}
default:
break;
}
break;
default:
break;
}
}
bool CheckSiamatsPlatform()
{
for (LCTDataTypes boss : { DATA_GENERAL_HUSAM, DATA_LOCKMAW_AND_AUGH, DATA_HIGH_PROPHET_BARIM })
if (GetBossState(boss) != DONE)
return false;
return true;
}
void Update(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SPAWN_AUGH:
if (!_heroicAughSpawned)
{
if (Creature* augh = instance->SummonCreature(BOSS_AUGH, AughSpawnPos))
augh->AI()->DoAction(ACTION_AUGH_INTRO);
_heroicAughSpawned = true;
}
else if (_heroicAughSpawned)
if (Creature* augh = instance->SummonCreature(BOSS_AUGH, AughHomePos))
augh->AI()->DoAction(ACTION_AUGH_ATTACKABLE);
break;
default:
break;
}
}
}
protected:
EventMap _events;
bool _heroicAughSpawned;
GuidVector addStalkerGUIDs;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
if (!InstanceScript::SetBossState(type, state))
return false;
return true;
return new instance_lost_city_of_the_tolvir_InstanceMapScript(map);
}
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_lost_city_of_the_tolvir_InstanceMapScript(map);
}
};
void AddSC_instance_lost_city_of_the_tolvir()

View File

@@ -21,21 +21,23 @@
#define LCTScriptName "instance_lost_city_of_the_tolvir"
#define DataHeader "LCT"
uint32 const EncounterCount = 4;
uint32 const EncounterCount = 6;
enum LCTDataTypes
{
// Encounter States
DATA_GENERAL_HUSAM = 1,
DATA_LOCKMAW = 2,
DATA_AUGH = 3,
DATA_HIGH_PROPHET_BARIM = 4,
DATA_SIAMAT = 5,
DATA_GENERAL_HUSAM = 0,
DATA_LOCKMAW_AND_AUGH = 1,
DATA_HIGH_PROPHET_BARIM = 2,
DATA_SIAMAT = 3,
DATA_LOCKMAW = 4,
DATA_AUGH = 5,
// Additional Data
DATA_SIAMAT_PLATFORM = 6,
DATA_BLAZE_OF_THE_HEAVENS = 7,
DATA_HARBINGER_OF_DARKNESS = 8,
DATA_SIAMAT_PLATFORM = 6,
DATA_BLAZE_OF_THE_HEAVENS = 7,
DATA_HARBINGER_OF_DARKNESS = 8,
DATA_LOCKMAW_COMBAT_ASSISTANCE = 9
};
enum LCTCreatureIds
@@ -56,6 +58,9 @@ enum LCTCreatureIds
NPC_BLAZE_OF_THE_HEAVENS = 48906,
NPC_SOUL_FRAGMENT = 43934,
NPC_HARBINGER_OF_DARKNESS = 43927,
NPC_DUST_FLAIL_FRONT_STALKER = 43655,
NPC_ADD_STALKER = 45124,
NPC_AUGH_DART = 45379
};
enum LCTGameObjectIds
@@ -63,6 +68,23 @@ enum LCTGameObjectIds
GO_SIAMAT_PLATFORM = 205365
};
enum LCTSpells
{
SPELL_SUMMON_CROCOLISK = 84242,
SPELL_SUMMON_AUGH_DART = 84809,
SPELL_SUMMON_AUGH_WHIRLWIND = 84808
};
enum LCTMisc
{
ZONE_ID_LOST_CITY = 5396,
ASSISTANCE_NONE = 0,
ASSISTANCE_SUMMON_AUGH_DART = 1,
ASSISTANCE_SUMMON_AUGH_WHIRLWIND = 2,
ASSISTANCE_SUMMON_CROCOLISKS = 3
};
template<class AI>
AI* GetLostCityOfTheTolvirAI(Creature* creature)
{