mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-02-05 08:28:57 +01:00
Scripts/EndTime: implement Echo of Jaina encounter
This commit is contained in:
80
sql/updates/world/4.3.4/2022_04_26_00_world.sql
Normal file
80
sql/updates/world/4.3.4/2022_04_26_00_world.sql
Normal file
@@ -0,0 +1,80 @@
|
||||
UPDATE `gameobject_template` SET `ScriptName`= 'go_end_time_time_transit_device' WHERE `entry` IN (209441, 209442);
|
||||
UPDATE `gameobject_template` SET `ScriptName`= 'go_end_time_fragment_of_jainas_staff' WHERE `entry`= 209318;
|
||||
|
||||
UPDATE `gossip_menu_option` SET `OptionType`= 1 WHERE `MenuId`= 13321;
|
||||
|
||||
UPDATE `creature_template` SET `unit_flags`= 33587968, `unit_flags2`= 2099200, `AIName`= 'NullCreatureAI' WHERE `entry`= 54641;
|
||||
UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= `flags_extra` | 128, `AIName`= 'NullCreatureAI' WHERE `entry`= 54639;
|
||||
UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= `flags_extra` | 128, `ScriptName`= 'npc_echo_of_jaina_blink_target' WHERE `entry`= 54542;
|
||||
UPDATE `creature_template` SET `unit_flags`= 33554432, `unit_flags2`= 34816, `flags_extra`= `flags_extra` | 128, `AIName`= 'NullCreatureAI' WHERE `entry`= 54446;
|
||||
|
||||
DELETE FROM `spawn_group_template` WHERE `groupId`= 460;
|
||||
INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES
|
||||
(460, 'End Time - Echo of Jaina - Jaina', 4);
|
||||
|
||||
DELETE FROM `spawn_group` WHERE `groupId`= 460;
|
||||
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
|
||||
(460, 0, 341769);
|
||||
|
||||
UPDATE `creature_template` SET `unit_flags`= 33088, `unit_flags2`= 2099200, `ScriptName`= 'boss_echo_of_jaina' WHERE `entry`= 54445;
|
||||
UPDATE `creature_template` SET `flags_extra`= `flags_extra` | 128, `AIName`= 'NullCreatureAI' WHERE `entry`= 54494;
|
||||
|
||||
DELETE FROM `creature_text` WHERE `CreatureID`= 54445;
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
|
||||
(54445, 0, 0, 'I don\'t know who you are, but I\'ll defend this shrine with my life. Leave, now, before we come to blows.', 12, 0, 100, 0, 0, 25920, 56573, 'Echo of Jaina - Intro'),
|
||||
(54445, 1, 0, 'You asked for it.', 14, 0, 100, 0, 0, 25917, 53040, 'Echo of Jaina - Aggro'),
|
||||
(54445, 2, 0, 'Why won\'t you give up?!', 14, 0, 100, 0, 0, 25926, 56580, 'Echo of Jaina - Blink 1'),
|
||||
(54445, 2, 1, 'Perhaps this will cool your heads...', 14, 0, 100, 0, 0, 25924, 56578, 'Echo of Jaina - Blink 2'),
|
||||
(54445, 2, 2, 'A little ice ought to quench the fire in your hearts...', 14, 0, 100, 0, 0, 25925, 56579, 'Echo of Jaina - Blink 3'),
|
||||
(54445, 3, 0, 'I understand, now. Farewell, and good luck.', 12, 0, 100, 0, 0, 25919, 56574, 'Echo of Jaina - Death'),
|
||||
(54445, 4, 0, 'You forced my hand.', 14, 0, 100, 0, 0, 25921, 56575, 'Echo of Jaina - Slay 1'),
|
||||
(54445, 4, 1, 'I didn\'t want to do that.', 14, 0, 100, 0, 0, 25922, 56576, 'Echo of Jaina - Slay 2'),
|
||||
(54445, 4, 2, 'I wish you\'d surrendered.', 14, 0, 100, 0, 0, 25923, 56577, 'Echo of Jaina - Slay 3');
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN
|
||||
('spell_echo_of_jaina_face_highest_threat_target',
|
||||
'spell_echo_of_jaina_frost_blade',
|
||||
'spell_echo_of_jaina_disable_stalker_search',
|
||||
'spell_echo_of_jaina_blink',
|
||||
'spell_echo_of_jaina_flarecore',
|
||||
'spell_echo_of_jaina_flarecore_triggered',
|
||||
'spell_echo_of_jaina_flarecore_periodic');
|
||||
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(107897, 'spell_echo_of_jaina_face_highest_threat_target'),
|
||||
(101337, 'spell_echo_of_jaina_frost_blade'),
|
||||
(101540, 'spell_echo_of_jaina_disable_stalker_search'),
|
||||
(101812, 'spell_echo_of_jaina_blink'),
|
||||
(101944, 'spell_echo_of_jaina_flarecore'),
|
||||
(101616, 'spell_echo_of_jaina_flarecore_triggered'),
|
||||
(101588, 'spell_echo_of_jaina_flarecore_periodic');
|
||||
|
||||
DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (54494, 54446);
|
||||
INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`) VALUES
|
||||
(54494, 0, 0, 2, 0),
|
||||
(54446, 0, 0, 2, 1);
|
||||
|
||||
DELETE FROM `conditions` WHERE `SourceEntry` IN (101812, 101540) AND `SourceTypeOrReferenceId`= 13;
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES
|
||||
(13, 1, 101812, 0, 0, 31, 0, 3, 54542, 0, 0, 0, '', 'Blink - Target Blink Target'),
|
||||
(13, 2, 101540, 0, 0, 31, 0, 3, 54445, 0, 0, 0, '', 'Disable Stalker Search - Target Echo of Jaina');
|
||||
|
||||
DELETE FROM `creature_onkill_reward` WHERE `creature_id`= 54445;
|
||||
INSERT INTO `creature_onkill_reward` (`creature_id`, `RewOnKillRepFaction1`, `MaxStanding1`, `IsTeamAward1`, `RewOnKillRepValue1`, `TeamDependent`, `CurrencyId1`, `CurrencyCount1`) VALUES
|
||||
(54445, 1162, 7, 0, 250, 0, 395, 7000);
|
||||
|
||||
UPDATE `creature_template`SET `mingold`= 17000, `maxgold`= 23000 WHERE `entry`= 54445;
|
||||
DELETE FROM `creature_loot_template` WHERE `Entry`= 54445;
|
||||
INSERT INTO `creature_loot_template` (`Entry`, `Reference`, `Item`, `Chance`, `GroupId`, `MinCount`, `MaxCount`, `LootMode`) VALUES
|
||||
(54445, 0, 72808, 20, 1, 1, 1, 1),
|
||||
(54445, 0, 72809, 15, 1, 1, 1, 1),
|
||||
(54445, 0, 72805, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72801, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72804, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72802, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72799, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72803, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72806, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72798, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72800, 5, 1, 1, 1, 1),
|
||||
(54445, 0, 72807, 5, 1, 1, 1, 1);
|
||||
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "end_time.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "PassiveAI.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Echo of Jaina
|
||||
SPELL_PYROBLAST = 101809,
|
||||
SPELL_FROSTBOLT_VOLLEY = 101810,
|
||||
SPELL_BLINK = 101812,
|
||||
SPELL_FACE_HIGHEST_THREAT_TARGET = 107897,
|
||||
SPELL_FROST_BLADES = 101339,
|
||||
SPELL_FLARECORE = 101944,
|
||||
|
||||
// Frost Blades
|
||||
SPELL_FROST_BLADES_PERIODIC = 101338,
|
||||
|
||||
// Blink Target
|
||||
SPELL_DISABLE_STALKER_SEARCH = 101540,
|
||||
|
||||
// Flarecore
|
||||
SPELL_FLARECORE_PERIODIC = 101588,
|
||||
SPELL_FLARE_UP = 101589,
|
||||
SPELL_UNSTABLE_FLARE = 101980,
|
||||
SPELL_FLARE = 101587,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
// Echo of Jaina
|
||||
EVENT_MAKE_ATTACKABLE = 1,
|
||||
EVENT_PYROBLAST,
|
||||
EVENT_FROSTBOLT_VOLLEY,
|
||||
EVENT_BLINK,
|
||||
EVENT_FACE_HIGHEST_THREAT_TARGET,
|
||||
EVENT_FLARECORE,
|
||||
|
||||
// Blink Target
|
||||
EVENT_DISABLE_STALKER_SEARCH
|
||||
};
|
||||
|
||||
enum Actions
|
||||
{
|
||||
// Blink Target
|
||||
ACTION_DISABLE_STALKER = 0
|
||||
};
|
||||
|
||||
enum Phases
|
||||
{
|
||||
PHASE_INTRO = 1,
|
||||
PHASE_COMBAT = 2
|
||||
};
|
||||
|
||||
enum Texts
|
||||
{
|
||||
SAY_INTRO = 0,
|
||||
SAY_AGGRO = 1,
|
||||
SAY_BLINK = 2,
|
||||
SAY_DEATH = 3,
|
||||
SAY_SLAY = 4
|
||||
};
|
||||
|
||||
enum Data
|
||||
{
|
||||
DATA_STALKER_DISABLED = 0
|
||||
};
|
||||
|
||||
struct boss_echo_of_jaina : public BossAI
|
||||
{
|
||||
boss_echo_of_jaina(Creature* creature) : BossAI(creature, DATA_ECHO_OF_JAINA), _firstSpawn(false), _frostBladeCount(0), _frostboltVolleyCount(0) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
_firstSpawn = instance->GetBossState(DATA_ECHO_OF_JAINA) == NOT_STARTED;
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
if (_firstSpawn)
|
||||
{
|
||||
Talk(SAY_INTRO);
|
||||
events.SetPhase(PHASE_INTRO);
|
||||
events.ScheduleEvent(EVENT_MAKE_ATTACKABLE, 9s, 0, PHASE_INTRO);
|
||||
}
|
||||
else
|
||||
me->SetImmuneToPC(false);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO, who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 1ms);
|
||||
events.ScheduleEvent(EVENT_FLARECORE, 15s);
|
||||
events.ScheduleEvent(EVENT_BLINK, 19s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
summons.DespawnAll();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH, killer);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
Talk(SAY_SLAY, victim);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
|
||||
switch (summon->GetEntry())
|
||||
{
|
||||
case NPC_FROST_BLADE:
|
||||
{
|
||||
summon->CastSpell(nullptr, SPELL_FROST_BLADES_PERIODIC);
|
||||
|
||||
float stepSize = float(M_PI_2 / 3);
|
||||
float angle = me->GetOrientation() - stepSize;
|
||||
angle = Position::NormalizeOrientation(angle + stepSize * _frostBladeCount);
|
||||
++_frostBladeCount;
|
||||
float x = me->GetPositionX() + std::cos(angle) * 50.f;
|
||||
float y = me->GetPositionY() + std::sin(angle) * 50.f;
|
||||
summon->GetMotionMaster()->MovePoint(0, x, y, me->GetPositionZ(), false);
|
||||
summon->DespawnOrUnsummon(6s + 500ms);
|
||||
break;
|
||||
}
|
||||
case NPC_FLARECORE_EMBER:
|
||||
summon->CastSpell(summon, SPELL_FLARECORE_PERIODIC);
|
||||
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_MAKE_ATTACKABLE:
|
||||
me->SetImmuneToPC(false);
|
||||
break;
|
||||
case EVENT_PYROBLAST:
|
||||
DoCastVictim(SPELL_PYROBLAST);
|
||||
events.Repeat(2s);
|
||||
break;
|
||||
case EVENT_FROSTBOLT_VOLLEY:
|
||||
DoCastAOE(SPELL_FROSTBOLT_VOLLEY);
|
||||
// Blink and Frost Blades have been pulled off, time to return to regular combat routine
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
++_frostboltVolleyCount;
|
||||
if (_frostboltVolleyCount < 3)
|
||||
events.Repeat(1ms);
|
||||
else
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 1ms);
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
Talk(SAY_BLINK);
|
||||
DoCastSelf(SPELL_BLINK);
|
||||
_frostBladeCount = 0;
|
||||
_frostboltVolleyCount = 0;
|
||||
events.ScheduleEvent(EVENT_FACE_HIGHEST_THREAT_TARGET, 1ms);
|
||||
events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 2s);
|
||||
events.CancelEvent(EVENT_PYROBLAST);
|
||||
events.Repeat(24s);
|
||||
break;
|
||||
case EVENT_FACE_HIGHEST_THREAT_TARGET:
|
||||
DoCast(me->GetThreatManager().GetCurrentVictim(), SPELL_FACE_HIGHEST_THREAT_TARGET);
|
||||
break;
|
||||
case EVENT_FLARECORE:
|
||||
DoCastAOE(SPELL_FLARECORE, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_MAX_TARGETS, 1));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _firstSpawn;
|
||||
uint8 _frostBladeCount;
|
||||
uint8 _frostboltVolleyCount;
|
||||
};
|
||||
|
||||
struct npc_echo_of_jaina_blink_target : public NullCreatureAI
|
||||
{
|
||||
npc_echo_of_jaina_blink_target(Creature* creature) : NullCreatureAI(creature), _disabled(false) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_DISABLE_STALKER_SEARCH, 2s + 500ms);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_DISABLE_STALKER:
|
||||
_disabled = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_STALKER_DISABLED:
|
||||
return _disabled ? 1 : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DISABLE_STALKER_SEARCH:
|
||||
_disabled = false;
|
||||
DoCastAOE(SPELL_DISABLE_STALKER_SEARCH);
|
||||
_events.Repeat(2s + 500ms);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
bool _disabled;
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_face_highest_threat_target : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FROST_BLADES });
|
||||
}
|
||||
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
caster->SetFacingToObject(GetHitUnit());
|
||||
caster->SetOrientationTowards(GetHitUnit()); // we need an updated orientation right now. No time to wait for the spline to update
|
||||
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
caster->CastSpell(caster, SPELL_FROST_BLADES);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget.Register(&spell_echo_of_jaina_face_highest_threat_target::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_frost_blade : public SpellScript
|
||||
{
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if([&](WorldObject const* target)
|
||||
{
|
||||
return target->GetExactDist2d(GetCaster()) > GetCaster()->GetCombatReach();
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect.Register(&spell_echo_of_jaina_frost_blade::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_disable_stalker_search : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FROST_BLADES });
|
||||
}
|
||||
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster || !caster->IsCreature())
|
||||
return;
|
||||
|
||||
if (CreatureAI* ai = caster->ToCreature()->AI())
|
||||
ai->DoAction(ACTION_DISABLE_STALKER);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget.Register(&spell_echo_of_jaina_disable_stalker_search::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnEffectHitTarget.Register(&spell_echo_of_jaina_disable_stalker_search::HandleDummyEffect, EFFECT_1, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_blink : public SpellScript
|
||||
{
|
||||
void SetTarget(SpellDestination& target)
|
||||
{
|
||||
std::list<Creature*> blinkTargets;
|
||||
GetCaster()->GetCreatureListWithEntryInGrid(blinkTargets, NPC_BLINK_TARGET, GetSpellInfo()->GetMaxRange());
|
||||
if (blinkTargets.empty())
|
||||
return;
|
||||
|
||||
blinkTargets.remove_if([](Creature const* creature)
|
||||
{
|
||||
if (CreatureAI const* ai = creature->AI())
|
||||
if (ai->GetData(DATA_STALKER_DISABLED))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (blinkTargets.size() > 1)
|
||||
{
|
||||
blinkTargets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
|
||||
blinkTargets.resize(1);
|
||||
target = *blinkTargets.front();
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnDestinationTargetSelect.Register(&spell_echo_of_jaina_blink::SetTarget, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_flarecore : public SpellScript
|
||||
{
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetHitUnit(), GetEffectValue(), true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget.Register(&spell_echo_of_jaina_flarecore::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_flarecore_triggered : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_UNSTABLE_FLARE, SPELL_FLARECORE_PERIODIC });
|
||||
}
|
||||
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (_detonated)
|
||||
return;
|
||||
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
caster->CastSpell(nullptr, SPELL_UNSTABLE_FLARE);
|
||||
caster->RemoveAurasDueToSpell(SPELL_FLARECORE_PERIODIC);
|
||||
|
||||
_detonated = true;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget.Register(&spell_echo_of_jaina_flarecore_triggered::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
private:
|
||||
bool _detonated = false;
|
||||
};
|
||||
|
||||
class spell_echo_of_jaina_flarecore_periodic : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FLARE_UP, SPELL_FLARE, SPELL_FLARECORE_PERIODIC });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (!((aurEff->GetTickNumber() - 1) % 4))
|
||||
GetTarget()->CastSpell(nullptr, SPELL_FLARE_UP);
|
||||
}
|
||||
|
||||
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode().HasFlag(AuraRemoveFlags::Expired))
|
||||
{
|
||||
GetTarget()->CastSpell(nullptr, SPELL_FLARE);
|
||||
GetTarget()->RemoveAurasDueToSpell(SPELL_FLARECORE_PERIODIC);
|
||||
}
|
||||
|
||||
if (Creature* creature = GetTarget()->ToCreature())
|
||||
creature->DespawnOrUnsummon(5s + 500ms);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic.Register(&spell_echo_of_jaina_flarecore_periodic::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
AfterEffectRemove.Register(&spell_echo_of_jaina_flarecore_periodic::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_echo_of_jaina()
|
||||
{
|
||||
RegisterEndTimeCreatureAI(boss_echo_of_jaina);
|
||||
RegisterEndTimeCreatureAI(npc_echo_of_jaina_blink_target);
|
||||
RegisterSpellScript(spell_echo_of_jaina_face_highest_threat_target);
|
||||
RegisterSpellScript(spell_echo_of_jaina_frost_blade);
|
||||
RegisterSpellScript(spell_echo_of_jaina_disable_stalker_search);
|
||||
RegisterSpellScript(spell_echo_of_jaina_blink);
|
||||
RegisterSpellScript(spell_echo_of_jaina_flarecore);
|
||||
RegisterSpellScript(spell_echo_of_jaina_flarecore_triggered);
|
||||
RegisterSpellScript(spell_echo_of_jaina_flarecore_periodic);
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
|
||||
#include "end_time.h"
|
||||
#include "GameObject.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "PassiveAI.h"
|
||||
#include "Player.h"
|
||||
@@ -50,7 +52,7 @@ enum Texts
|
||||
SAY_ENCOUNTER_OUTRO_4 = 4
|
||||
};
|
||||
|
||||
enum GossipMenus
|
||||
enum GossipMenuIds
|
||||
{
|
||||
GOSSIP_MENU_ID_NOZDORMU = 13360,
|
||||
GOSSIP_MENU_OPTION_ID_WELL_OF_ETERNITY = 0
|
||||
@@ -152,7 +154,101 @@ private:
|
||||
bool _introDone;
|
||||
};
|
||||
|
||||
enum TimeTransitDeviceAreaIds
|
||||
{
|
||||
AREA_ID_ENTRYWAY_OF_TIME = 5796
|
||||
};
|
||||
|
||||
enum TimeTransitDeviceSpells
|
||||
{
|
||||
SPELL_TELEPORT_TO_ENTRANCE = 102564,
|
||||
SPELL_TELEPORT_TO_BLUE_DRAGONSHRINE = 102126
|
||||
};
|
||||
|
||||
enum TimeTransitGossipMenuIds
|
||||
{
|
||||
GOSSIP_MENU_ID_SELECT_YOUR_DESTINATION = 13321
|
||||
};
|
||||
|
||||
enum TimeTransitGossipIndexes
|
||||
{
|
||||
GOSSIP_INDEX_TELEPORT_TO_ENTRYWAY_OF_TIME = 0,
|
||||
GOSSIP_INDEX_TELEPORT_TO_BLUE_DRAGONSHRINE_FIRST_ECHO = 3,
|
||||
GOSSIP_INDEX_TELEPORT_TO_BLUE_DRAGONSHRINE_SECOND_ECHO = 7
|
||||
};
|
||||
|
||||
static std::unordered_map<uint32 /*gossipMenuId*/, uint32 /*teleportSpellId*/> TransitDeviceTeleportSpells =
|
||||
{
|
||||
{ GOSSIP_INDEX_TELEPORT_TO_ENTRYWAY_OF_TIME, SPELL_TELEPORT_TO_ENTRANCE },
|
||||
{ GOSSIP_INDEX_TELEPORT_TO_BLUE_DRAGONSHRINE_FIRST_ECHO, SPELL_TELEPORT_TO_BLUE_DRAGONSHRINE },
|
||||
{ GOSSIP_INDEX_TELEPORT_TO_BLUE_DRAGONSHRINE_SECOND_ECHO, SPELL_TELEPORT_TO_BLUE_DRAGONSHRINE }
|
||||
};
|
||||
|
||||
struct go_end_time_time_transit_device : public GameObjectAI
|
||||
{
|
||||
go_end_time_time_transit_device(GameObject* gameObject) : GameObjectAI(gameObject), _instance(nullptr) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
_instance = me->GetInstanceScript();
|
||||
}
|
||||
|
||||
bool GossipHello(Player* player) override
|
||||
{
|
||||
if (!_instance)
|
||||
return false;
|
||||
|
||||
if (player->GetAreaId() != AREA_ID_ENTRYWAY_OF_TIME)
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ID_SELECT_YOUR_DESTINATION, GOSSIP_INDEX_TELEPORT_TO_ENTRYWAY_OF_TIME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_INDEX_TELEPORT_TO_ENTRYWAY_OF_TIME);
|
||||
|
||||
// @todo: world state based menu generation
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ID_SELECT_YOUR_DESTINATION, GOSSIP_INDEX_TELEPORT_TO_BLUE_DRAGONSHRINE_FIRST_ECHO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_INDEX_TELEPORT_TO_BLUE_DRAGONSHRINE_FIRST_ECHO);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(GOSSIP_MENU_ID_SELECT_YOUR_DESTINATION, me), me->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GossipSelect(Player* player, uint32 /*gossipMenuId*/, uint32 action) override
|
||||
{
|
||||
uint32 index = player->PlayerTalkClass->GetGossipOptionAction(action) - GOSSIP_ACTION_INFO_DEF;
|
||||
player->CastSpell(player, TransitDeviceTeleportSpells[index]);
|
||||
ClearGossipMenuFor(player);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
struct go_end_time_fragment_of_jainas_staff : public GameObjectAI
|
||||
{
|
||||
go_end_time_fragment_of_jainas_staff(GameObject* gameObject) : GameObjectAI(gameObject), _instance(nullptr) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
_instance = me->GetInstanceScript();
|
||||
}
|
||||
|
||||
bool GossipHello(Player* /*player*/) override
|
||||
{
|
||||
if (!_instance)
|
||||
return false;
|
||||
|
||||
_instance->SetData(DATA_COLLECTED_FRAGMENT_OF_JAINAS_STAFF, 0);
|
||||
me->DespawnOrUnsummon();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
void AddSC_end_time()
|
||||
{
|
||||
RegisterEndTimeCreatureAI(npc_end_time_nozdormu);
|
||||
RegisterGameObjectAI(go_end_time_time_transit_device);
|
||||
RegisterGameObjectAI(go_end_time_fragment_of_jainas_staff);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ enum ETDataTypes
|
||||
{
|
||||
// Bosses
|
||||
DATA_ECHO_OF_BAINE = 0,
|
||||
DATA_ECHO_OF_JANA = 1,
|
||||
DATA_ECHO_OF_JAINA = 1,
|
||||
DATA_ECHO_OF_SYLVANAS = 2,
|
||||
DATA_ECHO_OF_TYRANDE = 3,
|
||||
DATA_MUROZOND = 4,
|
||||
@@ -40,19 +40,27 @@ enum ETDataTypes
|
||||
// Additional Data
|
||||
DATA_HOURGLASS_OF_TIME,
|
||||
DATA_MUROZOND_INTRO,
|
||||
DATA_NOZDORMU_BRONZE_DRAGON_SHRINE
|
||||
DATA_NOZDORMU_BRONZE_DRAGON_SHRINE,
|
||||
DATA_ARCANE_CIRCLE,
|
||||
DATA_COLLECTED_FRAGMENT_OF_JAINAS_STAFF,
|
||||
};
|
||||
|
||||
enum ETCreatures
|
||||
{
|
||||
// Bosses
|
||||
BOSS_MUROZOND = 54432,
|
||||
BOSS_MUROZOND = 54432,
|
||||
|
||||
// Encounter Related Creatures
|
||||
/*Murozond*/
|
||||
NPC_INFINITE_WARDEN = 54923,
|
||||
NPC_INFINITE_SUPRESSOR = 54920,
|
||||
NPC_NOZDORMU_DRAGON_SHRINES = 54751
|
||||
NPC_INFINITE_WARDEN = 54923,
|
||||
NPC_INFINITE_SUPRESSOR = 54920,
|
||||
NPC_NOZDORMU_DRAGON_SHRINES = 54751,
|
||||
|
||||
/*Echo of Jaina*/
|
||||
NPC_ARCANE_CIRCLE = 54639,
|
||||
NPC_FROST_BLADE = 54494,
|
||||
NPC_BLINK_TARGET = 54542,
|
||||
NPC_FLARECORE_EMBER = 54446
|
||||
};
|
||||
|
||||
enum ETGameObjectIds
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_MUROZOND, DATA_MUROZOND },
|
||||
{ 0, 0 } // END
|
||||
{ BOSS_MUROZOND, DATA_MUROZOND },
|
||||
{ NPC_ARCANE_CIRCLE, DATA_ARCANE_CIRCLE },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
ObjectData const gameobjectData[] =
|
||||
@@ -48,7 +49,8 @@ enum Events
|
||||
|
||||
enum SpawnGroups
|
||||
{
|
||||
SPAWN_GROUP_ID_MUROZOND_CHEST = 437
|
||||
SPAWN_GROUP_ID_MUROZOND_CHEST = 437,
|
||||
SPAWN_GROUP_ID_ECHO_OF_JAINA = 460
|
||||
};
|
||||
|
||||
enum AreaIds
|
||||
@@ -56,6 +58,22 @@ enum AreaIds
|
||||
AREA_ID_BRONZE_DRAGON_SHRINE = 5795
|
||||
};
|
||||
|
||||
enum WorldStates
|
||||
{
|
||||
WORLD_STATE_ID_SHOW_COLLECTED_STAVE_FRAGMENTS = 6046,
|
||||
WORLD_STATE_ID_COLLECTED_STAVE_FRAGMENTS = 6025
|
||||
};
|
||||
|
||||
enum MapEvents
|
||||
{
|
||||
MAP_EVENT_AZURE_DRAGONSHRINE_ENTERED = 29225
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SUMMON_PHANTOM = 102200
|
||||
};
|
||||
|
||||
std::array<Position const, 2> MurozondSpawnPositions =
|
||||
{
|
||||
Position(4288.125f, -456.40277f, 160.4989f, 2.98451f), // Initial spawn position
|
||||
@@ -69,7 +87,8 @@ public:
|
||||
|
||||
struct instance_end_time_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_end_time_InstanceMapScript(InstanceMap* map) : InstanceScript(map), _killedInfiniteDragonkins(0)
|
||||
instance_end_time_InstanceMapScript(InstanceMap* map) : InstanceScript(map),
|
||||
_killedInfiniteDragonkins(0), _collectedStaffFragments(0)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
@@ -77,6 +96,25 @@ public:
|
||||
LoadObjectData(creatureData, gameobjectData);
|
||||
}
|
||||
|
||||
void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) override
|
||||
{
|
||||
if (_executedMapEvents.find(eventId) != _executedMapEvents.end())
|
||||
return;
|
||||
|
||||
switch (eventId)
|
||||
{
|
||||
case MAP_EVENT_AZURE_DRAGONSHRINE_ENTERED:
|
||||
if (GetBossState(DATA_ECHO_OF_JAINA) == DONE)
|
||||
break;
|
||||
instance->SetWorldState(WORLD_STATE_ID_SHOW_COLLECTED_STAVE_FRAGMENTS, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_executedMapEvents.insert(eventId);
|
||||
}
|
||||
|
||||
void Create() override
|
||||
{
|
||||
InstanceScript::Create();
|
||||
@@ -157,6 +195,14 @@ public:
|
||||
else if (state == DONE)
|
||||
instance->SpawnGroupSpawn(SPAWN_GROUP_ID_MUROZOND_CHEST);
|
||||
break;
|
||||
case DATA_ECHO_OF_JAINA:
|
||||
if (state == IN_PROGRESS)
|
||||
{
|
||||
instance->SetWorldState(WORLD_STATE_ID_SHOW_COLLECTED_STAVE_FRAGMENTS, 0);
|
||||
if (Creature* circle = GetCreature(DATA_ARCANE_CIRCLE))
|
||||
circle->DespawnOrUnsummon();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -164,6 +210,30 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 /*value*/) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_COLLECTED_FRAGMENT_OF_JAINAS_STAFF:
|
||||
if (GetBossState(DATA_ECHO_OF_JAINA) == DONE)
|
||||
break;
|
||||
|
||||
++_collectedStaffFragments;
|
||||
instance->SetWorldState(WORLD_STATE_ID_COLLECTED_STAVE_FRAGMENTS, _collectedStaffFragments);
|
||||
|
||||
if (_collectedStaffFragments < 16)
|
||||
{
|
||||
if (Creature* circle = GetCreature(DATA_ARCANE_CIRCLE))
|
||||
circle->CastSpell(nullptr, SPELL_SUMMON_PHANTOM);
|
||||
}
|
||||
else
|
||||
instance->SpawnGroupSpawn(SPAWN_GROUP_ID_ECHO_OF_JAINA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
@@ -184,6 +254,9 @@ public:
|
||||
private:
|
||||
EventMap _events;
|
||||
uint8 _killedInfiniteDragonkins;
|
||||
uint8 _collectedStaffFragments;
|
||||
|
||||
std::unordered_set<uint32> _executedMapEvents;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
|
||||
@@ -49,6 +49,7 @@ void AddSC_culling_of_stratholme();
|
||||
void AddSC_instance_culling_of_stratholme();
|
||||
void AddSC_end_time(); //CoT End Time
|
||||
void AddSC_boss_murozond();
|
||||
void AddSC_boss_echo_of_jaina();
|
||||
void AddSC_instance_end_time();
|
||||
void AddSC_instance_well_of_eternity(); //CoT Well of Eternity
|
||||
void AddSC_instance_hour_of_twilight(); //CoT Hour of Twilight
|
||||
@@ -187,6 +188,7 @@ void AddKalimdorScripts()
|
||||
AddSC_instance_culling_of_stratholme();
|
||||
AddSC_end_time(); //CoT End Time
|
||||
AddSC_boss_murozond();
|
||||
AddSC_boss_echo_of_jaina();
|
||||
AddSC_instance_end_time();
|
||||
AddSC_instance_well_of_eternity(); //CoT Well of Eternity
|
||||
AddSC_instance_hour_of_twilight(); //CoT Hour of Twilight
|
||||
|
||||
Reference in New Issue
Block a user