From ac1b00fdaac6eb8a6fd8e857d7c1cb152764dbc1 Mon Sep 17 00:00:00 2001 From: wincent Date: Thu, 6 Jun 2024 09:37:24 +0200 Subject: [PATCH] Updates to upgrades --- dGame/NejlikaHooks.cpp | 8 ++ dGame/UpgradeEffect.cpp | 145 ++++++++++++++++++++++- dGame/UpgradeEffect.h | 10 ++ dGame/UpgradeTriggerCondition.h | 17 +++ dGame/UpgradeTriggerType.h | 2 + dGame/dComponents/InventoryComponent.cpp | 28 +++++ dGame/dComponents/InventoryComponent.h | 2 + 7 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 dGame/UpgradeTriggerCondition.h diff --git a/dGame/NejlikaHooks.cpp b/dGame/NejlikaHooks.cpp index 4a2e2ac5..05511a31 100644 --- a/dGame/NejlikaHooks.cpp +++ b/dGame/NejlikaHooks.cpp @@ -91,6 +91,8 @@ void nejlika::NejlikaHooks::InstallHooks() auto& upgradeTemplate = *upgradeTemplateOpt.value(); entityData.AddUpgradeItem(item->GetId()); + + entityData.TriggerUpgradeItems(UpgradeTriggerType::Equip); }; EntityManager::OnEntityCreated += [](Entity* entity) { @@ -134,6 +136,8 @@ void nejlika::NejlikaHooks::InstallHooks() additionalData.AddUpgradeItem(id); } } + + additionalData.TriggerUpgradeItems(UpgradeTriggerType::Equip); }; EntityManager::OnEntityDestroyed += [](Entity* entity) { @@ -192,6 +196,8 @@ void nejlika::NejlikaHooks::InstallHooks() auto& entityData = *entityDataOpt.value(); + entityData.TriggerUpgradeItems(UpgradeTriggerType::Equip); + entityData.ApplyToEntity(); const auto itemDataOpt = GetAdditionalItemData(item->GetId()); @@ -232,6 +238,8 @@ void nejlika::NejlikaHooks::InstallHooks() auto& entityData = *entityDataOpt.value(); + entityData.TriggerUpgradeItems(UpgradeTriggerType::UnEquip); + entityData.ApplyToEntity(); }; diff --git a/dGame/UpgradeEffect.cpp b/dGame/UpgradeEffect.cpp index ac86c60e..29a950c4 100644 --- a/dGame/UpgradeEffect.cpp +++ b/dGame/UpgradeEffect.cpp @@ -2,6 +2,7 @@ #include "GeneralUtils.h" #include "GameMessages.h" +#include "InventoryComponent.h" #include #include @@ -48,6 +49,28 @@ nlohmann::json nejlika::UpgradeEffect::ToJson() const json["effect-type"] = effectType; } + if (!conditions.empty()) { + nlohmann::json conditionsJson = nlohmann::json::array(); + + for (const auto& condition : conditions) { + conditionsJson.push_back(magic_enum::enum_name(condition)); + } + + json["conditions"] = conditionsJson; + } + + if (equipSkillID != 0) { + json["grant-skill-id"] = equipSkillID; + } + + if (equipSkillSlot != BehaviorSlot::Invalid) { + json["grant-skill-slot"] = magic_enum::enum_name(equipSkillSlot); + } + + if (unequipSkill) { + json["unequip-skill"] = true; + } + return json; } @@ -70,9 +93,11 @@ void nejlika::UpgradeEffect::Load(const nlohmann::json& json) modifiers.clear(); - for (const auto& modifier : json["modifiers"]) { - ModifierTemplate effect(modifier); - modifiers.push_back(effect); + if (json.contains("modifiers")){ + for (const auto& modifier : json["modifiers"]) { + ModifierTemplate effect(modifier); + modifiers.push_back(effect); + } } if (json.contains("chance")) { @@ -93,6 +118,26 @@ void nejlika::UpgradeEffect::Load(const nlohmann::json& json) if (json.contains("effect-type")) { effectType = json["effect-type"].get(); } + + if (json.contains("conditions")) { + conditions.clear(); + + for (const auto& condition : json["conditions"]) { + conditions.push_back(magic_enum::enum_cast(condition.get()).value_or(UpgradeTriggerCondition::None)); + } + } + + if (json.contains("grant-skill-id")) { + equipSkillID = json["grant-skill-id"].get(); + } + + if (json.contains("grant-skill-slot")) { + equipSkillSlot = magic_enum::enum_cast(json["grant-skill-slot"].get()).value_or(BehaviorSlot::Invalid); + } + + if (json.contains("unequip-skill")) { + unequipSkill = json["unequip-skill"].get(); + } } float nejlika::UpgradeEffect::CalculateChance(int32_t level) const { @@ -112,6 +157,88 @@ float nejlika::UpgradeEffect::CalculateChance(int32_t level) const { return value; } +bool nejlika::UpgradeEffect::CheckConditions(LWOOBJID origin) const { + auto* entity = Game::entityManager->GetEntity(origin); + + if (!entity) { + return false; + } + + auto* inventory = entity->GetComponent(); + + if (!inventory) { + return false; + } + + const auto& skills = inventory->GetSkills(); + const auto& equipped = inventory->GetEquippedItems(); + + for (const auto& condition : conditions) { + switch (condition) { + case UpgradeTriggerCondition::None: + break; + case UpgradeTriggerCondition::Unarmed: + if (equipped.contains("special_r")) { + return false; + } + break; + case UpgradeTriggerCondition::Melee: + if (!equipped.contains("special_r")) { + return false; + } + break; + case UpgradeTriggerCondition::TwoHanded: + { + if (!equipped.contains("special_r")) { + return false; + } + + const auto& weaponLot = equipped.at("special_r").lot; + + const auto& info = Inventory::FindItemComponent(weaponLot); + + if (!info.isTwoHanded) { + return false; + } + break; + } + case UpgradeTriggerCondition::Shield: + if (!equipped.contains("special_l")) { + return false; + } + break; + default: + break; + } + } + + return true; +} + +void nejlika::UpgradeEffect::OnTrigger(LWOOBJID origin) const { + auto* entity = Game::entityManager->GetEntity(origin); + + if (!entity) { + return; + } + + auto* inventory = entity->GetComponent(); + + if (!inventory) { + return; + } + + if (equipSkillID != 0) { + std::cout << "Granting skill: " << equipSkillID << " to entity: " << origin << " in slot: " << magic_enum::enum_name(equipSkillSlot) << std::endl; + inventory->SetSkill(equipSkillSlot, equipSkillID); + } + + if (unequipSkill) { + std::cout << "Unequipping skill from entity: " << origin << " in slot: " << magic_enum::enum_name(equipSkillSlot) << std::endl; + inventory->ResetSkill(equipSkillSlot); + } +} + std::vector nejlika::UpgradeEffect::Trigger(const std::vector& modifiers, int32_t level, UpgradeTriggerType triggerType, LWOOBJID origin) { std::vector result; @@ -120,16 +247,28 @@ std::vector nejlika::UpgradeEffect::Trigger(const std::vector< continue; } + if (!modifier.CheckConditions(origin)) { + continue; + } + float chanceRoll = GeneralUtils::GenerateRandomNumber(0, 1); if (chanceRoll > modifier.CalculateChance(level)) { continue; } + std::cout << "Triggering effect trigger type: " << magic_enum::enum_name(triggerType) << std::endl; + + modifier.OnTrigger(origin); + auto instances = modifier.GenerateModifiers(level); result.insert(result.end(), instances.begin(), instances.end()); + if (modifier.effectID == 0) { + continue; + } + GameMessages::SendPlayFXEffect( origin, modifier.effectID, diff --git a/dGame/UpgradeEffect.h b/dGame/UpgradeEffect.h index 9f03bae3..1014fa14 100644 --- a/dGame/UpgradeEffect.h +++ b/dGame/UpgradeEffect.h @@ -2,6 +2,8 @@ #include "ModifierTemplate.h" #include "UpgradeTriggerType.h" +#include "UpgradeTriggerCondition.h" +#include #include @@ -21,6 +23,10 @@ public: float CalculateChance(int32_t level) const; + bool CheckConditions(LWOOBJID origin) const; + + void OnTrigger(LWOOBJID origin) const; + static std::vector Trigger(const std::vector& modifiers, int32_t level, UpgradeTriggerType triggerType, LWOOBJID origin); // Getters @@ -37,7 +43,11 @@ private: }; std::vector chance; + std::vector conditions; UpgradeTriggerType triggerType; + int32_t equipSkillID = 0; + bool unequipSkill = false; + BehaviorSlot equipSkillSlot = BehaviorSlot::Invalid; std::vector modifiers; int32_t effectID = 0; std::string effectType = ""; diff --git a/dGame/UpgradeTriggerCondition.h b/dGame/UpgradeTriggerCondition.h new file mode 100644 index 00000000..37995628 --- /dev/null +++ b/dGame/UpgradeTriggerCondition.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace nejlika +{ + +enum class UpgradeTriggerCondition +{ + None, + Unarmed, + Melee, + TwoHanded, + Shield +}; + +} \ No newline at end of file diff --git a/dGame/UpgradeTriggerType.h b/dGame/UpgradeTriggerType.h index f4c0fbb5..88e9d5fc 100644 --- a/dGame/UpgradeTriggerType.h +++ b/dGame/UpgradeTriggerType.h @@ -8,6 +8,8 @@ namespace nejlika enum class UpgradeTriggerType { OnHit, + Equip, + UnEquip, }; } diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index cd8f255c..6d5ba33a 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1617,3 +1617,31 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) { m_Skills.insert_or_assign(slot, skillId); return true; } + +void InventoryComponent::UnsetSkill(BehaviorSlot slot) { + const auto index = m_Skills.find(slot); + if (index == m_Skills.end()) return; + const auto old = index->second; + GameMessages::SendRemoveSkill(m_Parent, old); + m_Skills.erase(slot); +} + +void InventoryComponent::ResetSkill(BehaviorSlot slot) { + const auto index = m_Skills.find(slot); + if (index == m_Skills.end()) return; + const auto old = index->second; + GameMessages::SendRemoveSkill(m_Parent, old); + m_Skills.erase(slot); + + // Loop through all equipped items and find the first item that can be equipped in the slot + for (const auto& pair : m_Equipped) { + const auto item = pair.second; + const auto info = Inventory::FindItemComponent(item.lot); + const auto behaviorSlot = FindBehaviorSlot(static_cast(info.itemType)); + + if (behaviorSlot == slot) { + SetSkill(slot, FindSkill(item.lot)); + return; + } + } +} diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 6f03d3ee..b1aecc75 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -372,6 +372,8 @@ public: bool SetSkill(int slot, uint32_t skillId); bool SetSkill(BehaviorSlot slot, uint32_t skillId); + void UnsetSkill(BehaviorSlot slot); + void ResetSkill(BehaviorSlot slot); ~InventoryComponent() override;