From 87a4e493a39d94f2468728ffcde87c2f6ad9fa6b Mon Sep 17 00:00:00 2001 From: Artem <34547317+Zenslash@users.noreply.github.com> Date: Sat, 25 Sep 2021 17:59:49 +0300 Subject: [PATCH] fix(Core/Script): 'Battle at Valhalas' quests done automatically (#7036) * fix(Core/Script): 'Battle at Valhalas' quests done automatically Battle at Valhalas series of quests, get to automatically complete Closes #6753 * Refactoring * Refactoring * Refactoring PlayerUpdates.cpp Co-authored-by: IntelligentQuantum * Refactoring PlayerQuest.cpp Co-authored-by: IntelligentQuantum * Update src/server/scripts/Northrend/zone_icecrown.cpp Co-authored-by: IntelligentQuantum --- src/server/game/Entities/Player/Player.h | 1 + .../game/Entities/Player/PlayerQuest.cpp | 14 ++++++ .../game/Entities/Player/PlayerUpdates.cpp | 28 ++++-------- .../scripts/Northrend/zone_icecrown.cpp | 45 +++++++++++++------ 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 0198d6f12..84dbb6d15 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1444,6 +1444,7 @@ public: void ReputationChanged2(FactionEntry const* factionEntry); [[nodiscard]] bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId = 0, bool turnIn = false, bool* showInLoot = nullptr) const; [[nodiscard]] bool HasQuestForGO(int32 GOId) const; + [[nodiscard]] bool HasQuest(uint32 questId) const; void UpdateForQuestWorldObjects(); [[nodiscard]] bool CanShareQuest(uint32 quest_id) const; diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index 4d59eed70..5258424af 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -84,6 +84,20 @@ void Player::PrepareQuestMenu(ObjectGuid guid) } } +bool Player::HasQuest(uint32 questId) const +{ + for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i) + { + uint32 questid = GetQuestSlotQuestId(i); + if (questid == questId) + { + return true; + } + } + + return false; +} + void Player::SendPreparedQuest(ObjectGuid guid) { QuestMenu& questMenu = PlayerTalkClass->GetQuestMenu(); diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 5fe3eb63e..0d805d36b 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -1813,8 +1813,7 @@ void Player::UpdateForQuestWorldObjects() UpdateData udata; WorldPacket packet; - for (GuidUnorderedSet::iterator itr = m_clientGUIDs.begin(); - itr != m_clientGUIDs.end(); ++itr) + for (GuidUnorderedSet::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) { if ((*itr).IsGameObject()) { @@ -1823,8 +1822,7 @@ void Player::UpdateForQuestWorldObjects() } else if ((*itr).IsCreatureOrVehicle()) { - Creature* obj = - ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr); + Creature* obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr); if (!obj) continue; @@ -1832,23 +1830,15 @@ void Player::UpdateForQuestWorldObjects() if (!obj->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) continue; - SpellClickInfoMapBounds clickPair = - sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry()); - for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; - _itr != clickPair.second; ++_itr) + SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry()); + for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr) { - //! This code doesn't look right, but it was logically converted - //! to condition system to do the exact same thing it did - //! before. It definitely needs to be overlooked for intended - //! functionality. - ConditionList conds = - sConditionMgr->GetConditionsForSpellClickEvent( - obj->GetEntry(), _itr->second.spellId); + //! This code doesn't look right, but it was logically converted to condition system to do the exact + //! same thing it did before. It definitely needs to be overlooked for intended functionality. + ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId); bool buildUpdateBlock = false; - for (ConditionList::const_iterator jtr = conds.begin(); - jtr != conds.end() && !buildUpdateBlock; ++jtr) - if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || - (*jtr)->ConditionType == CONDITION_QUESTTAKEN) + for (ConditionList::const_iterator jtr = conds.begin(); jtr != conds.end() && !buildUpdateBlock; ++jtr) + if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN) buildUpdateBlock = true; if (buildUpdateBlock) diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 0bc5f1b0b..d2a0957ff 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -114,6 +114,11 @@ public: uint32 currentQuest; void Reset() override + { + ResetData(); + } + + void ResetData() { events.Reset(); summons.DespawnAll(); @@ -135,27 +140,27 @@ public: switch(currentQuest) { case QUEST_BFV_FALLEN_HEROES: - me->SummonCreature(NPC_ELDRETH, 8245.5f, 3522.7f, 627.67f, 3.11f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_GENESS, 8217.45f, 3546.0f, 628.20f, 4.41f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_JHADRAS, 8179.99f, 3523.72f, 628.1f, 5.95f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_MASUD, 8184.97f, 3491.2f, 625.33f, 0.6f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_RITH, 8213.5f, 3478.5f, 626.79f, 1.56f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_TALLA, 8238.30f, 3485.5f, 628.5f, 2.157f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_ELDRETH, 8245.5f, 3522.7f, 627.67f, 3.11f, TEMPSUMMON_MANUAL_DESPAWN, 30000); + me->SummonCreature(NPC_GENESS, 8217.45f, 3546.0f, 628.20f, 4.41f, TEMPSUMMON_MANUAL_DESPAWN, 30000); + me->SummonCreature(NPC_JHADRAS, 8179.99f, 3523.72f, 628.1f, 5.95f, TEMPSUMMON_MANUAL_DESPAWN, 30000); + me->SummonCreature(NPC_MASUD, 8184.97f, 3491.2f, 625.33f, 0.6f, TEMPSUMMON_MANUAL_DESPAWN, 30000); + me->SummonCreature(NPC_RITH, 8213.5f, 3478.5f, 626.79f, 1.56f, TEMPSUMMON_MANUAL_DESPAWN, 30000); + me->SummonCreature(NPC_TALLA, 8238.30f, 3485.5f, 628.5f, 2.157f, TEMPSUMMON_MANUAL_DESPAWN, 30000); break; case QUEST_BFV_DARK_MASTER: - me->SummonCreature(NPC_DARK_MASTER, 8184.97f, 3491.2f, 625.33f, 0.6f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DARK_MASTER, 8184.97f, 3491.2f, 625.33f, 0.6f, TEMPSUMMON_MANUAL_DESPAWN, 30000); break; case QUEST_BFV_SIGRID: - me->SummonCreature(NPC_SIGRID, 8238.30f, 3485.5f, 628.5f, 2.157f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_SIGRID, 8238.30f, 3485.5f, 628.5f, 2.157f, TEMPSUMMON_MANUAL_DESPAWN, 30000); break; case QUEST_BFV_CARNAGE: - me->SummonCreature(NPC_CARNAGE, 8179.99f, 3523.72f, 628.1f, 5.95f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_CARNAGE, 8179.99f, 3523.72f, 628.1f, 5.95f, TEMPSUMMON_MANUAL_DESPAWN, 30000); break; case QUEST_BFV_THANE: - me->SummonCreature(NPC_THANE, 8217.45f, 3546.0f, 628.20f, 4.41f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_THANE, 8217.45f, 3546.0f, 628.20f, 4.41f, TEMPSUMMON_MANUAL_DESPAWN, 30000); break; case QUEST_BFV_FINAL: - me->SummonCreature(NPC_PRINCE, 8245.5f, 3522.7f, 627.67f, 3.11f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_PRINCE, 8245.5f, 3522.7f, 627.67f, 3.11f, TEMPSUMMON_MANUAL_DESPAWN, 30000); break; } } @@ -202,7 +207,6 @@ public: me->MonsterYell("The unthinkable has happened... $N has slain Prince Sandoval!", LANG_UNIVERSAL, ObjectAccessor::GetPlayer(*me, playerGUID)); break; } - player->GroupEventHappens(quest, player); } playerGUID2 = playerGUID; @@ -210,6 +214,18 @@ public: if (quest == QUEST_BFV_FINAL) events.ScheduleEvent(EVENT_VALHALAS_THIRD, 7000); } + else + { + uint32 quest = currentQuest; + if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) + { + if (!player->HasQuest(quest)) + { + ResetData(); + return; + } + } + } } void UpdateAI(uint32 diff) override @@ -310,8 +326,11 @@ public: bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override { + npc_battle_at_valhalasAI* vAI = CAST_AI(npc_battle_at_valhalas::npc_battle_at_valhalasAI, creature->AI()); + vAI->ResetData(); + creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - if (npc_battle_at_valhalasAI* vAI = CAST_AI(npc_battle_at_valhalas::npc_battle_at_valhalasAI, creature->AI())) + if (vAI) vAI->StartBattle(player->GetGUID(), quest->GetQuestId()); switch (quest->GetQuestId())