mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-12 19:28:21 +00:00
Added upgrades
This commit is contained in:
parent
d5b2278dc5
commit
364bcf822a
@ -7,6 +7,9 @@
|
||||
#include <InventoryComponent.h>
|
||||
#include <BaseCombatAIComponent.h>
|
||||
#include <TeamManager.h>
|
||||
#include <Item.h>
|
||||
|
||||
using namespace nejlika;
|
||||
|
||||
float nejlika::AdditionalEntityData::CalculateModifier(ModifierType type, ModifierOperator op, bool resistance) const
|
||||
{
|
||||
@ -86,9 +89,27 @@ float nejlika::AdditionalEntityData::CalculateModifier(ModifierType type, std::v
|
||||
|
||||
float multiplicative = CalculateModifier(type, additionalModifiers, ModifierOperator::Multiplicative, false);
|
||||
|
||||
std::cout << "Scaler: " << scaler << " Additive: " << additive << " Multiplicative: " << multiplicative << std::endl;
|
||||
static const std::unordered_set<ModifierType> damageTypes = {
|
||||
ModifierType::Slashing,
|
||||
ModifierType::Piercing,
|
||||
ModifierType::Bludgeoning,
|
||||
ModifierType::Fire,
|
||||
ModifierType::Cold,
|
||||
ModifierType::Lightning,
|
||||
ModifierType::Corruption,
|
||||
ModifierType::Psychic
|
||||
};
|
||||
|
||||
return (scaler + additive) * (1 + multiplicative / 100);
|
||||
if (damageTypes.contains(type)) {
|
||||
additive += CalculateModifier(ModifierType::Damage, additionalModifiers, ModifierOperator::Additive, false);
|
||||
multiplicative += CalculateModifier(ModifierType::Damage, additionalModifiers, ModifierOperator::Multiplicative, false);
|
||||
}
|
||||
|
||||
float total = (scaler + additive) * (1 + multiplicative / 100);
|
||||
|
||||
std::cout << "Scaler: " << scaler << " Additive: " << additive << " Multiplicative: " << multiplicative << " Total: " << total << std::endl;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
float nejlika::AdditionalEntityData::CalculateResistance(ModifierType type) const
|
||||
@ -96,6 +117,44 @@ float nejlika::AdditionalEntityData::CalculateResistance(ModifierType type) cons
|
||||
return CalculateModifier(type, ModifierOperator::Multiplicative, true);
|
||||
}
|
||||
|
||||
std::vector<ModifierInstance> nejlika::AdditionalEntityData::TriggerUpgradeItems(UpgradeTriggerType triggerType) {
|
||||
auto* entity = Game::entityManager->GetEntity(id);
|
||||
|
||||
if (entity == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventoryComponent == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<ModifierInstance> result;
|
||||
|
||||
for (const auto& itemID : upgradeItems) {
|
||||
auto* item = inventoryComponent->FindItemById(itemID);
|
||||
|
||||
if (item == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto upgradeDataOpt = NejlikaData::GetUpgradeTemplate(item->GetLot());
|
||||
|
||||
if (!upgradeDataOpt.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& upgradeData = *upgradeDataOpt.value();
|
||||
|
||||
const auto modifiers = upgradeData.Trigger(item->GetCount(), triggerType, id);
|
||||
|
||||
result.insert(result.end(), modifiers.begin(), modifiers.end());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void nejlika::AdditionalEntityData::RollStandardModifiers(int32_t level) {
|
||||
standardModifiers.clear();
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
#include "ModifierInstance.h"
|
||||
#include "EntityTemplate.h"
|
||||
#include "UpgradeTriggerType.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace nejlika
|
||||
{
|
||||
@ -40,6 +43,14 @@ public:
|
||||
|
||||
LOT GetLOT() const { return lot; }
|
||||
|
||||
const std::unordered_set<LWOOBJID>& GetUpgradeItems() const { return upgradeItems; }
|
||||
|
||||
void AddUpgradeItem(LWOOBJID id) { upgradeItems.insert(id); }
|
||||
|
||||
void RemoveUpgradeItem(LWOOBJID id) { upgradeItems.erase(id); }
|
||||
|
||||
std::vector<ModifierInstance> TriggerUpgradeItems(UpgradeTriggerType triggerType);
|
||||
|
||||
private:
|
||||
void RollStandardModifiers(int32_t level);
|
||||
|
||||
@ -47,6 +58,7 @@ private:
|
||||
|
||||
std::vector<ModifierInstance> standardModifiers;
|
||||
std::vector<ModifierInstance> activeModifiers;
|
||||
std::unordered_set<LWOOBJID> upgradeItems;
|
||||
|
||||
LWOOBJID id;
|
||||
LOT lot;
|
||||
|
@ -19,6 +19,8 @@ set(DGAME_SOURCES "Character.cpp"
|
||||
"EntityTemplate.cpp"
|
||||
"AdditionalEntityData.cpp"
|
||||
"NejlikaHooks.cpp"
|
||||
"UpgradeTemplate.cpp"
|
||||
"UpgradeEffect.cpp"
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
@ -3,8 +3,25 @@
|
||||
nejlika::ModifierScale::ModifierScale(const nlohmann::json & json)
|
||||
{
|
||||
level = json["level"].get<int32_t>();
|
||||
min = json["min"].get<float>();
|
||||
max = json["max"].get<float>();
|
||||
|
||||
if (json.contains("min")) {
|
||||
min = json["min"].get<float>();
|
||||
}
|
||||
else {
|
||||
min = 0.0f;
|
||||
}
|
||||
|
||||
if (json.contains("max")) {
|
||||
max = json["max"].get<float>();
|
||||
}
|
||||
else {
|
||||
max = 0.0f;
|
||||
}
|
||||
|
||||
if (json.contains("value")) {
|
||||
min = json["value"].get<float>();
|
||||
max = json["value"].get<float>();
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json nejlika::ModifierScale::ToJson() const
|
||||
|
@ -26,6 +26,8 @@ enum class ModifierType : uint8_t
|
||||
|
||||
Psychic,
|
||||
|
||||
Damage,
|
||||
|
||||
Invalid
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,8 @@ std::unordered_map<LWOOBJID, nejlika::AdditionalEntityData> additionalEntityData
|
||||
|
||||
std::unordered_map<LOT, nejlika::EntityTemplate> entityTemplates;
|
||||
|
||||
std::unordered_map<LOT, nejlika::UpgradeTemplate> upgradeTemplates;
|
||||
|
||||
}
|
||||
|
||||
const std::unordered_map<ModifierNameType,std::vector<ModifierNameTemplate>>& nejlika::NejlikaData::GetModifierNameTemplates()
|
||||
@ -69,6 +71,16 @@ const std::optional<EntityTemplate*> nejlika::NejlikaData::GetEntityTemplate(LOT
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const std::optional<UpgradeTemplate*> nejlika::NejlikaData::GetUpgradeTemplate(LOT lot) {
|
||||
const auto& it = upgradeTemplates.find(lot);
|
||||
|
||||
if (it != upgradeTemplates.end()) {
|
||||
return std::optional<UpgradeTemplate*>(&it->second);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void nejlika::NejlikaData::SetAdditionalItemData(LWOOBJID id, AdditionalItemData data) {
|
||||
additionalItemData[id] = data;
|
||||
}
|
||||
@ -147,5 +159,17 @@ void nejlika::NejlikaData::LoadNejlikaData()
|
||||
}
|
||||
|
||||
LOG("Loaded %d entity templates", entityTemplates.size());
|
||||
|
||||
if (json.contains("upgrade-templates"))
|
||||
{
|
||||
const auto& upgradeTemplatesArray = json["upgrade-templates"];
|
||||
|
||||
for (const auto& value : upgradeTemplatesArray)
|
||||
{
|
||||
auto upgradeTemplate = UpgradeTemplate(value);
|
||||
|
||||
upgradeTemplates[upgradeTemplate.GetLot()] = upgradeTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "EntityTemplate.h"
|
||||
#include "AdditionalItemData.h"
|
||||
#include "AdditionalEntityData.h"
|
||||
#include "UpgradeTemplate.h"
|
||||
|
||||
namespace nejlika::NejlikaData
|
||||
{
|
||||
@ -21,6 +22,8 @@ const std::optional<AdditionalEntityData*> GetAdditionalEntityData(LWOOBJID id);
|
||||
|
||||
const std::optional<EntityTemplate*> GetEntityTemplate(LOT lot);
|
||||
|
||||
const std::optional<UpgradeTemplate*> GetUpgradeTemplate(LOT lot);
|
||||
|
||||
void SetAdditionalItemData(LWOOBJID id, AdditionalItemData data);
|
||||
|
||||
void SetAdditionalEntityData(LWOOBJID id, AdditionalEntityData data);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <PlayerManager.h>
|
||||
#include <eGameMessageType.h>
|
||||
#include <dServer.h>
|
||||
#include <Item.h>
|
||||
|
||||
#include "NejlikaData.h"
|
||||
|
||||
@ -39,6 +40,7 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
InventoryComponent::OnItemCreated += [](InventoryComponent* component, Item* item) {
|
||||
const auto& itemType = static_cast<eItemType>(item->GetInfo().itemType);
|
||||
|
||||
/*
|
||||
static const std::unordered_set<eItemType> listOfHandledItems {
|
||||
eItemType::HAT,
|
||||
eItemType::CHEST,
|
||||
@ -51,7 +53,9 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
if (listOfHandledItems.find(itemType) == listOfHandledItems.end()) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// No to the Thinking Hat
|
||||
if (item->GetLot() == 6086) {
|
||||
return;
|
||||
}
|
||||
@ -69,6 +73,24 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
additionalData.RollModifiers(item, levelProgressionComponent->GetLevel());
|
||||
|
||||
SetAdditionalItemData(item->GetId(), additionalData);
|
||||
|
||||
auto entityDataOpt = GetAdditionalEntityData(component->GetParent()->GetObjectID());
|
||||
|
||||
if (!entityDataOpt.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& entityData = *entityDataOpt.value();
|
||||
|
||||
auto upgradeTemplateOpt = GetUpgradeTemplate(item->GetLot());
|
||||
|
||||
if (!upgradeTemplateOpt.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& upgradeTemplate = *upgradeTemplateOpt.value();
|
||||
|
||||
entityData.AddUpgradeItem(item->GetId());
|
||||
};
|
||||
|
||||
EntityManager::OnEntityCreated += [](Entity* entity) {
|
||||
@ -89,6 +111,29 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
auto& additionalData = *additionalDataOpt.value();
|
||||
|
||||
additionalData.ApplyToEntity();
|
||||
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventoryComponent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through all items and check if they are upgrade items
|
||||
const auto& inventories = inventoryComponent->GetInventories();
|
||||
|
||||
for (const auto& [type, inventory] : inventories) {
|
||||
for (const auto& [id, item] : inventory->GetItems()) {
|
||||
const auto upgradeTemplateOpt = GetUpgradeTemplate(item->GetLot());
|
||||
|
||||
if (!upgradeTemplateOpt.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& upgradeTemplate = *upgradeTemplateOpt.value();
|
||||
|
||||
additionalData.AddUpgradeItem(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EntityManager::OnEntityDestroyed += [](Entity* entity) {
|
||||
@ -101,6 +146,38 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
|
||||
InventoryComponent::OnItemDestroyed += [](InventoryComponent* component, Item* item) {
|
||||
UnsetAdditionalItemData(item->GetId());
|
||||
|
||||
auto entityDataOpt = GetAdditionalEntityData(component->GetParent()->GetObjectID());
|
||||
|
||||
if (!entityDataOpt.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& entityData = *entityDataOpt.value();
|
||||
|
||||
entityData.RemoveUpgradeItem(item->GetId());
|
||||
};
|
||||
|
||||
LevelProgressionComponent::OnLevelUp += [](LevelProgressionComponent* component) {
|
||||
auto* parent = component->GetParent();
|
||||
|
||||
auto entityDataOpt = GetAdditionalEntityData(parent->GetObjectID());
|
||||
|
||||
if (!entityDataOpt.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& entityData = *entityDataOpt.value();
|
||||
|
||||
entityData.ApplyToEntity();
|
||||
|
||||
auto* inventoryComponent = parent->GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventoryComponent) {
|
||||
return;
|
||||
}
|
||||
|
||||
inventoryComponent->AddItem(2097253, 1, eLootSourceType::LEVEL_REWARD);
|
||||
};
|
||||
|
||||
InventoryComponent::OnItemEquipped += [](InventoryComponent* component, Item* item) {
|
||||
@ -260,6 +337,11 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
modifiers.insert(modifiers.end(), skillModifiers.begin(), skillModifiers.end());
|
||||
}
|
||||
|
||||
// Upgrades
|
||||
const auto upgradeModifiers = offenderEntity.TriggerUpgradeItems(UpgradeTriggerType::OnHit);
|
||||
|
||||
modifiers.insert(modifiers.end(), upgradeModifiers.begin(), upgradeModifiers.end());
|
||||
|
||||
std::unordered_set<ModifierType> damageTypes;
|
||||
|
||||
for (const auto& modifier : modifiers) {
|
||||
@ -275,13 +357,14 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
damageTypes.insert(modifier.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the following: Offensive, Defensive, Health, Armor, Imagination
|
||||
damageTypes.erase(ModifierType::Offensive);
|
||||
damageTypes.erase(ModifierType::Defensive);
|
||||
damageTypes.erase(ModifierType::Health);
|
||||
damageTypes.erase(ModifierType::Armor);
|
||||
damageTypes.erase(ModifierType::Imagination);
|
||||
damageTypes.erase(ModifierType::Damage);
|
||||
damageTypes.erase(ModifierType::Invalid);
|
||||
|
||||
uint32_t totalDamage = 0;
|
||||
|
||||
@ -291,11 +374,12 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
// Calculate resistance, can't go below 20% of the original damage
|
||||
const auto resistance = std::max(1 - (damagedEntity.CalculateResistance(type) / 100), 0.2f);
|
||||
|
||||
damageValue *= resistance;
|
||||
float reductedDamage = damageValue * resistance;
|
||||
|
||||
totalDamage += static_cast<uint32_t>(damageValue);
|
||||
totalDamage += static_cast<uint32_t>(reductedDamage);
|
||||
|
||||
std::cout << "Damage type: " << magic_enum::enum_name(type) << " - " << damageValue << std::endl << " Resistance: " << resistance << std::endl;
|
||||
std::cout << "Damage type: " << magic_enum::enum_name(type) << " - " << damageValue << std::endl;
|
||||
std::cout << "Resistance: " << resistance << " - " << reductedDamage << std::endl;
|
||||
std::cout << "Heath left: " << damaged->GetComponent<DestroyableComponent>()->GetHealth() << std::endl;
|
||||
}
|
||||
|
||||
@ -325,12 +409,23 @@ void nejlika::NejlikaHooks::InstallHooks()
|
||||
roll = std::min(roll, 5.0f);
|
||||
totalDamage += static_cast<uint32_t>(totalDamage * roll);
|
||||
|
||||
const auto effectName = std::to_string(GeneralUtils::GenerateRandomNumber<uint32_t>());
|
||||
const auto damagedID = damaged->GetObjectID();
|
||||
|
||||
GameMessages::SendPlayFXEffect(
|
||||
damaged->GetObjectID(),
|
||||
20041,
|
||||
u"onhit",
|
||||
std::to_string(GeneralUtils::GenerateRandomNumber<uint32_t>())
|
||||
damagedID,
|
||||
1531,
|
||||
u"create",
|
||||
effectName
|
||||
);
|
||||
|
||||
damaged->AddCallbackTimer(0.5f, [damaged, effectName] () {
|
||||
GameMessages::SendStopFXEffect(
|
||||
damaged,
|
||||
true,
|
||||
effectName
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Add a random +10% to the damage
|
||||
|
142
dGame/UpgradeEffect.cpp
Normal file
142
dGame/UpgradeEffect.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#include "UpgradeEffect.h"
|
||||
|
||||
#include "GeneralUtils.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace nejlika;
|
||||
|
||||
nejlika::UpgradeEffect::UpgradeEffect(const nlohmann::json& json)
|
||||
{
|
||||
Load(json);
|
||||
}
|
||||
|
||||
nlohmann::json nejlika::UpgradeEffect::ToJson() const
|
||||
{
|
||||
nlohmann::json json;
|
||||
|
||||
json["trigger-type"] = static_cast<int32_t>(triggerType);
|
||||
|
||||
nlohmann::json modifiersJson = nlohmann::json::array();
|
||||
|
||||
for (const auto& modifier : modifiers) {
|
||||
modifiersJson.push_back(modifier.ToJson());
|
||||
}
|
||||
|
||||
json["modifiers"] = modifiersJson;
|
||||
|
||||
if (!chance.empty()) {
|
||||
nlohmann::json chanceJson = nlohmann::json::array();
|
||||
|
||||
for (const auto& scale : chance) {
|
||||
chanceJson.push_back({
|
||||
{"level", scale.level},
|
||||
{"value", scale.value}
|
||||
});
|
||||
}
|
||||
|
||||
json["chance"] = chanceJson;
|
||||
}
|
||||
|
||||
if (effectID != 0) {
|
||||
json["effect-id"] = effectID;
|
||||
}
|
||||
|
||||
if (!effectType.empty()) {
|
||||
json["effect-type"] = effectType;
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
std::vector<ModifierInstance> nejlika::UpgradeEffect::GenerateModifiers(int32_t level) const
|
||||
{
|
||||
std::vector<ModifierInstance> result;
|
||||
|
||||
for (const auto& modifier : modifiers) {
|
||||
auto instances = modifier.GenerateModifiers(level);
|
||||
|
||||
result.insert(result.end(), instances.begin(), instances.end());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void nejlika::UpgradeEffect::Load(const nlohmann::json& json)
|
||||
{
|
||||
triggerType = magic_enum::enum_cast<UpgradeTriggerType>(json["trigger-type"].get<std::string>()).value_or(UpgradeTriggerType::OnHit);
|
||||
|
||||
modifiers.clear();
|
||||
|
||||
for (const auto& modifier : json["modifiers"]) {
|
||||
ModifierTemplate effect(modifier);
|
||||
modifiers.push_back(effect);
|
||||
}
|
||||
|
||||
if (json.contains("chance")) {
|
||||
chance.clear();
|
||||
|
||||
for (const auto& scale : json["chance"]) {
|
||||
chance.push_back({
|
||||
scale["level"].get<int32_t>(),
|
||||
scale["value"].get<float>()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (json.contains("effect-id")) {
|
||||
effectID = json["effect-id"].get<int32_t>();
|
||||
}
|
||||
|
||||
if (json.contains("effect-type")) {
|
||||
effectType = json["effect-type"].get<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
float nejlika::UpgradeEffect::CalculateChance(int32_t level) const {
|
||||
if (chance.empty()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find the highest level that is less than or equal to the given level
|
||||
float value = 0;
|
||||
|
||||
for (const auto& scale : chance) {
|
||||
if (scale.level <= level) {
|
||||
value = scale.value;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<ModifierInstance> nejlika::UpgradeEffect::Trigger(const std::vector<UpgradeEffect>& modifiers, int32_t level, UpgradeTriggerType triggerType, LWOOBJID origin) {
|
||||
std::vector<ModifierInstance> result;
|
||||
|
||||
for (const auto& modifier : modifiers) {
|
||||
if (modifier.GetTriggerType() != triggerType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float chanceRoll = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
|
||||
if (chanceRoll > modifier.CalculateChance(level)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto instances = modifier.GenerateModifiers(level);
|
||||
|
||||
result.insert(result.end(), instances.begin(), instances.end());
|
||||
|
||||
GameMessages::SendPlayFXEffect(
|
||||
origin,
|
||||
modifier.effectID,
|
||||
GeneralUtils::UTF8ToUTF16(modifier.effectType),
|
||||
std::to_string(GeneralUtils::GenerateRandomNumber<size_t>())
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
46
dGame/UpgradeEffect.h
Normal file
46
dGame/UpgradeEffect.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "ModifierTemplate.h"
|
||||
#include "UpgradeTriggerType.h"
|
||||
|
||||
#include <dCommonVars.h>
|
||||
|
||||
namespace nejlika
|
||||
{
|
||||
|
||||
class UpgradeEffect
|
||||
{
|
||||
public:
|
||||
UpgradeEffect(const nlohmann::json& json);
|
||||
|
||||
nlohmann::json ToJson() const;
|
||||
|
||||
std::vector<ModifierInstance> GenerateModifiers(int32_t level) const;
|
||||
|
||||
void Load(const nlohmann::json& json);
|
||||
|
||||
float CalculateChance(int32_t level) const;
|
||||
|
||||
static std::vector<ModifierInstance> Trigger(const std::vector<UpgradeEffect>& modifiers, int32_t level, UpgradeTriggerType triggerType, LWOOBJID origin);
|
||||
|
||||
// Getters
|
||||
|
||||
const std::vector<ModifierTemplate>& GetModifiers() const { return modifiers; }
|
||||
|
||||
UpgradeTriggerType GetTriggerType() const { return triggerType; }
|
||||
|
||||
private:
|
||||
struct UpgradeScale
|
||||
{
|
||||
int32_t level;
|
||||
float value;
|
||||
};
|
||||
|
||||
std::vector<UpgradeScale> chance;
|
||||
UpgradeTriggerType triggerType;
|
||||
std::vector<ModifierTemplate> modifiers;
|
||||
int32_t effectID = 0;
|
||||
std::string effectType = "";
|
||||
};
|
||||
|
||||
}
|
49
dGame/UpgradeTemplate.cpp
Normal file
49
dGame/UpgradeTemplate.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "UpgradeTemplate.h"
|
||||
|
||||
using namespace nejlika;
|
||||
|
||||
nejlika::UpgradeTemplate::UpgradeTemplate(const nlohmann::json& json)
|
||||
{
|
||||
Load(json);
|
||||
}
|
||||
|
||||
nlohmann::json nejlika::UpgradeTemplate::ToJson() const
|
||||
{
|
||||
nlohmann::json json;
|
||||
|
||||
json["name"] = name;
|
||||
json["lot"] = lot;
|
||||
json["max-level"] = maxLevel;
|
||||
|
||||
nlohmann::json passivesJson = nlohmann::json::array();
|
||||
|
||||
for (const auto& passive : passives) {
|
||||
passivesJson.push_back(passive.ToJson());
|
||||
}
|
||||
|
||||
json["passives"] = passivesJson;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
void nejlika::UpgradeTemplate::Load(const nlohmann::json& json)
|
||||
{
|
||||
name = json["name"].get<std::string>();
|
||||
lot = json["lot"].get<int32_t>();
|
||||
maxLevel = json["max-level"].contains("max-level") ? json["max-level"].get<int32_t>() : 1;
|
||||
|
||||
passives.clear();
|
||||
|
||||
for (const auto& passive : json["passives"]) {
|
||||
UpgradeEffect effect(passive);
|
||||
passives.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ModifierInstance> nejlika::UpgradeTemplate::Trigger(int32_t level, UpgradeTriggerType triggerType, LWOOBJID origin) const {
|
||||
level = std::min(level, maxLevel);
|
||||
|
||||
return UpgradeEffect::Trigger(passives, level, triggerType, origin);
|
||||
}
|
||||
|
||||
|
40
dGame/UpgradeTemplate.h
Normal file
40
dGame/UpgradeTemplate.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
#include "UpgradeEffect.h"
|
||||
|
||||
namespace nejlika
|
||||
{
|
||||
|
||||
class UpgradeTemplate
|
||||
{
|
||||
public:
|
||||
UpgradeTemplate() = default;
|
||||
|
||||
UpgradeTemplate(const nlohmann::json& json);
|
||||
|
||||
nlohmann::json ToJson() const;
|
||||
|
||||
void Load(const nlohmann::json& json);
|
||||
|
||||
const std::string& GetName() const { return name; }
|
||||
int32_t GetLot() const { return lot; }
|
||||
int32_t GetMaxLevel() const { return maxLevel; }
|
||||
const std::vector<UpgradeEffect>& GetPassives() const { return passives; }
|
||||
|
||||
std::vector<ModifierInstance> Trigger(int32_t level, UpgradeTriggerType triggerType, LWOOBJID origin) const;
|
||||
|
||||
private:
|
||||
std::string name = "";
|
||||
int32_t lot = 0;
|
||||
int32_t maxLevel = 0;
|
||||
std::vector<UpgradeEffect> passives;
|
||||
|
||||
};
|
||||
|
||||
}
|
13
dGame/UpgradeTriggerType.h
Normal file
13
dGame/UpgradeTriggerType.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace nejlika
|
||||
{
|
||||
|
||||
enum class UpgradeTriggerType
|
||||
{
|
||||
OnHit,
|
||||
};
|
||||
|
||||
}
|
@ -24,7 +24,13 @@ void HealBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit_strea
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->Heal(this->m_health);
|
||||
auto maxHealth = destroyable->GetMaxHealth();
|
||||
|
||||
// 1 health is 5% of the max health, minimum of 5 health
|
||||
auto health = static_cast<int32_t>(maxHealth * 0.05f) * this->m_health;
|
||||
health = std::max(5u, health);
|
||||
|
||||
destroyable->Heal(health);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "CDRewardsTable.h"
|
||||
|
||||
Observable<LevelProgressionComponent*> LevelProgressionComponent::OnLevelUp;
|
||||
|
||||
LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component(parent) {
|
||||
m_Parent = parent;
|
||||
m_Level = 1;
|
||||
@ -80,6 +82,8 @@ void LevelProgressionComponent::HandleLevelUp() {
|
||||
}
|
||||
// Tell the client we have finished sending level rewards.
|
||||
if (rewardingItem) GameMessages::NotifyLevelRewards(m_Parent->GetObjectID(), m_Parent->GetSystemAddress(), m_Level, !rewardingItem);
|
||||
|
||||
OnLevelUp(this);
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::SetRetroactiveBaseSpeed(){
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Component.h"
|
||||
#include "eCharacterVersion.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "Observable.h"
|
||||
|
||||
/**
|
||||
* Component that handles level progression and serilization.
|
||||
@ -81,6 +82,8 @@ public:
|
||||
*/
|
||||
void SetRetroactiveBaseSpeed();
|
||||
|
||||
static Observable<LevelProgressionComponent*> OnLevelUp;
|
||||
|
||||
private:
|
||||
/**
|
||||
* whether the level is dirty
|
||||
|
@ -973,7 +973,7 @@ void GameMessages::SendResurrect(Entity* entity) {
|
||||
if (levelComponent) {
|
||||
int32_t healthToRestore = levelComponent->GetLevel() >= 45 ? 8 : 4;
|
||||
if (healthToRestore > destroyableComponent->GetMaxHealth()) healthToRestore = destroyableComponent->GetMaxHealth();
|
||||
destroyableComponent->SetHealth(healthToRestore);
|
||||
destroyableComponent->SetHealth(destroyableComponent->GetMaxHealth());
|
||||
|
||||
int32_t imaginationToRestore = levelComponent->GetLevel() >= 45 ? 20 : 6;
|
||||
if (imaginationToRestore > destroyableComponent->GetMaxImagination()) imaginationToRestore = destroyableComponent->GetMaxImagination();
|
||||
|
Loading…
Reference in New Issue
Block a user