mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 01:08:35 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
16
data/sql/updates/db_world/2025_09_23_00.sql
Normal file
16
data/sql/updates/db_world/2025_09_23_00.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- DB update 2025_09_22_03 -> 2025_09_23_00
|
||||
|
||||
-- Update SmartAIs
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` IN (18855, 19643, 21660));
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0) AND (`entryorguid` IN (18855, 19643, 21660));
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(18855, 0, 0, 0, 0, 0, 100, 0, 3000, 6000, 3000, 4000, 0, 0, 11, 9053, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunfury Magister - In Combat - Cast \'Fireball\''),
|
||||
(18855, 0, 1, 0, 0, 0, 100, 0, 8000, 12000, 26000, 31000, 0, 0, 11, 35778, 33, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunfury Magister - In Combat - Cast \'Bloodcrystal Surge\''),
|
||||
(18855, 0, 2, 0, 2, 0, 100, 512, 0, 15, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunfury Magister - Between 0-15% Health - Flee For Assist'),
|
||||
(18855, 0, 3, 0, 1, 0, 50, 0, 10000, 20000, 15000, 30000, 0, 0, 11, 34397, 0, 0, 0, 0, 0, 19, 19421, 30, 0, 0, 0, 0, 0, 0, 'Sunfury Magister - Out of Combat - Cast \'Red Beam\''),
|
||||
(19643, 0, 0, 0, 1, 0, 100, 0, 1000, 1000, 600000, 600000, 0, 0, 11, 35917, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunfury Astromancer - Out of Combat - Cast \'Fiery Intellect\''),
|
||||
(19643, 0, 1, 0, 0, 0, 100, 0, 2000, 3000, 1500, 2000, 0, 30, 11, 38391, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunfury Astromancer - In Combat - Cast \'Scorch\''),
|
||||
(19643, 0, 2, 0, 0, 0, 100, 0, 12000, 16000, 12000, 16000, 0, 30, 11, 35914, 64, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunfury Astromancer - In Combat - Cast \'Astral Focus\''),
|
||||
(21660, 0, 0, 0, 0, 0, 100, 0, 0, 0, 2400, 3800, 0, 0, 11, 34447, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cabal Abjurist - In Combat - Cast \'Arcane Missiles\''),
|
||||
(21660, 0, 1, 0, 106, 0, 100, 0, 5000, 9000, 13000, 18000, 0, 10, 11, 11831, 64, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Cabal Abjurist - On Hostile in Range - Cast \'Frost Nova\'');
|
||||
19
data/sql/updates/db_world/2025_09_23_01.sql
Normal file
19
data/sql/updates/db_world/2025_09_23_01.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
-- DB update 2025_09_23_00 -> 2025_09_23_01
|
||||
--
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27996);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(27996, 0, 0, 0, 1, 0, 100, 512, 9000, 9000, 30000, 30000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - Out of Combat - Say Line 0'),
|
||||
(27996, 0, 1, 0, 2, 0, 100, 513, 0, 33, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - Between 0-33% Health - Say Line 1 (No Repeat)'),
|
||||
(27996, 0, 3, 0, 54, 0, 100, 512, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - On Just Summoned - Set Reactstate Passive'),
|
||||
(27996, 0, 4, 5, 28, 0, 100, 512, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 0, 202, 15, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - On Passenger Removed - Move To Random Point'),
|
||||
(27996, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - On Passenger Removed - Say Line 2'),
|
||||
(27996, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - On Passenger Removed - Despawn In 3000 ms'),
|
||||
(27996, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 134, 44795, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrmrest Vanquisher - On Passenger Removed - Invoker Cast \'Parachute\'');
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 2800500 AND `source_type` = 9;
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28005) AND (`source_type` = 0) AND (`id` IN (1));
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_dragonblight_devour_ghoul', 'spell_dragonblight_devour_ghoul_periodic');
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(50430, 'spell_dragonblight_devour_ghoul'),
|
||||
(50432, 'spell_dragonblight_devour_ghoul_periodic');
|
||||
@@ -746,27 +746,39 @@ void BossAI::UpdateAI(uint32 diff)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void BossAI::OnSpellCastFinished(SpellInfo const* spellInfo, SpellFinishReason reason)
|
||||
{
|
||||
ScriptedAI::OnSpellCastFinished(spellInfo, reason);
|
||||
// Check if any health check events are pending (i.e. waiting for the boss to stop casting.
|
||||
if (_nextHealthCheck.IsPending() && me->IsInCombat())
|
||||
{
|
||||
_nextHealthCheck.UpdateStatus(HEALTH_CHECK_PROCESSED);
|
||||
// This must be delayed because creature might still have unit state casting at this point, which might break scripts.
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
context.Repeat();
|
||||
else
|
||||
ProcessHealthCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void BossAI::DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask)
|
||||
{
|
||||
ScriptedAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
|
||||
|
||||
if (_nextHealthCheck._valid)
|
||||
if (!_nextHealthCheck.HasBeenProcessed())
|
||||
{
|
||||
if (!_nextHealthCheck._allowedWhileCasting && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (me->HealthBelowPctDamaged(_nextHealthCheck._healthPct, damage))
|
||||
{
|
||||
_nextHealthCheck._exec();
|
||||
_nextHealthCheck._valid = false;
|
||||
|
||||
_healthCheckEvents.remove_if([&](HealthCheckEventData data) -> bool
|
||||
if (!_nextHealthCheck._allowedWhileCasting && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return data._healthPct == _nextHealthCheck._healthPct;
|
||||
});
|
||||
_nextHealthCheck.UpdateStatus(HEALTH_CHECK_PENDING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_healthCheckEvents.empty())
|
||||
_nextHealthCheck = _healthCheckEvents.front();
|
||||
ProcessHealthCheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -780,18 +792,32 @@ void BossAI::DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damage
|
||||
*/
|
||||
void BossAI::ScheduleHealthCheckEvent(uint32 healthPct, std::function<void()> exec, bool allowedWhileCasting /*=true*/)
|
||||
{
|
||||
_healthCheckEvents.push_back(HealthCheckEventData(healthPct, exec, true, allowedWhileCasting));
|
||||
_healthCheckEvents.push_back(HealthCheckEventData(healthPct, exec, HEALTH_CHECK_SCHEDULED, allowedWhileCasting));
|
||||
_nextHealthCheck = _healthCheckEvents.front();
|
||||
};
|
||||
|
||||
void BossAI::ScheduleHealthCheckEvent(std::initializer_list<uint8> healthPct, std::function<void()> exec, bool allowedWhileCasting /*=true*/)
|
||||
{
|
||||
for (auto const& checks : healthPct)
|
||||
_healthCheckEvents.push_back(HealthCheckEventData(checks, exec, true, allowedWhileCasting));
|
||||
_healthCheckEvents.push_back(HealthCheckEventData(checks, exec, HEALTH_CHECK_SCHEDULED, allowedWhileCasting));
|
||||
|
||||
_nextHealthCheck = _healthCheckEvents.front();
|
||||
}
|
||||
|
||||
void BossAI::ProcessHealthCheck()
|
||||
{
|
||||
_nextHealthCheck.UpdateStatus(HEALTH_CHECK_PROCESSED);
|
||||
_nextHealthCheck._exec();
|
||||
|
||||
_healthCheckEvents.remove_if([&](HealthCheckEventData data) -> bool
|
||||
{
|
||||
return data._healthPct == _nextHealthCheck._healthPct;
|
||||
});
|
||||
|
||||
if (!_healthCheckEvents.empty())
|
||||
_nextHealthCheck = _healthCheckEvents.front();
|
||||
}
|
||||
|
||||
void BossAI::ScheduleEnrageTimer(uint32 spellId, Milliseconds timer, uint8 textId /*= 0*/)
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([this, spellId, textId]
|
||||
|
||||
@@ -454,14 +454,27 @@ private:
|
||||
std::unordered_set<uint32> _uniqueTimedEvents;
|
||||
};
|
||||
|
||||
enum HealthCheckStatus
|
||||
{
|
||||
HEALTH_CHECK_PROCESSED,
|
||||
HEALTH_CHECK_SCHEDULED,
|
||||
HEALTH_CHECK_PENDING
|
||||
};
|
||||
|
||||
struct HealthCheckEventData
|
||||
{
|
||||
HealthCheckEventData(uint8 healthPct, std::function<void()> exec, bool valid = true, bool allowedWhileCasting = true) : _healthPct(healthPct), _exec(exec), _valid(valid), _allowedWhileCasting(allowedWhileCasting) { };
|
||||
HealthCheckEventData(uint8 healthPct, std::function<void()> exec, uint8 status = HEALTH_CHECK_SCHEDULED, bool allowedWhileCasting = true, Milliseconds Delay = 0s) : _healthPct(healthPct), _exec(exec), _status(status), _allowedWhileCasting(allowedWhileCasting), _delay(Delay) { };
|
||||
|
||||
uint8 _healthPct;
|
||||
std::function<void()> _exec;
|
||||
bool _valid;
|
||||
uint8 _status;
|
||||
bool _allowedWhileCasting;
|
||||
Milliseconds _delay;
|
||||
|
||||
[[nodiscard]] bool HasBeenProcessed() const { return _status == HEALTH_CHECK_PROCESSED; };
|
||||
[[nodiscard]] bool IsPending() const { return _status == HEALTH_CHECK_PENDING; };
|
||||
[[nodiscard]] Milliseconds GetDelay() const { return _delay; };
|
||||
void UpdateStatus(uint8 status) { _status = status; };
|
||||
};
|
||||
|
||||
class BossAI : public ScriptedAI
|
||||
@@ -476,6 +489,7 @@ public:
|
||||
|
||||
bool CanRespawn() override;
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override;
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override;
|
||||
void JustSummoned(Creature* summon) override;
|
||||
void SummonedCreatureDespawn(Creature* summon) override;
|
||||
@@ -485,6 +499,7 @@ public:
|
||||
|
||||
void ScheduleHealthCheckEvent(uint32 healthPct, std::function<void()> exec, bool allowedWhileCasting = true);
|
||||
void ScheduleHealthCheckEvent(std::initializer_list<uint8> healthPct, std::function<void()> exec, bool allowedWhileCasting = true);
|
||||
void ProcessHealthCheck();
|
||||
|
||||
// @brief Casts the spell after the fixed time and says the text id if provided. Timer will run even if the creature is casting or out of combat.
|
||||
// @param spellId The spell to cast.
|
||||
|
||||
@@ -272,7 +272,7 @@ bool TemporaryThreatModifierEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
Creature::Creature(): Unit(), MovableMapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_lootRecipientGroup(0),
|
||||
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500),
|
||||
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
|
||||
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_alreadyCallForHelp(false), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f),_sparringPct(0.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0),
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true)
|
||||
@@ -2486,6 +2486,9 @@ void Creature::CallForHelp(float radius, Unit* target /*= nullptr*/)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_alreadyCallForHelp) // avoid recursive call for help for any reason
|
||||
return;
|
||||
|
||||
Acore::CallOfHelpCreatureInRangeDo u_do(this, target, radius);
|
||||
Acore::CreatureWorker<Acore::CallOfHelpCreatureInRangeDo> worker(this, u_do);
|
||||
Cell::VisitObjects(this, worker, radius);
|
||||
|
||||
@@ -268,6 +268,7 @@ public:
|
||||
void DoFleeToGetAssistance();
|
||||
void CallForHelp(float fRadius, Unit* target = nullptr);
|
||||
void CallAssistance(Unit* target = nullptr);
|
||||
void SetNoCallForHelp(bool val) { m_alreadyCallForHelp = val; }
|
||||
void SetNoCallAssistance(bool val) { m_AlreadyCallAssistance = val; }
|
||||
void SetNoSearchAssistance(bool val) { m_AlreadySearchedAssistance = val; }
|
||||
bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; }
|
||||
@@ -469,6 +470,7 @@ protected:
|
||||
uint8 m_equipmentId;
|
||||
int8 m_originalEquipmentId; // can be -1
|
||||
|
||||
bool m_alreadyCallForHelp;
|
||||
bool m_AlreadyCallAssistance;
|
||||
bool m_AlreadySearchedAssistance;
|
||||
bool m_regenHealth;
|
||||
|
||||
@@ -1157,7 +1157,11 @@ namespace Acore
|
||||
return;
|
||||
|
||||
if (u->AI())
|
||||
{
|
||||
u->SetNoCallForHelp(true); // avoid recursive call for help causing stack overflow
|
||||
u->AI()->AttackStart(i_enemy);
|
||||
u->SetNoCallForHelp(false);
|
||||
}
|
||||
}
|
||||
private:
|
||||
Unit* const i_funit;
|
||||
|
||||
@@ -5287,6 +5287,8 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
vse->m_flags &= ~VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE;
|
||||
vse = const_cast<VehicleSeatEntry*>(sVehicleSeatStore.LookupEntry(4693)); // Siege Engine, Accessory
|
||||
vse->m_flags &= ~VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE;
|
||||
vse = const_cast<VehicleSeatEntry*>(sVehicleSeatStore.LookupEntry(1520)); // Wyrmrest Vanquisher
|
||||
vse->m_flags |= VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE;
|
||||
|
||||
// pussywizard: fix z offset for some vehicles:
|
||||
vse = const_cast<VehicleSeatEntry*>(sVehicleSeatStore.LookupEntry(6206)); // Marrowgar - Bone Spike
|
||||
|
||||
@@ -56,21 +56,24 @@ enum Misc
|
||||
{
|
||||
ACHIEV_TIMED_START_EVENT = 20381,
|
||||
|
||||
EVENT_CHECK_HEALTH_25 = 1,
|
||||
EVENT_CHECK_HEALTH_50 = 2,
|
||||
EVENT_CHECK_HEALTH_75 = 3,
|
||||
EVENT_CARRION_BEETELS = 4,
|
||||
EVENT_LEECHING_SWARM = 5,
|
||||
EVENT_IMPALE = 6,
|
||||
EVENT_POUND = 7,
|
||||
EVENT_CLOSE_DOORS = 8,
|
||||
EVENT_EMERGE = 9,
|
||||
EVENT_SUMMON_VENOMANCER = 10,
|
||||
EVENT_SUMMON_DARTER = 11,
|
||||
EVENT_SUMMON_GUARDIAN = 12,
|
||||
EVENT_SUMMON_ASSASSINS = 13,
|
||||
EVENT_ENABLE_ROTATE = 14,
|
||||
EVENT_KILL_TALK = 15
|
||||
EVENT_CARRION_BEETELS = 1,
|
||||
EVENT_LEECHING_SWARM = 2,
|
||||
EVENT_IMPALE = 3,
|
||||
EVENT_POUND = 4,
|
||||
EVENT_CLOSE_DOORS = 5,
|
||||
EVENT_EMERGE = 6,
|
||||
EVENT_SUMMON_VENOMANCER = 7,
|
||||
EVENT_SUMMON_DARTER = 8,
|
||||
EVENT_SUMMON_GUARDIAN = 9,
|
||||
EVENT_SUMMON_ASSASSINS = 10,
|
||||
EVENT_ENABLE_ROTATE = 11,
|
||||
EVENT_KILL_TALK = 12
|
||||
};
|
||||
|
||||
enum ANAnubarakNpcs
|
||||
{
|
||||
NPC_ANUBAR_GUARDIAN = 29216,
|
||||
NPC_ANUBAR_VENOMANCER = 29217
|
||||
};
|
||||
|
||||
class boss_anub_arak : public CreatureScript
|
||||
@@ -83,11 +86,10 @@ class boss_anub_arak : public CreatureScript
|
||||
boss_anub_arakAI(Creature* creature) : BossAI(creature, DATA_ANUBARAK_EVENT)
|
||||
{
|
||||
me->m_SightDistance = 120.0f;
|
||||
intro = false;
|
||||
_intro = false;
|
||||
_summonedMinions = false;
|
||||
}
|
||||
|
||||
bool intro;
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->DisableRotate(false);
|
||||
@@ -96,9 +98,9 @@ class boss_anub_arak : public CreatureScript
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!intro && who->IsPlayer())
|
||||
if (!_intro && who->IsPlayer())
|
||||
{
|
||||
intro = true;
|
||||
_intro = true;
|
||||
Talk(SAY_INTRO);
|
||||
}
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
@@ -129,8 +131,42 @@ class boss_anub_arak : public CreatureScript
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_summonedMinions = false;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
||||
|
||||
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{
|
||||
Talk(SAY_SUBMERGE);
|
||||
_summonedMinions = false;
|
||||
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true);
|
||||
DoCastSelf(SPELL_SUBMERGE, false);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this] {
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoCastSelf(SPELL_IMPALE_PERIODIC, true);
|
||||
}, 2s);
|
||||
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_EMERGE, 60s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 2s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 15s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 20s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_DARTER, 30s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 35s);
|
||||
}, false);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) override
|
||||
{
|
||||
if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
|
||||
return;
|
||||
|
||||
if (_summonedMinions && !summons.IsAnyCreatureWithEntryAlive(NPC_ANUBAR_GUARDIAN) && !summons.IsAnyCreatureWithEntryAlive(NPC_ANUBAR_VENOMANCER))
|
||||
{
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_EMERGE, 5s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* ) override
|
||||
@@ -141,16 +177,13 @@ class boss_anub_arak : public CreatureScript
|
||||
events.ScheduleEvent(EVENT_CARRION_BEETELS, 6500ms);
|
||||
events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s);
|
||||
events.ScheduleEvent(EVENT_POUND, 15s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_75, 1s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_50, 1s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 1s);
|
||||
events.ScheduleEvent(EVENT_CLOSE_DOORS, 5s);
|
||||
}
|
||||
|
||||
void SummonHelpers(float x, float y, float z, uint32 spellId)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
me->SummonCreature(spellInfo->Effects[EFFECT_0].MiscValue, x, y, z);
|
||||
me->SummonCreature(spellInfo->Effects[EFFECT_0].MiscValue, x, y, z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -159,10 +192,12 @@ class boss_anub_arak : public CreatureScript
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CLOSE_DOORS:
|
||||
_JustEngagedWith();
|
||||
@@ -191,34 +226,14 @@ class boss_anub_arak : public CreatureScript
|
||||
me->RemoveAurasDueToSpell(SPELL_SELF_ROOT);
|
||||
me->DisableRotate(false);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH_25:
|
||||
case EVENT_CHECK_HEALTH_50:
|
||||
case EVENT_CHECK_HEALTH_75:
|
||||
if (me->HealthBelowPct(eventId*25))
|
||||
{
|
||||
Talk(SAY_SUBMERGE);
|
||||
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true);
|
||||
me->CastSpell(me, SPELL_IMPALE_PERIODIC, true);
|
||||
me->CastSpell(me, SPELL_SUBMERGE, false);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
events.DelayEvents(46000, 0);
|
||||
events.ScheduleEvent(EVENT_EMERGE, 45s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 2s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 15s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 20s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_DARTER, 30s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 35s);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(eventId, 500ms);
|
||||
break;
|
||||
case EVENT_EMERGE:
|
||||
me->CastSpell(me, SPELL_EMERGE, true);
|
||||
me->RemoveAura(SPELL_SUBMERGE);
|
||||
me->RemoveAura(SPELL_IMPALE_PERIODIC);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
events.ScheduleEvent(EVENT_CARRION_BEETELS, 6500ms);
|
||||
events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s);
|
||||
events.ScheduleEvent(EVENT_POUND, 15s);
|
||||
break;
|
||||
case EVENT_SUMMON_ASSASSINS:
|
||||
SummonHelpers(509.32f, 247.42f, 239.48f, SPELL_SUMMON_ASSASSIN);
|
||||
@@ -232,6 +247,7 @@ class boss_anub_arak : public CreatureScript
|
||||
SummonHelpers(550.34f, 316.00f, 234.30f, SPELL_SUMMON_GUARDIAN);
|
||||
break;
|
||||
case EVENT_SUMMON_VENOMANCER:
|
||||
_summonedMinions = true;
|
||||
SummonHelpers(550.34f, 316.00f, 234.30f, SPELL_SUMMON_VENOMANCER);
|
||||
break;
|
||||
}
|
||||
@@ -239,6 +255,10 @@ class boss_anub_arak : public CreatureScript
|
||||
if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _intro;
|
||||
bool _summonedMinions;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -75,21 +75,32 @@ class boss_slad_ran : public CreatureScript
|
||||
public:
|
||||
boss_slad_ran() : CreatureScript("boss_slad_ran") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetGundrakAI<boss_slad_ranAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_slad_ranAI : public BossAI
|
||||
{
|
||||
boss_slad_ranAI(Creature* creature) : BossAI(creature, DATA_SLAD_RAN)
|
||||
{
|
||||
}
|
||||
boss_slad_ranAI(Creature* creature) : BossAI(creature, DATA_SLAD_RAN) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_achievement = true;
|
||||
|
||||
ScheduleHealthCheckEvent(90, [&] {
|
||||
Talk(SAY_SUMMON_SNAKES);
|
||||
|
||||
ScheduleTimedEvent(1s, [&] {
|
||||
for (uint8 i = MAX_CONSTRICTOR; i < MAX_SUMMONS; ++i)
|
||||
me->SummonCreature(NPC_SLADRAN_VIPER, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20 * IN_MILLISECONDS);
|
||||
}, 8s);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(DUNGEON_MODE(50, 75), [&] {
|
||||
Talk(SAY_SUMMON_CONSTRICTORS);
|
||||
|
||||
ScheduleTimedEvent(1s, [&] {
|
||||
for (uint8 i = 0; i < MAX_CONSTRICTOR; ++i)
|
||||
me->SummonCreature(NPC_SLADRAN_CONSTRICTORS, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20 * IN_MILLISECONDS);
|
||||
}, 3s, 5s);
|
||||
});
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const override
|
||||
@@ -110,11 +121,18 @@ public:
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_POISON_NOVA, 10s);
|
||||
events.ScheduleEvent(EVENT_POWERFULL_BITE, 3s);
|
||||
events.ScheduleEvent(EVENT_VENOM_BOLT, 15s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH1, 1s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1s);
|
||||
ScheduleTimedEvent(10s, [&]{
|
||||
Talk(EMOTE_NOVA);
|
||||
DoCastAOE(SPELL_POISON_NOVA);
|
||||
}, 15s);
|
||||
|
||||
ScheduleTimedEvent(3s, [&] {
|
||||
DoCastVictim(SPELL_POWERFULL_BITE);
|
||||
}, 10s);
|
||||
|
||||
ScheduleTimedEvent(15s, [&] {
|
||||
DoCastVictim(SPELL_VENOM_BOLT);
|
||||
}, 10s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
@@ -133,72 +151,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summon->SetInCombatWithZone();
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_HEALTH1:
|
||||
if (me->HealthBelowPct(70))
|
||||
{
|
||||
Talk(SAY_SUMMON_SNAKES);
|
||||
events.ScheduleEvent(EVENT_SUMMON1, 1s);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH1, 1s);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH2:
|
||||
if (me->HealthBelowPct(50))
|
||||
{
|
||||
Talk(SAY_SUMMON_CONSTRICTORS);
|
||||
events.ScheduleEvent(EVENT_SUMMON2, 1s);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1s);
|
||||
break;
|
||||
case EVENT_POISON_NOVA:
|
||||
Talk(EMOTE_NOVA);
|
||||
me->CastSpell(me, SPELL_POISON_NOVA, false);
|
||||
events.ScheduleEvent(EVENT_POISON_NOVA, 15s);
|
||||
break;
|
||||
case EVENT_POWERFULL_BITE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_POWERFULL_BITE, false);
|
||||
events.ScheduleEvent(EVENT_POWERFULL_BITE, 10s);
|
||||
break;
|
||||
case EVENT_VENOM_BOLT:
|
||||
me->CastSpell(me->GetVictim(), SPELL_VENOM_BOLT, false);
|
||||
events.ScheduleEvent(EVENT_VENOM_BOLT, 10s);
|
||||
break;
|
||||
case EVENT_SUMMON1:
|
||||
for (uint8 i = MAX_CONSTRICTOR; i < MAX_SUMMONS; ++i)
|
||||
me->SummonCreature(NPC_SLADRAN_VIPER, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20 * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_SUMMON1, 8s);
|
||||
break;
|
||||
case EVENT_SUMMON2:
|
||||
for (uint8 i = 0; i < MAX_CONSTRICTOR; ++i)
|
||||
me->SummonCreature(NPC_SLADRAN_CONSTRICTORS, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20 * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_SUMMON2, 3s, 5s);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _achievement;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetGundrakAI<boss_slad_ranAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_sladran_grip_of_sladran_aura : public AuraScript
|
||||
|
||||
@@ -2271,6 +2271,66 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
enum DevourGhoulSpells
|
||||
{
|
||||
SPELL_DEVOUR_GHOUL_RIDE_VEHICLE = 50437,
|
||||
SPELL_DEVOUR_PERIODIC = 50432,
|
||||
SPELL_NOURISHMENT = 50443
|
||||
};
|
||||
|
||||
// 50430 - Devour Ghoul
|
||||
class spell_dragonblight_devour_ghoul: public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_dragonblight_devour_ghoul);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DEVOUR_GHOUL_RIDE_VEHICLE });
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetCaster())
|
||||
{
|
||||
GetHitUnit()->CastSpell(GetCaster(), SPELL_DEVOUR_GHOUL_RIDE_VEHICLE, true);
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_DEVOUR_PERIODIC, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_dragonblight_devour_ghoul::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
// 50432 - Devour Ghoul
|
||||
class spell_dragonblight_devour_ghoul_periodic : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_dragonblight_devour_ghoul_periodic);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_NOURISHMENT });
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetCaster())
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_NOURISHMENT, true);
|
||||
|
||||
if (GetUnitOwner() && GetUnitOwner()->ToCreature())
|
||||
{
|
||||
GetUnitOwner()->ExitVehicle();
|
||||
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2000);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_dragonblight_devour_ghoul_periodic::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_dragonblight()
|
||||
{
|
||||
new npc_conversing_with_the_depths_trigger();
|
||||
@@ -2299,4 +2359,6 @@ void AddSC_dragonblight()
|
||||
RegisterSpellScript(spell_dragonblight_corrosive_spit);
|
||||
RegisterSpellScript(spell_handover_reins);
|
||||
RegisterSpellScript(spell_dragonblight_flame_fury);
|
||||
RegisterSpellScript(spell_dragonblight_devour_ghoul);
|
||||
RegisterSpellScript(spell_dragonblight_devour_ghoul_periodic);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user