aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/wotlk_classic/2024_01_09_06_world_2024_01_08_02_world.sql1
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp21
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp30
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp1
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp1
9 files changed, 56 insertions, 4 deletions
diff --git a/sql/updates/world/wotlk_classic/2024_01_09_06_world_2024_01_08_02_world.sql b/sql/updates/world/wotlk_classic/2024_01_09_06_world_2024_01_08_02_world.sql
new file mode 100644
index 00000000000..250c1f30b23
--- /dev/null
+++ b/sql/updates/world/wotlk_classic/2024_01_09_06_world_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 91ae066041d..f38760f39c2 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -660,6 +660,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 1ea6fd84276..5641d4cfbea 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -15864,6 +15864,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
{
@@ -24134,6 +24153,7 @@ void Player::DailyReset()
SetQuestSlot(slot, 0);
AbandonQuest(questId);
RemoveActiveQuest(questId);
+ DespawnPersonalSummonsForQuest(questId);
if (quest->GetLimitTime())
RemoveTimedQuest(questId);
@@ -24170,6 +24190,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 c55b0b3dc16..f09b8d5c2c0 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1551,6 +1551,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 8c14a95a2d2..78540a5c6eb 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -393,8 +393,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);
@@ -676,8 +674,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)
{
@@ -731,6 +729,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 5cd6cb11557..88fafda8609 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 94f829086b5..450bcfd7757 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4038,6 +4038,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 bece9fcfb1f..cd1ebc11478 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2087,6 +2087,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);