This commit is contained in:
Jelle Meeus
2025-07-13 10:24:11 +02:00
parent 1c51dcea1d
commit 64c0fde3d8

View File

@@ -15,7 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "ScriptMgr.h" #include "CreatureScript.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SpellInfo.h" #include "SpellInfo.h"
#include "naxxramas.h" #include "naxxramas.h"
@@ -36,30 +36,19 @@ enum Spells
SPELL_POISON_BOLT_VOLLEY = 28796, SPELL_POISON_BOLT_VOLLEY = 28796,
SPELL_RAIN_OF_FIRE = 28794, SPELL_RAIN_OF_FIRE = 28794,
SPELL_FRENZY = 28798, SPELL_FRENZY = 28798,
SPELL_WIDOWS_EMBRACE = 28732 SPELL_WIDOWS_EMBRACE = 28732,
SPELL_MINION_WIDOWS_EMBRACE = 54097
}; };
enum SpellValues : int32 enum Groups
{ {
POISON_BOLT_VOLLEY_BP0 = 1224, GROUP_FRENZY = 1
POISON_BOLT_VOLLEY_BP1 = 416,
RAIN_OF_FIRE_BP0 = 1849,
FRENZY_BP0 = 149,
FRENZY_BP1 = 74,
FRENZY_BP2 = 49
};
enum Events
{
EVENT_POISON_BOLT = 1,
EVENT_RAIN_OF_FIRE = 2,
EVENT_FRENZY = 3
}; };
enum Misc enum Misc
{ {
NPC_NAXXRAMAS_WORSHIPPER = 351081, // NPC_NAXXRAMAS_WORSHIPPER = 16506,
NPC_NAXXRAMAS_FOLLOWER = 351080 // NPC_NAXXRAMAS_FOLLOWER = 16505
}; };
class boss_faerlina_40 : public CreatureScript class boss_faerlina_40 : public CreatureScript
@@ -74,16 +63,7 @@ public:
struct boss_faerlina_40AI : public BossAI struct boss_faerlina_40AI : public BossAI
{ {
boss_faerlina_40AI(Creature* c) : BossAI(c, BOSS_FAERLINA), summons(me) boss_faerlina_40AI(Creature* c) : BossAI(c, BOSS_FAERLINA), _introDone(false) { }
{
pInstance = me->GetInstanceScript();
sayGreet = false;
}
InstanceScript* pInstance;
EventMap events;
SummonList summons;
bool sayGreet;
void SummonHelpers() void SummonHelpers()
{ {
@@ -91,28 +71,18 @@ public:
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3344.3f, -3618.31f, 261.08f, 4.69494f); me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3344.3f, -3618.31f, 261.08f, 4.69494f);
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3356.71f, -3620.05f, 261.08f, 4.57276f); me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3356.71f, -3620.05f, 261.08f, 4.57276f);
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3350.26f, -3619.11f, 261.08f, 4.67748f); me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3350.26f, -3619.11f, 261.08f, 4.67748f);
// if (Is25ManRaid())
{
me->SummonCreature(NPC_NAXXRAMAS_FOLLOWER, 3347.49f, -3617.59f, 261.0f, 4.49f); me->SummonCreature(NPC_NAXXRAMAS_FOLLOWER, 3347.49f, -3617.59f, 261.0f, 4.49f);
me->SummonCreature(NPC_NAXXRAMAS_FOLLOWER, 3359.64f, -3619.16f, 261.0f, 4.56f); me->SummonCreature(NPC_NAXXRAMAS_FOLLOWER, 3359.64f, -3619.16f, 261.0f, 4.56f);
} }
void JustSummoned(Creature* cr) override
{
summons.Summon(cr);
} }
void Reset() override void Reset() override
{ {
BossAI::Reset(); BossAI::Reset();
events.Reset();
summons.DespawnAll(); summons.DespawnAll();
SummonHelpers(); SummonHelpers();
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_FAERLINA_WEB)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
} }
void JustEngagedWith(Unit* who) override void JustEngagedWith(Unit* who) override
@@ -121,122 +91,54 @@ public:
me->CallForHelp(VISIBLE_RANGE); me->CallForHelp(VISIBLE_RANGE);
summons.DoZoneInCombat(); summons.DoZoneInCombat();
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_POISON_BOLT, urand(7000, 12000));
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, urand(8000, 12000)); ScheduleTimedEvent(7s, 15s, [&]{
events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000), 1); if (!me->HasAura(SPELL_WIDOWS_EMBRACE))
events.SetPhase(1); DoCastVictim(SPELL_POISON_BOLT_VOLLEY);
if (pInstance) }, 7s, 15s);
ScheduleTimedEvent(8s, 18s, [&] {
DoCastRandomTarget(SPELL_RAIN_OF_FIRE);
}, 8s, 18s);
scheduler.Schedule(60s, 80s, GROUP_FRENZY, [this](TaskContext context) {
if (!me->HasAura(SPELL_WIDOWS_EMBRACE))
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_FAERLINA_WEB))) Talk(SAY_FRENZY);
{ Talk(EMOTE_FRENZY);
go->SetGoState(GO_STATE_READY); DoCastSelf(SPELL_FRENZY, true);
} context.Repeat(1min);
} }
else
context.Repeat(30s);
});
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
if (!sayGreet && who->GetTypeId() == TYPEID_PLAYER) if (!_introDone && who->IsPlayer())
{ {
Talk(SAY_GREET); Talk(SAY_GREET);
sayGreet = true; _introDone = true;
} }
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() != TYPEID_PLAYER) if (!who->IsPlayer())
return; return;
if (!urand(0, 3)) if (!urand(0, 3))
{
Talk(SAY_SLAY); Talk(SAY_SLAY);
}
if (pInstance) instance->StorePersistentData(PERSISTENT_DATA_IMMORTAL_FAIL, 1);
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
} }
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(SAY_DEATH);
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_FAERLINA_WEB)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
void UpdateAI(uint32 diff) override
{
if (!me->IsInCombat() && sayGreet)
{
for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr)
{
if (pInstance)
{
if (Creature* cr = pInstance->instance->GetCreature(*itr))
{
if (cr->IsInCombat())
DoZoneInCombat();
}
}
}
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_POISON_BOLT:
if (!me->HasAura(SPELL_WIDOWS_EMBRACE))
{
CustomSpellValues values;
int32 bp0 = POISON_BOLT_VOLLEY_BP0;
int32 bp1 = POISON_BOLT_VOLLEY_BP1;
values.AddSpellMod(SPELLVALUE_MAX_TARGETS, 10);
values.AddSpellMod(SPELLVALUE_BASE_POINT0, bp0);
values.AddSpellMod(SPELLVALUE_BASE_POINT1, bp1);
me->CastCustomSpell(SPELL_POISON_BOLT_VOLLEY, values, me, TRIGGERED_NONE, nullptr, nullptr, ObjectGuid::Empty);
}
events.RepeatEvent(urand(7000, 12000));
break;
case EVENT_RAIN_OF_FIRE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
int32 bp0 = RAIN_OF_FIRE_BP0;
me->CastCustomSpell(target, SPELL_RAIN_OF_FIRE, &bp0, 0, 0, false, nullptr, nullptr, ObjectGuid::Empty);
}
events.RepeatEvent(urand(8000, 12000));
break;
case EVENT_FRENZY:
if (!me->HasAura(SPELL_FRENZY))
{
Talk(SAY_FRENZY);
Talk(EMOTE_FRENZY);
int32 bp0 = FRENZY_BP0;
int32 bp1 = FRENZY_BP1;
int32 bp2 = FRENZY_BP2;
me->CastCustomSpell(me, SPELL_FRENZY, &bp0, &bp1, &bp2, true, nullptr, nullptr, ObjectGuid::Empty);
events.RepeatEvent(60000);
}
else
{
events.RepeatEvent(30000);
}
break;
}
DoMeleeAttackIfReady();
} }
void SpellHit(Unit* caster, SpellInfo const* spell) override void SpellHit(Unit* caster, SpellInfo const* spell) override
@@ -246,17 +148,18 @@ public:
Talk(EMOTE_WIDOWS_EMBRACE); // %s is affected by Widow's Embrace! Talk(EMOTE_WIDOWS_EMBRACE); // %s is affected by Widow's Embrace!
if (me->HasAura(SPELL_FRENZY)) if (me->HasAura(SPELL_FRENZY))
{ {
events.RescheduleEvent(EVENT_FRENZY, 60000); // You must sacrifice the worshiper AFTER she enrages if you want to stop her for the full 60 seconds. scheduler.RescheduleGroup(GROUP_FRENZY, 1min); // You must sacrifice the worshiper AFTER she enrages if you want to stop her for the full 60 seconds.
me->RemoveAurasDueToSpell(SPELL_FRENZY); me->RemoveAurasDueToSpell(SPELL_FRENZY);
pInstance->SetData(DATA_FRENZY_REMOVED, 0); // achievement instance->SetData(DATA_FRENZY_REMOVED, 0); // achievement
} }
else else
{ scheduler.RescheduleGroup(GROUP_FRENZY, 30s); // If you sacrifice the Worshiper before the enrage, it will merely delay the enrage for 30 seconds.
events.RescheduleEvent(EVENT_FRENZY, 30000); // If you sacrifice the Worshiper before the enrage, it will merely delay the enrage for 30 seconds. caster->KillSelf();
}
Unit::Kill(caster, caster);
} }
} }
private:
bool _introDone;
}; };
}; };