Scripts/Naxxramas: Faerlina cleanup:

- Move greeting to areatrigger instead of MoveInLineOfSight hack
- Clean up add spawn handling to prevent various glitching with combinations of evade state and add aggro
- Ensure all adds are always pulled alongside the boss and vice versa
- Add missing texts.
- Fix a bug in the core that prevents castable-while-dead spells (such as Widow's Embrace) from appearing on possess bars.
This commit is contained in:
treeston
2015-10-08 20:11:19 +02:00
parent 50cf74f0db
commit 577fcf356e
5 changed files with 135 additions and 43 deletions

View File

@@ -0,0 +1,34 @@
-- farlina cleanup
-- areatrigger for greeting
DELETE FROM `areatrigger_scripts` WHERE `entry`=4115;
INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES
(4115,"at_faerlina_entrance");
DELETE FROM `creature_text` WHERE `entry`=15953 AND `groupid` IN (4,5);
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
(15953,4,0,"%s is affected by Widow's Embrace!",41,100,31019,3,"Faerlina EMOTE_WIDOW_EMBRACE"),
(15953,5,0,"%s goes into a frenzy!",41,100,2384,3,"Faerlina EMOTE_FRENZY");
-- remove some random spiders that aren't there on retail
DELETE FROM `creature` WHERE `guid` IN (127961,127962);
-- move followers to summon groups to avoid buggy respawn behavior of minions
DELETE FROM `creature` WHERE `guid` IN (128061,128062,128063,128064);
DELETE FROM `linked_respawn` WHERE `guid` IN (128061,128062,128063,128064);
DELETE FROM `creature_summon_groups` WHERE `summonerId`=15953;
INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`) VALUES
(15953,0,1,16506,3362.66 ,-3620.97,261.08,4.57276,8),
(15953,0,1,16506,3356.71 ,-3620.05,261.08,4.57276,8),
(15953,0,2,16505,3359.685,-3620.51,261.08,4.57276,8),
(15953,0,1,16506,3344.3 ,-3618.31,261.08,4.69494,8),
(15953,0,1,16506,3350.26 ,-3619.11,261.08,4.69494,8),
(15953,0,2,16505,3347.28 ,-3618.71,261.08,4.69494,8);
-- adds' fireball spell
DELETE FROM `spelldifficulty_dbc` WHERE `id`=54095;
INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
(54095,54095,54096);
-- naxxramas follower SAI changes
DELETE FROM `smart_scripts` WHERE `entryorguid`=16505 AND `source_type`=0 AND `id`=2;
INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`event_type`,`event_chance`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`target_type`,`comment`) VALUES
(16505,0,2,4,100,39,75,0,0,0, "Naxxramas Follower - On Aggro - Call For Help (75yd)");

View File

@@ -13769,7 +13769,7 @@ void CharmInfo::InitPossessCreateSpells()
{
uint32 spellId = _unit->ToCreature()->m_spells[i];
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (spellInfo && !spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
if (spellInfo)
{
if (spellInfo->IsPassive())
_unit->CastSpell(_unit, spellInfo, true);
@@ -13797,7 +13797,7 @@ void CharmInfo::InitCharmCreateSpells()
uint32 spellId = _unit->ToCreature()->m_spells[x];
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo || spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
if (!spellInfo)
{
_charmspells[x].SetActionAndType(spellId, ACT_DISABLED);
continue;

View File

@@ -18,14 +18,20 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "naxxramas.h"
#include "Player.h"
#include "SpellAuras.h"
#include "SpellInfo.h"
enum Yells
{
SAY_GREET = 0,
SAY_AGGRO = 1,
SAY_SLAY = 2,
SAY_DEATH = 3
SAY_GREET = 0,
SAY_AGGRO = 1,
SAY_SLAY = 2,
SAY_DEATH = 3,
EMOTE_WIDOW_EMBRACE = 4,
EMOTE_FRENZY = 5
};
enum Spells
@@ -33,7 +39,9 @@ enum Spells
SPELL_POISON_BOLT_VOLLEY = 28796,
SPELL_RAIN_OF_FIRE = 28794,
SPELL_FRENZY = 28798,
SPELL_WIDOWS_EMBRACE = 28732
SPELL_WIDOWS_EMBRACE = 28732,
SPELL_ADD_FIREBALL = 54095 // 25-man: 54096
};
#define SPELL_WIDOWS_EMBRACE_HELPER RAID_MODE<uint32>(28732, 54097)
@@ -45,6 +53,12 @@ enum Events
EVENT_FRENZY = 3
};
enum SummonGroups
{
SUMMON_GROUP_WORSHIPPERS = 1,
SUMMON_GROUP_FOLLOWERS = 2
};
enum Misc
{
DATA_FRENZY_DISPELS = 1
@@ -57,39 +71,46 @@ class boss_faerlina : public CreatureScript
struct boss_faerlinaAI : public BossAI
{
boss_faerlinaAI(Creature* creature) : BossAI(creature, BOSS_FAERLINA),
_frenzyDispels(0), _introDone(false), _delayFrenzy(false)
boss_faerlinaAI(Creature* creature) : BossAI(creature, BOSS_FAERLINA), _frenzyDispels(0) { }
void SummonAdds()
{
me->SummonCreatureGroup(SUMMON_GROUP_WORSHIPPERS);
if (Is25ManRaid())
me->SummonCreatureGroup(SUMMON_GROUP_FOLLOWERS);
}
void InitializeAI() override
{
if (!me->isDead())
{
Reset();
SummonAdds();
}
}
void JustReachedHome() override
{
_JustReachedHome();
SummonAdds();
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_POISON, urand(10000, 15000));
events.ScheduleEvent(EVENT_FIRE, urand(6000, 18000));
events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000));
summons.DoZoneInCombat();
events.ScheduleEvent(EVENT_POISON, urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS));
events.ScheduleEvent(EVENT_FIRE, urand(6 * IN_MILLISECONDS, 18 * IN_MILLISECONDS));
events.ScheduleEvent(EVENT_FRENZY, urand(60 * IN_MILLISECONDS, 80 * IN_MILLISECONDS));
}
void Reset() override
{
_Reset();
_delayFrenzy = false;
_frenzyDispels = 0;
}
void MoveInLineOfSight(Unit* who) override
{
if (!_introDone && who->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_GREET);
_introDone = true;
}
BossAI::MoveInLineOfSight(who);
}
void KilledUnit(Unit* /*victim*/) override
{
if (!urand(0, 2))
@@ -106,9 +127,8 @@ class boss_faerlina : public CreatureScript
{
if (spell->Id == SPELL_WIDOWS_EMBRACE_HELPER)
{
/// @todo Add Text
++_frenzyDispels;
_delayFrenzy = true;
Talk(EMOTE_WIDOW_EMBRACE, caster);
me->Kill(caster);
}
}
@@ -126,12 +146,6 @@ class boss_faerlina : public CreatureScript
if (!UpdateVictim())
return;
if (_delayFrenzy && !me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER))
{
_delayFrenzy = false;
DoCast(me, SPELL_FRENZY, true);
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
@@ -152,13 +166,14 @@ class boss_faerlina : public CreatureScript
events.ScheduleEvent(EVENT_FIRE, urand(6000, 18000));
break;
case EVENT_FRENZY:
/// @todo Add Text
if (!me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER))
DoCast(me, SPELL_FRENZY);
if (Aura* widowsEmbrace = me->GetAura(SPELL_WIDOWS_EMBRACE_HELPER))
events.ScheduleEvent(EVENT_FRENZY, widowsEmbrace->GetDuration()+1 * IN_MILLISECONDS);
else
_delayFrenzy = true;
events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000));
{
DoCast(SPELL_FRENZY);
Talk(EMOTE_FRENZY);
events.ScheduleEvent(EVENT_FRENZY, urand(60 * IN_MILLISECONDS, 80 * IN_MILLISECONDS));
}
break;
}
}
@@ -168,8 +183,6 @@ class boss_faerlina : public CreatureScript
private:
uint32 _frenzyDispels;
bool _introDone;
bool _delayFrenzy;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -192,19 +205,36 @@ class npc_faerlina_add : public CreatureScript
void Reset() override
{
if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) {
if (!Is25ManRaid()) {
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_BIND, true);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true);
}
}
void EnterCombat(Unit* /*who*/) override
{
if (Creature* faerlina = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FAERLINA)))
faerlina->AI()->DoZoneInCombat(nullptr, 250.0f);
}
void JustDied(Unit* /*killer*/) override
{
if (_instance && GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
if (!Is25ManRaid())
if (Creature* faerlina = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FAERLINA)))
DoCast(faerlina, SPELL_WIDOWS_EMBRACE);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoCastVictim(SPELL_ADD_FIREBALL);
DoMeleeAttackIfReady(); // this will only happen if the fireball cast fails for some reason
}
private:
InstanceScript* const _instance;
};
@@ -226,9 +256,29 @@ class achievement_momma_said_knock_you_out : public AchievementCriteriaScript
}
};
class at_faerlina_entrance : public AreaTriggerScript
{
public:
at_faerlina_entrance() : AreaTriggerScript("at_faerlina_entrance") { }
bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
InstanceScript* instance = player->GetInstanceScript();
if (!instance || instance->GetData(DATA_HAD_FAERLINA_GREET) || instance->GetBossState(BOSS_FAERLINA) != NOT_STARTED)
return true;
if (Creature* faerlina = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_FAERLINA)))
faerlina->AI()->Talk(SAY_GREET);
instance->SetData(DATA_HAD_FAERLINA_GREET, 1u);
return true;
}
};
void AddSC_boss_faerlina()
{
new boss_faerlina();
new npc_faerlina_add();
new at_faerlina_entrance();
new achievement_momma_said_knock_you_out();
}

View File

@@ -60,7 +60,6 @@ DoorData const doorData[] =
MinionData const minionData[] =
{
{ NPC_FOLLOWER_WORSHIPPER, BOSS_FAERLINA },
{ NPC_DK_UNDERSTUDY, BOSS_RAZUVIOUS },
{ NPC_SIR, BOSS_HORSEMEN },
{ NPC_THANE, BOSS_HORSEMEN },
@@ -125,6 +124,7 @@ class instance_naxxramas : public InstanceMapScript
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
AbominationCount = 0;
hadFaerlinaGreet = false;
CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT;
playerDied = 0;
@@ -319,6 +319,9 @@ class instance_naxxramas : public InstanceMapScript
case DATA_ABOMINATION_KILLED:
AbominationCount = value;
break;
case DATA_HAD_FAERLINA_GREET:
hadFaerlinaGreet = (value == 1u);
break;
}
}
@@ -328,6 +331,8 @@ class instance_naxxramas : public InstanceMapScript
{
case DATA_ABOMINATION_KILLED:
return AbominationCount;
case DATA_HAD_FAERLINA_GREET:
return (uint32)hadFaerlinaGreet;
default:
break;
}
@@ -635,6 +640,7 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid KelthuzadDoorGUID;
ObjectGuid LichKingGUID;
uint8 AbominationCount;
bool hadFaerlinaGreet;
uint8 CurrentWingTaunt;
/* The Immortal / The Undying */

View File

@@ -47,6 +47,8 @@ enum Data
DATA_GOTHIK_GATE,
DATA_SAPPHIRON_BIRTH,
DATA_HAD_FAERLINA_GREET,
DATA_HORSEMEN0,
DATA_HORSEMEN1,
DATA_HORSEMEN2,