mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-24 02:46:33 +01:00
Core/Scripts: boss The Curator (Karazhan) rework (#19040)
Closes #16099
This commit is contained in:
20
sql/updates/world/3.3.5/2017_02_05_04_world.sql
Normal file
20
sql/updates/world/3.3.5/2017_02_05_04_world.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
UPDATE `creature` SET `position_x`=-11187.9, `position_y`=-1883.373, `position_z`=156.0449, `orientation`=5.375582, `spawndist`=0 WHERE `guid`=135489;
|
||||
UPDATE `creature_template` SET `unit_flags`=33554432, `flags_extra`=256, `ScriptName`='npc_curator_astral_flare' WHERE `entry` IN (17096,19781,19782,19783);
|
||||
|
||||
DELETE FROM `creature_template_addon` WHERE `entry` IN (17096,19781,19782,19783);
|
||||
INSERT INTO `creature_template_addon` (`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES
|
||||
(19781,0,0,0,1,0,30234),
|
||||
(19782,0,0,0,1,0,30234),
|
||||
(19783,0,0,0,1,0,30234),
|
||||
(17096,0,0,0,1,0,30234);
|
||||
|
||||
DELETE FROM `waypoint_data` WHERE `id`=1354890;
|
||||
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||
(1354890, 1, -11172.98, -1902.532, 165.7656, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 2, -11160.56, -1901.736, 165.7654, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 3, -11104.56, -1856.968, 165.7654, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 4, -11114.04, -1864.641, 165.7654, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 5, -11166.35, -1906.356, 165.7654, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 6, -11170.42, -1906.521, 165.7654, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 7, -11180.58, -1892.599, 160.9129, 0, 0, 0, 0, 100, 0),
|
||||
(1354890, 8, -11194.23, -1875.336, 153.5438, 0, 0, 0, 0, 100, 0);
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
*
|
||||
* 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
|
||||
@@ -16,197 +15,177 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Curator
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum Curator
|
||||
enum CuratorSays
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SUMMON = 1,
|
||||
SAY_EVOCATE = 2,
|
||||
SAY_ENRAGE = 3,
|
||||
SAY_KILL = 4,
|
||||
SAY_DEATH = 5,
|
||||
|
||||
//Flare spell info
|
||||
SPELL_ASTRAL_FLARE_PASSIVE = 30234, //Visual effect + Flare damage
|
||||
|
||||
//Curator spell info
|
||||
SPELL_HATEFUL_BOLT = 30383,
|
||||
SPELL_EVOCATION = 30254,
|
||||
SPELL_ENRAGE = 30403, //Arcane Infusion: Transforms Curator and adds damage.
|
||||
SPELL_BERSERK = 26662,
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SUMMON = 1,
|
||||
SAY_EVOCATE = 2,
|
||||
SAY_ENRAGE = 3,
|
||||
SAY_KILL = 4,
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
|
||||
enum CuratorSpells
|
||||
{
|
||||
SPELL_HATEFUL_BOLT = 30383,
|
||||
SPELL_EVOCATION = 30254,
|
||||
SPELL_ARCANE_INFUSION = 30403,
|
||||
SPELL_BERSERK = 26662,
|
||||
SPELL_SUMMON_ASTRAL_FLARE_NE = 30236,
|
||||
SPELL_SUMMON_ASTRAL_FLARE_NW = 30239,
|
||||
SPELL_SUMMON_ASTRAL_FLARE_SE = 30240,
|
||||
SPELL_SUMMON_ASTRAL_FLARE_SW = 30241
|
||||
};
|
||||
|
||||
|
||||
enum CuratorEvents
|
||||
{
|
||||
EVENT_HATEFUL_BOLT = 1,
|
||||
EVENT_SUMMON_ASTRAL_FLARE,
|
||||
EVENT_ARCANE_INFUSION,
|
||||
EVENT_BERSERK
|
||||
};
|
||||
|
||||
class boss_curator : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_curator() : CreatureScript("boss_curator") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
struct boss_curatorAI : public BossAI
|
||||
{
|
||||
return new boss_curatorAI(creature);
|
||||
}
|
||||
|
||||
struct boss_curatorAI : public ScriptedAI
|
||||
{
|
||||
boss_curatorAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
AddTimer = 10000;
|
||||
HatefulBoltTimer = 15000; //This time may be wrong
|
||||
BerserkTimer = 720000; //12 minutes
|
||||
Enraged = false;
|
||||
Evocating = false;
|
||||
}
|
||||
|
||||
uint32 AddTimer;
|
||||
uint32 HatefulBoltTimer;
|
||||
uint32 BerserkTimer;
|
||||
|
||||
bool Enraged;
|
||||
bool Evocating;
|
||||
boss_curatorAI(Creature* creature) : BossAI(creature, DATA_CURATOR), _infused(false) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
_Reset();
|
||||
_infused = false;
|
||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_HATEFUL_BOLT, Seconds(12));
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASTRAL_FLARE, Seconds(10));
|
||||
events.ScheduleEvent(EVENT_BERSERK, Minutes(12));
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
|
||||
{
|
||||
if (!HealthAbovePct(15) && !_infused)
|
||||
{
|
||||
_infused = true;
|
||||
events.ScheduleEvent(EVENT_ARCANE_INFUSION, Milliseconds(1));
|
||||
events.CancelEvent(EVENT_SUMMON_ASTRAL_FLARE);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_HATEFUL_BOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
|
||||
DoCast(target, SPELL_HATEFUL_BOLT);
|
||||
events.Repeat(Seconds(7), Seconds(15));
|
||||
break;
|
||||
case EVENT_ARCANE_INFUSION:
|
||||
DoCastSelf(SPELL_ARCANE_INFUSION, true);
|
||||
break;
|
||||
case EVENT_SUMMON_ASTRAL_FLARE:
|
||||
if (roll_chance_i(50))
|
||||
Talk(SAY_SUMMON);
|
||||
|
||||
DoCastSelf(RAND(SPELL_SUMMON_ASTRAL_FLARE_NE, SPELL_SUMMON_ASTRAL_FLARE_NW, SPELL_SUMMON_ASTRAL_FLARE_SE, SPELL_SUMMON_ASTRAL_FLARE_SW), true);
|
||||
|
||||
if (int32 mana = int32(me->GetMaxPower(POWER_MANA) / 10))
|
||||
{
|
||||
me->ModifyPower(POWER_MANA, -mana);
|
||||
|
||||
if (me->GetPower(POWER_MANA) * 100 / me->GetMaxPower(POWER_MANA) < 10)
|
||||
{
|
||||
Talk(SAY_EVOCATE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCastSelf(SPELL_EVOCATION);
|
||||
}
|
||||
}
|
||||
events.Repeat(Seconds(10));
|
||||
break;
|
||||
case EVENT_BERSERK:
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _infused;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetKarazhanAI<boss_curatorAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_curator_astral_flare : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_curator_astral_flare() : CreatureScript("npc_curator_astral_flare") { }
|
||||
|
||||
struct npc_curator_astral_flareAI : public ScriptedAI
|
||||
{
|
||||
npc_curator_astral_flareAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoZoneInCombat();
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//always decrease BerserkTimer
|
||||
if (BerserkTimer <= diff)
|
||||
{
|
||||
//if evocate, then break evocate
|
||||
if (Evocating)
|
||||
{
|
||||
if (me->HasAura(SPELL_EVOCATION))
|
||||
me->RemoveAurasDueToSpell(SPELL_EVOCATION);
|
||||
|
||||
Evocating = false;
|
||||
}
|
||||
|
||||
//may not be correct SAY (generic hard enrage)
|
||||
Talk(SAY_ENRAGE);
|
||||
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
DoCast(me, SPELL_BERSERK);
|
||||
|
||||
//don't know if he's supposed to do summon/evocate after hard enrage (probably not)
|
||||
Enraged = true;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
if (Evocating)
|
||||
{
|
||||
//not supposed to do anything while evocate
|
||||
if (me->HasAura(SPELL_EVOCATION))
|
||||
return;
|
||||
else
|
||||
Evocating = false;
|
||||
}
|
||||
|
||||
if (!Enraged)
|
||||
{
|
||||
if (AddTimer <= diff)
|
||||
{
|
||||
//Summon Astral Flare
|
||||
Creature* AstralFlare = DoSpawnCreature(17096, float(rand32() % 37), float(rand32() % 37), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
|
||||
Unit* target = NULL;
|
||||
target = SelectTarget(SELECT_TARGET_RANDOM, 0);
|
||||
|
||||
if (AstralFlare && target)
|
||||
{
|
||||
AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false);
|
||||
AstralFlare->AI()->AttackStart(target);
|
||||
}
|
||||
|
||||
//Reduce Mana by 10% of max health
|
||||
if (int32 mana = me->GetMaxPower(POWER_MANA))
|
||||
{
|
||||
mana /= 10;
|
||||
me->ModifyPower(POWER_MANA, -mana);
|
||||
|
||||
//if this get's us below 10%, then we evocate (the 10th should be summoned now)
|
||||
if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10)
|
||||
{
|
||||
Talk(SAY_EVOCATE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(me, SPELL_EVOCATION);
|
||||
Evocating = true;
|
||||
//no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (urand(0, 1) == 0)
|
||||
{
|
||||
Talk(SAY_SUMMON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddTimer = 10000;
|
||||
} else AddTimer -= diff;
|
||||
|
||||
if (!HealthAbovePct(15))
|
||||
{
|
||||
Enraged = true;
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
Talk(SAY_ENRAGE);
|
||||
}
|
||||
}
|
||||
|
||||
if (HatefulBoltTimer <= diff)
|
||||
{
|
||||
if (Enraged)
|
||||
HatefulBoltTimer = 7000;
|
||||
else
|
||||
HatefulBoltTimer = 15000;
|
||||
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
|
||||
DoCast(target, SPELL_HATEFUL_BOLT);
|
||||
} else HatefulBoltTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetKarazhanAI<npc_curator_astral_flareAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_curator()
|
||||
{
|
||||
new boss_curator();
|
||||
new npc_curator_astral_flare();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef DEF_KARAZHAN_H
|
||||
#define DEF_KARAZHAN_H
|
||||
|
||||
#define KZScriptName "instance_karazhan"
|
||||
#define DataHeader "KZ"
|
||||
|
||||
uint32 const EncounterCount = 12;
|
||||
@@ -110,4 +111,10 @@ enum KZMisc
|
||||
OPTIONAL_BOSS_REQUIRED_DEATH_COUNT = 50
|
||||
};
|
||||
|
||||
template<class AI, class T>
|
||||
inline AI* GetKarazhanAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, KZScriptName);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user