Skip to content

Commit

Permalink
Mechanar: Modernize pathaleon the calculator with spell lists and spe…
Browse files Browse the repository at this point in the history
…ll scripts

cmangos/issues#3444
  • Loading branch information
killerwife committed Sep 28, 2023
1 parent e5c8bfa commit 84deb19
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 161 deletions.
4 changes: 4 additions & 0 deletions sql/base/dbc/cmangos_fixes/Spell.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3003,6 +3003,10 @@ INSERT INTO spell_template(Id, Category, Dispel, Mechanic, Attributes, Attribute
('34707', '0', '0', '0', '400', '268435456', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '101', '0', '0', '0', '0', '21', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '-1', '0', '0', '6', '6', '6', '0', '1', '1', '0', '0', '0', '0', '-501', '499', '0', '0', '0', '1', '1', '1', '0', '0', '0', '0', '0', '0', '56', '22', '22', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '19931', '32', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '53', '0', '0', 'Laj (Nature)', '', '', '', '', '', '', '', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '0', '0', '0', '0', '0', '0', '1', '0', '0'),
('34710', '0', '0', '0', '400', '268435456', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '101', '0', '0', '0', '0', '21', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '-1', '0', '0', '6', '6', '6', '0', '1', '1', '0', '0', '0', '0', '-501', '499', '0', '0', '0', '1', '1', '1', '0', '0', '0', '0', '0', '0', '56', '22', '22', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '17980', '32', '32', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '53', '0', '0', 'Laj (Shadow)', '', '', '', '', '', '', '', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '0', '0', '0', '0', '0', '0', '1', '0', '0');

-- Pathaleon the Calculator summon spell
INSERT INTO spell_template(Id, Category, Dispel, Mechanic, Attributes, AttributesEx, AttributesEx2, AttributesEx3, AttributesEx4, AttributesEx5, AttributesEx6, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, CasterAuraState, TargetAuraState, CasterAuraStateNot, TargetAuraStateNot, CastingTimeIndex, RecoveryTime, CategoryRecoveryTime, InterruptFlags, AuraInterruptFlags, ChannelInterruptFlags, ProcFlags, ProcChance, ProcCharges, MaxLevel, BaseLevel, SpellLevel, DurationIndex, PowerType, ManaCost, ManaCostPerlevel, ManaPerSecond, ManaPerSecondPerLevel, RangeIndex, Speed, ModalNextSpell, StackAmount, Totem1, Totem2, Reagent1, Reagent2, Reagent3, Reagent4, Reagent5, Reagent6, Reagent7, Reagent8, ReagentCount1, ReagentCount2, ReagentCount3, ReagentCount4, ReagentCount5, ReagentCount6, ReagentCount7, ReagentCount8, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, Effect1, Effect2, Effect3, EffectDieSides1, EffectDieSides2, EffectDieSides3, EffectRealPointsPerLevel1, EffectRealPointsPerLevel2, EffectRealPointsPerLevel3, EffectBasePoints1, EffectBasePoints2, EffectBasePoints3, EffectMechanic1, EffectMechanic2, EffectMechanic3, EffectImplicitTargetA1, EffectImplicitTargetA2, EffectImplicitTargetA3, EffectImplicitTargetB1, EffectImplicitTargetB2, EffectImplicitTargetB3, EffectRadiusIndex1, EffectRadiusIndex2, EffectRadiusIndex3, EffectApplyAuraName1, EffectApplyAuraName2, EffectApplyAuraName3, EffectAmplitude1, EffectAmplitude2, EffectAmplitude3, EffectMultipleValue1, EffectMultipleValue2, EffectMultipleValue3, EffectChainTarget1, EffectChainTarget2, EffectChainTarget3, EffectItemType1, EffectItemType2, EffectItemType3, EffectMiscValue1, EffectMiscValue2, EffectMiscValue3, EffectMiscValueB1, EffectMiscValueB2, EffectMiscValueB3, EffectTriggerSpell1, EffectTriggerSpell2, EffectTriggerSpell3, EffectPointsPerComboPoint1, EffectPointsPerComboPoint2, EffectPointsPerComboPoint3, SpellVisual, SpellIconID, ActiveIconID, SpellPriority, SpellName, SpellName2, SpellName3, SpellName4, SpellName5, SpellName6, SpellName7, SpellName8, SpellName9, SpellName10, SpellName11, SpellName12, SpellName13, SpellName14, SpellName15, SpellName16, Rank1, Rank2, Rank3, Rank4, Rank5, Rank6, Rank7, Rank8, Rank9, Rank10, Rank11, Rank12, Rank13, Rank14, Rank15, Rank16, ManaCostPercentage, StartRecoveryCategory, StartRecoveryTime, MaxTargetLevel, SpellFamilyName, SpellFamilyFlags, MaxAffectedTargets, DmgClass, PreventionType, StanceBarOrder, DmgMultiplier1, DmgMultiplier2, DmgMultiplier3, MinFactionId, MinReputation, RequiredAuraVision, TotemCategory1, TotemCategory2, AreaId, SchoolMask, IsServerSide, AttributesServerside) VALUES
('35284', '0', '0', '0', '256', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '101', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '-1', '0', '0', '77', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1489', '0', '0', 'Summon Nether Wraiths', '', '', '', '', '', '', '', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '64', '0', '0');

-- ============================================================
-- WOTLK section
-- ============================================================
Expand Down
1 change: 1 addition & 0 deletions sql/scriptdev2/spell.sql
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ INSERT INTO spell_scripts(Id, ScriptName) VALUES
(31531,'spell_summon_gnomes'),
(31532,'spell_repair_mekgineer'),
(37936,'spell_repair_mekgineer'),
(35284,'spell_summon_nether_wraiths'),
(35781,'spell_countercharge'),
(37866,'spell_summon_water_globules'),
(38028,'spell_watery_grave'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ EndScriptData */

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

enum
{
Expand All @@ -40,236 +41,130 @@ enum
SPELL_ARCANE_TORRENT = 36022,
SPELL_DOMINATION = 35280,
SPELL_ARCANE_EXPLOSION_H = 15453,
SPELL_FRENZY = 36992,
SPELL_ENRAGE = 36992,
SPELL_SUICIDE = 35301, // kill the Nether Wraiths
SPELL_DISGRUNTLED_ANGER = 35289, // empower a Nether Wraith

SPELL_SUMMON_NETHER_WRAITH_1 = 35285,
SPELL_SUMMON_NETHER_WRAITH_2 = 35286,
SPELL_SUMMON_NETHER_WRAITH_2 = 35286, // not used post nerf it seems
SPELL_SUMMON_NETHER_WRAITH_3 = 35287,
SPELL_SUMMON_NETHER_WRAITH_4 = 35288,

SPELL_SUMMON_NETHER_WRAITHS = 35284,

// Add Spells
SPELL_DETONATION = 35058,
SPELL_ARCANE_BOLT = 20720,
};

static const uint32 aWraithSummonSpells[4] = {SPELL_SUMMON_NETHER_WRAITH_1, SPELL_SUMMON_NETHER_WRAITH_2, SPELL_SUMMON_NETHER_WRAITH_3, SPELL_SUMMON_NETHER_WRAITH_4};
static const uint32 aWraithSummonSpells[4] = {SPELL_SUMMON_NETHER_WRAITH_1/*, SPELL_SUMMON_NETHER_WRAITH_2*/, SPELL_SUMMON_NETHER_WRAITH_3, SPELL_SUMMON_NETHER_WRAITH_4};

struct boss_pathaleon_the_calculatorAI : public ScriptedAI
struct boss_pathaleon_the_calculatorAI : public CombatAI
{
boss_pathaleon_the_calculatorAI(Creature* pCreature) : ScriptedAI(pCreature)
boss_pathaleon_the_calculatorAI(Creature* creature) : CombatAI(creature, 0), m_instance(static_cast<ScriptedInstance*>(creature->GetInstanceData())),
m_isRegularMode(creature->GetMap()->IsRegularDifficulty())
{
m_pInstance = static_cast<ScriptedInstance*>(pCreature->GetInstanceData());
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
m_creature->GetCombatManager().SetLeashingDisable(true);
Reset();
AddOnKillText(SAY_SLAY_1, SAY_SLAY_2);
}

ScriptedInstance* m_pInstance;
bool m_bIsRegularMode;

uint32 m_uiSummonTimer;
uint32 m_uiAngerTimer;
uint32 m_uiManaTapTimer;
uint32 m_uiArcaneTorrentTimer;
uint32 m_uiDominationTimer;
uint32 m_uiArcaneExplosionTimer;
bool m_bIsEnraged;

void Reset() override
{
m_uiSummonTimer = urand(12000, 23000);
m_uiAngerTimer = urand(31000, 42000);
m_uiManaTapTimer = urand(2000, 9000);
m_uiArcaneTorrentTimer = urand(11000, 24000);
m_uiDominationTimer = urand(25000, 40000);
m_uiArcaneExplosionTimer = urand(18000, 45000);
m_bIsEnraged = false;
}
ScriptedInstance* m_instance;
bool m_isRegularMode;

void Aggro(Unit* /*pWho*/) override
void Aggro(Unit* /*who*/) override
{
DoBroadcastText(SAY_AGGRO, m_creature);
}

void KilledUnit(Unit* /*pVictim*/) override
{
DoBroadcastText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, m_creature);
}

void JustDied(Unit* /*pKiller*/) override
void JustDied(Unit* /*killer*/) override
{
DoBroadcastText(SAY_DEATH, m_creature);

m_creature->RemoveGuardians();

if (m_pInstance)
m_pInstance->SetData(TYPE_PATHALEON, DONE);
if (m_instance)
m_instance->SetData(TYPE_PATHALEON, DONE);
}

void JustReachedHome() override
{
m_creature->RemoveGuardians();

if (m_pInstance)
m_pInstance->SetData(TYPE_PATHALEON, FAIL);
if (m_instance)
m_instance->SetData(TYPE_PATHALEON, FAIL);
}

void JustSummoned(Creature* pSummoned) override
void JustSummoned(Creature* summoned) override
{
if (m_creature->GetVictim())
pSummoned->AI()->AttackStart(m_creature->GetVictim());
summoned->SetInCombatWithZone();
summoned->AI()->AttackClosestEnemy();
}

void UpdateAI(const uint32 uiDiff) override
void OnSpellCast(SpellEntry const* spellInfo, Unit* target) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->GetVictim())
return;

if (m_uiManaTapTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_MANA_TAP, SELECT_FLAG_PLAYER | SELECT_FLAG_POWER_MANA))
{
if (DoCastSpellIfCan(pTarget, SPELL_MANA_TAP) == CAST_OK)
m_uiManaTapTimer = urand(16000, 34000);
}
}
else
m_uiManaTapTimer -= uiDiff;

