fix(Core/BWL): Nefarian weekly adds spawn mechanics (#10981)

* fix(Core/BWL): Nefarian weekly spawn mechanics
This commit is contained in:
Nefertumm
2022-03-13 08:34:09 -03:00
committed by GitHub
parent f2522f9dda
commit 7decab3ccd
4 changed files with 282 additions and 65 deletions

View File

@@ -0,0 +1,20 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1647042448722452100');
UPDATE `creature_template` SET `unit_flags` = `unit_flags`|256|512|33554432, `AIName` = 'SmartAI', `flags_extra` = `flags_extra`|2|64 WHERE `entry` IN (14307, 14309, 14310, 14311, 14312);
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (14307, 14309, 14310, 14311, 14312) AND `source_type` = 0;
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
(14307, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 11, 22653, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - On Respawn - Cast \'Serverside - Drakonid Spawner\''),
(14307, 0, 1, 0, 1, 0, 100, 1, 1000, 60000, 60000, 60000, 0, 11, 22680, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - Out of Combat - Cast \'Spawn Chromatic Drakonid\' (No Repeat)'),
(14309, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 11, 22653, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - On Respawn - Cast \'Serverside - Drakonid Spawner\''),
(14309, 0, 1, 0, 1, 0, 100, 1, 1000, 60000, 60000, 60000, 0, 11, 22680, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - Out of Combat - Cast \'Spawn Chromatic Drakonid\' (No Repeat)'),
(14310, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 11, 22653, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - On Respawn - Cast \'Serverside - Drakonid Spawner\''),
(14310, 0, 1, 0, 1, 0, 100, 1, 1000, 60000, 60000, 60000, 0, 11, 22680, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - Out of Combat - Cast \'Spawn Chromatic Drakonid\' (No Repeat)'),
(14311, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 11, 22653, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - On Respawn - Cast \'Serverside - Drakonid Spawner\''),
(14311, 0, 1, 0, 1, 0, 100, 1, 1000, 60000, 60000, 60000, 0, 11, 22680, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - Out of Combat - Cast \'Spawn Chromatic Drakonid\' (No Repeat)'),
(14312, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 11, 22653, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - On Respawn - Cast \'Serverside - Drakonid Spawner\''),
(14312, 0, 1, 0, 1, 0, 100, 1, 1000, 60000, 60000, 60000, 0, 11, 22680, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Black Drakonid Spawner - Out of Combat - Cast \'Spawn Chromatic Drakonid\' (No Repeat)');
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_spawn_drakonid';
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(22659, 'spell_spawn_drakonid');

View File

@@ -20,7 +20,7 @@
#include "CreatureAIImpl.h"
uint32 const EncounterCount = 8;
constexpr uint32 EncounterCount = 8;
#define BWLScriptName "instance_blackwing_lair"
#define DataHeader "BWL"
@@ -59,7 +59,22 @@ enum BWLCreatureIds
NPC_FLAMEGOR = 11981,
NPC_CHROMAGGUS = 14020,
NPC_VICTOR_NEFARIUS = 10162,
NPC_NEFARIAN = 11583
NPC_NEFARIAN = 11583,
// Nefarian fight
NPC_BLACK_SPAWNER = 14307,
NPC_RED_SPAWNER = 14309,
NPC_GREEN_SPAWNER = 14310,
NPC_BRONZE_SPAWNER = 14311,
NPC_BLUE_SPAWNER = 14312,
NPC_BRONZE_DRAKONID = 14263,
NPC_BLUE_DRAKONID = 14261,
NPC_RED_DRAKONID = 14264,
NPC_GREEN_DRAKONID = 14262,
NPC_BLACK_DRAKONID = 14265,
NPC_CHROMATIC_DRAKONID = 14302,
NPC_BONE_CONSTRUCT = 14605
};
enum BWLGameObjectIds
@@ -90,7 +105,12 @@ enum BWLMisc
DATA_EGG_EVENT = 2,
TALK_EGG_BROKEN_RAND = 3,
SAY_NEFARIAN_VAEL_INTRO = 14
SAY_NEFARIAN_VAEL_INTRO = 14,
// Nefarian fight
DATA_NEFARIAN_LEFT_TUNNEL = 15,
DATA_NEFARIAN_RIGHT_TUNNEL = 16,
ACTION_NEFARIUS_ADD_KILLED = 2
};
template <class AI, class T>

