aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTeleqraph <nyrdeveloper@gmail.com>2022-10-10 13:16:16 +0200
committerGitHub <noreply@github.com>2022-10-10 13:16:16 +0200
commitd3e76fc7febaccffd557d88c46de789a75a874a8 (patch)
treeef069adb3c36381c4414bd380c763eb6d7791a10 /src
parentb6ec81fff808388d934f098546c7faad9105c975 (diff)
Scripts/Silverpine: Implemented Waiting to Exsanguinate (questId 27045) (#28275)
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp992
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp17
2 files changed, 1009 insertions, 0 deletions
diff --git a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
index bb68b4f25e2..2b381c85c73 100644
--- a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
@@ -1596,6 +1596,990 @@ private:
ObjectGuid _playerGUID;
};
+enum AbandonedOuthouse
+{
+ QUEST_WAITING_TO_EXSANGUINATE = 27045,
+
+ SPELL_SUMMON_DEATHSTALKER_YORICK = 83751
+};
+
+// 205143 - Abandoned Outhouse
+struct go_silverpine_abandoned_outhouse : public GameObjectAI
+{
+ go_silverpine_abandoned_outhouse(GameObject* go) : GameObjectAI(go) { }
+
+ void OnQuestAccept(Player* player, Quest const* quest) override
+ {
+ if (quest->GetQuestId() == QUEST_WAITING_TO_EXSANGUINATE)
+ player->CastSpell(player, SPELL_SUMMON_DEATHSTALKER_YORICK, true);
+ }
+
+ bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override
+ {
+ player->CastSpell(player, SPELL_SUMMON_DEATHSTALKER_YORICK, true);
+ CloseGossipMenuFor(player);
+ return false;
+ }
+};
+
+Position const YorickReadyPosition = { 1313.7f, 1211.99f, 58.5f, 4.564474f };
+
+Position const YorickDeathPosition = { 1295.52f, 1206.58f, 58.501f };
+
+enum DeathstalkerRaneYorick
+{
+ PHASE_WAITING_TO_EXSANGUINATE = 265,
+
+ NPC_ARMOIRE_SUMMONED = 44893,
+ NPC_PACKLEADER_IVAR_BLOODFANG = 44884,
+
+ SPELL_STEALTH = 34189,
+ SPELL_PERMANENT_FEIGN_DEATH = 29266,
+ SPELL_HIDDEN_IN_ARMOIRE = 83788,
+ SPELL_SUMMON_YORICK = 83751,
+ SPELL_CANCEL_SUMMON_YORICK = 83755,
+
+ EVENT_START_QUEST_EXSANGUINATE = 1,
+ EVENT_WAIT_FOR_PLAYER_EXSANGUINATE = 3,
+ EVENT_RANE_HIDE = 4,
+ EVENT_SET_GUID_FOR_ARMOIRE = 5,
+ EVENT_RANE_TALK_TO_PLAYER = 6,
+ EVENT_RANE_LAST_MOVE = 7,
+
+ ACTION_RANE_JUMP_DEATH = 1,
+ ACTION_RANE_SKIP_PATH = 2,
+
+ TALK_YORICK_EXSANGUINATE_SUMMON = 0,
+ TALK_YORICK_EXSANGUINATE_HIDE = 1,
+
+ PATH_YORICK_UP = 448820,
+ PATH_YORICK_HIDE = 448821,
+
+ WAYPOINT_CLOSE_TO_ARMOIRE = 15,
+ WAYPOINT_HIDDEN_NEXT_TO_ARMOIRE = 2
+};
+
+// 44882 - Deathstalker Rane Yorick
+struct npc_silverpine_deathstalker_rane_yorick : public ScriptedAI
+{
+ npc_silverpine_deathstalker_rane_yorick(Creature* creature) : ScriptedAI(creature), _playerArrived(false), _playerSkipped(false) { }
+
+ void JustAppeared() override
+ {
+ me->SetPowerType(POWER_ENERGY);
+ me->SetMaxPower(POWER_ENERGY, 100);
+ me->SetPower(POWER_ENERGY, 100, true);
+ }
+
+ void IsSummonedBy(WorldObject* summoner) override
+ {
+ me->SetFacingToObject(summoner);
+
+ _events.ScheduleEvent(EVENT_START_QUEST_EXSANGUINATE, 1s);
+ }
+
+ void WaypointReached(uint32 waypointId, uint32 pathId) override
+ {
+ if (pathId == PATH_YORICK_UP && waypointId == WAYPOINT_CLOSE_TO_ARMOIRE)
+ _events.ScheduleEvent(EVENT_WAIT_FOR_PLAYER_EXSANGUINATE, 1s);
+
+ if (pathId == PATH_YORICK_HIDE && waypointId == WAYPOINT_HIDDEN_NEXT_TO_ARMOIRE)
+ {
+ me->SetFacingTo(4.6425757f);
+
+ DoCastSelf(SPELL_STEALTH);
+
+ me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
+
+ _playerSkipped = true;
+ }
+ }
+
+ void DoAction(int32 param) override
+ {
+ switch (param)
+ {
+ case ACTION_RANE_JUMP_DEATH:
+ me->SetDisableGravity(true);
+ _events.ScheduleEvent(EVENT_RANE_LAST_MOVE, 10ms);
+ break;
+
+ case ACTION_RANE_SKIP_PATH:
+ {
+ me->PauseMovement();
+
+ me->GetMotionMaster()->Clear();
+
+ me->NearTeleportTo(YorickReadyPosition, false);
+
+ _events.Reset();
+
+ _events.ScheduleEvent(EVENT_SET_GUID_FOR_ARMOIRE, 1s);
+
+ DoCastSelf(SPELL_STEALTH);
+
+ me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ TempSummon* tempSummon = me->ToTempSummon();
+ if (!tempSummon)
+ return;
+
+ _events.Update(diff);
+
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (!summoner->HasAura(SPELL_SUMMON_YORICK))
+ me->DespawnOrUnsummon();
+ }
+
+ if (!_playerSkipped)
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (summoner->HasAura(SPELL_HIDDEN_IN_ARMOIRE))
+ {
+ _playerSkipped = true;
+
+ DoAction(ACTION_RANE_SKIP_PATH);
+ }
+ }
+ }
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_START_QUEST_EXSANGUINATE:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ Talk(TALK_YORICK_EXSANGUINATE_SUMMON, summoner);
+
+ _events.ScheduleEvent(EVENT_START_QUEST_EXSANGUINATE + 1, 1s + 500ms);
+ }
+ break;
+ }
+
+ case EVENT_START_QUEST_EXSANGUINATE + 1:
+ me->GetMotionMaster()->MovePath(PATH_YORICK_UP, false);
+ break;
+
+ case EVENT_WAIT_FOR_PLAYER_EXSANGUINATE:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (summoner->GetDistance2d(me) <= 5.0f && !_playerArrived)
+ {
+ _events.ScheduleEvent(EVENT_RANE_TALK_TO_PLAYER, 1s);
+ _playerArrived = true;
+ }
+ else
+ _events.ScheduleEvent(EVENT_WAIT_FOR_PLAYER_EXSANGUINATE, 1s);
+ }
+ break;
+ }
+
+ case EVENT_RANE_TALK_TO_PLAYER:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ Talk(TALK_YORICK_EXSANGUINATE_HIDE, summoner);
+
+ _events.ScheduleEvent(EVENT_RANE_HIDE, 3s);
+ _events.ScheduleEvent(EVENT_SET_GUID_FOR_ARMOIRE, 1s);
+ }
+ break;
+ }
+
+ case EVENT_RANE_HIDE:
+ me->GetMotionMaster()->MovePath(PATH_YORICK_HIDE, false);
+ break;
+
+ case EVENT_SET_GUID_FOR_ARMOIRE:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (!_bloodfangGUID)
+ {
+ if (Creature* bloodfang = me->FindNearestCreature(NPC_PACKLEADER_IVAR_BLOODFANG, 30.0f))
+ {
+ if (bloodfang->GetOwnerGUID() == summoner->GetGUID())
+ _bloodfangGUID = bloodfang->GetGUID();
+ }
+ }
+
+ if (!_armoireGUID)
+ {
+ if (Creature* armoire = me->FindNearestCreature(NPC_ARMOIRE_SUMMONED, 30.0f))
+ {
+ if (armoire->GetOwnerGUID() == summoner->GetGUID())
+ {
+ _armoireGUID = armoire->GetGUID();
+
+ if (armoire->IsAIEnabled())
+ armoire->GetAI()->SetGUID(me->GetGUID(), me->GetEntry());
+ }
+ }
+ }
+ }
+
+ if (!_bloodfangGUID || !_armoireGUID)
+ _events.ScheduleEvent(EVENT_SET_GUID_FOR_ARMOIRE, 1s);
+ break;
+ }
+
+ case EVENT_RANE_LAST_MOVE:
+ me->GetMotionMaster()->MoveJump(YorickDeathPosition, 10.0f, 10.0f);
+ DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH);
+ _events.ScheduleEvent(EVENT_RANE_LAST_MOVE + 1, 2s);
+ break;
+
+ case EVENT_RANE_LAST_MOVE + 1:
+ me->SetDisableGravity(false);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+private:
+ EventMap _events;
+ ObjectGuid _armoireGUID;
+ ObjectGuid _bloodfangGUID;
+ bool _playerArrived;
+ bool _playerSkipped;
+};
+
+enum WaitingToExsanguinate
+{
+ NPC_DEATHSTALKER_RANE_YORICK = 44882,
+ NPC_LORD_DARIUS_CROWLEY = 44883,
+
+ SPELL_SUMMON_CROWLEY_BLOODFANG_MASTER = 83762,
+ SPELL_ARMOIRE_CAMERA_ON_CROWLEY = 83763,
+ SPELL_ARMOIRE_CAMERA_ON_BLOODFANG = 83764,
+ SPELL_RIDE_REVERSE_CAST_EXSANGUINATE = 83781,
+ SPELL_EJECT_PASSENGER_01 = 80743,
+ SPELL_KILL_CREDIT_YORICK = 83786,
+ SPELL_HIDE_IN_ARMOIRE = 83788,
+
+ EVENT_START_SCENE_EXSANGUINATE = 1,
+ EVENT_TALK_SCENE_EXSANGUINATE = 4,
+ EVENT_ACTION_SCENE_EXSANGUINATE = 27,
+ EVENT_SWITCH_SCENE_CAMERA = 33,
+ EVENT_FINISH_SCENE_EXSANGUINATE = 40,
+
+ TALK_YORICK_EXSANGUINATE_DEATH = 2,
+ TALK_CROWLEY_EXSANGUINATE_0 = 0,
+ TALK_CROWLEY_EXSANGUINATE_1 = 1,
+ TALK_CROWLEY_EXSANGUINATE_2 = 2,
+ TALK_CROWLEY_EXSANGUINATE_3 = 3,
+ TALK_CROWLEY_EXSANGUINATE_4 = 4,
+ TALK_CROWLEY_EXSANGUINATE_5 = 5,
+ TALK_CROWLEY_EXSANGUINATE_6 = 6,
+ TALK_BLOODFANG_EXSANGUINATE_0 = 0,
+ TALK_BLOODFANG_EXSANGUINATE_1 = 1,
+ TALK_BLOODFANG_EXSANGUINATE_2 = 2,
+ TALK_BLOODFANG_EXSANGUINATE_3 = 3,
+ TALK_BLOODFANG_EXSANGUINATE_4 = 4,
+ TALK_BLOODFANG_EXSANGUINATE_5 = 5,
+ TALK_BLOODFANG_EXSANGUINATE_6 = 6,
+ TALK_BLOODFANG_EXSANGUINATE_7 = 7,
+ TALK_BLOODFANG_EXSANGUINATE_8 = 8,
+ TALK_BLOODFANG_EXSANGUINATE_9 = 9,
+ TALK_BLOODFANG_EXSANGUINATE_10 = 10,
+
+ PATH_CROWLEY_ENTER = 448830,
+ PATH_BLOODFANG_ENTER = 448840,
+ PATH_BLOODFANG_NEAR_YORICK = 448841,
+ PATH_BLOODFANG_WITH_YORICK = 448842,
+ PATH_BLOODFANG_EXIT = 448843,
+ PATH_CROWLEY_EXIT = 448831
+};
+
+// 44893 - Armoire
+struct npc_silverpine_armoire : public VehicleAI
+{
+ npc_silverpine_armoire(Creature* creature) : VehicleAI(creature) { }
+
+ void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override
+ {
+ if (apply)
+ {
+ if (Player* player = passenger->ToPlayer())
+ {
+ if (player->GetQuestStatus(QUEST_WAITING_TO_EXSANGUINATE) == QUEST_STATUS_INCOMPLETE)
+ _events.ScheduleEvent(EVENT_START_SCENE_EXSANGUINATE, 400ms);
+ }
+ }
+ else
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ crowley->DespawnOrUnsummon();
+
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ bloodfang->DespawnOrUnsummon();
+
+ if (Creature* yorick = ObjectAccessor::GetCreature(*me, _yorickGUID))
+ yorick->CastSpell(nullptr, SPELL_CANCEL_SUMMON_YORICK, true);
+
+ me->DespawnOrUnsummon(1s);
+ }
+ }
+
+ void SetGUID(ObjectGuid const& guid, int32 id) override
+ {
+ switch (id)
+ {
+ case NPC_DEATHSTALKER_RANE_YORICK:
+ _yorickGUID = guid;
+ break;
+
+ case NPC_LORD_DARIUS_CROWLEY:
+ _crowleyGUID = guid;
+ break;
+
+ case NPC_PACKLEADER_IVAR_BLOODFANG:
+ _bloodfangGUID = guid;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ TempSummon* tempSummon = me->ToTempSummon();
+ if (!tempSummon)
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_START_SCENE_EXSANGUINATE:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(summoner, SPELL_SUMMON_CROWLEY_BLOODFANG_MASTER, true);
+
+ _events.ScheduleEvent(EVENT_START_SCENE_EXSANGUINATE + 1, 100ms);
+ }
+ break;
+ }
+
+ case EVENT_START_SCENE_EXSANGUINATE + 1:
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ crowley->GetMotionMaster()->MovePath(PATH_CROWLEY_ENTER, false);
+
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_ENTER, false);
+
+ _events.ScheduleEvent(EVENT_START_SCENE_EXSANGUINATE + 2, 7s);
+ }
+ }
+ break;
+ }
+
+ case EVENT_START_SCENE_EXSANGUINATE + 2:
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ crowley->SetFacingToObject(bloodfang);
+
+ bloodfang->SetFacingToObject(crowley);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE, 2s);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ if (crowley->IsAIEnabled())
+ crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_0, summoner);
+
+ _events.ScheduleEvent(EVENT_SWITCH_SCENE_CAMERA, 3s + 900ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_SWITCH_SCENE_CAMERA:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_BLOODFANG, true);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 1, 2s + 500ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 1:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_0, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 2, 3s + 100ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 2:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
+
+ _events.ScheduleEvent(EVENT_SWITCH_SCENE_CAMERA + 1, 4s + 800ms);
+ }
+ break;
+ }
+
+ case EVENT_SWITCH_SCENE_CAMERA + 1:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_CROWLEY, true);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 3, 2s + 500ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 3:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ if (crowley->IsAIEnabled())
+ crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_1, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 4, 3s + 500ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 4:
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ crowley->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 5, 5s + 400ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 5:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ if (crowley->IsAIEnabled())
+ crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_2, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 6, 3s + 100ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 6:
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ crowley->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
+
+ _events.ScheduleEvent(EVENT_SWITCH_SCENE_CAMERA + 2, 3s + 550ms);
+ }
+ break;
+ }
+
+ case EVENT_SWITCH_SCENE_CAMERA + 2:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_BLOODFANG, true);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 7, 2s + 500ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 7:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_1, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 8, 3s + 800ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 8:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_2, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 9, 2s + 400ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 9:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_3, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 10, 3s + 900ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 10:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
+
+ _events.ScheduleEvent(EVENT_SWITCH_SCENE_CAMERA + 3, 4s + 450ms);
+ }
+ break;
+ }
+
+ case EVENT_SWITCH_SCENE_CAMERA + 3:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_CROWLEY, true);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 11, 3s);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 11:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ if (crowley->IsAIEnabled())
+ crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_3, summoner);
+
+ _events.ScheduleEvent(EVENT_SWITCH_SCENE_CAMERA + 4, 1s + 900ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_SWITCH_SCENE_CAMERA + 4:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_BLOODFANG, true);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 12, 2s + 500ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 12:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_4, summoner);
+
+ _events.ScheduleEvent(EVENT_ACTION_SCENE_EXSANGUINATE, 2s + 300ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_ACTION_SCENE_EXSANGUINATE:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->SetFacingTo(0.6457718f);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 13, 1s + 300ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 13:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_5, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 14, 4s);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 14:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_6, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 15, 3s + 500ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 15:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_YES);
+
+ _events.ScheduleEvent(EVENT_ACTION_SCENE_EXSANGUINATE + 1, 2s + 800ms);
+ }
+ break;
+ }
+
+ case EVENT_ACTION_SCENE_EXSANGUINATE + 1:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_NEAR_YORICK, false);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 16, 3s);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 16:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 17, 200ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 17:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_7, summoner);
+
+ _events.ScheduleEvent(EVENT_ACTION_SCENE_EXSANGUINATE + 2, 2s + 300ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_ACTION_SCENE_EXSANGUINATE + 2:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (Creature* yorick = ObjectAccessor::GetCreature(*me, _yorickGUID))
+ {
+ yorick->RemoveAura(SPELL_STEALTH);
+
+ yorick->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
+
+ bloodfang->CastSpell(yorick, SPELL_RIDE_REVERSE_CAST_EXSANGUINATE, true);
+
+ _events.ScheduleEvent(EVENT_ACTION_SCENE_EXSANGUINATE + 3, 1s + 100ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_ACTION_SCENE_EXSANGUINATE + 3:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_WITH_YORICK, false);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 18, 3s);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 18:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->SetFacingTo(3.054326f);
+
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_8, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 19, 3s + 600ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 19:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* yorick = ObjectAccessor::GetCreature(*me, _yorickGUID))
+ {
+ if (yorick->IsAIEnabled())
+ yorick->AI()->Talk(TALK_YORICK_EXSANGUINATE_DEATH, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 20, 4s + 850ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 20:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (Creature* yorick = ObjectAccessor::GetCreature(*me, _yorickGUID))
+ {
+ bloodfang->CastSpell(yorick, SPELL_EJECT_PASSENGER_01, false);
+
+ if (yorick->IsAIEnabled())
+ yorick->AI()->DoAction(ACTION_RANE_JUMP_DEATH);
+
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_9, summoner);
+
+ _events.ScheduleEvent(EVENT_ACTION_SCENE_EXSANGUINATE + 4, 3s + 600ms);
+ }
+ }
+ }
+ break;
+ }
+
+ case EVENT_ACTION_SCENE_EXSANGUINATE + 4:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->SetFacingTo(0.0f);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 21, 1s + 100ms);
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 21:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ if (bloodfang->IsAIEnabled())
+ bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_10, summoner);
+
+ _events.ScheduleEvent(EVENT_TALK_SCENE_EXSANGUINATE + 22, 4s + 100ms);
+ }
+ }
+ break;
+ }
+
+ case EVENT_TALK_SCENE_EXSANGUINATE + 22:
+ {
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
+
+ _events.ScheduleEvent(EVENT_SWITCH_SCENE_CAMERA + 5, 3s + 250ms);
+ }
+ break;
+ }
+
+ case EVENT_SWITCH_SCENE_CAMERA + 5:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_CROWLEY, true);
+
+ if (Creature* bloodfang = ObjectAccessor::GetCreature(*me, _bloodfangGUID))
+ {
+ bloodfang->SetWalk(false);
+ bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_EXIT, false);
+
+ _events.ScheduleEvent(EVENT_ACTION_SCENE_EXSANGUINATE + 5, 3s);
+ }
+ }
+ break;
+ }
+
+ case EVENT_ACTION_SCENE_EXSANGUINATE + 5:
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ {
+ crowley->GetMotionMaster()->MovePath(PATH_CROWLEY_EXIT, false);
+
+ _events.ScheduleEvent(EVENT_FINISH_SCENE_EXSANGUINATE, 4s);
+ }
+ break;
+ }
+
+ case EVENT_FINISH_SCENE_EXSANGUINATE:
+ {
+ if (Unit* summoner = tempSummon->GetSummonerUnit())
+ {
+ if (Creature* crowley = ObjectAccessor::GetCreature(*me, _crowleyGUID))
+ crowley->CastSpell(summoner, SPELL_KILL_CREDIT_YORICK, false);
+
+ if (Creature* yorick = ObjectAccessor::GetCreature(*me, _yorickGUID))
+ yorick->CastSpell(summoner, SPELL_CANCEL_SUMMON_YORICK, true);
+
+ summoner->GetMotionMaster()->Clear();
+
+ summoner->RemoveAura(SPELL_HIDE_IN_ARMOIRE);
+
+ summoner->ExitVehicle();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ }
+
+private:
+ EventMap _events;
+ ObjectGuid _yorickGUID;
+ ObjectGuid _crowleyGUID;
+ ObjectGuid _bloodfangGUID;
+};
+
+enum DariusCrowleyExsanguinate
+{
+ WAYPOINT_ON_CROWLEY_DESPAWN = 2
+};
+
+// 44883 - Lord Darius Crowley
+struct npc_silverpine_lord_darius_crowley_exsanguinate : public ScriptedAI
+{
+ npc_silverpine_lord_darius_crowley_exsanguinate(Creature* creature) : ScriptedAI(creature) { }
+
+ void JustAppeared() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void IsSummonedBy(WorldObject* /*summoner*/) override
+ {
+ if (Creature* armoire = me->FindNearestCreature(NPC_ARMOIRE_SUMMONED, 100.0f))
+ {
+ if (armoire->IsAIEnabled())
+ armoire->GetAI()->SetGUID(me->GetGUID(), me->GetEntry());
+ }
+ }
+
+ void WaypointReached(uint32 waypointId, uint32 pathId) override
+ {
+ if (pathId == PATH_CROWLEY_EXIT && waypointId == WAYPOINT_ON_CROWLEY_DESPAWN)
+ me->DespawnOrUnsummon();
+ }
+};
+
+enum IvarBloodfangExsanguinate
+{
+ WAYPOINT_ON_BLOODFANG_DESPAWN = 3
+};
+
+// 44884 - Packleader Ivar Bloodfang
+struct npc_silverpine_packleader_ivar_bloodfang_exsanguinate : public ScriptedAI
+{
+ npc_silverpine_packleader_ivar_bloodfang_exsanguinate(Creature* creature) : ScriptedAI(creature) { }
+
+ void JustAppeared() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void IsSummonedBy(WorldObject* /*summoner*/) override
+ {
+ if (Creature* armoire = me->FindNearestCreature(NPC_ARMOIRE_SUMMONED, 30.0f))
+ {
+ if (armoire->IsAIEnabled())
+ armoire->GetAI()->SetGUID(me->GetGUID(), me->GetEntry());
+ }
+ }
+
+ void WaypointReached(uint32 waypointId, uint32 pathId) override
+ {
+ if (pathId == PATH_BLOODFANG_EXIT && waypointId == WAYPOINT_ON_BLOODFANG_DESPAWN)
+ me->DespawnOrUnsummon();
+ }
+};
+
void AddSC_silverpine_forest()
{
/* Vehicles */
@@ -1616,4 +2600,12 @@ void AddSC_silverpine_forest()
RegisterCreatureAI(npc_silverpine_forsaken_trooper);
RegisterCreatureAI(npc_silverpine_bat_handler_maggotbreath);
RegisterCreatureAI(npc_silverpine_forsaken_bat);
+
+ /* Ivar Patch */
+
+ RegisterGameObjectAI(go_silverpine_abandoned_outhouse);
+ RegisterCreatureAI(npc_silverpine_deathstalker_rane_yorick);
+ RegisterCreatureAI(npc_silverpine_armoire);
+ RegisterCreatureAI(npc_silverpine_lord_darius_crowley_exsanguinate);
+ RegisterCreatureAI(npc_silverpine_packleader_ivar_bloodfang_exsanguinate);
}
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 98271b04737..8cb2b7d547c 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -5141,6 +5141,22 @@ class spell_gen_eject_passengers_3_8 : public SpellScript
}
};
+// 83781 - Reverse Cast Ride Vehicle
+class spell_gen_reverse_cast_target_to_caster_triggered: public SpellScript
+{
+ PrepareSpellScript(spell_gen_reverse_cast_target_to_caster_triggered);
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex).CalcValue(), true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_reverse_cast_target_to_caster_triggered::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_gen_absorb0_hitlimit1);
@@ -5299,4 +5315,5 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_mount_check_aura);
RegisterSpellScript(spell_gen_ancestral_call);
RegisterSpellScript(spell_gen_eject_passengers_3_8);
+ RegisterSpellScript(spell_gen_reverse_cast_target_to_caster_triggered);
}