mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 07:48:02 +00:00
fix(Core/Scripts): Fix multiple ICC encounter regressions after threat system port (#25303)
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com> Co-authored-by: Treeston <treeston.mmoc@gmail.com> Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Co-authored-by: ccrs <ccrs@users.noreply.github.com>
This commit is contained in:
@@ -688,14 +688,14 @@ public:
|
||||
if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
// Blizzlike: ship wipes when all players are in cannons (vehicles) with nobody on deck
|
||||
// See: azerothcore/azerothcore-wotlk#17856
|
||||
bool playerOnDeck = false;
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (!player->GetVehicle() && player->IsAlive())
|
||||
playerOnDeck = true;
|
||||
});
|
||||
|
||||
// Wipe if no player is on the deck
|
||||
if (!playerOnDeck)
|
||||
{
|
||||
// Script runs on enemy ship. We want to kill our ship.
|
||||
|
||||
@@ -653,6 +653,8 @@ public:
|
||||
_lastTalkTimeBuff = 0;
|
||||
_bFrostmournePhase = false;
|
||||
_bFordringMustFallYell = false;
|
||||
me->SetRegeneratingHealth(true);
|
||||
me->SetIsCombatDisallowed(false);
|
||||
|
||||
_Reset();
|
||||
DoAction(ACTION_RESTORE_LIGHT);
|
||||
@@ -792,12 +794,15 @@ public:
|
||||
if (_phase == PHASE_THREE && HealthBelowPct(10) && !me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
_phase = PHASE_OUTRO;
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->SetIsCombatDisallowed(true);
|
||||
EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE);
|
||||
summons.DoAction(ACTION_TELEPORT_BACK, pred);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->CombatStop(true);
|
||||
me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FURY_OF_FROSTMOURNE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->CastSpell((Unit*)nullptr, SPELL_FURY_OF_FROSTMOURNE, false);
|
||||
@@ -1253,6 +1258,9 @@ public:
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (_phase == PHASE_OUTRO || _phase == PHASE_FROSTMOURNE)
|
||||
return;
|
||||
|
||||
EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE);
|
||||
summons.DoAction(ACTION_TELEPORT_BACK, pred);
|
||||
instance->SetBossState(DATA_THE_LICH_KING, FAIL);
|
||||
|
||||
@@ -508,31 +508,26 @@ public:
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
|
||||
instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, NOT_STARTED);
|
||||
_Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
checkTimer = 5000;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* target) override
|
||||
void JustEnteredCombat(Unit* target) override
|
||||
{
|
||||
if (IsEngaged())
|
||||
return;
|
||||
|
||||
if (!instance->CheckRequiredBosses(DATA_VALITHRIA_DREAMWALKER, target->ToPlayer()))
|
||||
{
|
||||
me->setActive(true);
|
||||
EnterEvadeMode();
|
||||
EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK);
|
||||
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
|
||||
return;
|
||||
}
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == DONE)
|
||||
{
|
||||
me->CombatStop();
|
||||
return;
|
||||
}
|
||||
|
||||
EngagementStart(target);
|
||||
|
||||
me->setActive(true);
|
||||
me->SetInCombatWithZone();
|
||||
DoZoneInCombat();
|
||||
instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, IN_PROGRESS);
|
||||
if (Creature* valithria = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)))
|
||||
valithria->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
@@ -547,17 +542,6 @@ public:
|
||||
(*itr)->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* target) override
|
||||
{
|
||||
if (target->IsPlayer())
|
||||
BossAI::AttackStart(target);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override
|
||||
{
|
||||
CreatureAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
@@ -565,48 +549,27 @@ public:
|
||||
return target->IsPlayer();
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
void JustExitedCombat() override
|
||||
{
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
|
||||
DoAction(ACTION_DEATH); // setActive(false) in ValithriaDespawner
|
||||
else
|
||||
_JustReachedHome();
|
||||
EngagementOver();
|
||||
|
||||
me->setActive(false);
|
||||
|
||||
if (!me->IsAlive())
|
||||
return;
|
||||
DoAction(ACTION_DEATH);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_DEATH)
|
||||
{
|
||||
instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, NOT_STARTED);
|
||||
me->m_Events.AddEventAtOffset(new ValithriaDespawner(me), 5s);
|
||||
else if (action == ACTION_ENTER_COMBAT)
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
me->SetInCombatWithZone();
|
||||
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
|
||||
lichKing->AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
return;
|
||||
|
||||
if (checkTimer <= diff)
|
||||
{
|
||||
checkTimer = 3000;
|
||||
me->SetInCombatWithZone();
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
if (Unit* target = ref->GetVictim())
|
||||
if (target->IsAlive() && target->IsPlayer() && me->GetExactDist(target) < 200.0f && !target->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_ALL))
|
||||
return;
|
||||
}
|
||||
EnterEvadeMode();
|
||||
}
|
||||
else
|
||||
checkTimer -= diff;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16 checkTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -712,7 +675,7 @@ public:
|
||||
struct npc_risen_archmageAI : public ScriptedAI
|
||||
{
|
||||
npc_risen_archmageAI(Creature* creature) : ScriptedAI(creature),
|
||||
_instance(creature->GetInstanceScript())
|
||||
_instance(creature->GetInstanceScript()), _isInitialArchmage(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -725,23 +688,34 @@ public:
|
||||
{
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 5s, 15s);
|
||||
_events.ScheduleEvent(EVENT_MANA_VOID, 15s, 25s);
|
||||
_events.ScheduleEvent(EVENT_MANA_VOID, 20s, 25s);
|
||||
_events.ScheduleEvent(EVENT_COLUMN_OF_FROST, 10s, 20s);
|
||||
_isInitialArchmage = me->GetSpawnId() != 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*target*/) override
|
||||
void JustEnteredCombat(Unit* who) override
|
||||
{
|
||||
me->FinishSpell(CURRENT_CHANNELED_SPELL, false);
|
||||
me->SetInCombatWithZone();
|
||||
if (me->GetSpawnId())
|
||||
if (IsEngaged())
|
||||
return;
|
||||
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
EngagementStart(who);
|
||||
|
||||
if (_isInitialArchmage)
|
||||
{
|
||||
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
|
||||
DoZoneInCombat(lichKing);
|
||||
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
|
||||
trigger->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
DoZoneInCombat(trigger);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_ENTER_COMBAT && !me->IsInCombat())
|
||||
me->SetInCombatWithZone();
|
||||
if (action == ACTION_ENTER_COMBAT)
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
@@ -754,10 +728,8 @@ public:
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
if (me->GetSpawnId())
|
||||
if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
me->CastSpell(me, SPELL_CORRUPTION, true);
|
||||
if (!me->IsInCombat() && me->IsAlive() && _isInitialArchmage && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
DoCastSelf(SPELL_CORRUPTION);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
@@ -796,6 +768,7 @@ public:
|
||||
private:
|
||||
EventMap _events;
|
||||
InstanceScript* _instance;
|
||||
bool _isInitialArchmage;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -345,11 +345,17 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 corpseDelay = creature->GetCorpseDelay();
|
||||
uint32 respawnDelay = creature->GetRespawnDelay();
|
||||
creature->SetCorpseDelay(1);
|
||||
creature->SetRespawnDelay(2);
|
||||
|
||||
if (CreatureData const* data = creature->GetCreatureData())
|
||||
creature->SetPosition(data->posX, data->posY, data->posZ, data->orientation);
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
creature->SetRespawnTime(5);
|
||||
creature->SetCorpseDelay(corpseDelay);
|
||||
creature->SetRespawnDelay(respawnDelay);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -730,7 +736,7 @@ public:
|
||||
{
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
_didUnderTenPercentText = false;
|
||||
_wipeCheckTimer = 3000;
|
||||
_wipeCheckTimer = 1000;
|
||||
_handledWP4 = false;
|
||||
|
||||
_events.Reset();
|
||||
@@ -868,6 +874,27 @@ public:
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!_wipeCheckTimer)
|
||||
{
|
||||
_wipeCheckTimer = 1000;
|
||||
Player* player = nullptr;
|
||||
Acore::AnyPlayerInObjectRangeCheck check(me, 60.0f);
|
||||
Acore::PlayerSearcher<Acore::AnyPlayerInObjectRangeCheck> searcher(me, player, check);
|
||||
Cell::VisitObjects(me, searcher, 60.0f);
|
||||
// wipe
|
||||
if (!player)
|
||||
{
|
||||
damage *= 100;
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
FrostwingGauntletRespawner respawner;
|
||||
Acore::CreatureWorker<FrostwingGauntletRespawner> worker(me, respawner);
|
||||
Cell::VisitObjects(me, worker, 333.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HealthBelowPct(10))
|
||||
{
|
||||
if (!_didUnderTenPercentText)
|
||||
@@ -885,37 +912,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 /*diff*/) override {}
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (_wipeCheckTimer <= diff)
|
||||
_wipeCheckTimer = 0;
|
||||
else
|
||||
_wipeCheckTimer -= diff;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
//Position pos = me->GetHomePosition();
|
||||
if (!me->isActiveObject()/* && me->GetExactDist(&pos) < 5.0f*/) // during event
|
||||
if (!me->isActiveObject())
|
||||
return;
|
||||
|
||||
if (_wipeCheckTimer <= diff)
|
||||
{
|
||||
_wipeCheckTimer = 3000;
|
||||
|
||||
Player* player = nullptr;
|
||||
Acore::AnyPlayerInObjectRangeCheck check(me, 140.0f);
|
||||
Acore::PlayerSearcher<Acore::AnyPlayerInObjectRangeCheck> searcher(me, player, check);
|
||||
Cell::VisitObjects(me, searcher, 140.0f);
|
||||
// wipe
|
||||
if (!player || me->GetExactDist(4357.0f, 2606.0f, 350.0f) > 125.0f)
|
||||
{
|
||||
//Talk(SAY_CROK_DEATH);
|
||||
FrostwingGauntletRespawner respawner;
|
||||
Acore::CreatureWorker<FrostwingGauntletRespawner> worker(me, respawner);
|
||||
Cell::VisitObjects(me, worker, 333.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
_wipeCheckTimer -= diff;
|
||||
|
||||
UpdateVictim();
|
||||
|
||||
_events.Update(diff);
|
||||
@@ -968,7 +979,7 @@ public:
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
// do not see targets inside Frostwing Halls when we are not there
|
||||
return !target->IsPlayer() && (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f) && target->GetEntry() != NPC_SINDRAGOSA;
|
||||
return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -995,18 +1006,30 @@ public:
|
||||
|
||||
struct boss_sister_svalnaAI : public BossAI
|
||||
{
|
||||
boss_sister_svalnaAI(Creature* creature) : BossAI(creature, DATA_SISTER_SVALNA)
|
||||
boss_sister_svalnaAI(Creature* creature) : BossAI(creature, DATA_SISTER_SVALNA),
|
||||
_isEventInProgress(false)
|
||||
{
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
if (!me->isDead())
|
||||
Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
_isEventInProgress = false;
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
_JustReachedHome();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetCanFly(true);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
me->SetDisableGravity(false);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -1080,6 +1103,8 @@ public:
|
||||
break;
|
||||
case ACTION_START_GAUNTLET:
|
||||
me->setActive(true);
|
||||
me->SetImmuneToAll(true);
|
||||
_isEventInProgress = true;
|
||||
events.ScheduleEvent(EVENT_SVALNA_START, 25s);
|
||||
break;
|
||||
case ACTION_RESURRECT_CAPTAINS:
|
||||
@@ -1106,16 +1131,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void JustExitedCombat() override
|
||||
{
|
||||
if (_isEventInProgress)
|
||||
return;
|
||||
CreatureAI::JustExitedCombat();
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != EFFECT_MOTION_TYPE || id != POINT_LAND)
|
||||
return;
|
||||
|
||||
_isEventInProgress = false;
|
||||
me->setActive(false);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoZoneInCombat(nullptr, 150.0f);
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||
@@ -1140,43 +1170,51 @@ public:
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->isActiveObject())
|
||||
if (!UpdateVictim() && !_isEventInProgress)
|
||||
return;
|
||||
|
||||
UpdateVictim();
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SVALNA_START:
|
||||
Talk(SAY_SVALNA_EVENT_START);
|
||||
break;
|
||||
case EVENT_SVALNA_RESURRECT:
|
||||
Talk(SAY_SVALNA_RESURRECT_CAPTAINS);
|
||||
me->CastSpell(me, SPELL_REVIVE_CHAMPION, false);
|
||||
break;
|
||||
case EVENT_SVALNA_COMBAT:
|
||||
Talk(SAY_SVALNA_AGGRO);
|
||||
break;
|
||||
case EVENT_IMPALING_SPEAR:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_IMPALING_SPEAR))
|
||||
{
|
||||
DoCast(me, SPELL_AETHER_SHIELD);
|
||||
me->AddAura(70203, me);
|
||||
DoCast(target, SPELL_IMPALING_SPEAR);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_IMPALING_SPEAR, 20s, 25s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SVALNA_START:
|
||||
Talk(SAY_SVALNA_EVENT_START);
|
||||
break;
|
||||
case EVENT_SVALNA_RESURRECT:
|
||||
Talk(SAY_SVALNA_RESURRECT_CAPTAINS);
|
||||
me->CastSpell(me, SPELL_REVIVE_CHAMPION, false);
|
||||
break;
|
||||
case EVENT_SVALNA_COMBAT:
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
Talk(SAY_SVALNA_AGGRO);
|
||||
break;
|
||||
case EVENT_IMPALING_SPEAR:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_IMPALING_SPEAR))
|
||||
{
|
||||
DoCast(me, SPELL_AETHER_SHIELD);
|
||||
me->AddAura(70203, me);
|
||||
DoCast(target, SPELL_IMPALING_SPEAR);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_IMPALING_SPEAR, 20s, 25s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isEventInProgress;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
Reference in New Issue
Block a user