mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 05:36:23 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
26
data/sql/updates/db_world/2023_04_17_00.sql
Normal file
26
data/sql/updates/db_world/2023_04_17_00.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- DB update 2023_04_15_00 -> 2023_04_17_00
|
||||
--
|
||||
DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (18708, 20657);
|
||||
INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Rooted`, `Flight`) VALUES
|
||||
(18708, 1, 1, 1),
|
||||
(20657, 1, 1, 1);
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` = 33711;
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(33711, 'spell_murmur_touch');
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = -146210) AND (`source_type` = 0) AND (`id` IN (1));
|
||||
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`, `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
|
||||
(-146210, 0, 1, 0, 58, 0, 100, 0, 8, 1863400, 0, 0, 0, 225, 0, 1, 0, 0, 0, 0, 10, 146104, 18708, 0, 0, 0, 0, 0, 0, 'Cabal Summoner - On Waypoint Finished - Send GUID to Murmur');
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -146209 AND `id` = 4);
|
||||
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`, `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
|
||||
(-146209, 0, 4, 0, 34, 0, 100, 0, 8, 1, 0, 0, 0, 225, 0, 1, 0, 0, 0, 0, 10, 146104, 18708, 0, 0, 0, 0, 0, 0, 'Cabal Summoner - On Reached Point 1 - Send GUID to Murmur'); -- This is a hack as it will trigger spell 33331 instead of 33329
|
||||
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceEntry` = 33329);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(13, 1, 33329, 0, 0, 31, 0, 3, 18639, 146225, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'),
|
||||
(13, 1, 33329, 0, 1, 31, 0, 3, 18634, 146226, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'),
|
||||
(13, 1, 33329, 0, 2, 31, 0, 3, 18639, 146227, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'),
|
||||
(13, 1, 33329, 0, 3, 31, 0, 3, 18634, 146228, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'),
|
||||
(13, 1, 33329, 0, 4, 31, 0, 3, 18639, 146229, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids');
|
||||
7
data/sql/updates/db_world/2023_04_17_01.sql
Normal file
7
data/sql/updates/db_world/2023_04_17_01.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- DB update 2023_04_17_00 -> 2023_04_17_01
|
||||
--
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` = 33332);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(13, 1, 33332, 0, 1, 31, 0, 3, 18639, 0, 0, 0, 0, '', 'Suppression Blast (33332) can only target a set of Entries'),
|
||||
(13, 1, 33332, 0, 2, 31, 0, 3, 18634, 0, 0, 0, 0, '', 'Suppression Blast (33332) can only target a set of Entries'),
|
||||
(13, 1, 33332, 0, 3, 31, 0, 3, 18632, 0, 0, 0, 0, '', 'Suppression Blast (33332) can only target a set of Entries');
|
||||
7
data/sql/updates/db_world/2023_04_17_02.sql
Normal file
7
data/sql/updates/db_world/2023_04_17_02.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- DB update 2023_04_17_01 -> 2023_04_17_02
|
||||
-- 184906 (Power Converter)
|
||||
UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = 184906;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 1 AND `entryorguid` = 184906);
|
||||
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`, `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
|
||||
(184906, 1, 0, 0, 70, 0, 100, 0, 2, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Power Converter - On Gameobject State Changed - Despawn In 1000 ms');
|
||||
7
data/sql/updates/db_world/2023_04_18_00.sql
Normal file
7
data/sql/updates/db_world/2023_04_18_00.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- DB update 2023_04_17_02 -> 2023_04_18_00
|
||||
--
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 21694) AND (`source_type` = 0) AND (`id` IN (2, 3, 4, 5));
|
||||
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`, `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
|
||||
(21694, 0, 2, 0, 0, 0, 100, 0, 7000, 9500, 12000, 15000, 0, 11, 40340, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bog Overlord - In Combat - Cast \'Trample\''),
|
||||
(21694, 0, 3, 4, 2, 0, 100, 1, 0, 20, 0, 0, 0, 11, 8599, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bog Overlord - Between 0-20% Health - Cast \'Enrage\' (No Repeat)'),
|
||||
(21694, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bog Overlord - Between 0-20% Health - Say Line 0 (No Repeat)');
|
||||
6
data/sql/updates/db_world/2023_04_18_01.sql
Normal file
6
data/sql/updates/db_world/2023_04_18_01.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
-- DB update 2023_04_18_00 -> 2023_04_18_01
|
||||
--
|
||||
UPDATE `smart_scripts` SET `action_type`=134 WHERE `action_type` = 85;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=25418 AND `source_type`=0 AND `id`=4 AND `link`=5;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=25416 AND `source_type`=0 AND `id`=4 AND `link`=5;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=33518 AND `source_type`=0 AND `id`=3 AND `link`=0;
|
||||
3
data/sql/updates/db_world/2023_04_18_02.sql
Normal file
3
data/sql/updates/db_world/2023_04_18_02.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2023_04_18_01 -> 2023_04_18_02
|
||||
--
|
||||
UPDATE `creature_template` SET `dmgschool` = 0 WHERE (`entry` IN (21695, 21696, 21916, 21917));
|
||||
@@ -107,6 +107,11 @@ void TaskScheduler::Dispatch(success_t const& callback)
|
||||
callback();
|
||||
}
|
||||
|
||||
bool TaskScheduler::IsGroupScheduled(group_t const group)
|
||||
{
|
||||
return _task_holder.IsGroupQueued(group);
|
||||
}
|
||||
|
||||
void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
|
||||
{
|
||||
container.insert(task);
|
||||
@@ -159,6 +164,19 @@ void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)
|
||||
container.insert(cache.begin(), cache.end());
|
||||
}
|
||||
|
||||
bool TaskScheduler::TaskQueue::IsGroupQueued(group_t const group)
|
||||
{
|
||||
for (auto const& task : container)
|
||||
{
|
||||
if (task->IsInGroup(group))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TaskScheduler::TaskQueue::IsEmpty() const
|
||||
{
|
||||
return container.empty();
|
||||
|
||||
@@ -136,6 +136,9 @@ class TaskScheduler
|
||||
|
||||
void ModifyIf(std::function<bool(TaskContainer const&)> const& filter);
|
||||
|
||||
/// Check if the group exists and is currently scheduled.
|
||||
bool IsGroupQueued(group_t const group);
|
||||
|
||||
bool IsEmpty() const;
|
||||
};
|
||||
|
||||
@@ -260,6 +263,9 @@ public:
|
||||
/// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}"
|
||||
TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups);
|
||||
|
||||
/// Check if the group exists and is currently scheduled.
|
||||
bool IsGroupScheduled(group_t const group);
|
||||
|
||||
/// Delays all tasks with the given duration.
|
||||
template<class _Rep, class _Period>
|
||||
TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> const& duration)
|
||||
|
||||
@@ -597,15 +597,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
|
||||
if (caster && caster != me) // Areatrigger cast
|
||||
{
|
||||
caster->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED));
|
||||
caster->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.castFlags & SMARTCAST_TRIGGERED));
|
||||
}
|
||||
else if (me && (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell)))
|
||||
else if (me && (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell)))
|
||||
{
|
||||
if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
|
||||
if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS)
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
// Xinef: flag usable only if caster has max dist set
|
||||
if ((e.action.cast.flags & SMARTCAST_COMBAT_MOVE) && GetCasterMaxDist() > 0.0f && me->GetMaxPower(GetCasterPowerType()) > 0)
|
||||
if ((e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE) && GetCasterMaxDist() > 0.0f && me->GetMaxPower(GetCasterPowerType()) > 0)
|
||||
{
|
||||
// Xinef: check mana case only and operate movement accordingly, LoS and range is checked in targetet movement generator
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell);
|
||||
@@ -623,12 +623,45 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
}
|
||||
|
||||
me->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED));
|
||||
me->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.castFlags & SMARTCAST_TRIGGERED));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SELF_CAST:
|
||||
{
|
||||
if (targets.empty())
|
||||
break;
|
||||
|
||||
if (e.action.cast.targetsLimit)
|
||||
Acore::Containers::RandomResize(targets, e.action.cast.targetsLimit);
|
||||
|
||||
TriggerCastFlags triggerFlags = TRIGGERED_NONE;
|
||||
if (e.action.cast.castFlags & SMARTCAST_TRIGGERED)
|
||||
{
|
||||
if (e.action.cast.triggerFlags)
|
||||
triggerFlags = TriggerCastFlags(e.action.cast.triggerFlags);
|
||||
else
|
||||
triggerFlags = TRIGGERED_FULL_MASK;
|
||||
}
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
Unit* uTarget = target->ToUnit();
|
||||
if (!uTarget)
|
||||
continue;
|
||||
|
||||
if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !uTarget->HasAura(e.action.cast.spell))
|
||||
{
|
||||
if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS)
|
||||
uTarget->InterruptNonMeleeSpells(false);
|
||||
|
||||
uTarget->CastSpell(uTarget, e.action.cast.spell, triggerFlags);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_INVOKER_CAST:
|
||||
{
|
||||
Unit* tempLastInvoker = GetLastInvoker(unit); // xinef: can be used for area triggers cast
|
||||
@@ -638,7 +671,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (targets.empty())
|
||||
break;
|
||||
|
||||
if (e.action.cast.targetsLimit > 0 && targets.size() > e.action.cast.targetsLimit)
|
||||
if (e.action.cast.targetsLimit)
|
||||
Acore::Containers::RandomResize(targets, e.action.cast.targetsLimit);
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
@@ -646,12 +679,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (!IsUnit(target))
|
||||
continue;
|
||||
|
||||
if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell))
|
||||
if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell))
|
||||
{
|
||||
if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
|
||||
if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS)
|
||||
tempLastInvoker->InterruptNonMeleeSpells(false);
|
||||
|
||||
tempLastInvoker->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED));
|
||||
tempLastInvoker->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.castFlags & SMARTCAST_TRIGGERED));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4143,7 +4176,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
// delay spell cast event if another spell is being casted
|
||||
if (e.GetActionType() == SMART_ACTION_CAST)
|
||||
{
|
||||
if (!(e.action.cast.flags & (SMARTCAST_INTERRUPT_PREVIOUS | SMARTCAST_TRIGGERED)))
|
||||
if (!(e.action.cast.castFlags & (SMARTCAST_INTERRUPT_PREVIOUS | SMARTCAST_TRIGGERED)))
|
||||
{
|
||||
if (me && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
@@ -4402,7 +4435,7 @@ void SmartScript::OnInitialize(WorldObject* obj, AreaTrigger const* at)
|
||||
}
|
||||
|
||||
// Xinef: if smartcast combat move flag is present
|
||||
if (i->GetActionType() == SMART_ACTION_CAST && (i->action.cast.flags & SMARTCAST_COMBAT_MOVE))
|
||||
if (i->GetActionType() == SMART_ACTION_CAST && (i->action.cast.castFlags & SMARTCAST_COMBAT_MOVE))
|
||||
{
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i->action.cast.spell))
|
||||
{
|
||||
|
||||
@@ -409,7 +409,7 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
|
||||
case SMART_TARGET_INVOKER_PARTY:
|
||||
if (e.GetScriptType() != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && e.GetEventType() != SMART_EVENT_LINK && !EventHasInvoker(e.event.type))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invoker target, but action does not provide any invoker!", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invoker target, but event does not provide any invoker!", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -620,7 +620,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_THREAT_SINGLE_PCT: return sizeof(SmartAction::threatPCT);
|
||||
case SMART_ACTION_THREAT_ALL_PCT: return sizeof(SmartAction::threatPCT);
|
||||
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: return sizeof(SmartAction::quest);
|
||||
//case SMART_ACTION_RESERVED_16: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_RESERVED_16: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_SET_EMOTE_STATE: return sizeof(SmartAction::emote);
|
||||
case SMART_ACTION_SET_UNIT_FLAG: return sizeof(SmartAction::unitFlag);
|
||||
case SMART_ACTION_REMOVE_UNIT_FLAG: return sizeof(SmartAction::unitFlag);
|
||||
@@ -690,6 +690,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_ADD_NPC_FLAG: return sizeof(SmartAction::flag);
|
||||
case SMART_ACTION_REMOVE_NPC_FLAG: return sizeof(SmartAction::flag);
|
||||
case SMART_ACTION_SIMPLE_TALK: return sizeof(SmartAction::simpleTalk);
|
||||
case SMART_ACTION_SELF_CAST: return sizeof(SmartAction::cast);
|
||||
case SMART_ACTION_INVOKER_CAST: return sizeof(SmartAction::cast);
|
||||
case SMART_ACTION_CROSS_CAST: return sizeof(SmartAction::crossCast);
|
||||
case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: return sizeof(SmartAction::randTimedActionList);
|
||||
@@ -733,22 +734,21 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT: return sizeof(SmartAction::randomTimedEvent);
|
||||
case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS: return NO_PARAMS;
|
||||
// case SMART_ACTION_PAUSE_MOVEMENT: return sizeof(SmartAction::pauseMovement);
|
||||
//case SMART_ACTION_PLAY_ANIMKIT: return sizeof(SmartAction::raw);
|
||||
//case SMART_ACTION_SCENE_PLAY: return sizeof(SmartAction::raw);
|
||||
//case SMART_ACTION_SCENE_CANCEL: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_PLAY_ANIMKIT: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_SCENE_PLAY: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_SCENE_CANCEL: return sizeof(SmartAction::raw);
|
||||
// case SMART_ACTION_SPAWN_SPAWNGROUP: return sizeof(SmartAction::groupSpawn);
|
||||
// case SMART_ACTION_DESPAWN_SPAWNGROUP: return sizeof(SmartAction::groupSpawn);
|
||||
// case SMART_ACTION_RESPAWN_BY_SPAWNID: return sizeof(SmartAction::respawnData);
|
||||
// case SMART_ACTION_INVOKER_CAST: return sizeof(SmartAction::cast);
|
||||
case SMART_ACTION_PLAY_CINEMATIC: return sizeof(SmartAction::cinematic);
|
||||
case SMART_ACTION_SET_MOVEMENT_SPEED: return sizeof(SmartAction::movementSpeed);
|
||||
//case SMART_ACTION_PLAY_SPELL_VISUAL_KIT: return sizeof(SmartAction::raw);
|
||||
// case SMART_ACTION_PLAY_SPELL_VISUAL_KIT: return sizeof(SmartAction::raw);
|
||||
// case SMART_ACTION_OVERRIDE_LIGHT: return sizeof(SmartAction::overrideLight);
|
||||
// case SMART_ACTION_OVERRIDE_WEATHER: return sizeof(SmartAction::overrideWeather);
|
||||
//case SMART_ACTION_SET_AI_ANIM_KIT: return sizeof(SmartAction::raw);
|
||||
// case SMART_ACTION_SET_AI_ANIM_KIT: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_SET_HOVER: return sizeof(SmartAction::setHover);
|
||||
case SMART_ACTION_SET_HEALTH_PCT: return sizeof(SmartAction::setHealthPct);
|
||||
//case SMART_ACTION_CREATE_CONVERSATION: return sizeof(SmartAction::raw);
|
||||
// case SMART_ACTION_CREATE_CONVERSATION: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_MOVE_TO_POS_TARGET: return sizeof(SmartAction::moveToPos);
|
||||
case SMART_ACTION_EXIT_VEHICLE: return NO_PARAMS;
|
||||
case SMART_ACTION_SET_UNIT_MOVEMENT_FLAGS: return sizeof(SmartAction::movementFlag);
|
||||
@@ -1438,11 +1438,14 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_CAST:
|
||||
case SMART_ACTION_INVOKER_CAST:
|
||||
if (!IsSpellValid(e, e.action.cast.spell))
|
||||
if (e.GetScriptType() != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && e.GetEventType() != SMART_EVENT_LINK && !EventHasInvoker(e.event.type))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invoker cast action, but event does not provide any invoker!", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SMART_ACTION_CAST:
|
||||
case SMART_ACTION_CROSS_CAST:
|
||||
if (!IsSpellValid(e, e.action.crossCast.spell))
|
||||
return false;
|
||||
|
||||
@@ -607,7 +607,7 @@ enum SMART_ACTION
|
||||
SMART_ACTION_ADD_NPC_FLAG = 82, // Flags
|
||||
SMART_ACTION_REMOVE_NPC_FLAG = 83, // Flags
|
||||
SMART_ACTION_SIMPLE_TALK = 84, // groupID, can be used to make players say groupID, Text_over event is not triggered, whisper can not be used (Target units will say the text)
|
||||
SMART_ACTION_INVOKER_CAST = 85, // spellID, castFlags, if avaliable, last used invoker will cast spellId with castFlags on targets
|
||||
SMART_ACTION_SELF_CAST = 85, // spellID, castFlags
|
||||
SMART_ACTION_CROSS_CAST = 86, // spellID, castFlags, CasterTargetType, CasterTarget param1, CasterTarget param2, CasterTarget param3, ( + the origonal target fields as Destination target), CasterTargets will cast spellID on all Targets (use with caution if targeting multiple * multiple units)
|
||||
SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST = 87, // script9 ids 1-9
|
||||
SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST = 88, // script9 id min, max
|
||||
@@ -656,8 +656,8 @@ enum SMART_ACTION
|
||||
SMART_ACTION_SPAWN_SPAWNGROUP = 131, /// @todo: NOT SUPPORTED YET
|
||||
SMART_ACTION_DESPAWN_SPAWNGROUP = 132, /// @todo: NOT SUPPORTED YET
|
||||
SMART_ACTION_RESPAWN_BY_SPAWNID = 133, /// @todo: NOT SUPPORTED YET
|
||||
// SMART_ACTION_INVOKER_CAST = 134, /// @todo: solve name conflicts
|
||||
SMART_ACTION_PLAY_CINEMATIC = 135, // entry
|
||||
SMART_ACTION_INVOKER_CAST = 134, // spellID, castFlags
|
||||
SMART_ACTION_PLAY_CINEMATIC = 135, // entry, cinematic
|
||||
SMART_ACTION_SET_MOVEMENT_SPEED = 136, // movementType, speedInteger, speedFraction
|
||||
|
||||
SMART_ACTION_SET_HEALTH_PCT = 142, // percent
|
||||
@@ -801,7 +801,8 @@ struct SmartAction
|
||||
struct
|
||||
{
|
||||
uint32 spell;
|
||||
uint32 flags;
|
||||
uint32 castFlags;
|
||||
uint32 triggerFlags;
|
||||
uint32 targetsLimit;
|
||||
} cast;
|
||||
|
||||
|
||||
@@ -4575,6 +4575,8 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMo
|
||||
// only way correctly remove all auras from list
|
||||
//if (removedAuras != m_removedAurasCount) new aura may be added
|
||||
i = m_appliedAuras.begin();
|
||||
|
||||
sScriptMgr->OnAuraRemove(this, aurApp, removeMode);
|
||||
}
|
||||
|
||||
void Unit::_UnapplyAura(AuraApplication* aurApp, AuraRemoveMode removeMode)
|
||||
@@ -4718,8 +4720,6 @@ void Unit::RemoveAura(AuraApplicationMap::iterator& i, AuraRemoveMode mode)
|
||||
// Remove aura - for Area and Target auras
|
||||
if (aura->GetOwner() == this)
|
||||
aura->Remove(mode);
|
||||
|
||||
sScriptMgr->OnAuraRemove(this, aurApp, mode);
|
||||
}
|
||||
|
||||
void Unit::RemoveAura(uint32 spellId, ObjectGuid caster, uint8 reqEffMask, AuraRemoveMode removeMode)
|
||||
|
||||
@@ -422,6 +422,12 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
|
||||
AuctionEntry* auction = auctionHouse->GetAuction(auctionId);
|
||||
Player* player = GetPlayer();
|
||||
|
||||
if (!sScriptMgr->CanPlaceAuctionBid(player, auction))
|
||||
{
|
||||
SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_RESTRICTED_ACCOUNT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!auction || auction->owner == player->GetGUID())
|
||||
{
|
||||
//you cannot bid your own auction:
|
||||
|
||||
@@ -614,6 +614,21 @@ void ScriptMgr::OnQuestRewardItem(Player* player, Item* item, uint32 count)
|
||||
});
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanPlaceAuctionBid(Player* player, AuctionEntry* auction)
|
||||
{
|
||||
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript *script)
|
||||
{
|
||||
return !script->CanPlaceAuctionBid(player, auction);
|
||||
});
|
||||
|
||||
if (ret && *ret)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptMgr::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll)
|
||||
{
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
|
||||
@@ -1192,6 +1192,9 @@ public:
|
||||
// After receiving item as a quest reward
|
||||
virtual void OnQuestRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { }
|
||||
|
||||
// When placing a bid or buying out an auction
|
||||
[[nodiscard]] virtual bool CanPlaceAuctionBid(Player* /*player*/, AuctionEntry* /*auction*/) { return true; }
|
||||
|
||||
// After receiving item as a group roll reward
|
||||
virtual void OnGroupRollRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, RollVote /*voteType*/, Roll* /*roll*/) { }
|
||||
|
||||
@@ -2331,6 +2334,7 @@ public: /* PlayerScript */
|
||||
void OnStoreNewItem(Player* player, Item* item, uint32 count);
|
||||
void OnCreateItem(Player* player, Item* item, uint32 count);
|
||||
void OnQuestRewardItem(Player* player, Item* item, uint32 count);
|
||||
bool CanPlaceAuctionBid(Player* player, AuctionEntry* auction);
|
||||
void OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll);
|
||||
bool OnBeforeOpenItem(Player* player, Item* item);
|
||||
bool OnBeforePlayerQuestComplete(Player* player, uint32 quest_id);
|
||||
|
||||
@@ -98,21 +98,21 @@ struct boss_ambassador_hellmaw : public BossAI
|
||||
}
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SPELL_CORROSIVE, urand(5000, 10000));
|
||||
events.ScheduleEvent(EVENT_SPELL_CORROSIVE, urand(23050, 30350));
|
||||
|
||||
scheduler.Schedule(5s, 10s, [this](TaskContext context)
|
||||
scheduler.Schedule(23050ms, 30350ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CORROSIVE_ACID);
|
||||
context.Repeat(15s, 25s);
|
||||
}).Schedule(15s, 20s, [this](TaskContext context)
|
||||
context.Repeat(23050ms, 30350ms);
|
||||
}).Schedule(23s, 33s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_FEAR);
|
||||
context.Repeat(20s, 35s);
|
||||
context.Repeat(23s, 33s);
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(5min, [this](TaskContext)
|
||||
scheduler.Schedule(3min, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
});
|
||||
|
||||
@@ -85,10 +85,10 @@ public:
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SPELL_INCITE, 20000);
|
||||
events.ScheduleEvent(EVENT_SPELL_INCITE, 24000);
|
||||
events.ScheduleEvent(EVENT_INCITE_WAIT, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 0);
|
||||
events.ScheduleEvent(EVENT_SPELL_KNOCKBACK, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_KNOCKBACK, urand(16950, 26350));
|
||||
|
||||
if (instance)
|
||||
instance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS);
|
||||
@@ -127,18 +127,18 @@ public:
|
||||
DoResetThreatList();
|
||||
InciteChaos = true;
|
||||
events.DelayEvents(15000);
|
||||
events.RepeatEvent(40000);
|
||||
events.RepeatEvent(urand(50000, 70000));
|
||||
events.ScheduleEvent(EVENT_INCITE_WAIT, 15000);
|
||||
break;
|
||||
}
|
||||
case EVENT_SPELL_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_CHARGE, false);
|
||||
events.RepeatEvent(urand(15000, 25000));
|
||||
events.RepeatEvent(urand(30000, 50000));
|
||||
break;
|
||||
case EVENT_SPELL_KNOCKBACK:
|
||||
me->CastSpell(me, SPELL_WAR_STOMP, false);
|
||||
events.RepeatEvent(urand(18000, 24000));
|
||||
events.RepeatEvent(urand(16950, 26350));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,18 +47,20 @@ enum GrandmasterVorpil
|
||||
EVENT_SPELL_SHADOWBOLT = 1,
|
||||
EVENT_SPELL_DRAWSHADOWS = 2,
|
||||
EVENT_SUMMON_TRAVELER = 3,
|
||||
EVENT_SPELL_BANISH = 4
|
||||
EVENT_SPELL_BANISH = 4,
|
||||
EVENT_SPELL_RAIN_OF_FIRE = 5
|
||||
};
|
||||
|
||||
float VorpilPosition[3] = {-252.8820f, -264.3030f, 17.1f};
|
||||
float VorpilPosition[3] = {-253.548f, -263.646f, 17.0864f};
|
||||
|
||||
float VoidPortalCoords[5][3] =
|
||||
//x, y, z, and orientation
|
||||
float VoidPortalCoords[5][4] =
|
||||
{
|
||||
{-283.5894f, -239.5718f, 12.7f},
|
||||
{-306.5853f, -258.4539f, 12.7f},
|
||||
{-295.8789f, -269.0899f, 12.7f},
|
||||
{-209.3401f, -262.7564f, 17.1f},
|
||||
{-261.4533f, -297.3298f, 17.1f}
|
||||
{-208.411f, -263.652f, 17.086313f, 3.121870040893554687f}, //portal A 33566
|
||||
{-261.676f, -297.69f, 17.087011f, 1.360249996185302734f}, //portal B 33614
|
||||
{-282.272f, -240.432f, 12.683899f, 5.580170154571533203f}, //portal C 33615
|
||||
{-291.833f, -268.595f, 12.682545f, 0.047733999788761138f}, //portal D 33567
|
||||
{-303.966f, -255.759f, 12.683404f, 6.012829780578613281f} //portal E 33616
|
||||
};
|
||||
|
||||
class boss_grandmaster_vorpil : public CreatureScript
|
||||
@@ -85,6 +87,8 @@ public:
|
||||
|
||||
bool sayIntro, sayHelp;
|
||||
|
||||
int count = 0;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
sayHelp = false;
|
||||
@@ -98,13 +102,13 @@ public:
|
||||
void summonPortals()
|
||||
{
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 3000000);
|
||||
me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], VoidPortalCoords[i][3], TEMPSUMMON_CORPSE_DESPAWN, 3000000);
|
||||
}
|
||||
|
||||
void spawnVoidTraveler()
|
||||
{
|
||||
uint8 pos = urand(0, 4);
|
||||
me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], VoidPortalCoords[pos][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
if (!sayHelp)
|
||||
{
|
||||
Talk(SAY_HELP);
|
||||
@@ -112,6 +116,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int counterVoidSpawns(int count)
|
||||
{
|
||||
int timer = 0;
|
||||
switch(count)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
timer = 13300;
|
||||
break;
|
||||
case 3:
|
||||
timer = 12100;
|
||||
break;
|
||||
case 4:
|
||||
timer = 10900;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
timer = 9700;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
timer = 7200;
|
||||
break;
|
||||
case 9:
|
||||
timer = 6000;
|
||||
break;
|
||||
default:
|
||||
timer = 4800;
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
@@ -141,14 +177,17 @@ public:
|
||||
Talk(SAY_AGGRO);
|
||||
summonPortals();
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOWBOLT, urand(7000, 14000));
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAWSHADOWS, 45000);
|
||||
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOWBOLT, urand(9700, 20000));
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAWSHADOWS, 36400);
|
||||
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10900);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SPELL_BANISH, 17000);
|
||||
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_BANISH, urand(17000, 28000));
|
||||
}
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
@@ -172,19 +211,21 @@ public:
|
||||
{
|
||||
case EVENT_SPELL_SHADOWBOLT:
|
||||
me->CastSpell(me, SPELL_SHADOWBOLT_VOLLEY, false);
|
||||
events.RepeatEvent(urand(15000, 30000));
|
||||
events.RepeatEvent(urand(9700, 20000));
|
||||
break;
|
||||
case EVENT_SPELL_BANISH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30, false))
|
||||
me->CastSpell(target, SPELL_BANISH, false);
|
||||
events.RepeatEvent(16000);
|
||||
events.RepeatEvent(urand(17000, 28000));
|
||||
break;
|
||||
case EVENT_SUMMON_TRAVELER:
|
||||
spawnVoidTraveler();
|
||||
events.RepeatEvent(HealthBelowPct(20) ? 5000 : 10000);
|
||||
count++;
|
||||
events.RepeatEvent(counterVoidSpawns(count));
|
||||
break;
|
||||
case EVENT_SPELL_DRAWSHADOWS:
|
||||
{
|
||||
me->CastSpell(me, SPELL_DRAW_SHADOWS, true);
|
||||
Map* map = me->GetMap();
|
||||
Map::PlayerList const& PlayerList = map->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
@@ -193,15 +234,15 @@ public:
|
||||
player->TeleportTo(me->GetMapId(), VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT);
|
||||
|
||||
me->NearTeleportTo(VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0.0f);
|
||||
me->CastSpell(me, SPELL_DRAW_SHADOWS, true);
|
||||
me->CastSpell(me, SPELL_RAIN_OF_FIRE_N);
|
||||
|
||||
events.RepeatEvent(24000);
|
||||
events.DelayEvents(6000);
|
||||
events.ScheduleEvent(EVENT_SPELL_RAIN_OF_FIRE, 1000);
|
||||
events.RepeatEvent(urand(36400, 44950));
|
||||
break;
|
||||
}
|
||||
case EVENT_SPELL_RAIN_OF_FIRE:
|
||||
me->CastSpell(me, DUNGEON_MODE(SPELL_RAIN_OF_FIRE_N, SPELL_RAIN_OF_FIRE_H));
|
||||
events.DelayEvents(6000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,10 +24,15 @@ enum Murmur
|
||||
{
|
||||
EMOTE_SONIC_BOOM = 0,
|
||||
|
||||
SPELL_SUPPRESSION = 33332,
|
||||
SPELL_SHOCKWAVE = 33686,
|
||||
SPELL_SHOCKWAVE_SERVERSIDE = 33673,
|
||||
SPELL_RESONANCE = 33657,
|
||||
SPELL_MAGNETIC_PULL = 33689,
|
||||
SPELL_SONIC_SHOCK = 38797,
|
||||
SPELL_THUNDERING_STORM = 39365,
|
||||
SPELL_MURMUR_WRATH_AOE = 33329,
|
||||
SPELL_MURMUR_WRATH = 33331,
|
||||
|
||||
SPELL_SONIC_BOOM_CAST_N = 33923,
|
||||
SPELL_SONIC_BOOM_CAST_H = 38796,
|
||||
@@ -36,194 +41,217 @@ enum Murmur
|
||||
SPELL_MURMURS_TOUCH_N = 33711,
|
||||
SPELL_MURMURS_TOUCH_H = 38794,
|
||||
|
||||
EVENT_SPELL_SONIC_BOOM = 1,
|
||||
EVENT_SPELL_SONIC_BOOM_EFFECT = 2,
|
||||
EVENT_SPELL_MURMURS_TOUCH = 3,
|
||||
EVENT_SPELL_RESONANCE = 4,
|
||||
EVENT_SPELL_MAGNETIC = 5,
|
||||
EVENT_SPELL_THUNDERING = 6,
|
||||
EVENT_SPELL_SONIC_SHOCK = 7
|
||||
GROUP_RESONANCE = 1,
|
||||
GROUP_OOC_CAST = 2,
|
||||
|
||||
GUID_MURMUR_NPCS = 1
|
||||
};
|
||||
|
||||
class boss_murmur : public CreatureScript
|
||||
enum Creatures
|
||||
{
|
||||
public:
|
||||
boss_murmur() : CreatureScript("boss_murmur") { }
|
||||
NPC_CABAL_SPELLBINDER = 18639
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
struct boss_murmur : public BossAI
|
||||
{
|
||||
boss_murmur(Creature* creature) : BossAI(creature, DATA_MURMUR)
|
||||
{
|
||||
return GetShadowLabyrinthAI<boss_murmurAI>(creature);
|
||||
SetCombatMovement(false);
|
||||
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
struct boss_murmurAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_murmurAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
_Reset();
|
||||
me->SetHealth(me->CountPctFromMaxHealth(40));
|
||||
me->ResetPlayerDamageReq();
|
||||
CastSupressionOOC();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
me->SetHealth(me->CountPctFromMaxHealth(40));
|
||||
me->ResetPlayerDamageReq();
|
||||
|
||||
if (instance)
|
||||
instance->SetData(DATA_MURMUREVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_SONIC_BOOM, 30000);
|
||||
events.ScheduleEvent(EVENT_SPELL_MURMURS_TOUCH, urand(8000, 20000));
|
||||
events.ScheduleEvent(EVENT_SPELL_RESONANCE, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_MAGNETIC, urand(15000, 30000));
|
||||
if (IsHeroic())
|
||||
void CastSupressionOOC()
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([this] {
|
||||
if (me->FindNearestCreature(NPC_CABAL_SPELLBINDER, 35.0f))
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_THUNDERING, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SONIC_SHOCK, 10000);
|
||||
me->CastCustomSpell(SPELL_SUPPRESSION, SPELLVALUE_MAX_TARGETS, 5, (Unit*)nullptr, false);
|
||||
CastSupressionOOC();
|
||||
}
|
||||
}, 3600ms, 10900ms, GROUP_OOC_CAST);
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
return me->IsWithinMeleeRange(victim);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (me->GetThreatMgr().GetThreatList().empty())
|
||||
{
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldCastResonance()
|
||||
{
|
||||
if (Unit* victim = me->GetVictim())
|
||||
{
|
||||
if (!me->IsWithinMeleeRange(victim))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (instance)
|
||||
instance->SetData(DATA_MURMUREVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SetData(DATA_MURMUREVENT, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
if (Unit* victimTarget = victim->GetVictim())
|
||||
{
|
||||
case EVENT_SPELL_SONIC_BOOM:
|
||||
Talk(EMOTE_SONIC_BOOM);
|
||||
me->CastSpell(me, DUNGEON_MODE(SPELL_SONIC_BOOM_CAST_N, SPELL_SONIC_BOOM_CAST_H), false);
|
||||
events.RepeatEvent(28500);
|
||||
events.DelayEvents(1500);
|
||||
events.ScheduleEvent(EVENT_SPELL_SONIC_BOOM_EFFECT, 0);
|
||||
return;
|
||||
case EVENT_SPELL_SONIC_BOOM_EFFECT:
|
||||
me->CastSpell(me, DUNGEON_MODE(SPELL_SONIC_BOOM_EFFECT_N, SPELL_SONIC_BOOM_EFFECT_H), true);
|
||||
break;
|
||||
case EVENT_SPELL_MURMURS_TOUCH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 80.0f, true))
|
||||
me->CastSpell(target, DUNGEON_MODE(SPELL_MURMURS_TOUCH_N, SPELL_MURMURS_TOUCH_H), false);
|
||||
events.RepeatEvent(urand(25000, 35000));
|
||||
break;
|
||||
case EVENT_SPELL_RESONANCE:
|
||||
if (!me->IsWithinMeleeRange(me->GetVictim()))
|
||||
me->CastSpell(me, SPELL_RESONANCE, false);
|
||||
events.RepeatEvent(5000);
|
||||
break;
|
||||
case EVENT_SPELL_MAGNETIC:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 80.0f, true))
|
||||
return victimTarget != me;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid guid, int32 index) override
|
||||
{
|
||||
if (index == GUID_MURMUR_NPCS)
|
||||
{
|
||||
if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
|
||||
{
|
||||
DoCast(creature, SPELL_MURMUR_WRATH, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
scheduler.Schedule(28s, [this](TaskContext context)
|
||||
{
|
||||
Talk(EMOTE_SONIC_BOOM);
|
||||
DoCastAOE(DUNGEON_MODE(SPELL_SONIC_BOOM_CAST_N, SPELL_SONIC_BOOM_CAST_H));
|
||||
|
||||
scheduler.Schedule(1500ms, [this](TaskContext)
|
||||
{
|
||||
DoCastAOE(DUNGEON_MODE(SPELL_SONIC_BOOM_EFFECT_N, SPELL_SONIC_BOOM_EFFECT_H), true);
|
||||
});
|
||||
|
||||
context.Repeat(34s, 40s);
|
||||
}).Schedule(14600ms, 25500ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(DUNGEON_MODE(SPELL_MURMURS_TOUCH_N, SPELL_MURMURS_TOUCH_H));
|
||||
context.Repeat(14600ms, 25500ms);
|
||||
}).Schedule(15s, 30s, [this](TaskContext context)
|
||||
{
|
||||
if (DoCastRandomTarget(SPELL_MAGNETIC_PULL, 0, 80.0f) == SPELL_CAST_OK)
|
||||
{
|
||||
context.Repeat(15s, 30s);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat(500ms);
|
||||
}
|
||||
}).Schedule(3s, [this](TaskContext context)
|
||||
{
|
||||
if (ShouldCastResonance())
|
||||
{
|
||||
if (!scheduler.IsGroupScheduled(GROUP_RESONANCE))
|
||||
{
|
||||
scheduler.Schedule(5s, 5s, GROUP_RESONANCE, [this](TaskContext context)
|
||||
{
|
||||
me->CastSpell(target, SPELL_MAGNETIC_PULL, false);
|
||||
events.RepeatEvent(urand(15000, 30000));
|
||||
return;
|
||||
}
|
||||
events.RepeatEvent(500);
|
||||
break;
|
||||
case EVENT_SPELL_THUNDERING:
|
||||
me->CastSpell(me, SPELL_THUNDERING_STORM, true);
|
||||
events.RepeatEvent(15000);
|
||||
break;
|
||||
case EVENT_SPELL_SONIC_SHOCK:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SONIC_SHOCK, false);
|
||||
events.RepeatEvent(urand(10000, 20000));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!me->isAttackReady())
|
||||
return;
|
||||
|
||||
if (!me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
ThreatContainer::StorageType threatlist = me->GetThreatMgr().GetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i)
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
|
||||
if (target->IsAlive() && me->IsWithinMeleeRange(target))
|
||||
if (ShouldCastResonance())
|
||||
{
|
||||
me->TauntApply(target);
|
||||
break;
|
||||
DoCastAOE(SPELL_RESONANCE);
|
||||
context.Repeat(6s, 18s);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
class spell_murmur_sonic_boom_effect : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_murmur_sonic_boom_effect() : SpellScriptLoader("spell_murmur_sonic_boom_effect") { }
|
||||
|
||||
class spell_murmur_sonic_boom_effect_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_murmur_sonic_boom_effect_SpellScript)
|
||||
|
||||
public:
|
||||
spell_murmur_sonic_boom_effect_SpellScript() : SpellScript() { }
|
||||
|
||||
void RecalculateDamage()
|
||||
if (IsHeroic())
|
||||
{
|
||||
SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(90));
|
||||
scheduler.Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_THUNDERING_STORM);
|
||||
context.Repeat(6050ms, 10s);
|
||||
}).Schedule(3650ms, 9150ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SONIC_SHOCK);
|
||||
context.Repeat(9150ms, 10s);
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_murmur_sonic_boom_effect_SpellScript::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_murmur_sonic_boom_effect_SpellScript();
|
||||
me->m_Events.CancelEventGroup(GROUP_OOC_CAST);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_murmur_thundering_storm : public SpellScriptLoader
|
||||
class spell_murmur_thundering_storm : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_murmur_thundering_storm);
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 100.0f, true));
|
||||
targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 25.0f, false));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_murmur_thundering_storm::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 33711/38794 - Murmur's Touch
|
||||
class spell_murmur_touch : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_murmur_touch);
|
||||
|
||||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
{
|
||||
if (GetTarget())
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_SHOCKWAVE, true);
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_SHOCKWAVE_SERVERSIDE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_murmur_touch::HandleAfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_murmur_sonic_boom_effect : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_murmur_sonic_boom_effect)
|
||||
|
||||
public:
|
||||
spell_murmur_thundering_storm() : SpellScriptLoader("spell_murmur_thundering_storm") { }
|
||||
spell_murmur_sonic_boom_effect() : SpellScript() { }
|
||||
|
||||
class spell_murmur_thundering_storm_SpellScript : public SpellScript
|
||||
void RecalculateDamage()
|
||||
{
|
||||
PrepareSpellScript(spell_murmur_thundering_storm_SpellScript);
|
||||
SetHitDamage(GetHitUnit()->CountPctFromCurHealth(80));
|
||||
}
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 100.0f, true));
|
||||
targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 25.0f, false));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_murmur_thundering_storm_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_murmur_thundering_storm_SpellScript();
|
||||
OnHit += SpellHitFn(spell_murmur_sonic_boom_effect::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_murmur()
|
||||
{
|
||||
new boss_murmur();
|
||||
new spell_murmur_sonic_boom_effect();
|
||||
new spell_murmur_thundering_storm();
|
||||
RegisterShadowLabyrinthCreatureAI(boss_murmur);
|
||||
RegisterSpellScript(spell_murmur_thundering_storm);
|
||||
RegisterSpellScript(spell_murmur_touch);
|
||||
RegisterSpellScript(spell_murmur_sonic_boom_effect);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ enum slData
|
||||
TYPE_HELLMAW = 1,
|
||||
DATA_BLACKHEARTTHEINCITEREVENT = 2,
|
||||
DATA_GRANDMASTERVORPILEVENT = 3,
|
||||
DATA_MURMUREVENT = 4,
|
||||
MAX_ENCOUNTER = 5
|
||||
DATA_MURMUR = 4,
|
||||
DATA_MURMUREVENT = 5,
|
||||
MAX_ENCOUNTER = 6
|
||||
};
|
||||
|
||||
enum slNPCandGO
|
||||
|
||||
@@ -3663,7 +3663,9 @@ class spell_gen_ds_flush_knockback : public SpellScript
|
||||
60864 - Jaws of Death (spell_gen_default_count_pct_from_max_hp)
|
||||
38441 - Cataclysmic Bolt (spell_gen_50pct_count_pct_from_max_hp)
|
||||
66316, 67100, 67101, 67102 - Spinning Pain Spike (spell_gen_50pct_count_pct_from_max_hp)
|
||||
41360 - L5 Arcane Charge (spell_gen_100pct_count_pct_from_max_hp) */
|
||||
41360 - L5 Arcane Charge (spell_gen_100pct_count_pct_from_max_hp)
|
||||
33711/38794 - Murmur's Touch
|
||||
*/
|
||||
class spell_gen_count_pct_from_max_hp : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_gen_count_pct_from_max_hp)
|
||||
|
||||
Reference in New Issue
Block a user