if (m_uiArcaneTorrentTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_ARCANE_TORRENT) == CAST_OK)
m_uiArcaneTorrentTimer = urand(40000, 52000);
}
else
m_uiArcaneTorrentTimer -= uiDiff;

if (m_uiDominationTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, nullptr, SELECT_FLAG_PLAYER))
{
if (DoCastSpellIfCan(pTarget, SPELL_DOMINATION) == CAST_OK)
{
DoBroadcastText(urand(0, 1) ? SAY_DOMINATION_1 : SAY_DOMINATION_2, m_creature);
m_uiDominationTimer = urand(25000, 30000);
}
}
}
else
m_uiDominationTimer -= uiDiff;

// Only casting if Heroic Mode is used
if (!m_bIsRegularMode)
switch (spellInfo->Id)
{
if (m_uiArcaneExplosionTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_ARCANE_EXPLOSION_H) == CAST_OK)
m_uiArcaneExplosionTimer = urand(13000, 25000);
}
else
m_uiArcaneExplosionTimer -= uiDiff;
}

if (!m_bIsEnraged && m_creature->GetHealthPercent() < 21.0f)
{
if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
{
DoCastSpellIfCan(m_creature, SPELL_SUICIDE, CAST_TRIGGERED);
case SPELL_DOMINATION:
DoBroadcastText(urand(0, 1) ? SAY_DOMINATION_1 : SAY_DOMINATION_2, m_creature);
break;
case SPELL_ENRAGE:
DoCastSpellIfCan(nullptr, SPELL_SUICIDE, CAST_TRIGGERED);
DoBroadcastText(SAY_ENRAGE, m_creature);
m_bIsEnraged = true;
}
}

