Scripts/ScarletMonastery: Headless Horseman Rewrite (#25614)

This commit is contained in:
Keader
2020-10-26 14:04:36 -03:00
committed by GitHub
parent 28a1132211
commit a93abcf803
5 changed files with 1129 additions and 848 deletions

View File

@@ -0,0 +1,65 @@
-- GameObject update
UPDATE `gameobject_template` SET `ScriptName` = 'go_headless_horseman_pumpkin' WHERE `entry` = 186267;
-- Creature Updates
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|512|2097152 WHERE `entry` = 23682;
UPDATE `creature_template` SET `flags_extra` =`flags_extra`|512, `ScriptName` = 'npc_pulsing_pumpkin' WHERE `entry` = 23694;
UPDATE `creature_template` SET `ScriptName` = 'npc_flame_bunny' WHERE `entry` = 23686;
UPDATE `creature_template` SET `ScriptName` = 'npc_headless_horseman_head', `mechanic_immune_mask`=617299827 WHERE `entry` = 23775;
UPDATE `creature_template` SET `ScriptName` = 'npc_sir_thomas' WHERE `entry` = 23904;
UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` = 24034;
-- Model Updates
UPDATE `creature_model_info` SET `BoundingRadius` = 0.75, `CombatReach` = 2.25 WHERE `DisplayID` = 22351;
UPDATE `creature_model_info` SET `BoundingRadius` = 0.5, `CombatReach` = 1 WHERE `DisplayID` = 24720;
UPDATE `creature_model_info` SET `BoundingRadius` = 0.75, `CombatReach` = 1.125 WHERE `DisplayID` = 21822;
-- AllowableRaces for Sir Thomas' quests
UPDATE `quest_template` SET `AllowableRaces` = 1101 WHERE `ID` = 11242;
UPDATE `quest_template` SET `AllowableRaces` = 690 WHERE `ID` = 11403;
DELETE FROM `spell_script_names` WHERE `ScriptName` IN
('spell_headless_horseman_yell_timer',
'spell_headless_horseman_maniacal_laugh',
'spell_headless_horseman_head_reposition',
'spell_headless_horseman_send_head',
'spell_headless_horseman_head_periodic',
'spell_headless_horseman_command_head_request_body',
'spell_headless_horseman_return_head',
'spell_summon_pumpkin_burst_delay',
'spell_headless_horseman_head_is_dead',
'spell_headless_horseman_summoning_rhyme_aura',
'spell_headless_horseman_sprouting',
'spell_headless_horseman_wisp_teleport');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(42432,'spell_headless_horseman_yell_timer'),
(43893,'spell_headless_horseman_maniacal_laugh'),
(42410,'spell_headless_horseman_head_reposition'),
(42399,'spell_headless_horseman_send_head'),
(42603,'spell_headless_horseman_head_periodic'),
(43101,'spell_headless_horseman_command_head_request_body'),
(42401,'spell_headless_horseman_return_head'),
(52236,'spell_summon_pumpkin_burst_delay'),
(42428,'spell_headless_horseman_head_is_dead'),
(42879,'spell_headless_horseman_summoning_rhyme_aura'),
(42281,'spell_headless_horseman_sprouting'),
(42821,'spell_headless_horseman_wisp_teleport'),
(42818,'spell_headless_horseman_wisp_teleport');
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (42410, 43101, 43306);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
(13,1,42410,0,0,31,0,3,23775,0,0,0,0,'','Effect_0 hits Head of the Horseman'), -- Headless Horseman Climax - Command, Head Repositions
(13,1,43306,0,0,31,0,3,23682,0,0,0,0,'','Effect_0 hits Headless Horseman'), -- Headless Horseman Climax - Command, Head Requests Body
(13,1,43101,0,0,31,0,3,23682,0,0,0,0,'','Effect_0 hits Headless Horseman'); -- Headless Horseman Climax - Heal Body
DELETE FROM `creature_text` WHERE `CreatureID` IN (23682,23775);
INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
(23682,0,0,'It is over, your search is done. Let fate choose now, the righteous one.',12,0,100,0,0,11961,22261,0,'Headless Horseman SAY_ENTRANCE'),
(23682,1,0,'Here\'s my body, fit and pure! Now, your blackened souls I\'ll cure!',14,0,100,0,0,12567,22271,0,'Headless Horseman SAY_REJOINED'),
(23682,2,0,'Harken, cur! Tis you I spurn! Now feel... the burn!',11,0,100,0,0,12573,22587,0,'Headless Horseman SAY_CONFLAGRATION'),
(23682,3,0,'Soldiers arise, stand and fight! Bring victory at last to this fallen knight!',12,0,100,0,0,11963,23861,0,'Headless Horseman SAY_SPROUTING_PUMPKINS'),
(23682,4,0,'This end have I reached before. What new adventure lies in store?',12,0,100,0,0,11964,23455,0,'Headless Horseman SAY_DEATH'),
(23682,5,0,'Your body lies beaten, battered and broken! Let my curse be your own, fate has spoken!',14,0,100,0,0,11962,40546,0,'Headless Horseman SAY_KILL_PLAYER'),
(23775,0,0,'So eager you are, for my blood to spill. Yet to vanquish me, \'tis my head you must kill!',14,0,100,0,0,11969,22757,0,'Head of the Horseman SAY_LOST_HEAD'),
(23775,1,0,'Get over here, you idiot!',12,0,100,0,0,12569,22415,0,'Head of the Horseman SAY_REQUEST_BODY'),
(23775,2,0,'Horseman rise...',1,0,100,0,0,0,22695,0,'Head of the Horseman SAY_PLAYER_RISE'),
(23775,3,0,'Your time is nigh...',1,0,100,0,0,0,22696,0,'Head of the Horseman SAY_PLAYER_TIME'),
(23775,4,0,'You felt death once...',1,0,100,22,0,0,22720,0,'Head of the Horseman SAY_PLAYER_DEATH'),
(23775,5,0,'Now, know demise!',1,0,100,5,0,0,22721,0,'Head of the Horseman SAY_PLAYER_DEMISE');

View File

@@ -4913,6 +4913,14 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_MOD_DECREASE_SPEED;
});
// Headless Horseman Climax - Return Head (Hallow End)
// Headless Horseman Climax - Body Regen (confuse only - removed on death)
// Headless Horseman Climax - Head Is Dead
ApplySpellFix({ 42401, 43105, 42428 }, [](SpellInfo* spellInfo)
{
spellInfo->Attributes |= SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY;
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];

View File

@@ -17,25 +17,32 @@
#include "scarlet_monastery.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "EventMap.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
#include "ScriptMgr.h"
#include "TemporarySummon.h"
ObjectData const creatureData[] =
{
{ NPC_HEAD, DATA_HEAD },
{ NPC_HORSEMAN, DATA_HORSEMAN },
{ NPC_MOGRAINE, DATA_MOGRAINE },
{ NPC_VORREL, DATA_VORREL },
{ NPC_WHITEMANE, DATA_WHITEMANE },
{ 0, 0 } // END
{ NPC_HEADLESS_HORSEMAN_HEAD, DATA_HORSEMAN_HEAD },
{ NPC_HEADLESS_HORSEMAN, DATA_HEADLESS_HORSEMAN },
{ NPC_FLAME_BUNNY, DATA_FLAME_BUNNY },
{ NPC_EARTH_BUNNY, DATA_EARTH_BUNNY },
{ NPC_SIR_THOMAS, DATA_THOMAS },
{ NPC_MOGRAINE, DATA_MOGRAINE },
{ NPC_VORREL, DATA_VORREL },
{ NPC_WHITEMANE, DATA_WHITEMANE },
{ 0, 0 } // END
};
ObjectData const gameObjectData[] =
{
{ GO_PUMPKIN_SHRINE, DATA_PUMPKIN_SHRINE },
{ GO_HIGH_INQUISITORS_DOOR, DATA_HIGH_INQUISITORS_DOOR },
{ GO_LOOSELY_TURNED_SOIL, DATA_LOOSELY_TURNED_SOIL },
{ 0, 0 } // END
};
@@ -51,52 +58,92 @@ class instance_scarlet_monastery : public InstanceMapScript
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, gameObjectData);
_horsemanState = NOT_STARTED;
}
void OnCreatureCreate(Creature* creature) override
void HandleStartEvent()
{
switch (creature->GetEntry())
{
case NPC_PUMPKIN:
HorsemanAdds.insert(creature->GetGUID());
break;
default:
break;
}
_horsemanState = IN_PROGRESS;
for (uint32 data : {DATA_PUMPKIN_SHRINE, DATA_LOOSELY_TURNED_SOIL})
if (GameObject* gob = GetGameObject(data))
gob->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
InstanceScript::OnCreatureCreate(creature);
instance->SummonCreature(NPC_HEADLESS_HORSEMAN_HEAD, HeadlessHorsemanHeadSpawnPosition);
instance->SummonCreature(NPC_FLAME_BUNNY, BunnySpawnPosition);
instance->SummonCreature(NPC_EARTH_BUNNY, EarthBunnySpawnPosition);
_events.ScheduleEvent(EVENT_ACTIVE_EARTH_EXPLOSION, 1s + 500ms);
_events.ScheduleEvent(EVENT_SPAWN_HEADLESS_HORSEMAN, 3s);
_events.ScheduleEvent(EVENT_DESPAWN_OBJECTS, 10s);
if (Creature* thomas = GetCreature(DATA_THOMAS))
thomas->DespawnOrUnsummon();
}
bool SetBossState(uint32 type, EncounterState state) override
void SetData(uint32 type, uint32 data) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
switch (type)
{
case DATA_HORSEMAN_EVENT:
if (state == DONE || state == FAIL || state == NOT_STARTED)
{
for (ObjectGuid const& guid : HorsemanAdds)
{
Creature* add = instance->GetCreature(guid);
if (add)
add->DespawnOrUnsummon();
}
HorsemanAdds.clear();
if (state == DONE)
HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_PUMPKIN_SHRINE));
}
case DATA_START_HORSEMAN_EVENT:
if (_horsemanState != IN_PROGRESS)
HandleStartEvent();
break;
case DATA_HORSEMAN_EVENT_STATE:
_horsemanState = data;
break;
case DATA_PREPARE_RESET:
_horsemanState = NOT_STARTED;
for (uint32 data : {DATA_FLAME_BUNNY, DATA_EARTH_BUNNY})
if (Creature* bunny = GetCreature(data))
bunny->DespawnOrUnsummon();
break;
default:
break;
}
return true;
}
protected:
GuidUnorderedSet HorsemanAdds;
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_HORSEMAN_EVENT_STATE:
return _horsemanState;
default:
return 0;
}
}
void Update(uint32 diff) override
{
if (_events.Empty())
return;
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ACTIVE_EARTH_EXPLOSION:
if (Creature* earthBunny = GetCreature(DATA_EARTH_BUNNY))
earthBunny->CastSpell(earthBunny, SPELL_EARTH_EXPLOSION);
break;
case EVENT_SPAWN_HEADLESS_HORSEMAN:
if (TempSummon* horseman = instance->SummonCreature(NPC_HEADLESS_HORSEMAN, HeadlessHorsemanSpawnPosition))
horseman->AI()->DoAction(ACTION_HORSEMAN_EVENT_START);
break;
case EVENT_DESPAWN_OBJECTS:
for (uint32 data : {DATA_PUMPKIN_SHRINE, DATA_LOOSELY_TURNED_SOIL})
if (GameObject* gob = GetGameObject(data))
gob->RemoveFromWorld();
break;
default:
break;
}
}
}
private:
EventMap _events;
uint32 _horsemanState;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override

View File

@@ -19,12 +19,18 @@
#define SCARLET_M_
#include "CreatureAIImpl.h"
#include "Position.h"
#define SMScriptName "instance_scarlet_monastery"
#define DataHeader "SM"
uint32 const EncounterCount = 10;
Position const BunnySpawnPosition = { 1776.27f, 1348.74f, 19.20f };
Position const EarthBunnySpawnPosition = { 1765.28f, 1347.46f, 18.55f, 6.17f };
Position const HeadlessHorsemanSpawnPosition = { 1765.00f, 1347.00f, 15.00f };
Position const HeadlessHorsemanHeadSpawnPosition = { 1788.54f, 1348.05f, 18.88f }; // Guessed
enum SMDataTypes
{
DATA_INTERROGATOR_VISHAS = 0,
@@ -37,32 +43,52 @@ enum SMDataTypes
DATA_AZSHIR,
DATA_SCORN,
DATA_HORSEMAN_EVENT, // Last defined encounter
DATA_HEAD,
DATA_HORSEMAN,
DATA_MOGRAINE,
DATA_VORREL,
DATA_WHITEMANE,
// Headless Horseman
DATA_HORSEMAN_HEAD,
DATA_HEADLESS_HORSEMAN,
DATA_PUMPKIN_SHRINE,
DATA_HIGH_INQUISITORS_DOOR,
DATA_LOOSELY_TURNED_SOIL,
DATA_START_HORSEMAN_EVENT,
DATA_FLAME_BUNNY,
DATA_EARTH_BUNNY,
DATA_HORSEMAN_EVENT_STATE,
DATA_PREPARE_RESET,
DATA_THOMAS
};
enum SMCreatureIds
{
NPC_MOGRAINE = 3976,
NPC_WHITEMANE = 3977,
NPC_VORREL = 3981,
NPC_HORSEMAN = 23682,
NPC_HEAD = 23775,
NPC_PUMPKIN = 23694
NPC_MOGRAINE = 3976,
NPC_WHITEMANE = 3977,
NPC_VORREL = 3981,
NPC_HEADLESS_HORSEMAN = 23682,
NPC_HEADLESS_HORSEMAN_HEAD = 23775,
NPC_PULSING_PUMPKIN = 23694,
NPC_PUMPKIN_FIEND = 23545,
NPC_FLAME_BUNNY = 23686,
NPC_EARTH_BUNNY = 23758,
NPC_SIR_THOMAS = 23904
};
enum SMCreatureMisc
{
SPELL_EARTH_EXPLOSION = 42373,
EVENT_ACTIVE_EARTH_EXPLOSION = 1,
EVENT_SPAWN_HEADLESS_HORSEMAN = 2,
EVENT_DESPAWN_OBJECTS = 3,
ACTION_HORSEMAN_EVENT_START = 101
};
enum SMGameObjectIds
{
GO_HIGH_INQUISITORS_DOOR = 104600,
GO_PUMPKIN_SHRINE = 186267
GO_PUMPKIN_SHRINE = 186267,
GO_LOOSELY_TURNED_SOIL = 186314
};
template <class AI, class T>