Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2023-04-18 09:28:55 -06:00
committed by GitHub
21 changed files with 434 additions and 220 deletions

View File

@@ -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);
});

View File

@@ -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;
}

View File

@@ -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();
}
};

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)