From d64fa1680d707add7ce2a650e84c525e8dcfb9d4 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 30 Jul 2022 20:56:21 -0700 Subject: [PATCH] Fix missions re-ordering on reload (#686) * Fix missions re-ordering on reload Check for success rather than failure * Add a comment * Get base value from database * Update Mission.h --- dGame/dComponents/MissionComponent.cpp | 21 +++++++++++++++++---- dGame/dComponents/MissionComponent.h | 7 +++++++ dGame/dMission/Mission.cpp | 3 +++ dGame/dMission/Mission.h | 17 +++++++++++++++++ dZoneManager/dZoneManager.cpp | 9 +++++++++ dZoneManager/dZoneManager.h | 6 ++++++ 6 files changed, 59 insertions(+), 4 deletions(-) diff --git a/dGame/dComponents/MissionComponent.cpp b/dGame/dComponents/MissionComponent.cpp index ad77cf34..96f213e5 100644 --- a/dGame/dComponents/MissionComponent.cpp +++ b/dGame/dComponents/MissionComponent.cpp @@ -24,6 +24,7 @@ std::unordered_map> MissionComponent::m_Achievemen //! Initializer MissionComponent::MissionComponent(Entity* parent) : Component(parent) { + m_LastUsedMissionOrderUID = dZoneManager::Instance()->GetUniqueMissionIdStartingValue(); } //! Destructor @@ -83,6 +84,7 @@ void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipCh if (mission != nullptr) { if (mission->GetClientInfo().repeatable) { mission->Accept(); + if (mission->IsMission()) mission->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID); } return; @@ -90,6 +92,8 @@ void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipCh mission = new Mission(this, missionId); + if (mission->IsMission()) mission->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID); + mission->Accept(); this->m_Missions.insert_or_assign(missionId, mission); @@ -299,6 +303,8 @@ bool MissionComponent::LookForAchievements(MissionTaskType type, int32_t value, m_Missions.insert_or_assign(missionID, instance); + if (instance->IsMission()) instance->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID); + instance->Accept(); any = true; @@ -368,6 +374,8 @@ bool MissionComponent::LookForAchievements(MissionTaskType type, int32_t value, m_Missions.insert_or_assign(mission.id, instance); + if (instance->IsMission()) instance->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID); + instance->Accept(); any = true; @@ -523,6 +531,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { auto* currentM = cur->FirstChildElement(); + uint32_t missionOrder{}; while (currentM) { int missionId; @@ -532,6 +541,11 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { mission->LoadFromXml(currentM); + if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) { + mission->SetUniqueMissionOrderID(missionOrder); + if (missionOrder > m_LastUsedMissionOrderUID) m_LastUsedMissionOrderUID = missionOrder; + } + currentM = currentM->NextSiblingElement(); m_Missions.insert_or_assign(missionId, mission); @@ -565,17 +579,16 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) { if (mission) { const auto complete = mission->IsComplete(); - if (complete) { - auto* m = doc->NewElement("m"); + auto* m = doc->NewElement("m"); + if (complete) { mission->UpdateXml(m); done->LinkEndChild(m); continue; } - - auto* m = doc->NewElement("m"); + if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID()); mission->UpdateXml(m); diff --git a/dGame/dComponents/MissionComponent.h b/dGame/dComponents/MissionComponent.h index b4e53001..58185a68 100644 --- a/dGame/dComponents/MissionComponent.h +++ b/dGame/dComponents/MissionComponent.h @@ -193,6 +193,13 @@ private: * combination of tasks and values, so that they can be easily re-queried later */ static std::unordered_map> m_AchievementCache; + + /** + * Order of missions in the UI. This value is incremented by 1 + * for each mission the Entity that owns this component accepts. + * In live this value started at 745. + */ + uint32_t m_LastUsedMissionOrderUID = 746U; }; #endif // MISSIONCOMPONENT_H diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index bb02c4c8..6020e51c 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -26,6 +26,8 @@ Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) { m_Timestamp = 0; + m_UniqueMissionID = dZoneManager::Instance()->GetUniqueMissionIdStartingValue(); + m_Reward = 0; m_State = MissionState::MISSION_STATE_UNKNOWN; @@ -283,6 +285,7 @@ void Mission::Accept() { void Mission::Complete(const bool yieldRewards) { if (m_State != MissionState::MISSION_STATE_ACTIVE && m_State != MissionState::MISSION_STATE_COMPLETE_ACTIVE) { + // If we are accepting a mission here there is no point to giving it a unique ID since we just complete it immediately. Accept(); } diff --git a/dGame/dMission/Mission.h b/dGame/dMission/Mission.h index 94920cba..43b2a96c 100644 --- a/dGame/dMission/Mission.h +++ b/dGame/dMission/Mission.h @@ -220,6 +220,18 @@ public: * @return true if the mission exists, false otherwise */ static bool IsValidMission(uint32_t missionId, CDMissions& info); + + /** + * @brief Returns the unique mission order ID + * + * @return The unique order ID + */ + uint32_t GetUniqueMissionOrderID() { return m_UniqueMissionID; }; + + /** + * Sets the unique mission order ID of this mission + */ + void SetUniqueMissionOrderID(uint32_t value) { m_UniqueMissionID = value; }; private: /** * Progresses all the newly accepted tasks for this mission after it has been accepted to reflect the state of the @@ -261,6 +273,11 @@ private: * All the tasks that can be progressed for this mission */ std::vector m_Tasks; + + /** + * The unique ID what order this mission was accepted in. + */ + uint32_t m_UniqueMissionID; }; #endif diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 52d56f3c..102fb3af 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -240,3 +240,12 @@ std::vector dZoneManager::GetSpawnersInGroup(std::string group) { return spawnersInGroup; } + +uint32_t dZoneManager::GetUniqueMissionIdStartingValue() { + if (m_UniqueMissionIdStart == 0) { + auto tableData = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Missions WHERE isMission = 0 GROUP BY isMission;"); + m_UniqueMissionIdStart = tableData.getIntField(0, -1); + tableData.finalize(); + } + return m_UniqueMissionIdStart; +} diff --git a/dZoneManager/dZoneManager.h b/dZoneManager/dZoneManager.h index 66e56820..b2fef1e3 100644 --- a/dZoneManager/dZoneManager.h +++ b/dZoneManager/dZoneManager.h @@ -43,6 +43,7 @@ public: void Update(float deltaTime); Entity* GetZoneControlObject() { return m_ZoneControlObject; } bool GetPlayerLoseCoinOnDeath() { return m_PlayerLoseCoinsOnDeath; } + uint32_t GetUniqueMissionIdStartingValue(); private: /** @@ -55,6 +56,11 @@ private: */ int32_t m_CurrencyConversionRate = 0; + /** + * The starting unique mission ID. + */ + uint32_t m_UniqueMissionIdStart = 0; + static dZoneManager* m_Address; //Singleton Zone* m_pZone; LWOZONEID m_ZoneID;