/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 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 Affero 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 . */ #include "AreaDefines.h" #include "CreatureScript.h" #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "SpellInfo.h" /*###### # npc_gilthares ######*/ enum Gilthares { SAY_GIL_START = 0, SAY_GIL_AT_LAST = 1, SAY_GIL_PROCEED = 2, SAY_GIL_FREEBOOTERS = 3, SAY_GIL_AGGRO = 4, SAY_GIL_ALMOST = 5, SAY_GIL_SWEET = 6, SAY_GIL_FREED = 7, QUEST_FREE_FROM_HOLD = 898 }; class npc_gilthares : public CreatureScript { public: npc_gilthares() : CreatureScript("npc_gilthares") { } bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest) override { if (quest->GetQuestId() == QUEST_FREE_FROM_HOLD) { creature->SetFaction(FACTION_ESCORTEE_H_NEUTRAL_ACTIVE); //guessed, possible not needed for this quest creature->SetStandState(UNIT_STAND_STATE_STAND); creature->AI()->Talk(SAY_GIL_START, player); if (npc_giltharesAI* pEscortAI = CAST_AI(npc_gilthares::npc_giltharesAI, creature->AI())) pEscortAI->Start(false, false, player->GetGUID(), quest); } return true; } CreatureAI* GetAI(Creature* creature) const override { return new npc_giltharesAI(creature); } struct npc_giltharesAI : public npc_escortAI { npc_giltharesAI(Creature* creature) : npc_escortAI(creature) { } void Reset() override { } void WaypointReached(uint32 waypointId) override { Player* player = GetPlayerForEscort(); if (!player) return; switch (waypointId) { case 16: Talk(SAY_GIL_AT_LAST, player); break; case 17: Talk(SAY_GIL_PROCEED, player); break; case 18: Talk(SAY_GIL_FREEBOOTERS, player); break; case 37: Talk(SAY_GIL_ALMOST, player); break; case 47: Talk(SAY_GIL_SWEET, player); break; case 53: Talk(SAY_GIL_FREED, player); player->GroupEventHappens(QUEST_FREE_FROM_HOLD, me); break; } } void JustEngagedWith(Unit* who) override { //not always use if (rand() % 4) return; //only aggro text if not player and only in this area if (!who->IsPlayer() && me->GetAreaId() == AREA_THE_MERCHANT_COAST) { //appears to be pretty much random (possible only if escorter not in combat with who yet?) Talk(SAY_GIL_AGGRO, who); } } }; }; /*###### ## npc_taskmaster_fizzule ######*/ enum TaskmasterFizzule { FACTION_FRIENDLY_F = 35, SPELL_FLARE = 10113, SPELL_FOLLY = 10137, }; class npc_taskmaster_fizzule : public CreatureScript { public: npc_taskmaster_fizzule() : CreatureScript("npc_taskmaster_fizzule") { } CreatureAI* GetAI(Creature* creature) const override { return new npc_taskmaster_fizzuleAI(creature); } struct npc_taskmaster_fizzuleAI : public ScriptedAI { npc_taskmaster_fizzuleAI(Creature* creature) : ScriptedAI(creature) { factionNorm = creature->GetFaction(); } uint32 factionNorm; bool IsFriend; uint32 ResetTimer; uint8 FlareCount; void Reset() override { IsFriend = false; ResetTimer = 120000; FlareCount = 0; me->SetFaction(factionNorm); } void DoFriend() { me->RemoveAllAuras(); me->GetThreatMgr().ClearAllThreat(); me->CombatStop(true); me->StopMoving(); me->GetMotionMaster()->MoveIdle(); me->SetFaction(FACTION_FRIENDLY); me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); } void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { if (spell->Id == SPELL_FLARE || spell->Id == SPELL_FOLLY) { ++FlareCount; if (FlareCount >= 2) IsFriend = true; } } void JustEngagedWith(Unit* /*who*/) override { } void UpdateAI(uint32 diff) override { if (IsFriend) { if (ResetTimer <= diff) { EnterEvadeMode(); return; } else ResetTimer -= diff; } if (!UpdateVictim()) return; DoMeleeAttackIfReady(); } void ReceiveEmote(Player* /*player*/, uint32 emote) override { if (emote == TEXT_EMOTE_SALUTE) { if (FlareCount >= 2) { if (me->GetFaction() == FACTION_FRIENDLY_F) return; DoFriend(); } } } }; }; /*##### ## npc_twiggy_flathead #####*/ enum TwiggyFlathead { NPC_BIG_WILL = 6238, NPC_AFFRAY_CHALLENGER = 6240, SAY_TWIGGY_FLATHEAD_BEGIN = 0, SAY_TWIGGY_FLATHEAD_FRAY = 1, SAY_TWIGGY_FLATHEAD_DOWN = 2, SAY_TWIGGY_FLATHEAD_OVER = 3 }; Position const AffrayChallengerLoc[6] = { {-1683.0f, -4326.0f, 2.79f, 0.0f}, {-1682.0f, -4329.0f, 2.79f, 0.0f}, {-1683.0f, -4330.0f, 2.79f, 0.0f}, {-1680.0f, -4334.0f, 2.79f, 1.49f}, {-1674.0f, -4326.0f, 2.79f, 3.49f}, {-1677.0f, -4334.0f, 2.79f, 1.66f} }; class npc_twiggy_flathead : public CreatureScript { public: npc_twiggy_flathead() : CreatureScript("npc_twiggy_flathead") { } CreatureAI* GetAI(Creature* creature) const override { return new npc_twiggy_flatheadAI (creature); } struct npc_twiggy_flatheadAI : public ScriptedAI { npc_twiggy_flatheadAI(Creature* creature) : ScriptedAI(creature) {} bool EventInProgress; bool EventGrate; bool EventBigWill; bool ChallengerDown[6]; uint8 Wave; uint32 WaveTimer; uint32 ChallengerChecker; ObjectGuid PlayerGUID; ObjectGuid AffrayChallenger[6]; ObjectGuid BigWill; void Reset() override { EventInProgress = false; EventGrate = false; EventBigWill = false; WaveTimer = 600000; ChallengerChecker = 0; Wave = 0; PlayerGUID.Clear(); for (uint8 i = 0; i < 6; ++i) { AffrayChallenger[i].Clear(); ChallengerDown[i] = false; } BigWill.Clear(); } void JustEngagedWith(Unit* /*who*/) override { } void EnterEvadeMode(EvadeReason why) override { CleanUp(); ScriptedAI::EnterEvadeMode(why); } void CleanUp() { for (uint8 i = 0; i < 6; ++i) // unsummon challengers if (AffrayChallenger[i]) if (Creature* creature = ObjectAccessor::GetCreature((*me), AffrayChallenger[i])) creature->DespawnOrUnsummon(1); if (BigWill) // unsummon bigWill if (Creature* creature = ObjectAccessor::GetCreature((*me), BigWill)) creature->DespawnOrUnsummon(1); } void MoveInLineOfSight(Unit* who) override { if (!who->IsAlive() || EventInProgress || !who->IsPlayer()) return; if (me->IsWithinDistInMap(who, 10.0f) && who->ToPlayer()->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { PlayerGUID = who->GetGUID(); EventInProgress = true; } } void UpdateAI(uint32 diff) override { if (EventInProgress) { Player* pWarrior = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!pWarrior || me->GetDistance2d(pWarrior) >= 200.0f) { EnterEvadeMode(EVADE_REASON_OTHER); return; } if (!pWarrior->IsAlive() && pWarrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { Talk(SAY_TWIGGY_FLATHEAD_DOWN); pWarrior->FailQuest(1719); EnterEvadeMode(EVADE_REASON_OTHER); return; } if (!EventGrate) { float x, y, z; pWarrior->GetPosition(x, y, z); if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) { pWarrior->AreaExploredOrEventHappens(1719); Talk(SAY_TWIGGY_FLATHEAD_BEGIN, pWarrior); for (uint8 i = 0; i < 6; ++i) { Creature* creature = me->SummonCreature(NPC_AFFRAY_CHALLENGER, AffrayChallengerLoc[i], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); if (!creature) continue; creature->SetFaction(FACTION_FRIENDLY); creature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); AffrayChallenger[i] = creature->GetGUID(); } WaveTimer = 5000; ChallengerChecker = 1000; EventGrate = true; } } else { if (ChallengerChecker <= diff) { for (uint8 i = 0; i < 6; ++i) { if (AffrayChallenger[i]) { Creature* creature = ObjectAccessor::GetCreature(*me, AffrayChallenger[i]); if ((!creature || !creature->IsAlive()) && !ChallengerDown[i]) { Talk(SAY_TWIGGY_FLATHEAD_DOWN); ChallengerDown[i] = true; } } } ChallengerChecker = 1000; } else ChallengerChecker -= diff; if (WaveTimer <= diff) { if (Wave < 6 && !EventBigWill) { Talk(SAY_TWIGGY_FLATHEAD_FRAY); Creature* creature = ObjectAccessor::GetCreature(*me, AffrayChallenger[Wave]); if (creature && creature->IsAlive()) { creature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); creature->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); creature->SetFaction(FACTION_MONSTER); creature->AI()->AttackStart(pWarrior); } ++Wave; WaveTimer = 20000; } else if (Wave >= 6 && !EventBigWill) { if (Creature* creature = me->SummonCreature(NPC_BIG_WILL, -1722, -4341, 6.12f, 6.26f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 480000)) { BigWill = creature->GetGUID(); creature->GetMotionMaster()->MovePoint(2, -1682, -4329, 2.79f); creature->HandleEmoteCommand(EMOTE_STATE_READY_UNARMED); EventBigWill = true; WaveTimer = 10000; } } else if (Wave >= 6 && EventBigWill) { Creature* creature = ObjectAccessor::GetCreature(*me, BigWill); if (!creature || !creature->IsAlive()) { Talk(SAY_TWIGGY_FLATHEAD_OVER); EnterEvadeMode(EVADE_REASON_OTHER); return; } else // Makes BIG WILL attackable. { creature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); creature->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); creature->SetFaction(FACTION_MONSTER); creature->AI()->AttackStart(pWarrior); } WaveTimer = 2000; } } else WaveTimer -= diff; } } } }; }; /*##### ## npc_wizzlecrank_shredder #####*/ enum Wizzlecrank { SAY_MERCENARY = 0, SAY_START = 0, SAY_STARTUP1 = 1, SAY_STARTUP2 = 2, SAY_PROGRESS_1 = 3, SAY_PROGRESS_2 = 4, SAY_PROGRESS_3 = 5, SAY_END = 6, QUEST_ESCAPE = 863, NPC_PILOT_WIZZ = 3451, NPC_MERCENARY = 3282, }; class npc_wizzlecrank_shredder : public CreatureScript { public: npc_wizzlecrank_shredder() : CreatureScript("npc_wizzlecrank_shredder") { } struct npc_wizzlecrank_shredderAI : public npc_escortAI { npc_wizzlecrank_shredderAI(Creature* creature) : npc_escortAI(creature) { IsPostEvent = false; PostEventTimer = 1000; PostEventCount = 0; } bool IsPostEvent; uint32 PostEventTimer; uint32 PostEventCount; void Reset() override { if (!HasEscortState(STATE_ESCORT_ESCORTING)) { if (me->getStandState() == UNIT_STAND_STATE_DEAD) me->SetStandState(UNIT_STAND_STATE_STAND); IsPostEvent = false; PostEventTimer = 1000; PostEventCount = 0; } } void WaypointReached(uint32 waypointId) override { switch (waypointId) { case 0: Talk(SAY_STARTUP1); break; case 9: SetRun(false); break; case 17: if (Creature* temp = me->SummonCreature(NPC_MERCENARY, 1128.489f, -3037.611f, 92.701f, 1.472f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000)) { temp->AI()->Talk(SAY_MERCENARY); me->SummonCreature(NPC_MERCENARY, 1160.172f, -2980.168f, 97.313f, 3.690f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); } break; case 24: IsPostEvent = true; break; } } void WaypointStart(uint32 PointId) override { Player* player = GetPlayerForEscort(); if (!player) return; switch (PointId) { case 9: Talk(SAY_STARTUP2, player); break; case 18: Talk(SAY_PROGRESS_1, player); SetRun(); break; } } void JustSummoned(Creature* summoned) override { if (summoned->GetEntry() == NPC_PILOT_WIZZ) { me->SetStandState(UNIT_STAND_STATE_DEAD); me->RestoreFaction(); } if (summoned->GetEntry() == NPC_MERCENARY) summoned->AI()->AttackStart(me); } void UpdateEscortAI(uint32 Diff) override { if (!UpdateVictim()) { if (IsPostEvent) { if (PostEventTimer <= Diff) { switch (PostEventCount) { case 0: Talk(SAY_PROGRESS_2); break; case 1: Talk(SAY_PROGRESS_3); break; case 2: Talk(SAY_END); break; case 3: if (Player* player = GetPlayerForEscort()) { player->GroupEventHappens(QUEST_ESCAPE, me); me->SummonCreature(NPC_PILOT_WIZZ, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 180000); } break; } ++PostEventCount; PostEventTimer = 5000; } else PostEventTimer -= Diff; } return; } DoMeleeAttackIfReady(); } }; bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override { if (quest->GetQuestId() == QUEST_ESCAPE) { creature->SetFaction(FACTION_RATCHET); creature->AI()->Talk(SAY_START); if (npc_escortAI* pEscortAI = CAST_AI(npc_wizzlecrank_shredder::npc_wizzlecrank_shredderAI, creature->AI())) pEscortAI->Start(true, false, player->GetGUID()); } return true; } CreatureAI* GetAI(Creature* creature) const override { return new npc_wizzlecrank_shredderAI(creature); } }; void AddSC_the_barrens() { new npc_gilthares(); new npc_taskmaster_fizzule(); new npc_twiggy_flathead(); new npc_wizzlecrank_shredder(); }