Scripts/Drak'Tharon Keep: Modernize scripts (#30993)

(cherry picked from commit 7e03a1ce05baf33f8810658a679733c5e3626760)
This commit is contained in:
offl
2026-06-23 22:44:05 +02:00
committed by Shauren
parent c06a63a6ad
commit fa22929ebb
5 changed files with 220 additions and 213 deletions
@@ -0,0 +1,4 @@
--
DELETE FROM `creature_text` WHERE `CreatureID` = 27483;
INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
(27483,0,0,'%s raises his talons menacingly!',41,0,100,0,0,0,26745,0,'King Dred EMOTE_SLASH');
@@ -15,93 +15,112 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Comment: MAYBE need more improve the "Raptor Call".
*/
#include "ScriptMgr.h"
#include "drak_tharon_keep.h"
#include "Containers.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
enum Spells
enum DredTexts
{
SPELL_BELLOWING_ROAR = 22686, // fears the group, can be resisted/dispelled
SPELL_GRIEVOUS_BITE = 48920,
SPELL_MANGLING_SLASH = 48873, // cast on the current tank, adds debuf
SPELL_FEARSOME_ROAR = 48849,
SPELL_PIERCING_SLASH = 48878, // debuff --> Armor reduced by 75%
SPELL_RAPTOR_CALL = 59416, // dummy
SPELL_GUT_RIP = 49710,
SPELL_REND = 13738
EMOTE_SLASH = 0
};
enum Misc
enum DredSpells
{
ACTION_RAPTOR_KILLED = 1,
DATA_RAPTORS_KILLED = 2
// Dred
SPELL_BELLOWING_ROAR = 22686,
SPELL_GRIEVOUS_BITE = 48920,
SPELL_FEARSOME_ROAR = 48849,
SPELL_RAPTOR_CALL = 59416,
SPELL_MULTI_SLASH = 48856,
SPELL_PIERCING_SLASH = 48878,
SPELL_MANGLING_SLASH = 48873,
// Raptors
SPELL_GUT_RIP = 49710,
SPELL_REND = 13738
};
enum Events
enum DredEvents
{
EVENT_BELLOWING_ROAR = 1,
EVENT_BELLOWING_ROAR = 1,
EVENT_GRIEVOUS_BITE,
EVENT_MANGLING_SLASH,
EVENT_FEARSOME_ROAR,
EVENT_RAPTOR_CALL,
EVENT_MULTI_SLASH,
EVENT_PIERCING_SLASH,
EVENT_RAPTOR_CALL
EVENT_MANGLING_SLASH
};
enum DredMisc
{
ACTION_RAPTOR_KILLED = 1,
DATA_RAPTORS_KILLED = 2
};
// 27483 - King Dred
struct boss_king_dred : public BossAI
{
boss_king_dred(Creature* creature) : BossAI(creature, DATA_KING_DRED)
{
Initialize();
}
void Initialize()
{
raptorsKilled = 0;
}
boss_king_dred(Creature* creature) : BossAI(creature, DATA_KING_DRED), _raptorsKilled(0) { }
void Reset() override
{
Initialize();
_Reset();
_raptorsKilled = 0;
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_BELLOWING_ROAR, 33s);
events.ScheduleEvent(EVENT_GRIEVOUS_BITE, 20s);
events.ScheduleEvent(EVENT_MANGLING_SLASH, 18500ms);
events.ScheduleEvent(EVENT_BELLOWING_ROAR, 15s, 25s);
events.ScheduleEvent(EVENT_GRIEVOUS_BITE, 15s, 20s);
events.ScheduleEvent(EVENT_FEARSOME_ROAR, 10s, 20s);
events.ScheduleEvent(EVENT_PIERCING_SLASH, 15s);
events.ScheduleEvent(EVENT_RAPTOR_CALL, 20s, 25s);
events.ScheduleEvent(EVENT_RAPTOR_CALL, 15s, 20s);
events.ScheduleEvent(EVENT_MULTI_SLASH, 18s, 22s);
}
void OnSpellCast(SpellInfo const* spell) override
{
if (spell->Id == SPELL_MULTI_SLASH)
Talk(EMOTE_SLASH);
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_MULTI_SLASH)
{
events.ScheduleEvent(EVENT_PIERCING_SLASH, 1s);
events.ScheduleEvent(EVENT_MANGLING_SLASH, 3s);
}
if (spellInfo->Id == SPELL_RAPTOR_CALL)
{
/// @todo: This is wrong. Engage nearby alive not yet engaged raptor instead
float x, y, z;
me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 10.0f);
me->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1s);
}
}
void DoAction(int32 action) override
{
if (action == ACTION_RAPTOR_KILLED)
++raptorsKilled;
++_raptorsKilled;
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_RAPTORS_KILLED)
return raptorsKilled;
return _raptorsKilled;
return 0;
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -118,32 +137,29 @@ struct boss_king_dred : public BossAI
{
case EVENT_BELLOWING_ROAR:
DoCastAOE(SPELL_BELLOWING_ROAR);
events.ScheduleEvent(EVENT_BELLOWING_ROAR, 33s);
events.Repeat(15s, 20s);
break;
case EVENT_GRIEVOUS_BITE:
DoCastVictim(SPELL_GRIEVOUS_BITE);
events.ScheduleEvent(EVENT_GRIEVOUS_BITE, 20s);
break;
case EVENT_MANGLING_SLASH:
DoCastVictim(SPELL_MANGLING_SLASH);
events.ScheduleEvent(EVENT_MANGLING_SLASH, 18500ms);
events.Repeat(20s);
break;
case EVENT_FEARSOME_ROAR:
DoCastAOE(SPELL_FEARSOME_ROAR);
events.ScheduleEvent(EVENT_FEARSOME_ROAR, 10s, 20s);
events.Repeat(10s, 20s);
break;
case EVENT_RAPTOR_CALL:
DoCastSelf(SPELL_RAPTOR_CALL);
events.Repeat(30s);
break;
case EVENT_MULTI_SLASH:
DoCastSelf(SPELL_MULTI_SLASH);
events.Repeat(18s, 22s);
break;
case EVENT_PIERCING_SLASH:
DoCastVictim(SPELL_PIERCING_SLASH);
events.ScheduleEvent(EVENT_PIERCING_SLASH, 15s);
break;
case EVENT_RAPTOR_CALL:
DoCastVictim(SPELL_RAPTOR_CALL);
float x, y, z;
me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 10.0f);
me->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1s);
events.ScheduleEvent(EVENT_RAPTOR_CALL, 20s, 25s);
case EVENT_MANGLING_SLASH:
DoCastVictim(SPELL_MANGLING_SLASH);
break;
default:
break;
@@ -155,29 +171,32 @@ struct boss_king_dred : public BossAI
}
private:
uint8 raptorsKilled;
uint8 _raptorsKilled;
};
// 26641 - Drakkari Gutripper
struct npc_drakkari_gutripper : public ScriptedAI
{
npc_drakkari_gutripper(Creature* creature) : ScriptedAI(creature)
{
Initialize();
instance = me->GetInstanceScript();
}
void Initialize()
{
GutRipTimer = urand(10000, 15000);
}
InstanceScript* instance;
uint32 GutRipTimer;
npc_drakkari_gutripper(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void Reset() override
{
Initialize();
_scheduler.CancelAll();
}
void JustEngagedWith(Unit* /*who*/) override
{
_scheduler.Schedule(10s, 15s, [this](TaskContext& task)
{
DoCastVictim(SPELL_GUT_RIP);
task.Repeat(10s, 15s);
});
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* dred = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_KING_DRED)))
dred->AI()->DoAction(ACTION_RAPTOR_KILLED);
}
void UpdateAI(uint32 diff) override
@@ -185,42 +204,37 @@ struct npc_drakkari_gutripper : public ScriptedAI
if (!UpdateVictim())
return;
if (GutRipTimer <= diff)
{
DoCastVictim(SPELL_GUT_RIP, false);
GutRipTimer = urand(10000, 15000);
}
else
GutRipTimer -= diff;
_scheduler.Update(diff);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* Dred = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KING_DRED)))
Dred->AI()->DoAction(ACTION_RAPTOR_KILLED);
}
private:
TaskScheduler _scheduler;
InstanceScript* _instance;
};
// 26628 - Drakkari Scytheclaw
struct npc_drakkari_scytheclaw : public ScriptedAI
{
npc_drakkari_scytheclaw(Creature* creature) : ScriptedAI(creature)
{
Initialize();
instance = me->GetInstanceScript();
}
void Initialize()
{
uiRendTimer = urand(10000, 15000);
}
InstanceScript* instance;
uint32 uiRendTimer;
npc_drakkari_scytheclaw(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void Reset() override
{
Initialize();
_scheduler.CancelAll();
}
void JustEngagedWith(Unit* /*who*/) override
{
_scheduler.Schedule(10s, 15s, [this](TaskContext& task)
{
DoCastVictim(SPELL_REND);
task.Repeat(10s, 15s);
});
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* dred = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_KING_DRED)))
dred->AI()->DoAction(ACTION_RAPTOR_KILLED);
}
void UpdateAI(uint32 diff) override
@@ -228,20 +242,12 @@ struct npc_drakkari_scytheclaw : public ScriptedAI
if (!UpdateVictim())
return;
if (uiRendTimer <= diff)
{
DoCastVictim(SPELL_REND, false);
uiRendTimer = urand(10000, 15000);
}
else
uiRendTimer -= diff;
_scheduler.Update(diff);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* Dred = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KING_DRED)))
Dred->AI()->DoAction(ACTION_RAPTOR_KILLED);
}
private:
TaskScheduler _scheduler;
InstanceScript* _instance;
};
class achievement_king_dred : public AchievementCriteriaScript
@@ -24,7 +24,7 @@
#include "ScriptedCreature.h"
#include "SpellScript.h"
enum Yells
enum NovosTexts
{
SAY_AGGRO = 0,
SAY_KILL = 1,
@@ -34,7 +34,7 @@ enum Yells
EMOTE_SUMMONING_ADDS = 5 // unused
};
enum Spells
enum NovosSpells
{
SPELL_BEAM_CHANNEL = 52106,
SPELL_ARCANE_FIELD = 47346,
@@ -52,7 +52,7 @@ enum Spells
SPELL_SUMMON_MINIONS = 59910
};
enum Misc
enum NovosMisc
{
ACTION_RESET_CRYSTALS,
ACTION_ACTIVATE_CRYSTAL,
@@ -77,6 +77,7 @@ const SummonerInfo summoners[] =
#define MAX_Y_COORD_OH_NOVOS -771.95f
// 26631 - Novos the Summoner
struct boss_novos : public BossAI
{
boss_novos(Creature* creature) : BossAI(creature, DATA_NOVOS)
@@ -148,12 +149,12 @@ struct boss_novos : public BossAI
{
case EVENT_SUMMON_MINIONS:
DoCast(SPELL_SUMMON_MINIONS);
events.ScheduleEvent(EVENT_SUMMON_MINIONS, 15s);
events.Repeat(15s);
break;
case EVENT_ATTACK:
if (Unit* victim = SelectTarget(SelectTargetMethod::Random))
DoCast(victim, RAND(SPELL_ARCANE_BLAST, SPELL_BLIZZARD, SPELL_FROSTBOLT, SPELL_WRATH_OF_MISERY));
events.ScheduleEvent(EVENT_ATTACK, 3s);
events.Repeat(3s);
break;
default:
break;
@@ -291,6 +292,7 @@ private:
bool _bubbled;
};
// 26712 - Crystal Channel Target
struct npc_crystal_channel_target : public ScriptedAI
{
npc_crystal_channel_target(Creature* creature) : ScriptedAI(creature)
@@ -354,17 +356,6 @@ private:
uint32 _temp;
};
class achievement_oh_novos : public AchievementCriteriaScript
{
public:
achievement_oh_novos() : AchievementCriteriaScript("achievement_oh_novos") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
return target && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(DATA_NOVOS_ACHIEV);
}
};
// 59910 - Summon Minions
class spell_novos_summon_minions : public SpellScript
{
@@ -385,6 +376,17 @@ class spell_novos_summon_minions : public SpellScript
}
};
class achievement_oh_novos : public AchievementCriteriaScript
{
public:
achievement_oh_novos() : AchievementCriteriaScript("achievement_oh_novos") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
return target && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(DATA_NOVOS_ACHIEV);
}
};
void AddSC_boss_novos()
{
RegisterDrakTharonKeepCreatureAI(boss_novos);
@@ -15,16 +15,25 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Known Issues: Spell 49356 and 53463 will be interrupted for an unknown reason
*/
#include "ScriptMgr.h"
#include "drak_tharon_keep.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
/*
* Known Issues: Spell 49356 and 53463 will be interrupted for an unknown reason
*/
enum TharonjaTexts
{
SAY_AGGRO = 0,
SAY_KILL = 1,
SAY_FLESH = 2,
SAY_SKELETON = 3,
SAY_DEATH = 4
};
enum Spells
enum TharonjaSpells
{
// Skeletal Spells (phase 1)
SPELL_CURSE_OF_LIFE = 49527,
@@ -43,7 +52,7 @@ enum Spells
SPELL_DUMMY = 49551
};
enum Events
enum TharonjaEvents
{
EVENT_CURSE_OF_LIFE = 1,
EVENT_RAIN_OF_FIRE,
@@ -59,20 +68,12 @@ enum Events
EVENT_GOING_SKELETAL
};
enum Yells
{
SAY_AGGRO = 0,
SAY_KILL = 1,
SAY_FLESH = 2,
SAY_SKELETON = 3,
SAY_DEATH = 4
};
enum Models
enum TharonjaMisc
{
MODEL_FLESH = 27073
};
// 26632 - The Prophet Tharon'ja
struct boss_tharon_ja : public BossAI
{
boss_tharon_ja(Creature* creature) : BossAI(creature, DATA_THARON_JA) { }
@@ -126,30 +127,30 @@ struct boss_tharon_ja : public BossAI
case EVENT_CURSE_OF_LIFE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_CURSE_OF_LIFE);
events.ScheduleEvent(EVENT_CURSE_OF_LIFE, 10s, 15s);
events.Repeat(10s, 15s);
return;
case EVENT_SHADOW_VOLLEY:
DoCastVictim(SPELL_SHADOW_VOLLEY);
events.ScheduleEvent(EVENT_SHADOW_VOLLEY, 8s, 10s);
events.Repeat(8s, 10s);
return;
case EVENT_RAIN_OF_FIRE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_RAIN_OF_FIRE);
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 14s, 18s);
events.Repeat(14s, 18s);
return;
case EVENT_LIGHTNING_BREATH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_LIGHTNING_BREATH);
events.ScheduleEvent(EVENT_LIGHTNING_BREATH, 6s, 7s);
events.Repeat(6s, 7s);
return;
case EVENT_EYE_BEAM:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_EYE_BEAM);
events.ScheduleEvent(EVENT_EYE_BEAM, 4s, 6s);
events.Repeat(4s, 6s);
return;
case EVENT_POISON_CLOUD:
DoCastAOE(SPELL_POISON_CLOUD);
events.ScheduleEvent(EVENT_POISON_CLOUD, 10s, 12s);
events.Repeat(10s, 12s);
return;
case EVENT_DECAY_FLESH:
DoCastAOE(SPELL_DECAY_FLESH);
@@ -24,7 +24,16 @@
#include "SpellAuraEffects.h"
#include "SpellScript.h"
enum Spells
enum TrollgoreTexts
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_CONSUME = 2,
SAY_EXPLODE = 3,
SAY_DEATH = 4
};
enum TrollgoreSpells
{
SPELL_INFECTED_WOUND = 49637,
SPELL_CRUSH = 49639,
@@ -43,48 +52,32 @@ enum Spells
#define SPELL_CONSUME_BUFF_HELPER DUNGEON_MODE<uint32>(SPELL_CONSUME_BUFF, SPELL_CONSUME_BUFF_H)
enum Yells
enum TrollgoreEvents
{
SAY_AGGRO = 0,
SAY_KILL = 1,
SAY_CONSUME = 2,
SAY_EXPLODE = 3,
SAY_DEATH = 4
};
enum Misc
{
DATA_CONSUMPTION_JUNCTION = 1,
POINT_LANDING = 1
};
enum Events
{
EVENT_CONSUME = 1,
EVENT_CONSUME = 1,
EVENT_CRUSH,
EVENT_INFECTED_WOUND,
EVENT_CORPSE_EXPLODE,
EVENT_SPAWN
};
enum TrollgoreMisc
{
DATA_CONSUMPTION_JUNCTION = 1,
POINT_LANDING = 1
};
Position const Landing = { -263.0534f, -660.8658f, 26.50903f, 0.0f };
// 26630 - Trollgore
struct boss_trollgore : public BossAI
{
boss_trollgore(Creature* creature) : BossAI(creature, DATA_TROLLGORE)
{
Initialize();
}
void Initialize()
{
_consumptionJunction = true;
}
boss_trollgore(Creature* creature) : BossAI(creature, DATA_TROLLGORE), _consumptionJunction(true) { }
void Reset() override
{
_Reset();
Initialize();
_consumptionJunction = true;
}
void JustEngagedWith(Unit* who) override
@@ -99,6 +92,34 @@ struct boss_trollgore : public BossAI
events.ScheduleEvent(EVENT_SPAWN, 30s, 40s);
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_CONSUMPTION_JUNCTION)
return _consumptionJunction ? 1 : 0;
return 0;
}
void JustSummoned(Creature* summon) override
{
summon->GetMotionMaster()->MovePoint(POINT_LANDING, Landing);
summons.Summon(summon);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -116,20 +137,20 @@ struct boss_trollgore : public BossAI
case EVENT_CONSUME:
Talk(SAY_CONSUME);
DoCastAOE(SPELL_CONSUME);
events.ScheduleEvent(EVENT_CONSUME, 15s);
events.Repeat(15s);
break;
case EVENT_CRUSH:
DoCastVictim(SPELL_CRUSH);
events.ScheduleEvent(EVENT_CRUSH, 10s, 15s);
events.Repeat(10s, 15s);
break;
case EVENT_INFECTED_WOUND:
DoCastVictim(SPELL_INFECTED_WOUND);
events.ScheduleEvent(EVENT_INFECTED_WOUND, 25s, 35s);
events.Repeat(25s, 35s);
break;
case EVENT_CORPSE_EXPLODE:
Talk(SAY_EXPLODE);
DoCastAOE(SPELL_CORPSE_EXPLODE);
events.ScheduleEvent(EVENT_CORPSE_EXPLODE, 15s, 19s);
events.Repeat(15s, 19s);
break;
case EVENT_SPAWN:
for (uint8 i = 0; i < 3; ++i)
@@ -137,7 +158,7 @@ struct boss_trollgore : public BossAI
trigger->CastSpell(trigger, RAND(SPELL_SUMMON_INVADER_A, SPELL_SUMMON_INVADER_B, SPELL_SUMMON_INVADER_C), CastSpellExtraArgs(TRIGGERED_FULL_MASK)
.SetOriginalCaster(me->GetGUID()));
events.ScheduleEvent(EVENT_SPAWN, 30s, 40s);
events.Repeat(30s, 40s);
break;
default:
break;
@@ -155,38 +176,11 @@ struct boss_trollgore : public BossAI
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_CONSUMPTION_JUNCTION)
return _consumptionJunction ? 1 : 0;
return 0;
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_KILL);
}
void JustSummoned(Creature* summon) override
{
summon->GetMotionMaster()->MovePoint(POINT_LANDING, Landing);
summons.Summon(summon);
}
private:
bool _consumptionJunction;
private:
bool _consumptionJunction;
};
// 27709, 27753, 27754 - Drakkari Invader
struct npc_drakkari_invader : public ScriptedAI
{
npc_drakkari_invader(Creature* creature) : ScriptedAI(creature) { }