diff options
Diffstat (limited to 'src/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp')
-rw-r--r-- | src/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp | 1160 |
1 files changed, 1160 insertions, 0 deletions
diff --git a/src/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp new file mode 100644 index 0000000000..6a096e793d --- /dev/null +++ b/src/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -0,0 +1,1160 @@ +/* + * Copyright (C) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "Vehicle.h" +#include "ObjectMgr.h" +#include "ScriptedEscortAI.h" +#include "CombatAI.h" +#include "PassiveAI.h" +#include "Player.h" +#include "SpellInfo.h" +#include "CreatureTextMgr.h" +#include "PetAI.h" + +// Ours +enum eyeOfAcherus +{ + EVENT_REMOVE_CONTROL = 1, + EVENT_SPEAK_1 = 2, + EVENT_LAUNCH = 3, + EVENT_REGAIN_CONTROL = 4, + + EYE_TEXT_LAUNCH = 0, + EYE_TEXT_CONTROL = 1, + + SPELL_EYE_OF_ACHERUS_VISUAL = 51892, +}; + +class npc_eye_of_acherus : public CreatureScript +{ +public: + npc_eye_of_acherus() : CreatureScript("npc_eye_of_acherus") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_eye_of_acherusAI(creature); + } + + struct npc_eye_of_acherusAI : public NullCreatureAI + { + npc_eye_of_acherusAI(Creature* creature) : NullCreatureAI(creature) { } + + EventMap events; + + void InitializeAI() + { + events.Reset(); + events.ScheduleEvent(EVENT_REMOVE_CONTROL, 500); + events.ScheduleEvent(EVENT_SPEAK_1, 4000); + events.ScheduleEvent(EVENT_LAUNCH, 7000); + + me->CastSpell(me, SPELL_EYE_OF_ACHERUS_VISUAL, true); + } + + void MovementInform(uint32 type, uint32 point) + { + if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized()) + events.ScheduleEvent(EVENT_REGAIN_CONTROL, 1000); + } + + void SetControl(Player* player, bool on) + { + WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, me->GetPackGUID().size()+1); + data.append(me->GetPackGUID()); + data << uint8(on ? 1 : 0); + player->GetSession()->SendPacket(&data); + } + + void JustSummoned(Creature* creature) + { + if (Unit* target = creature->SelectNearbyTarget()) + creature->AI()->AttackStart(target); + } + + void UpdateAI(uint32 diff) + { + events.Update(diff); + switch (events.ExecuteEvent()) + { + case EVENT_REMOVE_CONTROL: + if (Player* player = me->GetCharmerOrOwnerPlayerOrPlayerItself()) + SetControl(player, false); + break; + case EVENT_SPEAK_1: + Talk(EYE_TEXT_LAUNCH, me->GetCharmerOrOwnerPlayerOrPlayerItself()); + break; + case EVENT_LAUNCH: + { + Movement::PointsArray path; + path.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ())); + path.push_back(G3D::Vector3(me->GetPositionX()-40.0f, me->GetPositionY(), me->GetPositionZ()+10.0f)); + path.push_back(G3D::Vector3(1768.0f, -5876.0f, 153.0f)); + me->GetMotionMaster()->MoveSplinePath(&path); + break; + } + case EVENT_REGAIN_CONTROL: + if (Player* player = me->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + SetControl(player, true); + Talk(EYE_TEXT_CONTROL, player); + } + break; + } + } + }; +}; + +class spell_q12641_death_comes_from_on_high_summon_ghouls : public SpellScriptLoader +{ + public: + spell_q12641_death_comes_from_on_high_summon_ghouls() : SpellScriptLoader("spell_q12641_death_comes_from_on_high_summon_ghouls") { } + + class spell_q12641_death_comes_from_on_high_summon_ghouls_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12641_death_comes_from_on_high_summon_ghouls_SpellScript); + + void HandleScriptEffect(SpellEffIndex effIndex) + { + PreventHitEffect(effIndex); + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 54522, true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12641_death_comes_from_on_high_summon_ghouls_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12641_death_comes_from_on_high_summon_ghouls_SpellScript(); + } +}; + +#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!" + +enum deathsChallenge +{ + SPELL_DUEL = 52996, + //SPELL_DUEL_TRIGGERED = 52990, + SPELL_DUEL_VICTORY = 52994, + SPELL_DUEL_FLAG = 52991, + + SAY_DUEL = 0, + + QUEST_DEATH_CHALLENGE = 12733, + FACTION_HOSTILE = 2068, + + DATA_IN_PROGRESS = 0, + + EVENT_SPEAK = 1, // 1 - 6 + EVENT_DUEL_LOST = 7, // 7 - 8 +}; + +class npc_death_knight_initiate : public CreatureScript +{ +public: + npc_death_knight_initiate() : CreatureScript("npc_death_knight_initiate") { } + + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) + { + player->PlayerTalkClass->ClearMenus(); + if (action == GOSSIP_ACTION_INFO_DEF) + { + player->CLOSE_GOSSIP_MENU(); + + if (player->IsInCombat() || creature->IsInCombat()) + return true; + + if (creature->AI()->GetData(DATA_IN_PROGRESS)) + return true; + + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); + + player->CastSpell(creature, SPELL_DUEL, false); + player->CastSpell(player, SPELL_DUEL_FLAG, true); + } + return true; + } + + bool OnGossipHello(Player* player, Creature* creature) + { + if (player->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE && creature->IsFullHealth()) + { + if (player->HealthBelowPct(10)) + return true; + + if (player->IsInCombat() || creature->IsInCombat()) + return true; + + if (!creature->AI()->GetData(player->GetGUIDLow())) + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + } + return true; + } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_death_knight_initiateAI(creature); + } + + struct npc_death_knight_initiateAI : public CombatAI + { + npc_death_knight_initiateAI(Creature* creature) : CombatAI(creature) { } + + bool _duelInProgress; + uint64 _duelGUID; + EventMap events; + std::set<uint32> playerGUIDs; + + uint32 GetData(uint32 data) const + { + if (data == DATA_IN_PROGRESS) + return _duelInProgress; + + return playerGUIDs.find(data) != playerGUIDs.end(); + } + + void Reset() + { + _duelInProgress = false; + _duelGUID = 0; + me->RestoreFaction(); + CombatAI::Reset(); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); + } + + void SpellHit(Unit* caster, const SpellInfo* pSpell) + { + if (!_duelInProgress && pSpell->Id == SPELL_DUEL) + { + playerGUIDs.insert(caster->GetGUIDLow()); + _duelGUID = caster->GetGUID(); + _duelInProgress = true; + + events.ScheduleEvent(EVENT_SPEAK, 3000); + events.ScheduleEvent(EVENT_SPEAK+1, 7000); + events.ScheduleEvent(EVENT_SPEAK+2, 8000); + events.ScheduleEvent(EVENT_SPEAK+3, 9000); + events.ScheduleEvent(EVENT_SPEAK+4, 10000); + events.ScheduleEvent(EVENT_SPEAK+5, 11000); + } + } + + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) + { + if (attacker && _duelInProgress && attacker->IsControlledByPlayer()) + { + if (attacker->GetCharmerOrOwnerOrOwnGUID() != _duelGUID) + damage = 0; + else if (damage >= me->GetHealth()) + { + damage = 0; + events.ScheduleEvent(EVENT_DUEL_LOST, 2000); + events.ScheduleEvent(EVENT_DUEL_LOST+1, 6000); + _duelGUID = 0; + _duelInProgress = 0; + + attacker->RemoveGameObject(SPELL_DUEL_FLAG, true); + attacker->AttackStop(); + me->CombatStop(false); + me->RemoveAllAuras(); + me->CastSpell(attacker, SPELL_DUEL_VICTORY, true); + me->RestoreFaction(); + } + } + } + + void UpdateAI(uint32 diff) + { + events.Update(diff); + switch (events.ExecuteEvent()) + { + case EVENT_SPEAK: + Talk(SAY_DUEL, ObjectAccessor::GetPlayer(*me, _duelGUID)); + break; + case EVENT_SPEAK+1: + Talk(SAY_DUEL+1, ObjectAccessor::GetPlayer(*me, _duelGUID)); + break; + case EVENT_SPEAK+2: + Talk(SAY_DUEL+2, ObjectAccessor::GetPlayer(*me, _duelGUID)); + break; + case EVENT_SPEAK+3: + Talk(SAY_DUEL+3, ObjectAccessor::GetPlayer(*me, _duelGUID)); + break; + case EVENT_SPEAK+4: + Talk(SAY_DUEL+4, ObjectAccessor::GetPlayer(*me, _duelGUID)); + break; + case EVENT_SPEAK+5: + me->setFaction(FACTION_HOSTILE); + if (Player* player = ObjectAccessor::GetPlayer(*me, _duelGUID)) + AttackStart(player); + return; + case EVENT_DUEL_LOST: + me->CastSpell(me, 7267, true); + break; + case EVENT_DUEL_LOST+1: + EnterEvadeMode(); + return; + } + + if (!events.Empty() || !UpdateVictim()) + return; + + if (_duelInProgress) + { + if (me->GetVictim()->GetGUID() == _duelGUID && me->GetVictim()->HealthBelowPct(10)) + { + me->GetVictim()->CastSpell(me->GetVictim(), 7267, true); // beg + me->GetVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); + EnterEvadeMode(); + return; + } + } + + CombatAI::UpdateAI(diff); + } + }; +}; + +enum GiftOfTheHarvester +{ + NPC_GHOUL = 28845, + MAX_GHOULS = 5, + + SPELL_GHOUL_EMERGE = 50142, + SPELL_SUMMON_SCARLET_GHOST = 52505, + SPELL_GHOUL_SUBMERGE = 26234, + + EVENT_GHOUL_RESTORE_STATE = 1, + EVENT_GHOUL_CHECK_COMBAT = 2, + EVENT_GHOUL_EMOTE = 3, + EVENT_GHOUL_MOVE_TO_PIT = 4, + + SAY_GOTHIK_PIT = 0 +}; + +class spell_item_gift_of_the_harvester : public SpellScriptLoader +{ + public: + spell_item_gift_of_the_harvester() : SpellScriptLoader("spell_item_gift_of_the_harvester") { } + + class spell_item_gift_of_the_harvester_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_gift_of_the_harvester_SpellScript); + + SpellCastResult CheckRequirement() + { + std::list<Creature*> ghouls; + GetCaster()->GetAllMinionsByEntry(ghouls, NPC_GHOUL); + if (ghouls.size() >= MAX_GHOULS) + { + SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_TOO_MANY_GHOULS); + return SPELL_FAILED_CUSTOM_ERROR; + } + + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_item_gift_of_the_harvester_SpellScript::CheckRequirement); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_gift_of_the_harvester_SpellScript(); + } +}; + +class spell_q12698_the_gift_that_keeps_on_giving : public SpellScriptLoader +{ + public: + spell_q12698_the_gift_that_keeps_on_giving() : SpellScriptLoader("spell_q12698_the_gift_that_keeps_on_giving") { } + + class spell_q12698_the_gift_that_keeps_on_giving_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12698_the_gift_that_keeps_on_giving_SpellScript); + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (GetOriginalCaster() && GetHitUnit()) + GetOriginalCaster()->CastSpell(GetHitUnit(), urand(0, 1) ? GetEffectValue() : SPELL_SUMMON_SCARLET_GHOST, true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12698_the_gift_that_keeps_on_giving_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12698_the_gift_that_keeps_on_giving_SpellScript(); + } +}; + +class npc_scarlet_ghoul : public CreatureScript +{ +public: + npc_scarlet_ghoul() : CreatureScript("npc_scarlet_ghoul") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_scarlet_ghoulAI(creature); + } + + struct npc_scarlet_ghoulAI : public ScriptedAI + { + npc_scarlet_ghoulAI(Creature* creature) : ScriptedAI(creature) + { + } + + EventMap events; + uint64 gothikGUID; + + void InitializeAI() + { + gothikGUID = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + ScriptedAI::InitializeAI(); + me->SetReactState(REACT_PASSIVE); + + events.ScheduleEvent(EVENT_GHOUL_EMOTE, 1); + events.ScheduleEvent(EVENT_GHOUL_RESTORE_STATE, 3500); + } + + void OwnerAttackedBy(Unit* attacker) + { + if (!me->IsInCombat() && me->GetReactState() == REACT_DEFENSIVE) + AttackStart(attacker); + } + + void SetGUID(uint64 guid, int32) + { + gothikGUID = guid; + events.ScheduleEvent(EVENT_GHOUL_MOVE_TO_PIT, 3000); + me->GetMotionMaster()->Clear(false); + } + + void MovementInform(uint32 type, uint32 point) + { + if (type == POINT_MOTION_TYPE && point == 1) + { + me->DespawnOrUnsummon(1500); + me->CastSpell(me, SPELL_GHOUL_SUBMERGE, true); + } + } + + void UpdateAI(uint32 diff) + { + events.Update(diff); + switch (events.GetEvent()) + { + case EVENT_GHOUL_MOVE_TO_PIT: + me->GetMotionMaster()->MovePoint(1, 2364.77f, -5776.14f, 151.36f); + if (Creature* gothik = ObjectAccessor::GetCreature(*me, gothikGUID)) + gothik->AI()->DoAction(SAY_GOTHIK_PIT); + events.PopEvent(); + break; + case EVENT_GHOUL_EMOTE: + me->CastSpell(me, SPELL_GHOUL_EMERGE, true); + events.PopEvent(); + break; + case EVENT_GHOUL_RESTORE_STATE: + me->SetReactState(REACT_DEFENSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + if (Player* owner = me->GetCharmerOrOwnerPlayerOrPlayerItself()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, frand(0.0f, 2*M_PI)); + events.PopEvent(); + events.ScheduleEvent(EVENT_GHOUL_CHECK_COMBAT, 1000); + return; + case EVENT_GHOUL_CHECK_COMBAT: + if (!me->IsInCombat()) + if (Player* owner = me->GetCharmerOrOwnerPlayerOrPlayerItself()) + if (owner->GetVictim()) + AttackStart(owner->GetVictim()); + + events.RepeatEvent(1000); + return; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + }; +}; + +class npc_dkc1_gothik : public CreatureScript +{ +public: + npc_dkc1_gothik() : CreatureScript("npc_dkc1_gothik") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_dkc1_gothikAI(creature); + } + + struct npc_dkc1_gothikAI : public ScriptedAI + { + npc_dkc1_gothikAI(Creature* creature) : ScriptedAI(creature) { spoken = 0; } + + int32 spoken; + + void DoAction(int32 action) + { + if (action == SAY_GOTHIK_PIT && spoken <= 0) + { + spoken = 5000; + Talk(SAY_GOTHIK_PIT); + } + } + + void MoveInLineOfSight(Unit* who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (!who->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC) && who->GetEntry() == NPC_GHOUL && me->IsWithinDistInMap(who, 10.0f)) + if (Unit* owner = who->GetOwner()) + if (Player* player = owner->ToPlayer()) + { + Creature* creature = who->ToCreature(); + if (player->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) + creature->CastSpell(owner, 52517, true); + + creature->AI()->SetGUID(me->GetGUID()); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + } + } + + void UpdateAI(uint32 diff) + { + if (spoken > 0) + spoken -= diff; + + ScriptedAI::UpdateAI(diff); + } + }; +}; + +class npc_scarlet_cannon : public CreatureScript +{ +public: + npc_scarlet_cannon() : CreatureScript("npc_scarlet_cannon") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_scarlet_cannonAI(creature); + } + + struct npc_scarlet_cannonAI : public VehicleAI + { + npc_scarlet_cannonAI(Creature* creature) : VehicleAI(creature) { summonAttackers = 0; } + + uint32 summonAttackers; + void PassengerBoarded(Unit* /*passenger*/, int8 /*seatId*/, bool apply) + { + summonAttackers = apply ? 8000 : 0; + } + + void UpdateAI(uint32 diff) + { + VehicleAI::UpdateAI(diff); + + if (summonAttackers) + { + summonAttackers += diff; + if (summonAttackers >= 15000) + { + for (uint8 i = 0; i < 15; ++i) + if (Creature* summon = me->SummonCreature(28834 /*NPC_SCARLET_FLEET_DEFENDER*/, 2192.56f+irand(-10, 10), -6147.90f+irand(-10, 10), 5.2f, 4.7f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 45000)) + { + summon->SetHomePosition(me->GetHomePosition()); + summon->AI()->AttackStart(me); + } + + summonAttackers = 1; + } + } + } + }; +}; + + +// Theirs +/*###### +##Quest 12848 +######*/ + +#define GCD_CAST 1 + +enum UnworthyInitiate +{ + SPELL_SOUL_PRISON_CHAIN_SELF = 54612, + SPELL_SOUL_PRISON_CHAIN = 54613, + SPELL_DK_INITIATE_VISUAL = 51519, + + SPELL_ICY_TOUCH = 52372, + SPELL_PLAGUE_STRIKE = 52373, + SPELL_BLOOD_STRIKE = 52374, + SPELL_DEATH_COIL = 52375, + + SAY_EVENT_START = 0, + SAY_EVENT_ATTACK = 1, + + EVENT_ICY_TOUCH = 1, + EVENT_PLAGUE_STRIKE = 2, + EVENT_BLOOD_STRIKE = 3, + EVENT_DEATH_COIL = 4 +}; + +enum UnworthyInitiatePhase +{ + PHASE_CHAINED, + PHASE_TO_EQUIP, + PHASE_EQUIPING, + PHASE_TO_ATTACK, + PHASE_ATTACKING, +}; + +uint32 acherus_soul_prison[12] = +{ + 191577, + 191580, + 191581, + 191582, + 191583, + 191584, + 191585, + 191586, + 191587, + 191588, + 191589, + 191590 +}; + +uint32 acherus_unworthy_initiate[5] = +{ + 29519, + 29520, + 29565, + 29566, + 29567 +}; + +class npc_unworthy_initiate : public CreatureScript +{ +public: + npc_unworthy_initiate() : CreatureScript("npc_unworthy_initiate") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_unworthy_initiateAI(creature); + } + + struct npc_unworthy_initiateAI : public ScriptedAI + { + npc_unworthy_initiateAI(Creature* creature) : ScriptedAI(creature) + { + me->SetReactState(REACT_PASSIVE); + if (!me->GetCurrentEquipmentId()) + me->SetCurrentEquipmentId(me->GetOriginalEquipmentId()); + } + + uint64 playerGUID; + UnworthyInitiatePhase phase; + uint32 wait_timer; + float anchorX, anchorY; + uint64 anchorGUID; + + EventMap events; + + void Reset() + { + anchorGUID = 0; + phase = PHASE_CHAINED; + events.Reset(); + me->setFaction(7); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); + me->LoadEquipment(0, true); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_ICY_TOUCH, 1000, GCD_CAST); + events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 3000, GCD_CAST); + events.ScheduleEvent(EVENT_BLOOD_STRIKE, 2000, GCD_CAST); + events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + { + wait_timer = 5000; + me->LoadEquipment(1); + me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); + + if (Player* starter = ObjectAccessor::GetPlayer(*me, playerGUID)) + sCreatureTextMgr->SendChat(me, SAY_EVENT_ATTACK, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, starter); + + phase = PHASE_TO_ATTACK; + } + } + + void EventStart(Creature* anchor, Player* target) + { + wait_timer = 5000; + phase = PHASE_TO_EQUIP; + + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN_SELF); + me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN); + + float z; + anchor->GetContactPoint(me, anchorX, anchorY, z, 1.0f); + + playerGUID = target->GetGUID(); + Talk(SAY_EVENT_START, target); + } + + void UpdateAI(uint32 diff) + { + switch (phase) + { + case PHASE_CHAINED: + if (!anchorGUID) + { + if (Creature* anchor = me->FindNearestCreature(29521, 30)) + { + anchor->AI()->SetGUID(me->GetGUID()); + anchor->CastSpell(me, SPELL_SOUL_PRISON_CHAIN, true); + anchorGUID = anchor->GetGUID(); + } + + float dist = 99.0f; + GameObject* prison = NULL; + + for (uint8 i = 0; i < 12; ++i) + { + if (GameObject* temp_prison = me->FindNearestGameObject(acherus_soul_prison[i], 30)) + { + if (me->IsWithinDist(temp_prison, dist, false)) + { + dist = me->GetDistance2d(temp_prison); + prison = temp_prison; + } + } + } + + if (prison) + prison->ResetDoorOrButton(); + } + break; + case PHASE_TO_EQUIP: + if (wait_timer) + { + if (wait_timer > diff) + wait_timer -= diff; + else + { + me->GetMotionMaster()->MovePoint(1, anchorX, anchorY, me->GetPositionZ()); + //sLog->outDebug(LOG_FILTER_TSCR, "npc_unworthy_initiateAI: move to %f %f %f", anchorX, anchorY, me->GetPositionZ()); + phase = PHASE_EQUIPING; + wait_timer = 0; + } + } + break; + case PHASE_TO_ATTACK: + if (wait_timer) + { + if (wait_timer > diff) + wait_timer -= diff; + else + { + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + phase = PHASE_ATTACKING; + + if (Player* target = ObjectAccessor::GetPlayer(*me, playerGUID)) + AttackStart(target); + wait_timer = 0; + } + } + break; + case PHASE_ATTACKING: + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ICY_TOUCH: + DoCastVictim(SPELL_ICY_TOUCH); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_ICY_TOUCH, 5000, GCD_CAST); + break; + case EVENT_PLAGUE_STRIKE: + DoCastVictim(SPELL_PLAGUE_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 5000, GCD_CAST); + break; + case EVENT_BLOOD_STRIKE: + DoCastVictim(SPELL_BLOOD_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_BLOOD_STRIKE, 5000, GCD_CAST); + break; + case EVENT_DEATH_COIL: + DoCastVictim(SPELL_DEATH_COIL); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); + break; + } + } + + DoMeleeAttackIfReady(); + break; + default: + break; + } + } + }; +}; + +class npc_unworthy_initiate_anchor : public CreatureScript +{ +public: + npc_unworthy_initiate_anchor() : CreatureScript("npc_unworthy_initiate_anchor") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_unworthy_initiate_anchorAI(creature); + } + + struct npc_unworthy_initiate_anchorAI : public PassiveAI + { + npc_unworthy_initiate_anchorAI(Creature* creature) : PassiveAI(creature), prisonerGUID(0) {} + + uint64 prisonerGUID; + + void SetGUID(uint64 guid, int32 /*id*/) + { + if (!prisonerGUID) + prisonerGUID = guid; + } + + uint64 GetGUID(int32 /*id*/) const + { + return prisonerGUID; + } + }; +}; + +class go_acherus_soul_prison : public GameObjectScript +{ +public: + go_acherus_soul_prison() : GameObjectScript("go_acherus_soul_prison") { } + + bool OnGossipHello(Player* player, GameObject* go) + { + if (Creature* anchor = go->FindNearestCreature(29521, 15)) + if (uint64 prisonerGUID = anchor->AI()->GetGUID()) + if (Creature* prisoner = ObjectAccessor::GetCreature(*player, prisonerGUID)) + CAST_AI(npc_unworthy_initiate::npc_unworthy_initiateAI, prisoner->AI())->EventStart(anchor, player); + + return false; + } + +}; + +/*#### +## npc_scarlet_miner_cart +####*/ + +enum Spells_SM +{ + SPELL_CART_CHECK = 54173, + SPELL_CART_DRAG = 52465 +}; + +class npc_scarlet_miner_cart : public CreatureScript +{ +public: + npc_scarlet_miner_cart() : CreatureScript("npc_scarlet_miner_cart") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_scarlet_miner_cartAI(creature); + } + + struct npc_scarlet_miner_cartAI : public PassiveAI + { + npc_scarlet_miner_cartAI(Creature* creature) : PassiveAI(creature), minerGUID(0) + { + me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + me->setFaction(35); + me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse. + } + + uint64 minerGUID; + + void SetGUID(uint64 guid, int32 /*id*/) + { + minerGUID = guid; + } + + void DoAction(int32 /*param*/) + { + if (Creature* miner = ObjectAccessor::GetCreature(*me, minerGUID)) + { + me->SetWalk(false); + + //Not 100% correct, but movement is smooth. Sometimes miner walks faster + //than normal, this speed is fast enough to keep up at those times. + me->SetSpeed(MOVE_RUN, 1.25f); + + me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); + me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + me->setFaction(35); + } + } + + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) + { + who->SetVisible(!apply); + if (!apply) + if (Creature* miner = ObjectAccessor::GetCreature(*me, minerGUID)) + miner->DisappearAndDie(); + } + }; + +}; + +/*#### +## npc_scarlet_miner +####*/ + +enum Says_SM +{ + SAY_SCARLET_MINER_0 = 0, + SAY_SCARLET_MINER_1 = 1 +}; + +class npc_scarlet_miner : public CreatureScript +{ +public: + npc_scarlet_miner() : CreatureScript("npc_scarlet_miner") { } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_scarlet_minerAI(creature); + } + + struct npc_scarlet_minerAI : public npc_escortAI + { + npc_scarlet_minerAI(Creature* creature) : npc_escortAI(creature) + { + me->SetReactState(REACT_PASSIVE); + } + + uint32 IntroTimer; + uint32 IntroPhase; + uint64 carGUID; + + void Reset() + { + carGUID = 0; + IntroTimer = 0; + IntroPhase = 0; + } + + void InitWaypoint() + { + AddWaypoint(1, 2389.03f, -5902.74f, 109.014f, 5000); + AddWaypoint(2, 2341.812012f, -5900.484863f, 102.619743f); + AddWaypoint(3, 2306.561279f, -5901.738281f, 91.792419f); + AddWaypoint(4, 2300.098389f, -5912.618652f, 86.014885f); + AddWaypoint(5, 2294.142090f, -5927.274414f, 75.316849f); + AddWaypoint(6, 2286.984375f, -5944.955566f, 63.714966f); + AddWaypoint(7, 2280.001709f, -5961.186035f, 54.228283f); + AddWaypoint(8, 2259.389648f, -5974.197754f, 42.359348f); + AddWaypoint(9, 2242.882812f, -5984.642578f, 32.827850f); + AddWaypoint(10, 2217.265625f, -6028.959473f, 7.675705f); + AddWaypoint(11, 2202.595947f, -6061.325684f, 5.882018f); + AddWaypoint(12, 2188.974609f, -6080.866699f, 3.370027f); + + if (urand(0, 1)) + { + AddWaypoint(13, 2176.483887f, -6110.407227f, 1.855181f); + AddWaypoint(14, 2172.516602f, -6146.752441f, 1.074235f); + AddWaypoint(15, 2138.918457f, -6158.920898f, 1.342926f); + AddWaypoint(16, 2129.866699f, -6174.107910f, 4.380779f); + AddWaypoint(17, 2117.709473f, -6193.830078f, 13.3542f, 10000); + } + else + { + AddWaypoint(13, 2184.190186f, -6166.447266f, 0.968877f); + AddWaypoint(14, 2234.265625f, -6163.741211f, 0.916021f); + AddWaypoint(15, 2268.071777f, -6158.750977f, 1.822252f); + AddWaypoint(16, 2270.028320f, -6176.505859f, 6.340538f); + AddWaypoint(17, 2271.739014f, -6195.401855f, 13.3542f, 10000); + } + } + + void InitCartQuest(Player* who) + { + carGUID = who->GetVehicleBase()->GetGUID(); + InitWaypoint(); + Start(false, false, who->GetGUID()); + SetDespawnAtFar(false); + } + + void WaypointReached(uint32 waypointId) + { + switch (waypointId) + { + case 1: + if (Unit* car = ObjectAccessor::GetCreature(*me, carGUID)) + { + me->SetFacingToObject(car); + // xinef: add some flags + car->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + car->setFaction(35); + } + Talk(SAY_SCARLET_MINER_0); + SetRun(true); + IntroTimer = 4000; + IntroPhase = 1; + break; + case 17: + if (Creature* car = ObjectAccessor::GetCreature(*me, carGUID)) + { + car->SetPosition(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ() + 1, car->GetOrientation()); + car->StopMovingOnCurrentPos(); + me->SetFacingToObject(car); + car->RemoveAura(SPELL_CART_DRAG); + } + Talk(SAY_SCARLET_MINER_1); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) + { + if (IntroPhase) + { + if (IntroTimer <= diff) + { + if (IntroPhase == 1) + { + if (Creature* car = ObjectAccessor::GetCreature(*me, carGUID)) + DoCast(car, SPELL_CART_DRAG); + IntroTimer = 800; + IntroPhase = 2; + } + else + { + if (Creature* car = ObjectAccessor::GetCreature(*me, carGUID)) + car->AI()->DoAction(0); + IntroPhase = 0; + } + } else IntroTimer-=diff; + } + npc_escortAI::UpdateAI(diff); + } + }; + +}; + +/*###### +## go_inconspicuous_mine_car +######*/ + +enum Spells_Cart +{ + SPELL_CART_SUMM = 52463 +}; + +class go_inconspicuous_mine_car : public GameObjectScript +{ +public: + go_inconspicuous_mine_car() : GameObjectScript("go_inconspicuous_mine_car") { } + + bool OnGossipHello(Player* player, GameObject* /*go*/) + { + if (player->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) + { + // Hack Why Trinity Dont Support Custom Summon Location + if (Creature* miner = player->SummonCreature(28841, 2383.869629f, -5900.312500f, 107.996086f, player->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1)) + { + player->CastSpell(player, SPELL_CART_SUMM, true); + if (Creature* car = player->GetVehicleCreatureBase()) + { + if (car->GetEntry() == 28817) + { + car->AI()->SetGUID(miner->GetGUID()); + CAST_AI(npc_scarlet_miner::npc_scarlet_minerAI, miner->AI())->InitCartQuest(player); + } + } + } + } + return true; + } + +}; + +void AddSC_the_scarlet_enclave_c1() +{ + // Ours + new npc_eye_of_acherus(); + new spell_q12641_death_comes_from_on_high_summon_ghouls(); + new npc_death_knight_initiate(); + new spell_item_gift_of_the_harvester(); + new spell_q12698_the_gift_that_keeps_on_giving(); + new npc_scarlet_ghoul(); + new npc_dkc1_gothik(); + new npc_scarlet_cannon(); + + // Theirs + new npc_unworthy_initiate(); + new npc_unworthy_initiate_anchor(); + new go_acherus_soul_prison(); + + new npc_scarlet_miner(); + new npc_scarlet_miner_cart(); + new go_inconspicuous_mine_car(); +} |