// Summon and empower Nether Wraiths only when not enraged
if (!m_bIsEnraged)
{
if (m_uiSummonTimer < uiDiff)
{
uint8 uiMaxWraith = urand(3, 4);
for (uint8 i = 0; i < uiMaxWraith; ++i)
DoCastSpellIfCan(m_creature, aWraithSummonSpells[i], CAST_TRIGGERED);

break;
case SPELL_SUMMON_NETHER_WRAITHS:
DoBroadcastText(SAY_SUMMON, m_creature);
m_uiSummonTimer = urand(45000, 50000);
}
else
m_uiSummonTimer -= uiDiff;

if (m_uiAngerTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_DISGRUNTLED_ANGER) == CAST_OK)
m_uiAngerTimer = urand(55000, 84000);
}
else
m_uiAngerTimer -= uiDiff;
break;
}

DoMeleeAttackIfReady();
}
};

struct mob_nether_wraithAI : public ScriptedAI
{
mob_nether_wraithAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}

uint32 m_uiArcaneMissilesTimer;

void Reset() override
{
m_uiArcaneMissilesTimer = urand(2000, 8000);
}
mob_nether_wraithAI(Creature* creature) : ScriptedAI(creature) {}

void JustDied(Unit* killer) override
{
m_creature->CastSpell(nullptr, SPELL_DETONATION, TRIGGERED_OLD_TRIGGERED);
}
};

