mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-20 01:15:35 +01:00
Core/Creatures: Added possibility to automatically despawn personal summons on quest remove (#29114)
(cherry picked from commit b3dce0ac08)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ALTER TABLE `creature_summoned_data` ADD COLUMN `DespawnOnQuestsRemoved` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL AFTER `FlyingMountDisplayID`;
|
||||
@@ -660,6 +660,7 @@ struct CreatureSummonedData
|
||||
Optional<uint32> CreatureIDVisibleToSummoner;
|
||||
Optional<uint32> GroundMountDisplayID;
|
||||
Optional<uint32> FlyingMountDisplayID;
|
||||
Optional<std::vector<uint32>> DespawnOnQuestsRemoved;
|
||||
};
|
||||
|
||||
enum InhabitTypeValues
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user