From d29287f9d9da1003deff3207c9d008a8f49836cd Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Mon, 26 Jun 2023 01:49:56 -0700 Subject: [PATCH] Buff Component fixes --- dGame/dComponents/BuffComponent.cpp | 109 +++++++++++----------------- dGame/dComponents/BuffComponent.h | 14 ++-- 2 files changed, 52 insertions(+), 71 deletions(-) diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index 92b33efb..3c80b990 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -16,12 +16,10 @@ std::unordered_map> BuffComponent::m_Cache{} void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { if (!bIsInitialUpdate) return; - if (m_Buffs.empty()) { - outBitStream->Write0(); - } else { - outBitStream->Write1(); - outBitStream->Write(m_Buffs.size()); + outBitStream->Write(!m_Buffs.empty()); + if (!m_Buffs.empty()) { + outBitStream->Write(m_Buffs.size()); for (const auto& buff : m_Buffs) { outBitStream->Write(buff.first); outBitStream->Write0(); @@ -41,7 +39,7 @@ void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUp } } - outBitStream->Write0(); + outBitStream->Write0(); // immunities } void BuffComponent::Update(float deltaTime) { @@ -49,30 +47,28 @@ void BuffComponent::Update(float deltaTime) { * Loop through all buffs and apply deltaTime to ther time. * If they have expired, remove the buff and break. */ - for (auto& buff : m_Buffs) { + for (auto& [buffId, buffInfo] : m_Buffs) { // For damage buffs - if (buff.second.tick != 0.0f && buff.second.stacks > 0) { - buff.second.tickTime -= deltaTime; + if (buffInfo.tick != 0.0f && buffInfo.stacks > 0) { + buffInfo.tickTime -= deltaTime; - if (buff.second.tickTime <= 0.0f) { - buff.second.tickTime = buff.second.tick; - buff.second.stacks--; + if (buffInfo.tickTime <= 0.0f) { + buffInfo.tickTime = buffInfo.tick; + buffInfo.stacks--; - SkillComponent::HandleUnmanaged(buff.second.behaviorID, m_ParentEntity->GetObjectID(), buff.second.source); + SkillComponent::HandleUnmanaged(buffInfo.behaviorID, m_ParentEntity->GetObjectID(), buffInfo.source); } } // These are indefinate buffs, don't update them. - if (buff.second.time == 0.0f) { - continue; - } + if (buffInfo.time == 0.0f) continue; - buff.second.time -= deltaTime; + buffInfo.time -= deltaTime; - if (buff.second.time <= 0.0f) { - RemoveBuff(buff.first); + if (buffInfo.time <= 0.0f) { + RemoveBuff(buffId); - break; + break; // Break because we modified or may modify the map. } } } @@ -81,9 +77,7 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO bool cancelOnDamaged, bool cancelOnDeath, bool cancelOnLogout, bool cancelOnRemoveBuff, bool cancelOnUi, bool cancelOnUnequip, bool cancelOnZone) { // Prevent buffs from stacking. - if (HasBuff(id)) { - return; - } + if (HasBuff(id)) return; GameMessages::SendAddBuff(m_ParentEntity->GetObjectID(), source, (uint32_t)id, (uint32_t)duration * 1000, addImmunity, cancelOnDamaged, cancelOnDeath, @@ -94,14 +88,14 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO int32_t behaviorID = 0; const auto& parameters = GetBuffParameters(id); + auto* skillBehaviorTable = CDClientManager::Instance().GetTable(); for (const auto& parameter : parameters) { if (parameter.name == "overtime") { - auto* behaviorTemplateTable = CDClientManager::Instance().GetTable(); - behaviorID = behaviorTemplateTable->GetSkillByID(parameter.values[0]).behaviorID; - stacks = static_cast(parameter.values[1]); - tick = parameter.values[2]; - const auto unknown2 = parameter.values[3]; // Always 0 + behaviorID = skillBehaviorTable->GetSkillByID(parameter.values.skillId).behaviorID; + stacks = static_cast(parameter.values.stacks); + tick = parameter.values.tick; + const auto unknown2 = parameter.values.unknown2; // Always 0 } } @@ -116,15 +110,13 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO buff.source = source; buff.behaviorID = behaviorID; - m_Buffs.emplace(id, buff); + m_Buffs.insert_or_assign(id, buff); } void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity) { const auto& iter = m_Buffs.find(id); - if (iter == m_Buffs.end()) { - return; - } + if (iter == m_Buffs.end()) return; GameMessages::SendRemoveBuff(m_ParentEntity, fromUnEquip, removeImmunity, id); @@ -181,7 +173,7 @@ void BuffComponent::RemoveBuffEffect(int32_t id) { auto* destroyable = this->GetParentEntity()->GetComponent(); - if (destroyable == nullptr) return; + if (!destroyable) return; destroyable->SetMaxHealth(destroyable->GetMaxHealth() - maxHealth); } else if (parameter.name == "max_armor") { @@ -189,7 +181,7 @@ void BuffComponent::RemoveBuffEffect(int32_t id) { auto* destroyable = this->GetParentEntity()->GetComponent(); - if (destroyable == nullptr) return; + if (!destroyable) return; destroyable->SetMaxArmor(destroyable->GetMaxArmor() - maxArmor); } else if (parameter.name == "max_imagination") { @@ -197,7 +189,7 @@ void BuffComponent::RemoveBuffEffect(int32_t id) { auto* destroyable = this->GetParentEntity()->GetComponent(); - if (destroyable == nullptr) return; + if (!destroyable) return; destroyable->SetMaxImagination(destroyable->GetMaxImagination() - maxImagination); } else if (parameter.name == "speed") { @@ -210,27 +202,19 @@ void BuffComponent::RemoveBuffEffect(int32_t id) { } void BuffComponent::RemoveAllBuffs() { - for (const auto& buff : m_Buffs) { - RemoveBuffEffect(buff.first); + for (const auto& [buffId, buffInfo] : m_Buffs) { + RemoveBuffEffect(buffId); } m_Buffs.clear(); } -void BuffComponent::Reset() { - RemoveAllBuffs(); -} - void BuffComponent::ReApplyBuffs() { - for (const auto& buff : m_Buffs) { - ApplyBuffEffect(buff.first); + for (const auto& [buffId, buffInfo] : m_Buffs) { + ApplyBuffEffect(buffId); } } -Entity* BuffComponent::GetParentEntity() const { - return m_ParentEntity; -} - void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { // Load buffs auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest"); @@ -239,9 +223,7 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { auto* buffElement = dest->FirstChildElement("buff"); // Old character, no buffs to load - if (buffElement == nullptr) { - return; - } + if (buffElement) return; auto* buffEntry = buffElement->FirstChildElement("b"); @@ -299,12 +281,9 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) { const std::vector& BuffComponent::GetBuffParameters(int32_t buffId) { const auto& pair = m_Cache.find(buffId); - if (pair != m_Cache.end()) { - return pair->second; - } + if (pair != m_Cache.end()) return pair->second; - auto query = CDClientDatabase::CreatePreppedStmt( - "SELECT * FROM BuffParameters WHERE BuffID = ?;"); + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM BuffParameters WHERE BuffID = ?;"); query.bind(1, (int)buffId); auto result = query.execQuery(); @@ -319,17 +298,15 @@ const std::vector& BuffComponent::GetBuffParameters(int32_t buffI param.value = result.getFloatField(2); if (!result.fieldIsNull(3)) { - std::istringstream stream(result.getStringField(3)); - std::string token; - - while (std::getline(stream, token, ',')) { - try { - const auto value = std::stof(token); - - param.values.push_back(value); - } catch (std::invalid_argument& exception) { - Game::logger->Log("BuffComponent", "Failed to parse value (%s): (%s)!", token.c_str(), exception.what()); - } + const auto parameterInfo = result.getStringField(3); + const auto values = GeneralUtils::SplitString(parameterInfo, ','); + if (values.size() >= 4) { + GeneralUtils::TryParse(values.at(0), param.values.skillId); + GeneralUtils::TryParse(values.at(1), param.values.stacks); + GeneralUtils::TryParse(values.at(2), param.values.tick); + GeneralUtils::TryParse(values.at(3), param.values.unknown2); + } else { + Game::logger->Log("BuffComponent", "Failed to parse %s into parameter struct. Too few parameters to split on.", parameterInfo); } } diff --git a/dGame/dComponents/BuffComponent.h b/dGame/dComponents/BuffComponent.h index 5c4bd168..0219e0ff 100644 --- a/dGame/dComponents/BuffComponent.h +++ b/dGame/dComponents/BuffComponent.h @@ -15,10 +15,16 @@ class Entity; * Extra information on effects to apply after applying a buff, for example whether to buff armor, imag or health and by how much */ struct BuffParameter { + struct ParameterValues { + int32_t skillId = 0; + int32_t stacks = 0; + float tick = 0.0f; + int32_t unknown2 = 0; + }; int32_t buffId = 0; std::string name; float value = 0.0f; - std::vector values; + ParameterValues values; int32_t effectId = 0; }; @@ -42,9 +48,7 @@ class BuffComponent final : public Component { public: inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF; - explicit BuffComponent(Entity* parent) : Component(parent) { }; - - Entity* GetParentEntity() const; + explicit BuffComponent(Entity* parent) : Component(parent) {}; void LoadFromXml(tinyxml2::XMLDocument* doc) override; @@ -106,7 +110,7 @@ public: /** * Removes all buffs for the entity and reverses all of their effects */ - void Reset(); + void Reset() { RemoveAllBuffs(); }; /** * Applies all effects for all buffs, active or not, again