diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/ExilesReach/zone_exiles_reach.cpp | 1650 |
1 files changed, 1640 insertions, 10 deletions
diff --git a/src/server/scripts/ExilesReach/zone_exiles_reach.cpp b/src/server/scripts/ExilesReach/zone_exiles_reach.cpp index 9f1083c9cea..26bb9c5c3fe 100644 --- a/src/server/scripts/ExilesReach/zone_exiles_reach.cpp +++ b/src/server/scripts/ExilesReach/zone_exiles_reach.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "AreaTrigger.h" #include "AreaTriggerAI.h" #include "Conversation.h" #include "CreatureAIImpl.h" @@ -30,11 +31,13 @@ #include "ScriptedCreature.h" #include "ScriptMgr.h" #include "ScriptSystem.h" +#include "SpellAuras.h" #include "SpellInfo.h" #include "SpellScript.h" #include "TemporarySummon.h" #include "Transport.h" #include "Loot.h" +#include "SpellHistory.h" template<class privateAI, class publicAI> CreatureAI* GetPrivatePublicPairAISelector(Creature* creature) @@ -284,6 +287,8 @@ public: // 325108 - Summon Throg - Combat Training (DNT) class spell_summon_sparring_partner : public SpellScript { + // @TODO: drop after TARGET_UNK_142 impl + void SelectTarget(WorldObject*& target) { Player* caster = GetCaster()->ToPlayer(); @@ -325,7 +330,7 @@ struct npc_sparring_partner_exiles_reach : public ScriptedAI _actorId = ACTOR_ID_HORDE; _actorIndex = 1; } - me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); + me->SetImmuneToPC(true); _events.ScheduleEvent(EVENT_MOVE_TO_A_POSITION, 1s); } @@ -1521,10 +1526,10 @@ struct npc_lana_jordan_beach_laying : public ScriptedAI enum ExilesReachMurlocsData { - ITEM_STITCHED_CLOTH_SHOES = 174791, - ITEM_STITCHED_LEATHER_BOOTS = 174792, - ITEM_LINKED_MAIL_BOOTS = 174793, - ITEM_DENTED_PLATE_BOOTS = 174794, + ITEM_STITCHED_CLOTH_SHOES = 174791, + ITEM_STITCHED_LEATHER_BOOTS = 174792, + ITEM_LINKED_MAIL_BOOTS = 174793, + ITEM_DENTED_PLATE_BOOTS = 174794, QUEST_MURLOC_HIDEAWAY_BOOTS_DROPPED = 58883 }; @@ -1836,7 +1841,7 @@ struct npc_garrick_summoned_beach : public ScriptedAI } case EVENT_FOLLOW_PLAYER: if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) - me->GetMotionMaster()->MoveFollow(player, 0.0f, 0.0f); + me->GetMotionMaster()->MoveFollow(player, 0.0f, float(M_PI / 4.0f)); break; default: break; @@ -1933,7 +1938,7 @@ struct npc_grimaxe_summoned_beach : public ScriptedAI } case EVENT_FOLLOW_PLAYER: if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) - me->GetMotionMaster()->MoveFollow(player, 0.0f, 0.0f); + me->GetMotionMaster()->MoveFollow(player, 0.0f, float(M_PI / 4.0f)); break; default: break; @@ -2018,6 +2023,8 @@ public: // 325076 - Summon Warlord Grimaxe class spell_summon_survivor_beach : public SpellScript { + // @TODO: drop after TARGET_UNK_142 impl + void SelectTarget(WorldObject*& target) { Player* caster = GetCaster()->ToPlayer(); @@ -2186,6 +2193,1618 @@ struct areatrigger_find_the_lost_expedition_follower : AreaTriggerAI } }; +enum EnhancedCombatTacticsData +{ + SPELL_SUMMON_CAPTAIN_GARRICK_COMBAT = 320211, + SPELL_SUMMON_WARLORD_GRIMAXE_COMBAT = 325180 +}; + +// 59254 - Enhanced Combat Tactics (Alliance) +// 59339 - Enhanced Combat Tactics (Alliance Monk) +// 59933 - Enhanced Combat Tactics (Horde) +// 59934 - Enhanced Combat Tactics (Horde Monk) +class quest_enhanced_combat_tactics : public QuestScript +{ +public: + quest_enhanced_combat_tactics() : QuestScript("quest_enhanced_combat_tactics") { } + + void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override + { + switch (newStatus) + { + case QUEST_STATUS_INCOMPLETE: + player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT); + player->CastSpell(player, player->GetTeam() == ALLIANCE ? SPELL_SUMMON_CAPTAIN_GARRICK_COMBAT : SPELL_SUMMON_WARLORD_GRIMAXE_COMBAT); + break; + case QUEST_STATUS_NONE: + player->RemoveAura(player->GetTeam() == ALLIANCE ? SPELL_SUMMON_CAPTAIN_GARRICK_COMBAT : SPELL_SUMMON_WARLORD_GRIMAXE_COMBAT); + player->UpdateObjectVisibility(); + player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT); + break; + default: + break; + } + } +}; + +// 320175 - Summon Garrick - Combat Training (DNT) +// 325181 - Summon Grimaxe - Combat Training (DNT) +class spell_summon_combat_trainer : public SpellScript +{ + // @TODO: drop after TARGET_UNK_142 impl + + void SelectTarget(WorldObject*& target) + { + Player* caster = GetCaster()->ToPlayer(); + if (!caster) + return; + + Creature* partner = FindCreatureIgnorePhase(caster, caster->GetTeam() == ALLIANCE ? "garrick_camp" : "grimaxe_camp", 10.0f); + if (!partner) + return; + + target = partner; + } + + void Register() override + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_summon_combat_trainer::SelectTarget, EFFECT_0, TARGET_DEST_NEARBY_ENTRY_OR_DB); + } +}; + +enum EnhancedCombatTrainerData +{ + ACTOR_ID_ALLIANCE_ENHANCED_TRAINING = 74771, + ACTOR_ID_HORDE_ENHANCED_TRAINING = 76285, + + CHARGE_CATEGORY_CHARGE_SPELL = 1386, + + CONVERSATION_PREFIGHT_WALK_ENHANCED = 13710, + CONVERSATION_USE_SPELLS_AT_RANGE = 13630, + CONVERSATION_READY_COMBAT = 14440, + // Warrior + CONVERSATION_READY_COMBAT_WARRIOR = 14441, + CONVERSATION_CHARGE_ZERO_RES_ENHANCED = 14444, + CONVERSATION_SLAM_ENHANCED = 14447, + CONVERSATION_CHARGE_ONE_RES_ENHANCED = 14448, + CONVERSATION_CHARGE_FINAL_ENHANCED = 14449, + CONVERSATION_CHARGE_KICKBACK = 13611, + // Paladin + CONVERSATION_HOLY_POWER_ONE_PALADIN = 14452, + CONVERSATION_CRUSADER_STRIKE_ONE_PALADIN = 14453, + CONVERSATION_CRUSADER_STRIKE_TWO_PALADIN = 14454, + CONVERSATION_SHIELD_SLAM_ONE_PALADIN = 14455, + CONVERSATION_HOLY_POWER_TWO_PALADIN = 14456, + CONVERSATION_SHIELD_SLAM_TWO_PALADIN = 14457, + CONVERSATION_CRUSADER_STRIKE_THREE_PALADIN = 14458, + CONVERSATION_HOLY_POWER_THREE_PALADIN = 14459, + // Rogue + CONVERSATION_SINISTER_STRIKE_ONE_ROGUE = 14486, + CONVERSATION_REGULAR_ATTACKS_ROGUE = 14487, + CONVERSATION_THREE_COMBO_POINTS_ROGUE = 14488, + CONVERSATION_THREE_COMBO_EVISCERATE_ROGUE = 14489, + CONVERSATION_SINISTER_STRIKE_TWO_ROGUE = 14490, + CONVERSATION_FOUR_COMBO_POINTS_ROGUE = 14491, + CONVERSATION_FOUR_COMBO_EVISCERATE_ROGUE = 14492, + CONVERSATION_SINISTER_STRIKE_THREE_ROGUE = 14493, + CONVERSATION_FIVE_COMBO_POINTS_ROGUE = 14494, + CONVERSATION_FAILED_EVISCERATE_ROGUE = 14495, + // Priest + CONVERSATION_SHADOW_WORD_PAIN_QUEST_CREDIT_PRIEST = 13892, + CONVERSATION_SMITE_PRE_COMBAT_PRIEST = 14460, + CONVERSATION_SHADOW_WORD_PAIN_PRE_COMBAT_PRIEST = 14461, + CONVERSATION_SHADOW_WORD_PAIN_TOO_SOON_PRIEST = 14462, + CONVERSATION_SHADOW_WORD_PAIN_FADING_PRIEST = 14463, + // Shaman + CONVERSATION_LIGHTNINGBOLT_FIRST_SHAMAN = 13631, + CONVERSATION_PRIMAL_STRIKE_FIRST_SHAMAN = 13632, + CONVERSATION_PRIMAL_STRIKE_QUEST_CREDIT_SHAMAN = 13633, + CONVERSATION_LIGHTNINGBOLT_RANGE_SHAMAN = 14475, + // Mage + CONVERSATION_FROSTBOLT_MAGE = 13634, + CONVERSATION_FIRE_BLAST_QUEST_CREDIT_MAGE = 13635, + CONVERSATION_FROSTBOLT_CLOSE_MAGE = 14476, + CONVERSATION_FIRE_BLAST_MAGE_NO_CREDIT = 14477, + // Warlock + CONVERSATION_CORRUPTION_QUEST_CREDIT_WARLOCK = 13895, + CONVERSATION_SHADOW_BOLT_PRE_COMBAT_WARLOCK = 14465, + CONVERSATION_CORRUPTION_CAST_PRE_COMBAT_WARLOCK = 14466, + CONVERSATION_CORRUPTION_CAST_TOO_SOON_WARLOCK = 14467, + CONVERSATION_CORRUPTION_IS_FADING_WARLOCK = 14468, + // Druid + CONVERSATION_MOONFIRE_QUEST_CREDIT_DRUID = 13893, + CONVERSATION_WRATH_PRE_COMBAT_DRUID = 14471, + CONVERSATION_MOONFIRE_CAST_PRE_COMBAT_DRUID = 14472, + CONVERSATION_MOONFIRE_CAST_TOO_SOON_DRUID = 14473, + CONVERSATION_MOONFIRE_WEARING_OFF_DRUID = 14474, + + // All classes + EVENT_COMBAT_TRAINING_WALK_AND_TALK = 1, + EVENT_COMBAT_TRAINING_FACE_PLAYER, + EVENT_COMBAT_RUN_BACK, + EVENT_COMBAT_TRAINING_END, + EVENT_COMBAT_CHECK_PLAYER, + // Rogue + EVENT_COMBAT_TRAINING_SINISTER_CHECK_ROGUE, + // Priest, Warlock, Druid + EVENT_COMBAT_TRAINING_SPELL_FADING, + // Shaman + EVENT_COMBAT_TRAINING_RESET_SHAMAN, + EVENT_COMBAT_TRAINING_AGGRO_CHECK_SHAMAN, + // Mage + EVENT_COMBAT_TRAINING_RESET_MAGE, + EVENT_COMBAT_TRAINING_AGGRO_CHECK_MAGE, + + NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED = 164577, + NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED2 = 164775, + //NPC_HORDE_SPARING_PARTNER_ENHANCED = 166916, + NPC_INVISBUNNY_CAMP = 167761, + + PATH_COMBAT_TRAINER_HOME = 10512100, + + POINT_WALK_POINT_ENHANCED_TRAINING = 1, + POINT_RUN_POINT_ENHANCED_TRAINING = 2, + POINT_TRAINING_POINT_ENHANCED_TRAINING = 3, + + QUEST_ENHANCED_COMBAT_TACTICS_ALLIANCE = 59254, + QUEST_ENHANCED_COMBAT_TACTICS_ALLIANCE_MONK = 59339, + QUEST_ENHANCED_COMBAT_TACTICS_HORDE = 59933, + QUEST_ENHANCED_COMBAT_TACTICS_HORDE_MONK = 59934, + + QUEST_OBJECTIVE_HORDE_ABILITIES_PROVEN = 397255, + QUEST_OBJECTIVE_HORDE_TIGER_PALM = 397258, + QUEST_OBJECTIVE_HORDE_BLACKOUT_KICK = 397259, + QUEST_OBJECTIVE_ALLIANCE_ABILITIES_PROVEN = 396220, + QUEST_OBJECTIVE_ALLIANCE_TIGER_PALM = 396353, + QUEST_OBJECTIVE_ALLIANCE_BLACKOUT_KICK = 396354, + + SPELL_DRINK_HEALING_POTION = 320229, + SPELL_KNOCKBACK = 320735, + SPELL_CHARGE_KNOCKBACK_DRUID = 320767, + SPELL_CHARGE = 100, + SPELL_SLAM = 1464, + SPELL_CHARGE_KNOCKBACK_WARRIOR = 320583, + SPELL_SHIELD_OF_THE_RIGHTEOUS = 53600, + SPELL_CRUSADER_STRIKE = 35395, + SPELL_SINISTER_STRIKE = 1752, + SPELL_EVISCERATE = 196819, + SPELL_SMITE = 585, + SPELL_SHADOW_WORD_PAIN = 589, + SPELL_CHARGE_KNOCKBACK = 320605, + SPELL_PRIMAL_STRIKE = 73899, + SPELL_LIGHTNING_BOLT = 188196, + SPELL_FIRE_BLAST = 319836, + SPELL_FROSTBOLT = 116, + SPELL_CORRUPTION = 172, + SPELL_SHADOWBOLT = 686, + SPELL_MOONFIRE = 164812, + SPELL_WRATH = 5176, + SPELL_TIGER_PALM = 100780, + SPELL_BLACKOUT_KICK = 100784, + SPELL_RANGED_ROOT_DNT = 320608, + SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR = 320741, + SPELL_AGGRO_RADIUS_CHECK_DNT_PRIEST = 320649, + SPELL_AGGRO_RADIUS_CHECK_DNT_SHAMAN = 320705, + SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE = 320741, + SPELL_AGGRO_RADIUS_CHECK_DNT_WARLOCK = 320606, + SPELL_AGGRO_RADIUS_CHECK_DNT_DRUID = 320766 +}; + +Position const EnhancedTrainingWalkPosition = { -250.60243f, -2485.2517f, 17.787413f }; +Position const EnhancedTrainingRunPosition = { -231.5225f, -2480.5276f, 19.019197f }; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_combat_training : public ScriptedAI +{ + npc_sparring_partner_combat_training(Creature* creature) : ScriptedAI(creature), _questID(0), _summonSpellAuraID(0) { } + + virtual void OnReadyPointReached() { } + + virtual void HandleClassEvent(uint32 /*eventId*/) { } + + void JustAppeared() override + { + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_WALK_AND_TALK, 2s); + } + + void IsSummonedBy(WorldObject* summonerWO) override + { + Unit* summoner = summonerWO->ToUnit(); + if (!summoner) + return; + + Player* player = summoner->ToPlayer(); + if (!player) + return; + + _playerGUID = player->GetGUID(); + + if (player->GetTeam() == ALLIANCE) + { + _summonSpellAuraID = SPELL_SUMMON_CAPTAIN_GARRICK_COMBAT; + + if (player->GetClass() == CLASS_MONK) + _questID = QUEST_ENHANCED_COMBAT_TACTICS_ALLIANCE_MONK; + else + _questID = QUEST_ENHANCED_COMBAT_TACTICS_ALLIANCE; + } + else + { + _summonSpellAuraID = SPELL_SUMMON_WARLORD_GRIMAXE_COMBAT; + + if (player->GetClass() == CLASS_MONK) + _questID = QUEST_ENHANCED_COMBAT_TACTICS_HORDE_MONK; + else + _questID = QUEST_ENHANCED_COMBAT_TACTICS_HORDE; + } + } + + uint8 GetQuestCredits() + { + Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID); + if (!player) + return 0; + + uint32 objectiveId = 0; + switch (_questID) + { + case QUEST_ENHANCED_COMBAT_TACTICS_ALLIANCE: + objectiveId = QUEST_OBJECTIVE_ALLIANCE_ABILITIES_PROVEN; + break; + case QUEST_ENHANCED_COMBAT_TACTICS_HORDE: + objectiveId = QUEST_OBJECTIVE_HORDE_ABILITIES_PROVEN; + break; + default: + break; + } + + return player->GetQuestSlotObjectiveData(_questID, objectiveId); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (!me->IsAlive()) + return; + + me->CombatStop(true); + EngagementOver(); + me->ResetPlayerDamageReq(); + } + + void MovementInform(uint32 uiType, uint32 uiId) override + { + if (uiType != POINT_MOTION_TYPE) + return; + + switch (uiId) + { + case POINT_WALK_POINT_ENHANCED_TRAINING: + me->SetWalk(false); + me->GetMotionMaster()->MovePoint(POINT_RUN_POINT_ENHANCED_TRAINING, EnhancedTrainingRunPosition); + break; + case POINT_RUN_POINT_ENHANCED_TRAINING: + { + std::list<Creature*> sparpoints; + GetCreatureListWithEntryInGrid(sparpoints, me, NPC_INVISBUNNY_CAMP, 100.0f); + Trinity::Containers::RandomResize(sparpoints, 1); + + for (Creature* creature : sparpoints) + me->GetMotionMaster()->MovePoint(POINT_TRAINING_POINT_ENHANCED_TRAINING, creature->GetPosition()); + break; + } + case POINT_TRAINING_POINT_ENHANCED_TRAINING: + { + Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID); + if (!player) + break; + + me->SetFacingToObject(player); + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + _events.ScheduleEvent(EVENT_COMBAT_CHECK_PLAYER, 1s); + + OnReadyPointReached(); + break; + } + default: + break; + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override + { + damage = me->GetHealth() - 1; + + if (me->HealthBelowPctDamaged(20, damage)) + me->CastSpell(me, SPELL_DRINK_HEALING_POTION); + } + + void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/) override + { + if (target->GetHealthPct() < 91) + damage = 0; + } + + void StartConversationWithPlayer(uint32 conversationId) + { + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + Conversation* conversation = Conversation::CreateConversation(conversationId, player, *player, player->GetGUID(), nullptr, false); + if (!conversation) + return; + + conversation->AddActor(ACTOR_ID_ALLIANCE_ENHANCED_TRAINING, 0, player->GetTeam() == ALLIANCE ? me->GetGUID() : ObjectGuid::Empty); + conversation->AddActor(ACTOR_ID_HORDE_ENHANCED_TRAINING, 1, player->GetTeam() == HORDE ? me->GetGUID() : ObjectGuid::Empty); + conversation->Start(); + } + } + + void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override + { + // Used to check if reached home + if (pathId == PATH_COMBAT_TRAINER_HOME) + { + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT); + player->RemoveAura(_summonSpellAuraID); + } + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_WALK_AND_TALK: + // Used by all classes + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_WALK_POINT_ENHANCED_TRAINING, EnhancedTrainingWalkPosition); + StartConversationWithPlayer(CONVERSATION_PREFIGHT_WALK_ENHANCED); + break; + case EVENT_COMBAT_TRAINING_FACE_PLAYER: + { + // Used by all classes + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + me->SetFacingToObject(player); + + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + break; + } + case EVENT_COMBAT_TRAINING_END: + // Used by all classes + me->SetImmuneToPC(true); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + me->RemoveAllAuras(); + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + me->SetFacingToObject(player); + StartConversationWithPlayer(CONVERSATION_CHARGE_FINAL_ENHANCED); + _events.ScheduleEvent(EVENT_COMBAT_RUN_BACK, 4s); + } + break; + case EVENT_COMBAT_RUN_BACK: + // Used by all classes + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePath(PATH_COMBAT_TRAINER_HOME, false); + break; + default: + HandleClassEvent(eventId); + break; + } + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + +protected: + uint32 _questID; + uint32 _summonSpellAuraID; + EventMap _events; + ObjectGuid _playerGUID; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_warrior : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_warrior(Creature* creature) : npc_sparring_partner_combat_training(creature), _slamCounter(0), _secondaryCheck(false) { } + + void ResetWarrior(Player* player) + { + _slamCounter = 0; + me->SetImmuneToPC(true); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + player->GetSpellHistory()->ResetCharges(CHARGE_CATEGORY_CHARGE_SPELL); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_FACE_PLAYER, 1s); + StartConversationWithPlayer(CONVERSATION_CHARGE_KICKBACK); + } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT_WARRIOR); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _secondaryCheck = true; + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_CHARGE) + { + me->RemoveAura(SPELL_RANGED_ROOT_DNT); + me->RemoveAura(SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE); + + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + switch (GetQuestCredits()) + { + case 1: + StartConversationWithPlayer(CONVERSATION_CHARGE_ZERO_RES_ENHANCED); + break; + case 2: + StartConversationWithPlayer(CONVERSATION_CHARGE_ONE_RES_ENHANCED); + break; + case 3: + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + break; + default: + break; + } + } + else if (spellInfo->Id == SPELL_SLAM) + { + ++_slamCounter; + + if (_slamCounter == 3 && GetQuestCredits()) + ResetWarrior(player); + + if (!_secondaryCheck) + return; + + _secondaryCheck = false; + StartConversationWithPlayer(CONVERSATION_SLAM_ENHANCED); + } + } + +private: + uint8 _slamCounter; + bool _secondaryCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_paladin : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_paladin(Creature* creature) : npc_sparring_partner_combat_training(creature), _secondaryCheck(false), _holyPowerCheck(false) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + _holyPowerCheck = true; + _secondaryCheck = true; + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_CHECK_PLAYER: + { + if (_holyPowerCheck) // Used by paladin + { + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + if (player->GetPower(POWER_HOLY_POWER) >= 3) + { + switch (GetQuestCredits()) + { + case 0: + StartConversationWithPlayer(CONVERSATION_HOLY_POWER_ONE_PALADIN); + break; + case 1: + StartConversationWithPlayer(CONVERSATION_HOLY_POWER_TWO_PALADIN); + break; + case 2: + StartConversationWithPlayer(CONVERSATION_HOLY_POWER_THREE_PALADIN); + break; + default: + break; + } + _holyPowerCheck = false; + } + } + } + _events.ScheduleEvent(EVENT_COMBAT_CHECK_PLAYER, 500ms); + break; + } + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_SHIELD_OF_THE_RIGHTEOUS) + { + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + switch (GetQuestCredits()) + { + case 1: + StartConversationWithPlayer(CONVERSATION_SHIELD_SLAM_ONE_PALADIN); + _secondaryCheck = true; + break; + case 2: + StartConversationWithPlayer(CONVERSATION_SHIELD_SLAM_TWO_PALADIN); + _secondaryCheck = true; + break; + case 3: + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + _events.CancelEvent(EVENT_COMBAT_CHECK_PLAYER); + break; + default: + break; + } + } + else if (spellInfo->Id == SPELL_CRUSADER_STRIKE) + { + if (_secondaryCheck) + { + switch (GetQuestCredits()) + { + case 0: + StartConversationWithPlayer(CONVERSATION_CRUSADER_STRIKE_ONE_PALADIN); + break; + case 1: + StartConversationWithPlayer(CONVERSATION_CRUSADER_STRIKE_TWO_PALADIN); + break; + case 2: + StartConversationWithPlayer(CONVERSATION_CRUSADER_STRIKE_THREE_PALADIN); + break; + default: + break; + } + _secondaryCheck = false; + _holyPowerCheck = true; + } + } + } + +private: + bool _secondaryCheck; + bool _holyPowerCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_rogue : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_rogue(Creature* creature) : npc_sparring_partner_combat_training(creature), _comboPointsCounter(0), _secondaryCheck(false), _comboPointCheck(false) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + _comboPointCheck = true; + _secondaryCheck = true; + } + + void JustEngagedWith(Unit* /*who*/) override + { + Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID); + if (!player) + return; + + if (!GetQuestCredits()) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SINISTER_CHECK_ROGUE, 8s, 20s); + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_SINISTER_CHECK_ROGUE: + StartConversationWithPlayer(CONVERSATION_REGULAR_ATTACKS_ROGUE); + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SINISTER_CHECK_ROGUE, 8s, 20s); + break; + case EVENT_COMBAT_CHECK_PLAYER: + { + if (_comboPointCheck) // Used by rogue + { + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + _comboPointsCounter = player->GetPower(POWER_COMBO_POINTS); + + if (_comboPointsCounter >= (GetQuestCredits() + 3)) + { + switch (GetQuestCredits()) + { + case 0: + StartConversationWithPlayer(CONVERSATION_THREE_COMBO_POINTS_ROGUE); + break; + case 1: + StartConversationWithPlayer(CONVERSATION_FOUR_COMBO_POINTS_ROGUE); + break; + case 2: + StartConversationWithPlayer(CONVERSATION_FIVE_COMBO_POINTS_ROGUE); + break; + default: + break; + } + _comboPointCheck = false; + } + } + _events.ScheduleEvent(EVENT_COMBAT_CHECK_PLAYER, 500ms); + break; + } + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_EVISCERATE) + { + _comboPointCheck = true; + if (_comboPointsCounter >= (GetQuestCredits() + 3)) + { + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + switch (GetQuestCredits()) + { + case 1: + StartConversationWithPlayer(CONVERSATION_THREE_COMBO_EVISCERATE_ROGUE); + _secondaryCheck = true; + break; + case 2: + StartConversationWithPlayer(CONVERSATION_FOUR_COMBO_EVISCERATE_ROGUE); + _secondaryCheck = true; + break; + case 3: + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + _events.CancelEvent(EVENT_COMBAT_CHECK_PLAYER); + break; + default: + break; + } + } + else + { + StartConversationWithPlayer(CONVERSATION_FAILED_EVISCERATE_ROGUE); + } + } + else if (spellInfo->Id == SPELL_SINISTER_STRIKE) + { + if (!GetQuestCredits()) + _events.RescheduleEvent(EVENT_COMBAT_TRAINING_SINISTER_CHECK_ROGUE, 8s, 20s); + + if (_secondaryCheck) + { + switch (GetQuestCredits()) + { + case 0: + StartConversationWithPlayer(CONVERSATION_SINISTER_STRIKE_ONE_ROGUE); + break; + case 1: + StartConversationWithPlayer(CONVERSATION_SINISTER_STRIKE_TWO_ROGUE); + break; + case 2: + StartConversationWithPlayer(CONVERSATION_SINISTER_STRIKE_THREE_ROGUE); + break; + default: + break; + } + _secondaryCheck = false; + } + } + } + +private: + uint8 _comboPointsCounter; + bool _secondaryCheck; + bool _comboPointCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_priest : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_priest(Creature* creature) : npc_sparring_partner_combat_training(creature), _shadowWordPainInPandemicWindow(false), _secondaryCheck(false) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_PRIEST); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _secondaryCheck = true; + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_SPELL_FADING: + { + Aura* aura = me->GetAura(SPELL_MOONFIRE); + if (!aura) + break; + + if (!_shadowWordPainInPandemicWindow) + { + int32 pandemicDuration = CalculatePct(aura->GetMaxDuration(), 30.0f); + if (aura->GetDuration() <= pandemicDuration) + { + _shadowWordPainInPandemicWindow = true; + StartConversationWithPlayer(CONVERSATION_SHADOW_WORD_PAIN_FADING_PRIEST); + } + } + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SPELL_FADING, 1s); + break; + } + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_SHADOW_WORD_PAIN) + { + if (_events.GetTimeUntilEvent(EVENT_COMBAT_TRAINING_SPELL_FADING) == Milliseconds::max()) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SPELL_FADING, 1s); + + if (!_shadowWordPainInPandemicWindow) + { + if (_secondaryCheck) + { + StartConversationWithPlayer(CONVERSATION_SHADOW_WORD_PAIN_PRE_COMBAT_PRIEST); + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + me->RemoveAura(SPELL_RANGED_ROOT_DNT); + _secondaryCheck = false; + } + else + StartConversationWithPlayer(CONVERSATION_SHADOW_WORD_PAIN_TOO_SOON_PRIEST); + } + else + { + _shadowWordPainInPandemicWindow = false; + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + if (player->GetQuestStatus(_questID) == QUEST_STATUS_COMPLETE) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + else + StartConversationWithPlayer(CONVERSATION_SHADOW_WORD_PAIN_QUEST_CREDIT_PRIEST); + } + } + else if (spellInfo->Id == SPELL_SMITE) + { + if (_secondaryCheck) + StartConversationWithPlayer(CONVERSATION_SMITE_PRE_COMBAT_PRIEST); + } + } + +private: + bool _shadowWordPainInPandemicWindow; + bool _secondaryCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_shaman : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_shaman(Creature* creature) : npc_sparring_partner_combat_training(creature), _primalStrikeCounter(0), _secondaryCheck(false) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_SHAMAN); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _secondaryCheck = true; + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_RESET_SHAMAN: + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + me->CastSpell(player, SPELL_KNOCKBACK); + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_AGGRO_CHECK_SHAMAN, 2s); + } + break; + case EVENT_COMBAT_TRAINING_AGGRO_CHECK_SHAMAN: + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_SHAMAN); + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + _secondaryCheck = true; + break; + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_PRIMAL_STRIKE) + { + if (!player->IsWithinDist(me, 2.0f)) + return; + + ++_primalStrikeCounter; + + if (_primalStrikeCounter < 3) + { + if (_primalStrikeCounter == 1) + StartConversationWithPlayer(CONVERSATION_PRIMAL_STRIKE_FIRST_SHAMAN); + return; + } + + _primalStrikeCounter = 0; + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + if (player->GetQuestStatus(_questID) == QUEST_STATUS_COMPLETE) + { + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + } + else + { + StartConversationWithPlayer(CONVERSATION_PRIMAL_STRIKE_QUEST_CREDIT_SHAMAN); + me->SetImmuneToPC(true); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_RESET_SHAMAN, 3s); + } + } + else if (spellInfo->Id == SPELL_LIGHTNING_BOLT) + { + me->RemoveAura(SPELL_RANGED_ROOT_DNT); + me->RemoveAura(SPELL_AGGRO_RADIUS_CHECK_DNT_SHAMAN); + if (_secondaryCheck) + { + StartConversationWithPlayer(CONVERSATION_LIGHTNINGBOLT_FIRST_SHAMAN); + _secondaryCheck = false; + } + else + { + if (player->IsWithinDist(me, 2.0f)) + StartConversationWithPlayer(CONVERSATION_LIGHTNINGBOLT_RANGE_SHAMAN); + } + } + } + +private: + uint8 _primalStrikeCounter; + bool _secondaryCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_mage : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_mage(Creature* creature) : npc_sparring_partner_combat_training(creature), _secondaryCheck(true) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _secondaryCheck = true; + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_RESET_MAGE: + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + me->CastSpell(player, SPELL_KNOCKBACK); + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_AGGRO_CHECK_MAGE, 2s); + } + break; + case EVENT_COMBAT_TRAINING_AGGRO_CHECK_MAGE: + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE); + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + _secondaryCheck = true; + break; + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_FIRE_BLAST) + { + if (player->IsWithinDist(me, 2.0f)) + { + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + if (player->GetQuestStatus(_questID) == QUEST_STATUS_COMPLETE) + { + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + } + else + { + StartConversationWithPlayer(CONVERSATION_FIRE_BLAST_QUEST_CREDIT_MAGE); + me->SetImmuneToPC(true); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_RESET_MAGE, 4s); + } + } + else + { + StartConversationWithPlayer(CONVERSATION_FIRE_BLAST_MAGE_NO_CREDIT); + } + } + else if (spellInfo->Id == SPELL_FROSTBOLT) + { + me->RemoveAura(SPELL_RANGED_ROOT_DNT); + me->RemoveAura(SPELL_AGGRO_RADIUS_CHECK_DNT_WARRIOR_MAGE); + if (_secondaryCheck) + { + StartConversationWithPlayer(CONVERSATION_FROSTBOLT_MAGE); + _secondaryCheck = false; + } + else + { + if (player->IsWithinDist(me, 2.0f)) + StartConversationWithPlayer(CONVERSATION_FROSTBOLT_CLOSE_MAGE); + } + } + } + +private: + bool _secondaryCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_warlock : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_warlock(Creature* creature) : npc_sparring_partner_combat_training(creature), _corruptionInPandemicWindow(false), _secondaryCheck(false) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_WARLOCK); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _secondaryCheck = true; + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_SPELL_FADING: + { + Aura* aura = me->GetAura(SPELL_MOONFIRE); + if (!aura) + break; + + if (!_corruptionInPandemicWindow) + { + int32 pandemicDuration = CalculatePct(aura->GetMaxDuration(), 30.0f); + if (aura->GetDuration() <= pandemicDuration) + { + _corruptionInPandemicWindow = true; + StartConversationWithPlayer(CONVERSATION_CORRUPTION_IS_FADING_WARLOCK); + } + } + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SPELL_FADING, 1s); + break; + } + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_CORRUPTION) + { + if (_events.GetTimeUntilEvent(EVENT_COMBAT_TRAINING_SPELL_FADING) == Milliseconds::max()) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SPELL_FADING, 1s); + + if (!_corruptionInPandemicWindow) + { + if (_secondaryCheck) + { + StartConversationWithPlayer(CONVERSATION_CORRUPTION_CAST_PRE_COMBAT_WARLOCK); + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + me->RemoveAura(SPELL_RANGED_ROOT_DNT); + _secondaryCheck = false; + } + else + StartConversationWithPlayer(CONVERSATION_CORRUPTION_CAST_TOO_SOON_WARLOCK); + } + else + { + _corruptionInPandemicWindow = false; + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + if (player->GetQuestStatus(_questID) == QUEST_STATUS_COMPLETE) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + else + StartConversationWithPlayer(CONVERSATION_CORRUPTION_QUEST_CREDIT_WARLOCK); + } + } + else if (spellInfo->Id == SPELL_SHADOWBOLT) + { + if (_secondaryCheck) + StartConversationWithPlayer(CONVERSATION_SHADOW_BOLT_PRE_COMBAT_WARLOCK); + } + } + +private: + bool _corruptionInPandemicWindow; + bool _secondaryCheck; +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_monk : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_monk(Creature* creature) : npc_sparring_partner_combat_training(creature) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_TIGER_PALM) + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + else if (spellInfo->Id == SPELL_BLACKOUT_KICK) + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED2); + + if (player->GetQuestStatus(_questID) == QUEST_STATUS_COMPLETE) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + } +}; + +// 164577 - Alliance Sparring Partner +// 166916 - Horde Sparring Partner +struct npc_sparring_partner_enhanced_combat_training_druid : public npc_sparring_partner_combat_training +{ + npc_sparring_partner_enhanced_combat_training_druid(Creature* creature) : npc_sparring_partner_combat_training(creature), _hitByMoonfire(false), _moonfireInPandemicWindow(false) { } + + void OnReadyPointReached() override + { + StartConversationWithPlayer(CONVERSATION_READY_COMBAT); + me->CastSpell(me, SPELL_AGGRO_RADIUS_CHECK_DNT_DRUID); + me->CastSpell(me, SPELL_RANGED_ROOT_DNT); + _moonfireInPandemicWindow = false; + _hitByMoonfire = false; + } + + void HandleClassEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_COMBAT_TRAINING_SPELL_FADING: + { + Aura* aura = me->GetAura(SPELL_MOONFIRE); + if (!aura) + break; + + if (!_moonfireInPandemicWindow) + { + int32 pandemicDuration = CalculatePct(aura->GetMaxDuration(), 30.0f); + if (aura->GetDuration() <= pandemicDuration) + { + _moonfireInPandemicWindow = true; + StartConversationWithPlayer(CONVERSATION_MOONFIRE_WEARING_OFF_DRUID); + } + } + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SPELL_FADING, 1s); + break; + } + default: + break; + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override + { + Player* player = caster->ToPlayer(); + if (!player) + return; + + if (spellInfo->Id == SPELL_MOONFIRE) + { + if (_events.GetTimeUntilEvent(EVENT_COMBAT_TRAINING_SPELL_FADING) == Milliseconds::max()) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_SPELL_FADING, 1s); + + if (!_moonfireInPandemicWindow) + { + if (!_hitByMoonfire) + { + StartConversationWithPlayer(CONVERSATION_MOONFIRE_CAST_PRE_COMBAT_DRUID); + me->SetImmuneToPC(false); + me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + me->RemoveAura(SPELL_RANGED_ROOT_DNT); + _hitByMoonfire = true; + } + else + StartConversationWithPlayer(CONVERSATION_MOONFIRE_CAST_TOO_SOON_DRUID); + } + else + { + _moonfireInPandemicWindow = false; + player->KilledMonsterCredit(NPC_ALLIANCE_SPARRING_PARTNER_ENHANCED); + + if (player->GetQuestStatus(_questID) == QUEST_STATUS_COMPLETE) + _events.ScheduleEvent(EVENT_COMBAT_TRAINING_END, 1s); + else + StartConversationWithPlayer(CONVERSATION_MOONFIRE_QUEST_CREDIT_DRUID); + } + } + else if (spellInfo->Id == SPELL_WRATH) + { + if (!_hitByMoonfire) + StartConversationWithPlayer(CONVERSATION_WRATH_PRE_COMBAT_DRUID); + } + } + +private: + bool _hitByMoonfire; + bool _moonfireInPandemicWindow; +}; + +CreatureAI* SparringPartnerEnhancedCombatTrainingSelector(Creature* creature) +{ + TempSummon* summon = creature->ToTempSummon(); + if (!summon) + return new NullCreatureAI(creature); + + Unit* summoner = summon->GetSummonerUnit(); + if (!summoner) + return new NullCreatureAI(creature); + + Player* player = summoner->ToPlayer(); + if (!player) + return new NullCreatureAI(creature); + + switch (player->GetClass()) + { + case CLASS_WARRIOR: + return new npc_sparring_partner_enhanced_combat_training_warrior(creature); + case CLASS_PALADIN: + return new npc_sparring_partner_enhanced_combat_training_paladin(creature); + case CLASS_ROGUE: + return new npc_sparring_partner_enhanced_combat_training_rogue(creature); + case CLASS_PRIEST: + return new npc_sparring_partner_enhanced_combat_training_priest(creature); + case CLASS_SHAMAN: + return new npc_sparring_partner_enhanced_combat_training_shaman(creature); + case CLASS_MAGE: + return new npc_sparring_partner_enhanced_combat_training_mage(creature); + case CLASS_WARLOCK: + return new npc_sparring_partner_enhanced_combat_training_warlock(creature); + case CLASS_MONK: + return new npc_sparring_partner_enhanced_combat_training_monk(creature); + case CLASS_DRUID: + return new npc_sparring_partner_enhanced_combat_training_druid(creature); + default: + return new NullCreatureAI(creature); + } + if (creature->IsPrivateObject()) + return new npc_survivors_beach_leave_private<PATH_KEE_LA_STANDING, 7 * IN_MILLISECONDS>(creature); + return new NullCreatureAI(creature); +}; + +struct at_aggro_radius_check_enhanced_combat_tactics : AreaTriggerAI +{ + at_aggro_radius_check_enhanced_combat_tactics(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + Player* player = unit->ToPlayer(); + if (!player) + return; + + Unit* caster = at->GetCaster(); + if (!caster) + { + at->RemoveFromWorld(); + return; + } + + caster->SetFacingToObject(player); + + switch (player->GetClass()) + { + case CLASS_WARRIOR: + caster->CastSpell(player, SPELL_CHARGE_KNOCKBACK_WARRIOR); + break; + case CLASS_PRIEST: + case CLASS_SHAMAN: + case CLASS_MAGE: + case CLASS_WARLOCK: + caster->CastSpell(player, SPELL_CHARGE_KNOCKBACK); + break; + case CLASS_DRUID: + caster->CastSpell(player, SPELL_CHARGE_KNOCKBACK_DRUID); + break; + default: + break; + } + } +}; + +// 320605 - Charge Knockback (DNT) +class spell_knockback_charge_enhanced_training : public SpellScript +{ + void HandleLaunch(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + } + + void HandleEffect(SpellEffIndex effIndex) + { + Unit* caster = GetCaster(); + if (!caster) + return; + + Player* player = GetHitUnit()->ToPlayer(); + if (!player) + return; + + Conversation* conversation = Conversation::CreateConversation(GetSpellInfo()->GetEffect(effIndex).MiscValue, player, *player, player->GetGUID(), nullptr, false); + if (!conversation) + return; + + conversation->AddActor(ACTOR_ID_ALLIANCE_ENHANCED_TRAINING, 0, player->GetTeam() == ALLIANCE ? caster->GetGUID() : ObjectGuid::Empty); + conversation->AddActor(ACTOR_ID_HORDE_ENHANCED_TRAINING, 1, player->GetTeam() == ALLIANCE ? ObjectGuid::Empty : caster->GetGUID()); + conversation->Start(); + } + + void Register() override + { + OnEffectLaunchTarget += SpellEffectFn(spell_knockback_charge_enhanced_training::HandleLaunch, EFFECT_1, SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION); + OnEffectHitTarget += SpellEffectFn(spell_knockback_charge_enhanced_training::HandleEffect, EFFECT_1, SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION); + } +}; + +enum NorthboundData +{ + CONVERSATION_QUEST_NORTHBOUND_ACCEPT_ALLIANCE = 12066, + CONVERSATION_QUEST_NORTHBOUND_ACCEPT_HORDE = 14499, + + POINT_LEADER_RUN = 0, + + ACTOR_ID_0_NORTHBOUND_ACCEPT_ALLIANCE = 71310, + ACTOR_ID_1_NORTHBOUND_ACCEPT_ALLIANCE = 71297, + ACTOR_ID_0_NORTHBOUND_ACCEPT_HORDE = 79890, + ACTOR_ID_1_NORTHBOUND_ACCEPT_HORDE = 79888, + ACTOR_ID_0_NORTHBOUND_AREATRIGGER_ALLIANCE = 71317, + ACTOR_ID_1_NORTHBOUND_AREATRIGGER_HORDE = 76319, + + QUEST_NORTHBOND_ALLIANCE = 55173, + QUEST_NORTHBOND_HORDE = 59935, + + SPELL_SUMMON_ADMIRAL_GARRICK_GUARDIAN_NORTHBOUND = 305660, + SPELL_SUMMON_WARLORD_GRIMAXE_GUARDIAN_NORTHBOUND = 344382, + SPELL_LINGER_NORTHBOUND_ALLIANCE = 305665, + SPELL_LINGER_NORTHBOUND_HORDE = 344385, +}; + +Position const GarrickQuillboarBriarpatchPosition = { -142.62154f, -2641.0364f, 48.775497f }; +Position const GrimaxeQuillboarBriarpatchPosition = { -142.56076f, -2640.9915f, 48.755478f }; + +// 165360 - Alliance Survivor +// This script is used by Captian Garrick Follower for Northbound quest +struct npc_leader_northbound : public ScriptedAI +{ + npc_leader_northbound(Creature* creature) : ScriptedAI(creature), _conversationId(0), _actorIdOne(0), _actorIdTwo(0), _lingerSpellId(0), _guardianSpellId(0) {} + + void JustAppeared() override + { + Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID); + if (!player) + return; + + player->UpdateVisibilityForPlayer(); + + Creature* survivor = FindCreatureIgnorePhase(player, player->GetTeam() == ALLIANCE ? "alaria_standing_abandoned_camp" : "wonza_standing_abandoned_camp", 5.0f); + if (!survivor) + return; + + if (player->GetTeam() == ALLIANCE) + { + _conversationId = CONVERSATION_QUEST_NORTHBOUND_ACCEPT_ALLIANCE; + _actorIdOne = ACTOR_ID_0_NORTHBOUND_ACCEPT_ALLIANCE; + _actorIdTwo = ACTOR_ID_1_NORTHBOUND_ACCEPT_ALLIANCE; + _runToPosition = GarrickQuillboarBriarpatchPosition; + _lingerSpellId = SPELL_LINGER_NORTHBOUND_ALLIANCE; + _guardianSpellId = SPELL_SUMMON_ADMIRAL_GARRICK_GUARDIAN_NORTHBOUND; + } + else + { + _conversationId = CONVERSATION_QUEST_NORTHBOUND_ACCEPT_HORDE; + _actorIdOne = ACTOR_ID_0_NORTHBOUND_ACCEPT_HORDE; + _actorIdTwo = ACTOR_ID_1_NORTHBOUND_ACCEPT_HORDE; + _runToPosition = GrimaxeQuillboarBriarpatchPosition; + _lingerSpellId = SPELL_LINGER_NORTHBOUND_HORDE; + _guardianSpellId = SPELL_SUMMON_WARLORD_GRIMAXE_GUARDIAN_NORTHBOUND; + } + + Conversation* conversation = Conversation::CreateConversation(_conversationId, player, *player, player->GetGUID(), nullptr, false); + if (!conversation) + return; + + conversation->AddActor(0, 0, player->GetGUID()); + conversation->AddActor(_actorIdOne, 1, me->GetGUID()); + conversation->AddActor(_actorIdTwo, 2, survivor->GetGUID()); + conversation->Start(); + } + + void IsSummonedBy(WorldObject* summoner) override + { + Player* player = summoner->ToPlayer(); + if (!player) + return; + + _playerGUID = player->GetGUID(); + + _events.ScheduleEvent(EVENT_FOLLOW_PLAYER, 3s); + } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == _lingerSpellId) + { + me->GetMotionMaster()->Remove(FOLLOW_MOTION_TYPE); + me->GetMotionMaster()->MovePoint(POINT_LEADER_RUN, _runToPosition, false); + } + return; + } + + void MovementInform(uint32 uiType, uint32 uiId) override + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiId != POINT_LEADER_RUN) + return; + + me->SetFacingTo(6.0737457275390625); + + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + { + player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT); + player->RemoveAura(_guardianSpellId); + player->UpdateVisibilityForPlayer(); + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FOLLOW_PLAYER: + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + me->GetMotionMaster()->MoveFollow(player, 0.0f, float(M_PI / 4.0f)); + break; + default: + break; + } + } + } + +private: + EventMap _events; + ObjectGuid _playerGUID; + uint32 _conversationId; + uint32 _actorIdOne; + uint32 _actorIdTwo; + Position _runToPosition; + uint32 _lingerSpellId; + uint32 _guardianSpellId; +}; + +// 55173 - Northbound +// 59935 - Northbound +class quest_northbound : public QuestScript +{ +public: + quest_northbound(char const* script) : QuestScript(script) { } + + void HandleQuestStatusChange(Player* player, QuestStatus newStatus, uint32 summonSpellId) + { + switch (newStatus) + { + case QUEST_STATUS_INCOMPLETE: + player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT); + player->CastSpell(player, summonSpellId); + break; + case QUEST_STATUS_NONE: + player->RemoveAura(summonSpellId); + player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT); + player->UpdateVisibilityForPlayer(); + break; + default: + break; + } + } +}; + +// 55173 - Northbound +class quest_northbound_alliance : public quest_northbound +{ +public: + quest_northbound_alliance() : quest_northbound("quest_northbound_alliance") { } + + void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override + { + HandleQuestStatusChange(player, newStatus, SPELL_SUMMON_ADMIRAL_GARRICK_GUARDIAN_NORTHBOUND); + } +}; + +// 59935 - Northbound +class quest_northbound_horde : public quest_northbound +{ +public: + quest_northbound_horde() : quest_northbound("quest_northbound_horde") { } + + void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override + { + HandleQuestStatusChange(player, newStatus, SPELL_SUMMON_WARLORD_GRIMAXE_GUARDIAN_NORTHBOUND); + } +}; + +// 305661 - Summon Admiral Garrick Guardian Summons Alliance Entry: 165360 +// 344383 - Summon Admiral Garrick Guardian Summons Horde Entry: 175034 +class spell_summon_leader_northbound : public SpellScript +{ + // @TODO: drop after TARGET_UNK_142 impl + + void SelectTarget(WorldObject*& target) + { + Player* caster = GetCaster()->ToPlayer(); + if (!caster) + return; + + Creature* survivor = FindCreatureIgnorePhase(caster, caster->GetTeam() == ALLIANCE ? "garrick_camp" : "grimaxe_camp", 5.0f); + if (!survivor) + return; + + target = survivor; + } + + void Register() override + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_summon_leader_northbound::SelectTarget, EFFECT_0, TARGET_DEST_NEARBY_ENTRY_OR_DB); + } +}; + +struct at_northbound_linger : AreaTriggerAI +{ + at_northbound_linger(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + Player* player = unit->ToPlayer(); + if (!player) + return; + + if (player->GetTeam() == ALLIANCE) + { + if (player->GetQuestStatus(QUEST_NORTHBOND_ALLIANCE) != QUEST_STATUS_COMPLETE) + return; + + if (!player->HasAura(SPELL_SUMMON_ADMIRAL_GARRICK_GUARDIAN_NORTHBOUND)) + return; + + if (player->HasAura(SPELL_LINGER_NORTHBOUND_ALLIANCE)) + return; + + player->CastSpell(player, SPELL_LINGER_NORTHBOUND_ALLIANCE); + } + else + { + if (player->GetQuestStatus(QUEST_NORTHBOND_HORDE) != QUEST_STATUS_COMPLETE) + return; + + if (!player->HasAura(SPELL_SUMMON_WARLORD_GRIMAXE_GUARDIAN_NORTHBOUND)) + return; + + if (player->HasAura(SPELL_LINGER_NORTHBOUND_HORDE)) + return; + + player->CastSpell(player, SPELL_LINGER_NORTHBOUND_HORDE); + } + } +}; + +// @TODO: drop +// 305665 - Scene Linger (DNT) +// 344385 - Scene Linger (DNT) +class spell_scene_linger_northbound: public SpellScript +{ + void HandleLaunch(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + } + + void HandleEffect(SpellEffIndex effIndex) + { + Player* player = GetHitUnit()->ToPlayer(); + if (!player) + return; + + Creature* scout = FindCreatureIgnorePhase(player, player->GetTeam() == ALLIANCE ? "huxworth_briarpatch" : "dawntracker_briarpatch", 100.0f); + if (!scout) + return; + + Conversation* conversation = Conversation::CreateConversation(GetSpellInfo()->GetEffect(effIndex).MiscValue, player, *player, player->GetGUID(), nullptr, false); + if (!conversation) + return; + + conversation->AddActor(ACTOR_ID_0_NORTHBOUND_AREATRIGGER_ALLIANCE, 0, player->GetTeam() == ALLIANCE ? scout->GetGUID() : ObjectGuid::Empty); + conversation->AddActor(ACTOR_ID_1_NORTHBOUND_AREATRIGGER_HORDE, 1, player->GetTeam() == ALLIANCE ? ObjectGuid::Empty : scout->GetGUID()); + conversation->Start(); + } + + void Register() override + { + OnEffectLaunchTarget += SpellEffectFn(spell_scene_linger_northbound::HandleLaunch, EFFECT_2, SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION); + OnEffectHitTarget += SpellEffectFn(spell_scene_linger_northbound::HandleEffect, EFFECT_2, SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION); + } +}; + void AddSC_zone_exiles_reach() { // Ship @@ -2205,7 +3824,6 @@ void AddSC_zone_exiles_reach() new quest_brace_for_impact(); new player_exiles_reach_ship_crash(); new scene_alliance_and_horde_ship(); - // Beach RegisterSpellScript(spell_knocked_down_exiles_reach_beach); new scene_alliance_and_horde_crash(); @@ -2235,7 +3853,6 @@ void AddSC_zone_exiles_reach() new quest_finding_the_lost_expedition_alliance(); new quest_finding_the_lost_expedition_horde(); RegisterSpellScript(spell_summon_survivor_beach); - // Abandoned Camp new GenericCreatureScript<npc_captain_abandoned_camp_exiles_reach<QUEST_COOKING_MEAT_ALLIANCE, CONVERSATION_QUEST_COOKING_MEAT_ACCEPT_ALLIANCE>>("npc_captain_garrick_abandoned_camp"); new GenericCreatureScript<npc_captain_abandoned_camp_exiles_reach<QUEST_COOKING_MEAT_HORDE, CONVERSATION_QUEST_COOKING_MEAT_ACCEPT_HORDE>>("npc_warlord_grimaxe_abandoned_camp"); @@ -2243,4 +3860,17 @@ void AddSC_zone_exiles_reach() new quest_cooking_meat_horde(); RegisterAreaTriggerAI(areatrigger_find_the_lost_expedition); RegisterAreaTriggerAI(areatrigger_find_the_lost_expedition_follower); -} + // Quest Enhanced Combat Tactics + new quest_enhanced_combat_tactics(); + RegisterSpellScript(spell_summon_combat_trainer); + new FactoryCreatureScript<CreatureAI, &SparringPartnerEnhancedCombatTrainingSelector>("npc_sparring_partner_combat_training"); + RegisterAreaTriggerAI(at_aggro_radius_check_enhanced_combat_tactics); + RegisterSpellScript(spell_knockback_charge_enhanced_training); + // Quest Northbound + RegisterCreatureAI(npc_leader_northbound); + new quest_northbound_alliance(); + new quest_northbound_horde(); + RegisterSpellScript(spell_summon_leader_northbound); + RegisterAreaTriggerAI(at_northbound_linger); + RegisterSpellScript(spell_scene_linger_northbound); +}; |