void UpdateAI(const uint32 uiDiff) override
// 35284 - Summon Nether Wraiths
struct SummonNetherWraiths : public SpellScript
{
void OnEffectExecute(Spell* spell, SpellEffectIndex /*effIdx*/) const override
{
if (!m_creature->SelectHostileTarget() || !m_creature->GetVictim())
return;

if (m_uiArcaneMissilesTimer < uiDiff)
{
Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, nullptr, SELECT_FLAG_PLAYER);
if (!pTarget)
pTarget = m_creature->GetVictim();
uint8 maxWraith = 3;
for (uint8 i = 0; i < maxWraith; ++i)
spell->GetCaster()->CastSpell(nullptr, aWraithSummonSpells[i], TRIGGERED_OLD_TRIGGERED);
}
};

if (pTarget)
// 36022 - Arcane Torrent
struct ArcaneTorrentPathaleon : public SpellScript
{
void OnCast(Spell* spell) const override
{
Unit* caster = spell->GetCaster();
if (SpellAuraHolder* manaTap = caster->GetSpellAuraHolder(SPELL_MANA_TAP))
if (uint32 stack = manaTap->GetStackAmount())
{
if (DoCastSpellIfCan(pTarget, SPELL_ARCANE_BOLT) == CAST_OK)
m_uiArcaneMissilesTimer = urand(5000, 10000);
// not confirmed to do anything despite the tooltip currently
}
}
else
m_uiArcaneMissilesTimer -= uiDiff;

DoMeleeAttackIfReady();
}
};

UnitAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature)
{
return new boss_pathaleon_the_calculatorAI(pCreature);
}

UnitAI* GetAI_mob_nether_wraith(Creature* pCreature)
{
return new mob_nether_wraithAI(pCreature);
}

void AddSC_boss_pathaleon_the_calculator()
{
Script* pNewScript = new Script;
pNewScript->Name = "boss_pathaleon_the_calculator";
pNewScript->GetAI = &GetAI_boss_pathaleon_the_calculator;
pNewScript->GetAI = &GetNewAIInstance<boss_pathaleon_the_calculatorAI>;
pNewScript->RegisterSelf();

pNewScript = new Script;
pNewScript->Name = "mob_nether_wraith";
pNewScript->GetAI = &GetAI_mob_nether_wraith;
pNewScript->GetAI = &GetNewAIInstance<mob_nether_wraithAI>;
pNewScript->RegisterSelf();

RegisterSpellScript<SummonNetherWraiths>("spell_summon_nether_wraiths");
RegisterSpellScript<ArcaneTorrentPathaleon>("spell_arcane_torrent_pathaleon");
}

0 comments on commit 84deb19

Please sign in to comment.