Skip to content

Commit

Permalink
SMV: Rework doomwalker using combatai, spell lists and spell scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
killerwife committed Sep 20, 2023
1 parent caec8f7 commit d6b6992
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 154 deletions.
10 changes: 0 additions & 10 deletions sql/scriptdev2/scriptdev2.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1529,16 +1529,6 @@ INSERT INTO script_texts (entry,content_default,sound,type,language,emote,broadc

('-1000156','Bloodmaul Brew? Me favorite!','0','0','0','0','18171','bladespire ogre SAY_BREW_1'),

('-1000159','Do not proceed. You will be eliminated.','11344','1','0','0','20941','doomwalker SAY_AGGRO'),
('-1000160','Tectonic disruption commencing.','11345','1','0','0','20942','doomwalker SAY_EARTHQUAKE_1'),
('-1000161','Magnitude set. Release.','11346','1','0','0','20943','doomwalker SAY_EARTHQUAKE_2'),
('-1000162','Trajectory locked.','11347','1','0','0','20944','doomwalker SAY_OVERRUN_1'),
('-1000163','Engage maximum speed.','11348','1','0','0','20945','doomwalker SAY_OVERRUN_2'),
('-1000164','Threat level zero.','11349','1','0','0','20946','doomwalker SAY_SLAY_1'),
('-1000165','Directive accomplished.','11350','1','0','0','20947','doomwalker SAY_SLAY_2'),
('-1000166','Target exterminated.','11351','1','0','0','20948','doomwalker SAY_SLAY_3'),
('-1000167','System failure in five, f-o-u-r...','11352','1','0','0','20949','doomwalker SAY_DEATH'),

('-1000168','Who dares awaken Aquementas?','0','1','0','0','5465','aquementas AGGRO_YELL_AQUE'),

('-1000169','Muahahahaha! You fool! You''ve released me from my banishment in the interstices between space and time!','0','1','0','0','19468','nether_drake SAY_NIHIL_1'),
Expand Down
2 changes: 2 additions & 0 deletions sql/scriptdev2/spell.sql
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ INSERT INTO spell_scripts(Id, ScriptName) VALUES
(37910,'spell_soaring'),
(37962,'spell_soaring'),
(37968,'spell_soaring'),
(32686,'spell_earthquake_doomwalker'),
(37127,'spell_mark_of_death'),
(42783,'spell_wrath_of_the_astromancer'),
(45043,'spell_power_circle'),
(44006,'spell_teleport_self_akilzon'),
Expand Down
233 changes: 101 additions & 132 deletions src/game/AI/ScriptDevAI/scripts/outland/boss_doomwalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ SDCategory: Shadowmoon Valley
EndScriptData */

#include "AI/ScriptDevAI/include/sc_common.h"
#include "AI/ScriptDevAI/base/CombatAI.h"

enum
{
Expand All @@ -31,17 +32,17 @@ enum
NPC_SHADOWHOOF_SUMMONER = 22859,
NPC_ILLIDARI_SUCCUBUS = 22860,

SAY_AGGRO = -1000159,
SAY_EARTHQUAKE_1 = -1000160,
SAY_EARTHQUAKE_2 = -1000161,
SAY_OVERRUN_1 = -1000162,
SAY_OVERRUN_2 = -1000163,
SAY_SLAY_1 = -1000164,
SAY_SLAY_2 = -1000165,
SAY_SLAY_3 = -1000166,
SAY_DEATH = -1000167,
SAY_AGGRO = 20941,
SAY_EARTHQUAKE_1 = 20942,
SAY_EARTHQUAKE_2 = 20943,
SAY_OVERRUN_1 = 20944,
SAY_OVERRUN_2 = 20945,
SAY_SLAY_1 = 20946,
SAY_SLAY_2 = 20947,
SAY_SLAY_3 = 20948,
SAY_DEATH = 20949,

EMOTE_FRENZY = -1000002,
EMOTE_FRENZY = 1191,

SPELL_EARTHQUAKE = 32686,
SPELL_CRUSH_ARMOR = 33661,
Expand All @@ -59,9 +60,19 @@ enum
POINT_OVERRUN = 1,
};

struct boss_doomwalkerAI : public ScriptedAI
enum DoomwalkerActions
{
boss_doomwalkerAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
DOOMWALKER_ACTION_MAX,
DOOMWALKER_OVERRUN_SPELL,
};

struct boss_doomwalkerAI : public CombatAI
{
boss_doomwalkerAI(Creature* creature) : CombatAI(creature, DOOMWALKER_ACTION_MAX)
{
AddOnKillText(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3);
AddCustomAction(DOOMWALKER_OVERRUN_SPELL, true, [&]() { HandleOverrunDamage(); }, TIMER_COMBAT_COMBAT);
}

uint32 m_uiChainTimer;
uint32 m_uiOverrunTimer;
Expand All @@ -73,76 +84,51 @@ struct boss_doomwalkerAI : public ScriptedAI
GuidVector m_overrunCandidates;
SelectAttackingTargetParams m_overrunParams;

bool m_bHasEnrage;

void Reset() override
{
m_uiArmorTimer = urand(5000, 13000);
m_uiChainTimer = urand(10000, 30000);
m_uiQuakeTimer = urand(25000, 35000);
m_uiOverrunTimer = urand(30000, 45000);

m_bHasEnrage = false;

CombatAI::Reset();
m_overrunTargets = 0;
m_overrunCandidates.clear();

m_overrunParams.range.minRange = 0;
m_overrunParams.range.maxRange = 30;

m_creature->RemoveAurasDueToSpell(SPELL_MARK_OF_DEATH_AURA);

m_creature->SetWalk(true);
SetCombatMovement(true);
SetMeleeEnabled(true);
SetCombatScriptStatus(false);
}

void KilledUnit(Unit* pVictim) override
void KilledUnit(Unit* victim) override
{
if (pVictim->GetTypeId() != TYPEID_PLAYER)
return;

pVictim->CastSpell(pVictim, SPELL_MARK_OF_DEATH_PLAYER, TRIGGERED_OLD_TRIGGERED, nullptr, nullptr, m_creature->GetObjectGuid());

if (urand(0, 4))
CombatAI::KilledUnit(victim);
if (victim->IsPlayer())

This comment has been minimized.

Copy link
@evil-at-wow

evil-at-wow Sep 20, 2023

Contributor

This looks like it's missing a not (!).

This comment has been minimized.

Copy link
@killerwife

killerwife Sep 20, 2023

Author Contributor

Fixed, ty.

return;

switch (urand(0, 2))
{
case 0: DoScriptText(SAY_SLAY_1, m_creature); break;
case 1: DoScriptText(SAY_SLAY_2, m_creature); break;
case 2: DoScriptText(SAY_SLAY_3, m_creature); break;
}
victim->CastSpell(nullptr, SPELL_MARK_OF_DEATH_PLAYER, TRIGGERED_OLD_TRIGGERED, nullptr, nullptr, m_creature->GetObjectGuid());
}

void MovementInform(uint32 movementType, uint32 data) override
{
if (movementType == POINT_MOTION_TYPE && data == POINT_OVERRUN)
{
if (Unit* victim = m_creature->GetVictim())
{
m_creature->MeleeAttackStart(victim);
m_creature->SetTarget(victim);
DoStartMovement(victim);
}
SetCombatScriptStatus(false);
m_creature->RemoveAurasDueToSpell(SPELL_OVERRUN);
DoResetThreat();
}
HandleOverrun();
}

void JustSummoned(Creature* summoned) override
{
m_creature->MeleeAttackStop(m_creature->GetVictim());
SetCombatMovement(false);
SetMeleeEnabled(false);
m_creature->SetTarget(nullptr);
SetCombatScriptStatus(true);
float x, y, z;
summoned->GetNearPoint(m_creature, x, y, z, 0.f, 0.f, summoned->GetAngle(m_creature));
m_creature->GetMotionMaster()->MovePoint(POINT_OVERRUN, x, y, z, FORCED_MOVEMENT_RUN);
m_overrunExecTimer = 250;
ResetTimer(DOOMWALKER_OVERRUN_SPELL, 250);
}

void JustRespawned() override
{
Reset();
CombatAI::JustRespawned();

std::list<Creature*> npcList;
GetCreatureListWithEntryInGrid(npcList, m_creature, NPC_DREADLORD, 200.0f);
Expand All @@ -155,116 +141,99 @@ struct boss_doomwalkerAI : public ScriptedAI
creature->Suicide();
}

void JustDied(Unit* /*pKiller*/) override
void JustDied(Unit* /*killer*/) override
{
DoScriptText(SAY_DEATH, m_creature);
DoBroadcastText(SAY_DEATH, m_creature);
m_creature->RemoveAurasDueToSpell(SPELL_MARK_OF_DEATH_AURA);
}

void Aggro(Unit* /*pWho*/) override
void Aggro(Unit* /*who*/) override
{
DoCastSpellIfCan(m_creature, SPELL_MARK_OF_DEATH_AURA, CAST_TRIGGERED);
DoScriptText(SAY_AGGRO, m_creature);
DoCastSpellIfCan(nullptr, SPELL_MARK_OF_DEATH_AURA, CAST_TRIGGERED);
DoBroadcastText(SAY_AGGRO, m_creature);
}

void UpdateAI(const uint32 uiDiff) override
void HandleOverrun()
{
if (!m_creature->SelectHostileTarget() || !m_creature->GetVictim())
return;

if (GetCombatScriptStatus())
auto fail = [&]()
{
if (m_overrunExecTimer <= uiDiff)
{
m_creature->CastSpell(nullptr, SPELL_OVERRUN_DAMAGE, TRIGGERED_NONE);
m_overrunExecTimer = 250;
}
else
m_overrunExecTimer -= uiDiff;
return;
}

// Spell Enrage, when hp <= 20% gain enrage
if (m_creature->GetHealthPercent() <= 20.0f && !m_bHasEnrage)
{
if (DoCastSpellIfCan(m_creature, SPELL_ENRAGE) == CAST_OK)
{
DoScriptText(EMOTE_FRENZY, m_creature);
m_bHasEnrage = true;
}
}

// Spell Overrun
if (m_uiOverrunTimer < uiDiff)
SetCombatMovement(true, true);
SetMeleeEnabled(true);
SetCombatScriptStatus(false);
m_creature->RemoveAurasDueToSpell(SPELL_OVERRUN);
DoResetThreat();
DisableTimer(DOOMWALKER_OVERRUN_SPELL);
AttackClosestEnemy();
};
if (m_overrunTargets == 0)
{
std::vector<Unit*> targets;
m_creature->SelectAttackingTargets(targets, ATTACKING_TARGET_ALL_SUITABLE, 0, nullptr, SELECT_FLAG_PLAYER | SELECT_FLAG_RANGE_AOE_RANGE, m_overrunParams);
while (targets.size() > COUNT_OVERRUN)
targets.erase(targets.begin() + urand(0, targets.size() - 1));

if (!targets.empty() && DoCastSpellIfCan(nullptr, SPELL_OVERRUN) == CAST_OK)
{
float angle = m_creature->GetAngle(targets[0]);
m_creature->SetFacingTo(angle);
m_creature->SetOrientation(angle);
m_creature->CastSpell(nullptr, SPELL_OVERRUN_TRIGGER_SPAWN, TRIGGERED_OLD_TRIGGERED); // shouldnt be sent to client
DoScriptText(urand(0, 1) ? SAY_OVERRUN_1 : SAY_OVERRUN_2, m_creature);
m_uiOverrunTimer = urand(25000, 40000);
}
fail();
return;
}
else
m_uiOverrunTimer -= uiDiff;

// Spell Earthquake
if (m_uiQuakeTimer < uiDiff)
if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER | SELECT_FLAG_RANGE_AOE_RANGE, m_overrunParams))
{
if (DoCastSpellIfCan(m_creature, SPELL_EARTHQUAKE) == CAST_OK)
{
DoScriptText(urand(0, 1) ? SAY_EARTHQUAKE_1 : SAY_EARTHQUAKE_2, m_creature);
m_uiQuakeTimer = urand(30000, 55000);
}
float angle = m_creature->GetAngle(target);
m_creature->SetFacingTo(angle);
m_creature->SetOrientation(angle);
m_creature->CastSpell(nullptr, SPELL_OVERRUN_TRIGGER_SPAWN, TRIGGERED_OLD_TRIGGERED); // shouldnt be sent to client
DoScriptText(urand(0, 1) ? SAY_OVERRUN_1 : SAY_OVERRUN_2, m_creature);
--m_overrunTargets;
}
else
m_uiQuakeTimer -= uiDiff;
fail();
}

