diff options
-rw-r--r-- | sql/updates/world/master/2024_01_08_02_world.sql | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureData.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 21 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 30 | ||||
-rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 1 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 3 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_quest.cpp | 1 |
9 files changed, 56 insertions, 4 deletions
diff --git a/sql/updates/world/master/2024_01_08_02_world.sql b/sql/updates/world/master/2024_01_08_02_world.sql new file mode 100644 index 00000000000..250c1f30b23 --- /dev/null +++ b/sql/updates/world/master/2024_01_08_02_world.sql @@ -0,0 +1 @@ +ALTER TABLE `creature_summoned_data` ADD COLUMN `DespawnOnQuestsRemoved` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL AFTER `FlyingMountDisplayID`; diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 562d7d03f5a..6c66d75d708 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -640,6 +640,7 @@ struct CreatureSummonedData Optional<uint32> CreatureIDVisibleToSummoner; Optional<uint32> GroundMountDisplayID; Optional<uint32> FlyingMountDisplayID; + Optional<std::vector<uint32>> DespawnOnQuestsRemoved; }; enum InhabitTypeValues diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 3c638747247..642d377d7dd 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -16382,6 +16382,25 @@ void Player::SkipQuests(std::vector<uint32> const& questIds) UpdateObjectVisibility(); } +void Player::DespawnPersonalSummonsForQuest(uint32 questId) +{ + std::list<Creature*> creatureList; + GetCreatureListWithOptionsInGrid(creatureList, 100.0f, { .IgnorePhases = true, .PrivateObjectOwnerGuid = GetGUID() }); // we might want to replace this with SummonList in Player at some point + + for (Creature* creature : creatureList) + { + CreatureSummonedData const* summonedData = sObjectMgr->GetCreatureSummonedData(creature->GetEntry()); + if (!summonedData) + continue; + + if (summonedData->DespawnOnQuestsRemoved) + { + if (std::find(summonedData->DespawnOnQuestsRemoved->begin(), summonedData->DespawnOnQuestsRemoved->end(), questId) != summonedData->DespawnOnQuestsRemoved->end()) + creature->DespawnOrUnsummon(); + } + } +} + // not used in Trinity, but used in scripting code uint16 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) const { @@ -24820,6 +24839,7 @@ void Player::DailyReset() SetQuestSlot(slot, 0); AbandonQuest(questId); RemoveActiveQuest(questId); + DespawnPersonalSummonsForQuest(questId); if (quest->GetLimitTime()) RemoveTimedQuest(questId); @@ -24859,6 +24879,7 @@ void Player::ResetWeeklyQuestStatus() SetQuestSlot(slot, 0); AbandonQuest(questId); RemoveActiveQuest(questId); + DespawnPersonalSummonsForQuest(questId); if (quest->GetLimitTime()) RemoveTimedQuest(questId); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index aa756c3e251..e9be541a0e5 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1594,6 +1594,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SendQuestUpdate(uint32 questId); QuestGiverStatus GetQuestDialogStatus(Object const* questGiver) const; void SkipQuests(std::vector<uint32> const& questIds); // removes quest from log, flags rewarded, but does not give any rewards to player + void DespawnPersonalSummonsForQuest(uint32 questId); void SetDailyQuestStatus(uint32 quest_id); bool IsDailyQuestDone(uint32 quest_id) const; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 8513001c8af..d04ff396c13 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -396,8 +396,6 @@ void ObjectMgr::LoadCreatureTemplates() // We load the creature models after loading but before checking LoadCreatureTemplateModels(); - LoadCreatureSummonedData(); - // Checking needs to be done after loading because of the difficulty self referencing for (auto const& ctPair : _creatureTemplateStore) CheckCreatureTemplate(&ctPair.second); @@ -677,8 +675,8 @@ void ObjectMgr::LoadCreatureSummonedData() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 - QueryResult result = WorldDatabase.Query("SELECT CreatureID, CreatureIDVisibleToSummoner, GroundMountDisplayID, FlyingMountDisplayID FROM creature_summoned_data"); + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT CreatureID, CreatureIDVisibleToSummoner, GroundMountDisplayID, FlyingMountDisplayID, DespawnOnQuestsRemoved FROM creature_summoned_data"); if (!result) { @@ -732,6 +730,30 @@ void ObjectMgr::LoadCreatureSummonedData() } } + if (!fields[4].IsNull()) + { + std::vector<uint32> questList; + for (std::string_view questStr : Trinity::Tokenize(fields[4].GetStringView(), ',', false)) + { + Optional<uint32> questId = Trinity::StringTo<uint32>(questStr); + if (!questId) + continue; + + Quest const* quest = GetQuestTemplate(*questId); + if (!quest) + { + TC_LOG_ERROR("sql.sql", "Table `creature_summoned_data` references non-existing quest {} in DespawnOnQuestsRemoved for creature {}, skipping", + *questId, creatureId); + continue; + } + + questList.push_back(*questId); + } + + if (!questList.empty()) + summonedData.DespawnOnQuestsRemoved = std::move(questList); + } + } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded {} creature summoned data definitions in {} ms", _creatureSummonedDataStore.size(), GetMSTimeDiffToNow(oldMSTime)); diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 889a98d8011..e98b85608aa 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -471,6 +471,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemove _player->TakeQuestSourceItem(questId, true); // remove quest src item from player _player->AbandonQuest(questId); // remove all quest items player received before abandoning quest. Note, this does not remove normal drop items that happen to be quest requirements. _player->RemoveActiveQuest(questId); + _player->DespawnPersonalSummonsForQuest(questId); TC_LOG_INFO("network", "Player {} abandoned quest {}", _player->GetGUID().ToString(), questId); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 2f3d4e266e5..1d14560266b 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4023,6 +4023,7 @@ void Spell::EffectQuestClear() player->RemoveActiveQuest(quest_id, false); player->RemoveRewardedQuest(quest_id); + player->DespawnPersonalSummonsForQuest(quest_id); sScriptMgr->OnQuestStatusChange(player, quest_id); sScriptMgr->OnQuestStatusChange(player, quest, oldStatus, QUEST_STATUS_NONE); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 3b2c171659e..7d6888255c9 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2089,6 +2089,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Game Event Data..."); // must be after loading pools fully sGameEventMgr->LoadFromDB(); + TC_LOG_INFO("server.loading", "Loading creature summoned data..."); + sObjectMgr->LoadCreatureSummonedData(); // must be after LoadCreatureTemplates() and LoadQuests() + TC_LOG_INFO("server.loading", "Loading UNIT_NPC_FLAG_SPELLCLICK Data..."); // must be after LoadQuests sObjectMgr->LoadNPCSpellClickSpells(); diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index 22ff3c39bd7..3dd04ef8eea 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -137,6 +137,7 @@ public: } player->RemoveActiveQuest(quest->GetQuestId(), false); player->RemoveRewardedQuest(quest->GetQuestId()); + player->DespawnPersonalSummonsForQuest(quest->GetQuestId()); sScriptMgr->OnQuestStatusChange(player, quest->GetQuestId()); sScriptMgr->OnQuestStatusChange(player, quest, oldStatus, QUEST_STATUS_NONE); |