diff --git a/dDatabase/CDClientManager.cpp b/dDatabase/CDClientManager.cpp index 7ad852bc..75ada1ea 100644 --- a/dDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientManager.cpp @@ -8,7 +8,7 @@ void CDClientManager::Initialize(void) { tables.insert(std::make_pair("ActivityRewards", new CDActivityRewardsTable())); UNUSED(tables.insert(std::make_pair("Animations", new CDAnimationsTable()))); tables.insert(std::make_pair("BehaviorParameter", new CDBehaviorParameterTable())); - UNUSED(tables.insert(std::make_pair("BehaviorTemplate", new CDBehaviorTemplateTable()))); + tables.insert(std::make_pair("BehaviorTemplate", new CDBehaviorTemplateTable())); tables.insert(std::make_pair("ComponentsRegistry", new CDComponentsRegistryTable())); tables.insert(std::make_pair("CurrencyTable", new CDCurrencyTableTable())); tables.insert(std::make_pair("DestructibleComponent", new CDDestructibleComponentTable())); diff --git a/dDatabase/Tables/CDBehaviorParameterTable.cpp b/dDatabase/Tables/CDBehaviorParameterTable.cpp index 4991ac82..bbbdb2b6 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.cpp +++ b/dDatabase/Tables/CDBehaviorParameterTable.cpp @@ -3,33 +3,25 @@ //! Constructor CDBehaviorParameterTable::CDBehaviorParameterTable(void) { -#ifdef CDCLIENT_CACHE_ALL auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); + size_t hash = 0; while (!tableData.eof()) { + hash = 0; CDBehaviorParameter entry; entry.behaviorID = tableData.getIntField(0, -1); entry.parameterID = tableData.getStringField(1, ""); entry.value = tableData.getFloatField(2, -1.0f); - //Check if we have an entry with this ID: - auto it = m_entries.find(entry.behaviorID); - if (it != m_entries.end()) { - it->second.insert(std::make_pair(entry.parameterID, entry.value)); - } - else { - //Otherwise, insert it: - m_entries.insert(std::make_pair(entry.behaviorID, std::map())); - auto jit = m_entries.find(entry.behaviorID); + GeneralUtils::hash_combine(hash, entry.behaviorID); + GeneralUtils::hash_combine(hash, entry.parameterID); - //Add our value as well: - jit->second.insert(std::make_pair(entry.parameterID, entry.value)); - } + auto it = m_Entries.find(entry.behaviorID); + m_ParametersList.insert(entry.parameterID); + m_Entries.insert(std::make_pair(hash, entry)); tableData.nextRow(); } - tableData.finalize(); -#endif } //! Destructor @@ -40,51 +32,33 @@ std::string CDBehaviorParameterTable::GetName(void) const { return "BehaviorParameter"; } -float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue) +CDBehaviorParameter CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue) { + CDBehaviorParameter returnValue; + returnValue.behaviorID = 0; + returnValue.parameterID = ""; + returnValue.value = defaultValue; + size_t hash = 0; GeneralUtils::hash_combine(hash, behaviorID); GeneralUtils::hash_combine(hash, name); // Search for specific parameter const auto& it = m_Entries.find(hash); - if (it != m_Entries.end()) { - return it->second; - } - - // Check if this behavior has already been checked - const auto& itChecked = m_Entries.find(behaviorID); - if (itChecked != m_Entries.end()) { - return defaultValue; - } - -#ifndef CDCLIENT_CACHE_ALL - auto query = CDClientDatabase::CreatePreppedStmt( - "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;"); - query.bind(1, (int) behaviorID); - - auto tableData = query.execQuery(); - - m_Entries.insert_or_assign(behaviorID, 0); - - while (!tableData.eof()) { - const std::string parameterID = tableData.getStringField(0, ""); - const float value = tableData.getFloatField(1, 0); - - size_t parameterHash = 0; - GeneralUtils::hash_combine(parameterHash, behaviorID); - GeneralUtils::hash_combine(parameterHash, parameterID); - - m_Entries.insert_or_assign(parameterHash, value); - - tableData.nextRow(); - } - - const auto& it2 = m_Entries.find(hash); - if (it2 != m_Entries.end()) { - return it2->second; - } -#endif - - return defaultValue; + return it != m_Entries.end() ? it->second : returnValue; +} + +std::map CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { + size_t hash; + std::map returnInfo; + for (auto parameterCandidate : m_ParametersList) { + hash = 0; + GeneralUtils::hash_combine(hash, behaviorID); + GeneralUtils::hash_combine(hash, parameterCandidate); + auto infoCandidate = m_Entries.find(hash); + if (infoCandidate != m_Entries.end()) { + returnInfo.insert(std::make_pair(infoCandidate->second.parameterID, infoCandidate->second.value)); + } + } + return returnInfo; } diff --git a/dDatabase/Tables/CDBehaviorParameterTable.h b/dDatabase/Tables/CDBehaviorParameterTable.h index 3d14d66d..17605636 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.h +++ b/dDatabase/Tables/CDBehaviorParameterTable.h @@ -2,7 +2,8 @@ // Custom Classes #include "CDTable.h" -#include +#include +#include /*! \file CDBehaviorParameterTable.hpp @@ -19,8 +20,8 @@ struct CDBehaviorParameter { //! BehaviorParameter table class CDBehaviorParameterTable : public CDTable { private: - std::map m_Entries; - + std::unordered_map m_Entries; + std::unordered_set m_ParametersList; public: //! Constructor @@ -35,5 +36,7 @@ public: */ std::string GetName(void) const override; - float GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0); + CDBehaviorParameter GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0); + + std::map GetParametersByBehaviorID(uint32_t behaviorID); }; diff --git a/dDatabase/Tables/CDBehaviorTemplateTable.cpp b/dDatabase/Tables/CDBehaviorTemplateTable.cpp index f9830317..c79f4177 100644 --- a/dDatabase/Tables/CDBehaviorTemplateTable.cpp +++ b/dDatabase/Tables/CDBehaviorTemplateTable.cpp @@ -16,7 +16,7 @@ CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) { // Reserve the size this->entries.reserve(size); - + // Now get the data auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorTemplate"); while (!tableData.eof()) { @@ -27,6 +27,7 @@ CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) { entry.effectHandle = tableData.getStringField(3, ""); this->entries.push_back(entry); + this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry)); tableData.nextRow(); } @@ -55,3 +56,15 @@ std::vector CDBehaviorTemplateTable::Query(std::function CDBehaviorTemplateTable::GetEntries(void) const { return this->entries; } + +const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) { + auto entry = this->entriesMappedByBehaviorID.find(behaviorID); + if (entry == this->entriesMappedByBehaviorID.end()) { + CDBehaviorTemplate entryToReturn; + entryToReturn.behaviorID = 0; + entryToReturn.effectHandle = ""; + return entryToReturn; + } else { + return entry->second; + } +} diff --git a/dDatabase/Tables/CDBehaviorTemplateTable.h b/dDatabase/Tables/CDBehaviorTemplateTable.h index a63c2160..36424c12 100644 --- a/dDatabase/Tables/CDBehaviorTemplateTable.h +++ b/dDatabase/Tables/CDBehaviorTemplateTable.h @@ -2,6 +2,7 @@ // Custom Classes #include "CDTable.h" +#include /*! \file CDBehaviorTemplateTable.hpp @@ -21,7 +22,7 @@ struct CDBehaviorTemplate { class CDBehaviorTemplateTable : public CDTable { private: std::vector entries; - + std::unordered_map entriesMappedByBehaviorID; public: //! Constructor @@ -47,5 +48,6 @@ public: \return The entries */ std::vector GetEntries(void) const; - + + const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID); }; diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 7305ed2d..ac1ab7de 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -7,6 +7,7 @@ #include "dLogger.h" #include "BehaviorTemplates.h" #include "BehaviorBranchContext.h" +#include /* * Behavior includes @@ -69,7 +70,7 @@ #include "RenderComponent.h" #include "DestroyableComponent.h" -std::map Behavior::Cache = {}; +std::unordered_map Behavior::Cache = {}; CDBehaviorParameterTable* Behavior::BehaviorParameterTable = nullptr; Behavior* Behavior::GetBehavior(const uint32_t behaviorId) @@ -285,28 +286,22 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) } BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) { - auto query = CDClientDatabase::CreatePreppedStmt( - "SELECT templateID FROM BehaviorTemplate WHERE behaviorID = ?;"); - query.bind(1, (int) behaviorId); + auto behaviorTemplateTable = CDClientManager::Instance()->GetTable("BehaviorTemplate"); - auto result = query.execQuery(); - - // Make sure we do not proceed if we are trying to load an invalid behavior - if (result.eof()) - { - if (behaviorId != 0) - { - Game::logger->Log("Behavior::GetBehaviorTemplate", "Failed to load behavior template with id (%i)!\n", behaviorId); + BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY; + // Find behavior template by its behavior id. Default to 0. + if (behaviorTemplateTable) { + auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); + if (templateEntry.behaviorID == behaviorId) { + templateID = static_cast(templateEntry.templateID); } - - return BehaviorTemplates::BEHAVIOR_EMPTY; } - const auto id = static_cast(result.getIntField(0)); + if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) { + Game::logger->Log("Behavior", "Failed to load behavior template with id (%i)!\n", behaviorId); + } - result.finalize(); - - return id; + return templateID; } // For use with enemies, to display the correct damage animations on the players @@ -412,6 +407,17 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID Behavior::Behavior(const uint32_t behaviorId) { + auto behaviorTemplateTable = CDClientManager::Instance()->GetTable("BehaviorTemplate"); + + CDBehaviorTemplate templateInDatabase; + + if (behaviorTemplateTable) { + auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); + if (templateEntry.behaviorID == behaviorId) { + templateInDatabase = templateEntry; + } + } + this->m_behaviorId = behaviorId; // Add to cache @@ -423,14 +429,8 @@ Behavior::Behavior(const uint32_t behaviorId) this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; } - auto query = CDClientDatabase::CreatePreppedStmt( - "SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = ?;"); - query.bind(1, (int) behaviorId); - - auto result = query.execQuery(); - // Make sure we do not proceed if we are trying to load an invalid behavior - if (result.eof()) + if (templateInDatabase.behaviorID == 0) { Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!\n", behaviorId); @@ -441,34 +441,19 @@ Behavior::Behavior(const uint32_t behaviorId) return; } - this->m_templateId = static_cast(result.getIntField(0)); + this->m_templateId = static_cast(templateInDatabase.templateID); - this->m_effectId = result.getIntField(1); + this->m_effectId = templateInDatabase.effectID; - if (!result.fieldIsNull(2)) - { - const std::string effectHandle = result.getStringField(2); - if (effectHandle == "") - { - this->m_effectHandle = nullptr; - } - else - { - this->m_effectHandle = new std::string(effectHandle); - } - } - else - { - this->m_effectHandle = nullptr; - } - - result.finalize(); + this->m_effectHandle = templateInDatabase.effectHandle != "" ? new std::string(templateInDatabase.effectHandle) : nullptr; } float Behavior::GetFloat(const std::string& name, const float defaultValue) const { - return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue); + // Get the behavior parameter entry and return its value. + if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable("BehaviorParameter"); + return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue).value; } @@ -498,24 +483,14 @@ Behavior* Behavior::GetAction(float value) const std::map Behavior::GetParameterNames() const { - std::map parameters; - - auto query = CDClientDatabase::CreatePreppedStmt( - "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;"); - query.bind(1, (int) this->m_behaviorId); - - auto tableData = query.execQuery(); - - while (!tableData.eof()) - { - parameters.insert_or_assign(tableData.getStringField(0, ""), tableData.getFloatField(1, 0)); - - tableData.nextRow(); + std::map templatesInDatabase; + // Find behavior template by its behavior id. + if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable("BehaviorParameter"); + if (BehaviorParameterTable) { + templatesInDatabase = BehaviorParameterTable->GetParametersByBehaviorID(this->m_behaviorId); } - tableData.finalize(); - - return parameters; + return templatesInDatabase; } void Behavior::Load() diff --git a/dGame/dBehaviors/Behavior.h b/dGame/dBehaviors/Behavior.h index e8700f48..34ba469b 100644 --- a/dGame/dBehaviors/Behavior.h +++ b/dGame/dBehaviors/Behavior.h @@ -19,7 +19,7 @@ public: /* * Static */ - static std::map Cache; + static std::unordered_map Cache; static CDBehaviorParameterTable* BehaviorParameterTable; static Behavior* GetBehavior(uint32_t behaviorId);