// Spell Chain Lightning
if (m_uiChainTimer < uiDiff)
{
Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, nullptr, SELECT_FLAG_PLAYER);
if (!pTarget)
pTarget = m_creature->GetVictim();

if (pTarget)
{
if (DoCastSpellIfCan(pTarget, SPELL_LIGHTNING_WRATH) == CAST_OK)
m_uiChainTimer = urand(7000, 27000);
}
}
else
m_uiChainTimer -= uiDiff;
void HandleOverrunDamage()
{
m_creature->CastSpell(nullptr, SPELL_OVERRUN_DAMAGE, TRIGGERED_NONE);
}

// Spell Sunder Armor
if (m_uiArmorTimer < uiDiff)
void OnSpellCast(SpellEntry const* spellInfo, Unit* target) override
{
switch (spellInfo->Id)
{
if (DoCastSpellIfCan(m_creature->GetVictim(), SPELL_CRUSH_ARMOR) == CAST_OK)
m_uiArmorTimer = urand(10000, 25000);
case SPELL_OVERRUN:
m_overrunTargets = COUNT_OVERRUN;
HandleOverrun();
break;
case SPELL_ENRAGE:
DoScriptText(EMOTE_FRENZY, m_creature);
break;
case SPELL_EARTHQUAKE:
DoScriptText(urand(0, 1) ? SAY_EARTHQUAKE_1 : SAY_EARTHQUAKE_2, m_creature);
break;
}
else
m_uiArmorTimer -= uiDiff;
}
};

