Scripts/AtalDazar: Implement Volkaal encounter (#30663)

This commit is contained in:
Aqua Deus
2025-02-04 19:14:20 +01:00
committed by GitHub
parent 2b1ad96be1
commit 17df38e025
5 changed files with 524 additions and 3 deletions

View File

@@ -0,0 +1,43 @@
DELETE FROM `creature` WHERE `guid` IN (7000217, 7000212, 7000196);
UPDATE `creature_template_difficulty` SET `ContentTuningID`=502, `StaticFlags1`=0x10000000, `VerifiedBuild`=58773 WHERE (`Entry`=122965 AND `DifficultyID`=0); -- 122965 (Vol'kaal) - CanSwim
UPDATE `creature_template_difficulty` SET `ContentTuningID`=502, `StaticFlags1`=0x20000100, `VerifiedBuild`=58773 WHERE (`Entry`=125977 AND `DifficultyID`=0); -- 125977 (Reanimation Totem) - Sessile, Floating - CannotTurn
UPDATE `creature_template` SET `unit_flags2`=0x0, `unit_flags3`=0x40000000, `ScriptName`='npc_volkaal_reanimation_totem' WHERE `entry`=125977; -- Reanimation Totem
UPDATE `creature_template` SET `unit_flags2`=0x800, `ScriptName`='boss_volkaal' WHERE `entry`=122965; -- Vol'kaal
UPDATE `creature_template_addon` SET `emote`=64, `auras`='250192' WHERE `entry`=122965; -- 122965 (Vol'kaal) - Bad Voodoo
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` = 250229;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `ConditionStringValue1`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 250229, 0, 0, 51, 0, 5, 125977, 0, '', 0, 0, 0, '', 'Spell \'Soul Anchor\' can only hit \'Reanimation Totem\'');
DELETE FROM `areatrigger_create_properties` WHERE (`IsCustom`=0 AND `Id` = 11243);
INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `SpellForVisuals`, `TimeToTargetScale`, `Speed`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES
(11243, 0, 16029, 0, 2, 0, 3477, 0, 0, -1, 0, 209, NULL, 60000, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 'at_volkaal_rapid_decay', 53989); -- Spell: 250696 (Rapid Decay)
DELETE FROM `areatrigger_template` WHERE (`IsCustom`=0 AND `Id` = 16029);
INSERT INTO `areatrigger_template` (`Id`, `IsCustom`, `Flags`, `VerifiedBuild`) VALUES
(16029, 0, 0, 53989);
DELETE FROM `spell_script_names` WHERE `spell_id` IN (250372, 250368, 250241, 250229, 259531, 250708, 250258);
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(250372, 'spell_volkaal_lingering_nausea'),
(250368, 'spell_volkaal_noxious_stench'),
(250241, 'spell_volkaal_rapid_decay'),
(259531, 'spell_volkaal_reanimate'),
(250229, 'spell_volkaal_soul_anchor'),
(250708, 'spell_volkaal_toxic_leap_selector'),
(250258, 'spell_volkaal_toxic_leap');
DELETE FROM `creature_text` WHERE `CreatureID`=122965;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(122965, 0, 0, 'You?! I tear you apart!', 14, 0, 100, 0, 0, 97344, 140446, 0, 'Vol\'kaal - Enter Combat'),
(122965, 1, 0, 'You die with me!', 14, 0, 100, 0, 0, 97349, 140453, 0, 'Vol\'kaal - Decay'),
(122965, 2, 0, 'Master gonna build me again...', 14, 0, 100, 0, 0, 97345, 140457, 0, 'Vol\'kaal - Death'),
(122965, 3, 0, 'You be in pieces.', 14, 0, 100, 0, 0, 97346, 140454, 0, 'Vol\'kaal - Slay'),
(122965, 3, 1, 'Flesh for master!', 14, 0, 100, 0, 0, 97347, 140455, 0, 'Vol\'kaal - Slay'),
(122965, 4, 0, 'Master take your parts. Make me stronger!', 14, 0, 100, 0, 0, 97348, 140456, 0, 'Vol\'kaal - Evade');
DELETE FROM `creature_summon_groups` WHERE `summonerId`=122965;
INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`, `Comment`) VALUES
(122965, 0, 0, 125977, -636.189, 2316.12, 709.963, 3.1168, 8, 0, 'Vol\'kaal - Group 0 - Reanimation Totem'),
(122965, 0, 0, 125977, -591.24, 2292.44, 709.968, 3.1168, 8, 0, 'Vol\'kaal - Group 0 - Reanimation Totem'),
(122965, 0, 0, 125977, -636.028, 2269.22, 709.974, 3.1168, 8, 0, 'Vol\'kaal - Group 0 - Reanimation Totem');

View File

@@ -38,11 +38,19 @@ enum AtalDazarCreatureIds
{
// Bosses
BOSS_PRIESTESS_ALUNZA = 129614,
BOSS_VOLKAAL = 129399,
BOSS_VOLKAAL = 122965,
BOSS_REZAN = 122963,
BOSS_YAZMA = 129412
};
enum AtalDazarGameObjectIds
{
GO_VOLKAAL_DOOR_1 = 292399,
GO_VOLKAAL_DOOR_2 = 292400,
GO_VOLKAAL_DOOR_3 = 292401,
GO_VOLKAAL_DOOR_4 = 292402
};
template <class AI, class T>
inline AI* GetAtalDazarAI(T* obj)
{

View File

@@ -0,0 +1,457 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AreaTriggerAI.h"
#include "CellImpl.h"
#include "Creature.h"
#include "GridNotifiersImpl.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "MoveSpline.h"
#include "ObjectAccessor.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "atal_dazar.h"
enum VolkaalSpells
{
SPELL_SOUL_ANCHOR = 259537,
SPELL_BAD_VOODOO = 250192,
SPELL_RAPID_DECAY = 250241,
SPELL_RAPID_DECAY_TARGET = 250694,
SPELL_RAPID_DECAY_RANDOM = 250697,
SPELL_TOXIC_POOL = 250585,
SPELL_REANIMATE = 259531,
SPELL_TOXIC_LEAP_SELECTOR = 250708,
SPELL_TOXIC_LEAP = 250258,
SPELL_TOXIC_LEAP_DAMAGE = 250259,
SPELL_NOXIOUS_STENCH = 259572,
SPELL_LINGERING_NAUSEA = 250372
};
enum VolkaalEvents
{
EVENT_TOXIC_LEAP = 1,
EVENT_NOXIOUS_STENCH,
};
enum VolkaalActions
{
ACTION_TOTEMS_DIED = 1
};
enum VolkaalSummonGroups
{
SUMMON_GROUP_VOLKAAL_TOTEMS = 0
};
enum VolkaalTexts
{
SAY_AGGRO = 0,
SAY_DECAY = 1,
SAY_DIED = 2,
SAY_SLAY = 3,
SAY_WIPE = 4
};
// 122965 - Vol'kaal
struct boss_volkaal : public BossAI
{
boss_volkaal(Creature* creature) : BossAI(creature, DATA_VOLKAAL), _toxicLeapCount(1), _leaping(false) { }
void JustAppeared() override
{
me->SummonCreatureGroup(SUMMON_GROUP_VOLKAAL_TOTEMS);
}
void Reset() override
{
_Reset();
_toxicLeapCount = 1;
_leaping = false;
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
Talk(SAY_WIPE);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
summons.DespawnAll();
_EnterEvadeMode();
_DespawnAtEvade();
}
void KilledUnit(Unit* victim) override
{
if (!victim->IsPlayer())
return;
Talk(SAY_SLAY);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
for (ObjectGuid summonGuid : summons)
{
if (Creature * totem = ObjectAccessor::GetCreature(*me, summonGuid))
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, totem, 2);
}
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_TOXIC_LEAP, 2200ms);
events.ScheduleEvent(EVENT_NOXIOUS_STENCH, 5800ms);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
summons.DespawnAll();
Talk(SAY_DIED);
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_RAPID_DECAY)
{
Talk(SAY_DECAY);
events.CancelEvent(EVENT_TOXIC_LEAP);
}
}
void MovementInform(uint32 /*type*/, uint32 id) override
{
if (id == EVENT_JUMP)
{
DoCastSelf(SPELL_TOXIC_LEAP_DAMAGE);
_leaping = false;
}
}
void DoAction(int32 action) override
{
if (action == ACTION_TOTEMS_DIED)
{
for (ObjectGuid summonGuid : summons)
{
if (Creature* totem = ObjectAccessor::GetCreature(*me, summonGuid))
{
totem->SetUnkillable(false);
totem->KillSelf();
}
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_TOXIC_LEAP:
{
_leaping = true;
DoCast(SPELL_TOXIC_LEAP_SELECTOR);
_toxicLeapCount++;
if (_toxicLeapCount % 3 == 2)
events.Repeat(8500ms);
else
events.Repeat(6s);
break;
}
case EVENT_NOXIOUS_STENCH:
{
if (!_leaping)
{
DoCast(SPELL_NOXIOUS_STENCH);
events.Repeat(19400ms);
}
else
events.Repeat(100ms);
break;
}
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
}
private:
uint32 _toxicLeapCount;
bool _leaping;
};
// 125977 - Reanimation Totem
struct npc_volkaal_reanimation_totem : public ScriptedAI
{
npc_volkaal_reanimation_totem(Creature* creature) : ScriptedAI(creature) { }
void JustAppeared() override
{
if (IsHeroicOrHigher())
me->SetUnkillable(true);
}
void JustEngagedWith(Unit* /*who*/) override
{
InstanceScript* instance = me->GetInstanceScript();
if (!instance)
return;
if (Creature* volkaal = instance->GetCreature(DATA_VOLKAAL))
volkaal->AI()->DoZoneInCombat();
}
void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (me->GetHealth() <= damage)
{
if (IsHeroicOrHigher())
{
DoCastSelf(SPELL_SOUL_ANCHOR);
DoCastSelf(SPELL_REANIMATE);
}
}
}
void JustDied(Unit* /*killer*/) override
{
InstanceScript* instance = me->GetInstanceScript();
if (!instance)
return;
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
}
};
// 250372 - Lingering Nausea
class spell_volkaal_lingering_nausea : public AuraScript
{
void HandlePeriodic(AuraEffect const* aurEff) const
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
caster->CastSpell(target, aurEff->GetAmount(), CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_volkaal_lingering_nausea::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 250368 - Noxious Stench
class spell_volkaal_noxious_stench : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo ({ SPELL_LINGERING_NAUSEA });
}
void HandleDummy(SpellEffIndex /*effIndex*/) const
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_LINGERING_NAUSEA, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_volkaal_noxious_stench::HandleDummy, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 250708 - Toxic Leap
class spell_volkaal_toxic_leap_selector : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_TOXIC_LEAP });
}
void HandleScript(SpellEffIndex /*effIndex*/) const
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_TOXIC_LEAP);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_volkaal_toxic_leap_selector::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 250258 - Toxic Leap
class spell_volkaal_toxic_leap : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_TOXIC_LEAP });
}
void HandleHit(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
float dist = GetCaster()->GetExactDist(GetHitDest());
float jumpGravity = 159500.0f / (dist * dist); // constant based on calculating avg of inverse from multiple leaps
GetCaster()->GetMotionMaster()->MoveJumpWithGravity(*GetHitDest(), 50, jumpGravity, EVENT_JUMP);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_volkaal_toxic_leap::HandleHit, EFFECT_1, SPELL_EFFECT_JUMP_CHARGE);
}
};
// 250229 - Soul Anchor
class spell_volkaal_soul_anchor : public SpellScript
{
void SelectTotem(std::list<WorldObject*>& targets) const
{
if (targets.empty())
{
InstanceScript* instance = GetCaster()->GetInstanceScript();
if (!instance)
return;
if (Creature* volkaal = instance->GetCreature(DATA_VOLKAAL))
volkaal->AI()->DoAction(ACTION_TOTEMS_DIED);
Unit* caster = GetCaster();
caster->RemoveAurasDueToSpell(SPELL_BAD_VOODOO);
caster->CastSpell(caster, SPELL_RAPID_DECAY, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_volkaal_soul_anchor::SelectTotem, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
}
};
// 259531 - Reanimate
class spell_volkaal_reanimate : public SpellScript
{
void HandleScript(SpellEffIndex /*effIndex*/) const
{
GetCaster()->RemoveAurasDueToSpell(SPELL_SOUL_ANCHOR);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_volkaal_reanimate::HandleScript, EFFECT_0, SPELL_EFFECT_HEAL_PCT);
}
};
// 250241 - Rapid Decay
class spell_volkaal_rapid_decay : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo ({ SPELL_RAPID_DECAY_TARGET, SPELL_RAPID_DECAY_RANDOM });
}
void HandleToxicPool(AuraEffect const* aurEff) const
{
Unit* caster = GetCaster();
if (!caster)
return;
float range = 100.0f;
Player* player = nullptr;
Trinity::AnyPlayerInObjectRangeCheck check(caster, range);
Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(caster, player, check);
Cell::VisitWorldObjects(caster, searcher, range);
CastSpellExtraArgs args;
args.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR;
args.TriggeringAura = aurEff;
caster->CastSpell(player->GetPosition(), SPELL_RAPID_DECAY_TARGET, args);
// not present in 11.0.7
//caster->CastSpell(caster, SPELL_RAPID_DECAY_RANDOM, args);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_volkaal_rapid_decay::HandleToxicPool, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
}
};
// 250696 - Rapid Decay
// ID - 11243
struct at_volkaal_rapid_decay : AreaTriggerAI
{
at_volkaal_rapid_decay(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnUnitEnter(Unit* unit) override
{
if (!unit->IsPlayer())
return;
unit->CastSpell(unit, SPELL_TOXIC_POOL, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
void OnUnitExit(Unit* unit) override
{
unit->RemoveAurasDueToSpell(SPELL_TOXIC_POOL);
}
};
void AddSC_boss_volkaal()
{
RegisterAtalDazarCreatureAI(boss_volkaal);
RegisterAtalDazarCreatureAI(npc_volkaal_reanimation_totem);
RegisterSpellScript(spell_volkaal_lingering_nausea);
RegisterSpellScript(spell_volkaal_noxious_stench);
RegisterSpellScript(spell_volkaal_toxic_leap_selector);
RegisterSpellScript(spell_volkaal_toxic_leap);
RegisterSpellScript(spell_volkaal_soul_anchor);
RegisterSpellScript(spell_volkaal_reanimate);
RegisterSpellScript(spell_volkaal_rapid_decay);
RegisterAreaTriggerAI(at_volkaal_rapid_decay);
}

View File

@@ -23,9 +23,10 @@
BossBoundaryData const boundaries =
{
{ DATA_REZAN, new ZRangeBoundary(639.0f, 650.0f) }, // 647.65f
{ DATA_VOLKAAL, new ZRangeBoundary(709.0f, 730.0f) },
};
ObjectData const creatureData[] =
constexpr ObjectData creatureData[] =
{
{ BOSS_PRIESTESS_ALUNZA, DATA_PRIESTESS_ALUNZA },
{ BOSS_VOLKAAL, DATA_VOLKAAL },
@@ -34,7 +35,16 @@ ObjectData const creatureData[] =
{ 0, 0 } // END
};
DungeonEncounterData const encounters[] =
constexpr DoorData doorData[] =
{
{ GO_VOLKAAL_DOOR_1, DATA_VOLKAAL, EncounterDoorBehavior::OpenWhenNotInProgress },
{ GO_VOLKAAL_DOOR_2, DATA_VOLKAAL, EncounterDoorBehavior::OpenWhenNotInProgress },
{ GO_VOLKAAL_DOOR_3, DATA_VOLKAAL, EncounterDoorBehavior::OpenWhenNotInProgress },
{ GO_VOLKAAL_DOOR_4, DATA_VOLKAAL, EncounterDoorBehavior::OpenWhenNotInProgress },
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
};
constexpr DungeonEncounterData encounters[] =
{
{ DATA_PRIESTESS_ALUNZA, {{ 2084 }} },
{ DATA_VOLKAAL, {{ 2085 }} },
@@ -54,6 +64,7 @@ public:
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, nullptr);
LoadDoorData(doorData);
LoadBossBoundaries(boundaries);
LoadDungeonEncounterData(encounters);
}

View File

@@ -20,6 +20,7 @@
// Atal'Dazar
void AddSC_instance_atal_dazar();
void AddSC_boss_rezan();
void AddSC_boss_volkaal();
// Underrot
void AddSC_instance_underrot();
@@ -38,6 +39,7 @@ void AddZandalarScripts()
// Atal'Dazar
AddSC_instance_atal_dazar();
AddSC_boss_rezan();
AddSC_boss_volkaal();
// Underrot
AddSC_instance_underrot();