From 84deb193a17994b6a47bdb91a4aa6056f2c17627 Mon Sep 17 00:00:00 2001 From: killerwife Date: Sat, 16 Sep 2023 17:24:55 +0200 Subject: [PATCH] Mechanar: Modernize pathaleon the calculator with spell lists and spell scripts https://github.com/cmangos/issues/issues/3444/ --- sql/base/dbc/cmangos_fixes/Spell.sql | 4 + sql/scriptdev2/spell.sql | 1 + .../boss_pathaleon_the_calculator.cpp | 217 +++++------------- 3 files changed, 61 insertions(+), 161 deletions(-) diff --git a/sql/base/dbc/cmangos_fixes/Spell.sql b/sql/base/dbc/cmangos_fixes/Spell.sql index c1872a725ff..66e9d030637 100644 --- a/sql/base/dbc/cmangos_fixes/Spell.sql +++ b/sql/base/dbc/cmangos_fixes/Spell.sql @@ -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 -- ============================================================ diff --git a/sql/scriptdev2/spell.sql b/sql/scriptdev2/spell.sql index a0b027b67b4..f41a2cfa1ea 100644 --- a/sql/scriptdev2/spell.sql +++ b/sql/scriptdev2/spell.sql @@ -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'), diff --git a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp index d18793bb30e..79416b9fd59 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp @@ -23,6 +23,7 @@ EndScriptData */ #include "AI/ScriptDevAI/include/sc_common.h" #include "mechanar.h" +#include "AI/ScriptDevAI/base/CombatAI.h" enum { @@ -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(creature->GetInstanceData())), + m_isRegularMode(creature->GetMap()->IsRegularDifficulty()) { - m_pInstance = static_cast(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; pNewScript->RegisterSelf(); pNewScript = new Script; pNewScript->Name = "mob_nether_wraith"; - pNewScript->GetAI = &GetAI_mob_nether_wraith; + pNewScript->GetAI = &GetNewAIInstance; pNewScript->RegisterSelf(); + + RegisterSpellScript("spell_summon_nether_wraiths"); + RegisterSpellScript("spell_arcane_torrent_pathaleon"); }