DoMeleeAttackIfReady();
// 32686 - Earthquake
struct EarthquakeDoomwalker : public AuraScript
{
void OnPeriodicTrigger(Aura* /*aura*/, PeriodicTriggerData& data) const override
{
if (urand(0, 1))
data.spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(13360);
}
};

UnitAI* GetAI_boss_doomwalker(Creature* pCreature)
// 37127 - Mark of Death
struct MarkofDeath : public AuraScript
{
return new boss_doomwalkerAI(pCreature);
}
void OnApply(Aura* aura, bool apply) const override
{
if (apply && aura->GetTarget()->HasAura(37128))
aura->GetTarget()->CastSpell(nullptr, 37131, TRIGGERED_OLD_TRIGGERED);
}
};

void AddSC_boss_doomwalker()
{
Script* pNewScript = new Script;
pNewScript->Name = "boss_doomwalker";
pNewScript->GetAI = &GetAI_boss_doomwalker;
pNewScript->GetAI = &GetNewAIInstance<boss_doomwalkerAI>;
pNewScript->RegisterSelf();

RegisterSpellScript<EarthquakeDoomwalker>("spell_earthquake_doomwalker");
RegisterSpellScript<MarkofDeath>("spell_mark_of_death");
}
12 changes: 0 additions & 12 deletions src/game/Spells/SpellAuras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1439,10 +1439,6 @@ void Aura::TriggerSpell()
}
// // Teleport Test
// case 32236: break;
case 32686: // Earthquake
if (urand(0, 1)) // 50% chance to trigger
triggerTarget->CastSpell(nullptr, 13360, TRIGGERED_OLD_TRIGGERED);
break;
// // Possess
// case 33401: break;
// // Draw Shadows
Expand Down Expand Up @@ -1559,8 +1555,6 @@ void Aura::TriggerSpell()
else
return;
break;
// // Mark of Death
// case 37125: break;
case 37268: // Arcane Flurry (Melee Component)
{
trigger_spell_id = 37271; // (Range Component, parentspell 37269)
Expand Down Expand Up @@ -2228,12 +2222,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
target->CastSpell(nullptr, 25473, TRIGGERED_OLD_TRIGGERED);
return;
}
case 37127: // Mark of Death
{
if (target->HasAura(37128))
target->CastSpell(target, 37131, TRIGGERED_OLD_TRIGGERED, nullptr, nullptr, GetCasterGuid());
return;
}
case 26681: // Cologne
{
if (Unit* target = GetTarget())
Expand Down

0 comments on commit d6b6992

Please sign in to comment.