diff options
author | Shauren <shauren.trinity@gmail.com> | 2021-01-12 23:11:51 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-10-04 00:19:38 +0200 |
commit | 1e99011edf5e74ef51a7b6f84ca0529e5dbf2492 (patch) | |
tree | 727676de0ad7ca6ccc4d9e8c42ea27e4f3391cf0 /src/server/game | |
parent | 461a9c024cb6524c7ac87036674ca96107b67c5e (diff) |
Core/Scenarios: Attempt to restore scenario state from completed encounter info
Diffstat (limited to 'src/server/game')
-rw-r--r-- | src/server/game/Instances/InstanceScript.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceScript.h | 2 | ||||
-rw-r--r-- | src/server/game/Scenarios/InstanceScenario.cpp | 161 | ||||
-rw-r--r-- | src/server/game/Scenarios/InstanceScenario.h | 9 | ||||
-rw-r--r-- | src/server/game/Scenarios/ScenarioMgr.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Scenarios/ScenarioMgr.h | 4 |
6 files changed, 59 insertions, 126 deletions
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 9c1956c4dfb..3d3a8cf3384 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -80,12 +80,6 @@ InstanceScript::~InstanceScript() { } -void InstanceScript::SaveToDB() -{ - if (InstanceScenario* scenario = instance->GetInstanceScenario()) - scenario->SaveToDB(); -} - bool InstanceScript::IsEncounterInProgress() const { for (std::vector<BossInfo>::const_iterator itr = bosses.begin(); itr != bosses.end(); ++itr) @@ -438,7 +432,6 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state) } bossInfo->state = state; - SaveToDB(); if (dungeonEncounter) instance->UpdateInstanceLock({ dungeonEncounter, id, state }); } diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index a296877d123..121e243033c 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -360,8 +360,6 @@ class TC_GAME_API InstanceScript : public ZoneScript void LoadDungeonEncounterData(uint32 bossId, std::array<uint32, MAX_DUNGEON_ENCOUNTERS_PER_BOSS> const& dungeonEncounterIds); void UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit* source); - void SaveToDB(); - std::string headers; std::vector<BossInfo> bosses; std::vector<PersistentInstanceScriptValueBase*> _persistentScriptValues; diff --git a/src/server/game/Scenarios/InstanceScenario.cpp b/src/server/game/Scenarios/InstanceScenario.cpp index 30336a6b8f9..31f7414be0f 100644 --- a/src/server/game/Scenarios/InstanceScenario.cpp +++ b/src/server/game/Scenarios/InstanceScenario.cpp @@ -16,20 +16,20 @@ */ #include "InstanceScenario.h" -#include "DatabaseEnv.h" +#include "Containers.h" #include "DB2Stores.h" #include "GameTime.h" -#include "Log.h" +#include "InstanceScript.h" #include "Map.h" +#include "ObjectMgr.h" #include "Player.h" +#include "ScenarioMgr.h" +#include "StringFormat.h" -// TODO -// Do not save to db except for scenario type 3 (SCENARIO_TYPE_USE_DUNGEON_DISPLAY) - -InstanceScenario::InstanceScenario(Map const* map, ScenarioData const* scenarioData) : Scenario(scenarioData), _map(map) +InstanceScenario::InstanceScenario(InstanceMap const* map, ScenarioData const* scenarioData) : Scenario(scenarioData), _map(map) { ASSERT(_map); - LoadInstanceData(_map->GetInstanceId()); + LoadInstanceData(); Map::PlayerList const& players = map->GetPlayers(); for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) @@ -37,124 +37,67 @@ InstanceScenario::InstanceScenario(Map const* map, ScenarioData const* scenarioD SendScenarioState(player); } -void InstanceScenario::SaveToDB() +void InstanceScenario::LoadInstanceData() { - if (_criteriaProgress.empty()) - return; - - DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(_map->GetDifficultyID()); - if (!difficultyEntry || difficultyEntry->Flags & DIFFICULTY_FLAG_CHALLENGE_MODE) // Map should have some sort of "CanSave" boolean that returns whether or not the map is savable. (Challenge modes cannot be saved for example) + InstanceScript const* instanceScript = _map->GetInstanceScript(); + if (!instanceScript) return; - uint32 id = _map->GetInstanceId(); - if (!id) - { - TC_LOG_DEBUG("scenario", "Scenario::SaveToDB: Can not save scenario progress without an instance save. Map::GetInstanceId() did not return an instance save."); - return; - } + std::vector<CriteriaTree const*> criteriaTrees; - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); - for (auto iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter) + CriteriaList const& killCreatureCriteria = sCriteriaMgr->GetScenarioCriteriaByTypeAndScenario(CriteriaType::KillCreature, _data->Entry->ID); + if (!killCreatureCriteria.empty()) { - if (!iter->second.Changed) - continue; - - Criteria const* criteria = sCriteriaMgr->GetCriteria(iter->first); - switch (CriteriaType(criteria->Entry->Type)) + if (std::vector<InstanceSpawnGroupInfo> const* spawnGroups = sObjectMgr->GetInstanceSpawnGroupsForMap(_map->GetId())) { - // Blizzard only appears to store creature kills and dungeon encounters - case CriteriaType::KillCreature: - case CriteriaType::DefeatDungeonEncounter: - break; - default: - continue; - } - - if (iter->second.Counter) - { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA); - stmt->setUInt32(0, id); - stmt->setUInt32(1, iter->first); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_SCENARIO_INSTANCE_CRITERIA); - stmt->setUInt32(0, id); - stmt->setUInt32(1, iter->first); - stmt->setUInt64(2, iter->second.Counter); - stmt->setInt64(3, iter->second.Date); - trans->Append(stmt); - } - - iter->second.Changed = false; - } - - CharacterDatabase.CommitTransaction(trans); -} - -void InstanceScenario::LoadInstanceData(uint32 instanceId) -{ - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE); - stmt->setUInt32(0, instanceId); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - if (result) - { - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); - time_t now = GameTime::GetGameTime(); - - std::vector<CriteriaTree const*> criteriaTrees; - do - { - Field* fields = result->Fetch(); - uint32 id = fields[0].GetUInt32(); - uint64 counter = fields[1].GetUInt64(); - time_t date = fields[2].GetInt64(); - - Criteria const* criteria = sCriteriaMgr->GetCriteria(id); - if (!criteria) + std::unordered_map<uint32, uint64> despawnedCreatureCountsById; + for (InstanceSpawnGroupInfo const& spawnGroup : *spawnGroups) { - // Removing non-existing criteria data for all instances - TC_LOG_ERROR("criteria.instancescenarios", "Removing scenario criteria %u data from the table `instance_scenario_progress`.", id); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA); - stmt->setUInt32(0, instanceId); - stmt->setUInt32(1, uint32(id)); - trans->Append(stmt); - continue; - } + if (instanceScript->GetBossState(spawnGroup.BossStateId) != DONE) + continue; - if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now) - continue; + bool isDespawned = !((1 << DONE) & spawnGroup.BossStates) || (spawnGroup.Flags & InstanceSpawnGroupInfo::FLAG_BLOCK_SPAWN); + if (isDespawned) + for (auto const& [spawnGroupId, spawn] : sObjectMgr->GetSpawnMetadataForGroup(spawnGroup.SpawnGroupId)) + if (SpawnData const* spawnData = spawn->ToSpawnData()) + ++despawnedCreatureCountsById[spawnData->id]; + } - switch (CriteriaType(criteria->Entry->Type)) + for (Criteria const* criteria : killCreatureCriteria) { - // Blizzard appears to only stores creatures killed progress for unknown reasons. Either technical shortcoming or intentional - case CriteriaType::KillCreature: - case CriteriaType::DefeatDungeonEncounter: - break; - default: - continue; + // count creatures in despawned spawn groups + if (uint64* progress = Trinity::Containers::MapGetValuePtr(despawnedCreatureCountsById, criteria->Entry->Asset.CreatureID)) + { + SetCriteriaProgress(criteria, *progress, nullptr, PROGRESS_SET); + + if (CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID)) + for (CriteriaTree const* tree : *trees) + criteriaTrees.push_back(tree); + } } + } + } - SetCriteriaProgress(criteria, counter, nullptr, PROGRESS_SET); + for (Criteria const* criteria : sCriteriaMgr->GetScenarioCriteriaByTypeAndScenario(CriteriaType::DefeatDungeonEncounter, _data->Entry->ID)) + { + if (!instanceScript->IsEncounterCompleted(criteria->Entry->Asset.DungeonEncounterID)) + continue; - if (CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID)) - for (CriteriaTree const* tree : *trees) - criteriaTrees.push_back(tree); - } - while (result->NextRow()); + SetCriteriaProgress(criteria, 1, nullptr, PROGRESS_SET); - CharacterDatabase.CommitTransaction(trans); + if (CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID)) + for (CriteriaTree const* tree : *trees) + criteriaTrees.push_back(tree); + } - for (CriteriaTree const* tree : criteriaTrees) - { - ScenarioStepEntry const* step = tree->ScenarioStep; - if (!step) - continue; + for (CriteriaTree const* tree : criteriaTrees) + { + ScenarioStepEntry const* step = tree->ScenarioStep; + if (!step) + continue; - if (IsCompletedCriteriaTree(tree)) - SetStepState(step, SCENARIO_STEP_DONE); - } + if (IsCompletedCriteriaTree(tree)) + SetStepState(step, SCENARIO_STEP_DONE); } } diff --git a/src/server/game/Scenarios/InstanceScenario.h b/src/server/game/Scenarios/InstanceScenario.h index e3c84c28ba5..8bd9385ea61 100644 --- a/src/server/game/Scenarios/InstanceScenario.h +++ b/src/server/game/Scenarios/InstanceScenario.h @@ -20,21 +20,20 @@ #include "Scenario.h" -class Map; +class InstanceMap; class TC_GAME_API InstanceScenario : public Scenario { public: - InstanceScenario(Map const* map, ScenarioData const* scenarioData); + InstanceScenario(InstanceMap const* map, ScenarioData const* scenarioData); - void SaveToDB(); - void LoadInstanceData(uint32 instanceId); + void LoadInstanceData(); protected: std::string GetOwnerInfo() const override; void SendPacket(WorldPacket const* data) const override; - Map const* _map; + InstanceMap const* _map; }; #endif // InstanceScenario_h__ diff --git a/src/server/game/Scenarios/ScenarioMgr.cpp b/src/server/game/Scenarios/ScenarioMgr.cpp index 36152089b2a..0d081403b92 100644 --- a/src/server/game/Scenarios/ScenarioMgr.cpp +++ b/src/server/game/Scenarios/ScenarioMgr.cpp @@ -30,7 +30,7 @@ ScenarioMgr* ScenarioMgr::Instance() return &instance; } -InstanceScenario* ScenarioMgr::CreateInstanceScenario(Map const* map, TeamId team) const +InstanceScenario* ScenarioMgr::CreateInstanceScenario(InstanceMap const* map, TeamId team) const { auto dbDataItr = _scenarioDBData.find(std::make_pair(map->GetId(), map->GetDifficultyID())); // No scenario registered for this map and difficulty in the database diff --git a/src/server/game/Scenarios/ScenarioMgr.h b/src/server/game/Scenarios/ScenarioMgr.h index 4445879d42c..46359461f07 100644 --- a/src/server/game/Scenarios/ScenarioMgr.h +++ b/src/server/game/Scenarios/ScenarioMgr.h @@ -25,8 +25,8 @@ #include <unordered_map> #include <vector> +class InstanceMap; class InstanceScenario; -class Map; struct ScenarioEntry; struct ScenarioStepEntry; @@ -105,7 +105,7 @@ private: public: static ScenarioMgr* Instance(); - InstanceScenario* CreateInstanceScenario(Map const* map, TeamId team) const; + InstanceScenario* CreateInstanceScenario(InstanceMap const* map, TeamId team) const; void LoadDBData(); void LoadDB2Data(); |