View File

@@ -30,7 +30,8 @@
enum Events
{
// Victor Nefarius
EVENT_SPAWN_ADD = 1,
EVENT_SPAWN_ADDS = 1,
EVENT_CHECK_PHASE_2,
EVENT_START_EVENT,
EVENT_SHADOW_BOLT,
EVENT_FEAR,
@@ -53,7 +54,8 @@ enum Events
EVENT_SUCCESS_3,
ACTION_RESET = 0,
ACTION_KILLED = 1
ACTION_KILLED = 1,
ACTION_ADD_KILLED = 2
};
enum Says
@@ -106,13 +108,6 @@ enum GameObjects
enum Creatures
{
NPC_BRONZE_DRAKANOID = 14263,
NPC_BLUE_DRAKANOID = 14261,
NPC_RED_DRAKANOID = 14264,
NPC_GREEN_DRAKANOID = 14262,
NPC_BLACK_DRAKANOID = 14265,
NPC_CHROMATIC_DRAKANOID = 14302,
NPC_BONE_CONSTRUCT = 14605,
NPC_TOTEM_C_FIRE_NOVA = 14662,
NPC_TOTEM_C_STONESKIN = 14663,
NPC_TOTEM_C_HEALING = 14664,
@@ -137,6 +132,14 @@ enum Spells
SPELL_NEFARIANS_BARRIER = 22663,
// Drakonid Spawner
SPELL_SPAWN_BLACK_DRAKONID = 22654,
SPELL_SPAWN_RED_DRAKONID = 22655,
SPELL_SPAWN_GREEN_DRAKONID = 22656,
SPELL_SPAWN_BRONZE_DRAKONID = 22657,
SPELL_SPAWN_BLUE_DRAKONID = 22658,
SPELL_SPAWN_CHROMATIC_DRAKONID = 22680,
// Nefarian
SPELL_SHADOWFLAME_INITIAL = 22992,
SPELL_SHADOWFLAME = 22539,
@@ -168,15 +171,27 @@ enum Spells
SPELL_CORRUPTED_WINDFURY_TOTEM = 23423
};
Position const DrakeSpawnLoc[2] = // drakonid
enum Misc
{
{-7591.151855f, -1204.051880f, 476.800476f, 3.0f},
{-7514.598633f, -1150.448853f, 476.796570f, 3.0f}
MAX_DRAKONID_KILLED = 42
};
Position const spawnerPositions[2] = // drakonid
{
{-7599.32f, -1191.72f, 475.545f, 3.05f},
{-7526.27f, -1135.04f, 473.445f, 5.76f}
};
Position const NefarianSpawn = { -7348.849f, -1495.134f, 552.5152f, 1.798f };
uint32 const Entry[5] = {NPC_BRONZE_DRAKANOID, NPC_BLUE_DRAKANOID, NPC_RED_DRAKANOID, NPC_GREEN_DRAKANOID, NPC_BLACK_DRAKANOID};
std::unordered_map<uint32, uint32> spawnerSpells =
{
{ NPC_BLACK_SPAWNER, SPELL_SPAWN_BLACK_DRAKONID },
{ NPC_BLUE_SPAWNER, SPELL_SPAWN_BLUE_DRAKONID },
{ NPC_BRONZE_SPAWNER, SPELL_SPAWN_BRONZE_DRAKONID },
{ NPC_GREEN_SPAWNER, SPELL_SPAWN_GREEN_DRAKONID },
{ NPC_RED_SPAWNER, SPELL_SPAWN_RED_DRAKONID }
};
class boss_victor_nefarius : public CreatureScript
{
@@ -188,6 +203,25 @@ public:
boss_victor_nefariusAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
{
Initialize();
_nefarianLeftTunnel = instance->GetData(DATA_NEFARIAN_LEFT_TUNNEL);
_nefarianRightTunnel = instance->GetData(DATA_NEFARIAN_RIGHT_TUNNEL);
if (!_nefarianLeftTunnel || !_nefarianRightTunnel)
{
// Victor Nefarius weekly mechanic drakonid spawn
// Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated).
std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER };
_nefarianRightTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
// delete the previous picked one so we don't get any repeated.
nefarianDrakonidSpawners.erase(std::remove(nefarianDrakonidSpawners.begin(), nefarianDrakonidSpawners.end(), _nefarianRightTunnel), nefarianDrakonidSpawners.end());
// Pick another one
_nefarianLeftTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
// save it to instance
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
instance->SetData(DATA_NEFARIAN_RIGHT_TUNNEL, _nefarianRightTunnel);
}
}
void Initialize()
@@ -237,6 +271,11 @@ public:
summons.DespawnAll();
}
if (action == ACTION_ADD_KILLED)
{
KilledAdds++;
}
if (action == ACTION_KILLED)
{
Unit::Kill(me, me);
@@ -263,19 +302,8 @@ public:
events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000));
events.ScheduleEvent(EVENT_SILENCE, urand(20000, 25000));
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
events.ScheduleEvent(EVENT_SPAWN_ADD, 10000);
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() != NPC_NEFARIAN)
{
summon->UpdateEntry(NPC_BONE_CONSTRUCT);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_PASSIVE);
summon->SetStandState(UNIT_STAND_STATE_DEAD);
++KilledAdds;
}
events.ScheduleEvent(EVENT_SPAWN_ADDS, 10000);
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 10000);
}
void JustSummoned(Creature* summon) override { summons.Summon(summon); }
@@ -348,7 +376,7 @@ public:
}
// Only do this if we haven't spawned nefarian yet
if (UpdateVictim() && KilledAdds <= 42)
if (UpdateVictim() && KilledAdds <= MAX_DRAKONID_KILLED)
{
events.Update(diff);
@@ -390,39 +418,33 @@ public:
DoCastSelf(SPELL_SHADOWBLINK);
events.ScheduleEvent(EVENT_SHADOWBLINK, urand(30000, 40000));
break;
case EVENT_SPAWN_ADD:
for (uint8 i=0; i<2; ++i)
case EVENT_SPAWN_ADDS:
// Spawn the spawners.
me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]);
me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]);
break;
case EVENT_CHECK_PHASE_2:
if (KilledAdds >= MAX_DRAKONID_KILLED)
{
uint32 CreatureID;
if (urand(0, 2) == 0)
CreatureID = NPC_CHROMATIC_DRAKANOID;
else
CreatureID = Entry[urand(0, 4)];
if (Creature* dragon = me->SummonCreature(CreatureID, DrakeSpawnLoc[i]))
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
dragon->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
dragon->AI()->AttackStart(me->GetVictim());
}
if (KilledAdds >= 42)
{
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.CancelEvent(EVENT_SILENCE);
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
return;
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.CancelEvent(EVENT_SILENCE);
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
// Despawn the spawners.
summons.DespawnEntry(_nefarianLeftTunnel);
summons.DespawnEntry(_nefarianRightTunnel);
return;
}
events.ScheduleEvent(EVENT_SPAWN_ADD, 4000);
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 1000);
break;
}
@@ -453,6 +475,8 @@ public:
private:
uint32 KilledAdds;
uint32 _nefarianRightTunnel;
uint32 _nefarianLeftTunnel;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -755,12 +779,12 @@ struct npc_corrupted_totem : public ScriptedAI
std::vector<uint32> mobsEntries;
mobsEntries.push_back(NPC_NEFARIAN);
mobsEntries.push_back(NPC_BONE_CONSTRUCT);
mobsEntries.push_back(NPC_BRONZE_DRAKANOID);
mobsEntries.push_back(NPC_BLUE_DRAKANOID);
mobsEntries.push_back(NPC_RED_DRAKANOID);
mobsEntries.push_back(NPC_GREEN_DRAKANOID);
mobsEntries.push_back(NPC_BLACK_DRAKANOID);
mobsEntries.push_back(NPC_CHROMATIC_DRAKANOID);
mobsEntries.push_back(NPC_BRONZE_DRAKONID);
mobsEntries.push_back(NPC_BLUE_DRAKONID);
mobsEntries.push_back(NPC_RED_DRAKONID);
mobsEntries.push_back(NPC_GREEN_DRAKONID);
mobsEntries.push_back(NPC_BLACK_DRAKONID);
mobsEntries.push_back(NPC_CHROMATIC_DRAKONID);
for (auto& entry : mobsEntries)
{
@@ -1155,6 +1179,33 @@ class spell_shadowblink : public SpellScript
}
};
// 22659
class spell_spawn_drakonid : public SpellScript
{
PrepareSpellScript(spell_spawn_drakonid);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SPAWN_BLACK_DRAKONID, SPELL_SPAWN_BLUE_DRAKONID, SPELL_SPAWN_BRONZE_DRAKONID, SPELL_SPAWN_GREEN_DRAKONID, SPELL_SPAWN_RED_DRAKONID });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
{
return;
}
caster->CastSpell(caster, spawnerSpells[caster->GetEntry()], true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_spawn_drakonid::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
void AddSC_boss_nefarian()
{
new boss_victor_nefarius();
@@ -1167,4 +1218,5 @@ void AddSC_boss_nefarian()
RegisterSpellScript(aura_class_call_berserk);
RegisterSpellScript(spell_corrupted_totems);
RegisterSpellScript(spell_shadowblink);
RegisterSpellScript(spell_spawn_drakonid);
}

View File

@@ -75,6 +75,8 @@ public:
// Razorgore
EggCount = 0;
EggEvent = 0;
NefarianLeftTunnel = 0;
NefarianRightTunnel = 0;
}
void OnCreatureCreate(Creature* creature) override
@@ -102,6 +104,24 @@ public:
case NPC_VICTOR_NEFARIUS:
victorNefariusGUID = creature->GetGUID();
break;
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID:
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
{
if (CreatureAI* nefariusAI = nefarius->AI())
{
nefariusAI->JustSummoned(creature);
}
}
if (creature->AI())
{
creature->AI()->DoZoneInCombat();
}
break;
default:
break;
}
@@ -166,6 +186,21 @@ public:
}
}
uint32 GetData(uint32 data) const override
{
switch (data)
{
case DATA_NEFARIAN_LEFT_TUNNEL:
return NefarianLeftTunnel;
case DATA_NEFARIAN_RIGHT_TUNNEL:
return NefarianRightTunnel;
default:
break;
}
return 0;
}
bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override
{
switch (bossId)
@@ -268,6 +303,16 @@ public:
break;
}
}
if (type == DATA_NEFARIAN_LEFT_TUNNEL)
{
NefarianLeftTunnel = data;
}
if (type == DATA_NEFARIAN_RIGHT_TUNNEL)
{
NefarianRightTunnel = data;
}
}
ObjectGuid GetGuidData(uint32 type) const override
@@ -276,6 +321,8 @@ public:
{
case DATA_RAZORGORE_THE_UNTAMED:
return razorgoreGUID;
case DATA_LORD_VICTOR_NEFARIUS:
return victorNefariusGUID;
case DATA_CHROMAGGUS:
return chromaggusGUID;
case DATA_GO_CHROMAGGUS_DOOR:
@@ -292,6 +339,32 @@ public:
//! HACK, needed because of buggy CreatureAI after charm
if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(DATA_RAZORGORE_THE_UNTAMED) != DONE)
SetBossState(DATA_RAZORGORE_THE_UNTAMED, DONE);
switch (unit->GetEntry())
{
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID:
if (Creature* summon = unit->ToCreature())
{
summon->UpdateEntry(NPC_BONE_CONSTRUCT);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_PASSIVE);
summon->SetStandState(UNIT_STAND_STATE_DEAD);
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
{
if (nefarius->AI())
{
nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
}
}
}
break;
}
}
void Update(uint32 diff) override
@@ -329,6 +402,54 @@ public:
}
}
std::string GetSaveData() override
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "B W L " << GetBossSaveData() << NefarianLeftTunnel << ' ' << NefarianRightTunnel;
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(char const* data) override
{
if (!data)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(data);
char dataHead1, dataHead2, dataHead3;
std::istringstream loadStream(data);
loadStream >> dataHead1 >> dataHead2 >> dataHead3;
if (dataHead1 == 'B' && dataHead2 == 'W' && dataHead3 == 'L')
{
for (uint32 i = 0; i < EncounterCount; ++i)
{
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState == FAIL || tmpState > SPECIAL)
tmpState = NOT_STARTED;
SetBossState(i, EncounterState(tmpState));
}
loadStream >> NefarianLeftTunnel;
loadStream >> NefarianRightTunnel;
}
else
{
OUT_LOAD_INST_DATA_FAIL;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
protected:
ObjectGuid razorgoreGUID;
ObjectGuid chromaggusGUID;
@@ -342,6 +463,10 @@ public:
uint32 EggEvent;
GuidList EggList;
// Nefarian
uint32 NefarianLeftTunnel;
uint32 NefarianRightTunnel;
// Misc
EventMap _events;
};