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 | |
parent | 461a9c024cb6524c7ac87036674ca96107b67c5e (diff) |
Core/Scenarios: Attempt to restore scenario state from completed encounter info
-rw-r--r-- | sql/base/characters_database.sql | 28 | ||||
-rw-r--r-- | sql/updates/characters/master/2022_10_03_02_characters.sql | 1 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 5 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.h | 4 | ||||
-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 |
10 files changed, 62 insertions, 161 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 8fed83db228..f730f61f659 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -2587,31 +2587,6 @@ LOCK TABLES `instance` WRITE; UNLOCK TABLES; -- --- Table structure for table `instance_scenario_progress` --- - -DROP TABLE IF EXISTS `instance_scenario_progress`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `instance_scenario_progress` ( - `id` int unsigned NOT NULL, - `criteria` int unsigned NOT NULL, - `counter` bigint unsigned NOT NULL, - `date` bigint NOT NULL DEFAULT '0', - PRIMARY KEY (`id`,`criteria`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `instance_scenario_progress` --- - -LOCK TABLES `instance_scenario_progress` WRITE; -/*!40000 ALTER TABLE `instance_scenario_progress` DISABLE KEYS */; -/*!40000 ALTER TABLE `instance_scenario_progress` ENABLE KEYS */; -UNLOCK TABLES; - --- -- Table structure for table `item_instance` -- @@ -3629,7 +3604,8 @@ INSERT INTO `updates` VALUES ('2022_08_21_00_characters.sql','1D75688392FBDA18CD8494F32CF682DCB49642EC','ARCHIVED','2022-08-21 00:02:03',0), ('2022_09_18_00_characters.sql','A7DF0C1F0E074F3E63A6CDD0AF873A1F3DC33B29','RELEASED','2022-09-18 21:48:42',0), ('2022_10_03_00_characters.sql','7B062787230D9158A622EB4AFE7FA6D18AB47BB3','RELEASED','2022-10-03 22:32:58',0), -('2022_10_03_01_characters.sql','7CF58BD9CC366301CC992017028568C8774C4BC2','RELEASED','2022-10-03 22:36:38',0); +('2022_10_03_01_characters.sql','7CF58BD9CC366301CC992017028568C8774C4BC2','RELEASED','2022-10-03 22:36:38',0), +('2022_10_03_02_characters.sql','33135AB3132943F15F4849A16EC5EFEA402F24F6','RELEASED','2022-10-03 22:38:27',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/characters/master/2022_10_03_02_characters.sql b/sql/updates/characters/master/2022_10_03_02_characters.sql new file mode 100644 index 00000000000..0bc7b663012 --- /dev/null +++ b/sql/updates/characters/master/2022_10_03_02_characters.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `instance_scenario_progress`; diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 766f1bc620b..723e85311b5 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -748,11 +748,6 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_BLACKMARKET_AUCTIONS, "UPDATE blackmarket_auctions SET currentBid = ?, time = ?, numBids = ?, bidder = ? WHERE marketId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_BLACKMARKET_AUCTIONS, "INSERT INTO blackmarket_auctions (marketId, currentBid, time, numBids, bidder) VALUES (?, ?, ?, ? ,?)", CONNECTION_ASYNC); - // Scenario - PrepareStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, "SELECT criteria, counter, date FROM instance_scenario_progress WHERE id = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA, "DELETE FROM instance_scenario_progress WHERE id = ? AND criteria = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_INS_SCENARIO_INSTANCE_CRITERIA, "INSERT INTO instance_scenario_progress (id, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); - // Spell Location PrepareStatement(CHAR_SEL_CHARACTER_AURA_STORED_LOCATIONS, "SELECT Spell, MapId, PositionX, PositionY, PositionZ, Orientation FROM character_aura_stored_location WHERE Guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHARACTER_AURA_STORED_LOCATIONS_BY_GUID, "DELETE FROM character_aura_stored_location WHERE Guid = ?", CONNECTION_ASYNC); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index 588c0dccf60..26ec666a5d7 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -619,10 +619,6 @@ enum CharacterDatabaseStatements : uint32 CHAR_UPD_BLACKMARKET_AUCTIONS, CHAR_INS_BLACKMARKET_AUCTIONS, - CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, - CHAR_DEL_SCENARIO_INSTANCE_CRITERIA, - CHAR_INS_SCENARIO_INSTANCE_CRITERIA, - CHAR_SEL_CHARACTER_AURA_STORED_LOCATIONS, CHAR_DEL_CHARACTER_AURA_STORED_LOCATIONS_BY_GUID, CHAR_DEL_CHARACTER_AURA_STORED_LOCATION, 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(); |