Stat & equipment definition continued (WIP)
This commit is contained in:
parent
415e29576b
commit
7f0d4ec7f3
@ -118,7 +118,7 @@ namespace Kryz.CharacterStats
|
||||
public class CharacterStat
|
||||
{
|
||||
public GameTag statTag;
|
||||
public CharacterStatType statType;
|
||||
public StatDefinition statDefinition;
|
||||
|
||||
public float BaseValue;
|
||||
|
||||
|
||||
@ -1,197 +1,252 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using Kryz.CharacterStats;
|
||||
|
||||
namespace Kryz.CharacterStats.Examples
|
||||
{
|
||||
|
||||
public class CharacterStats : MonoBehaviour
|
||||
{
|
||||
[Header("---------------------------------------------------------------------------------------------")]
|
||||
[Header("Primary Stats:")]
|
||||
public CharacterStat Cunning;
|
||||
public CharacterStat Flow;
|
||||
public CharacterStat Presence;
|
||||
[Header("Runtime Stats (Auto-Generated)")]
|
||||
[SerializeField] private bool showDebugStats = false;
|
||||
|
||||
//Secondary
|
||||
[Space]
|
||||
[Header("---------------------------------------------------------------------------------------------")]
|
||||
[Header("Offensive Stats:")]
|
||||
[Space]
|
||||
public CharacterStat AttackDamage;
|
||||
public CharacterStat SpellDamage;
|
||||
|
||||
public CharacterStat AttackSpeed;
|
||||
|
||||
|
||||
public CharacterStat CritChance;
|
||||
public CharacterStat CritDamage;
|
||||
|
||||
public CharacterStat AuraPower;
|
||||
|
||||
[Space]
|
||||
[Header("---------------------------------------------------------------------------------------------")]
|
||||
[Header("Resource Stats:")]
|
||||
[Space]
|
||||
public CharacterStat MaxHealth;
|
||||
public CharacterStat HealthRegen;
|
||||
public CharacterStat MaxMana;
|
||||
public CharacterStat ManaRegen;
|
||||
|
||||
[Space]
|
||||
[Header("---------------------------------------------------------------------------------------------")]
|
||||
[Header("Defensive Stats:")]
|
||||
[Space]
|
||||
public CharacterStat Armor;
|
||||
public CharacterStat MagicResistance;
|
||||
public CharacterStat DodgeChance;
|
||||
public CharacterStat BlockChance;
|
||||
public CharacterStat BlockEffectiveness;
|
||||
|
||||
[Space]
|
||||
[Header("---------------------------------------------------------------------------------------------")]
|
||||
[Header("Misc Stats:")]
|
||||
[Space]
|
||||
public CharacterStat AreaEffectiveness;
|
||||
public CharacterStat CooldownReduction;
|
||||
public CharacterStat MovementSpeed;
|
||||
public CharacterStat ReputationGainIncrease;
|
||||
public CharacterStat GoldCostReduction;
|
||||
|
||||
|
||||
//Awakening Related
|
||||
//public CharacterStat
|
||||
// Main stats dictionary - all stats live here
|
||||
private Dictionary<string, CharacterStat> allStats = new Dictionary<string, CharacterStat>();
|
||||
|
||||
// Compatibility dictionaries for existing systems
|
||||
public Dictionary<string, CharacterStat> primaryStatsDictionary = new Dictionary<string, CharacterStat>();
|
||||
public Dictionary<string, CharacterStat> secondaryStatsDictionary = new Dictionary<string, CharacterStat>();
|
||||
|
||||
// Events
|
||||
public UnityEvent onUpdateStatValues = new UnityEvent();
|
||||
public UnityEvent onAllStatsUpdated = new UnityEvent();
|
||||
|
||||
// Quick access properties for primary stats (for compatibility)
|
||||
public CharacterStat Cunning => GetStat("cunning");
|
||||
public CharacterStat Flow => GetStat("flow");
|
||||
public CharacterStat Presence => GetStat("presence");
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Cunning.statType = CharacterStatType.Cunning;
|
||||
Flow.statType = CharacterStatType.Flow;
|
||||
Presence.statType = CharacterStatType.Presence;
|
||||
|
||||
AttackDamage.statType = CharacterStatType.AttackDamage;
|
||||
SpellDamage.statType = CharacterStatType.SpellDamage;
|
||||
AttackSpeed.statType = CharacterStatType.AttackSpeed;
|
||||
CritChance.statType = CharacterStatType.CritChance;
|
||||
CritDamage.statType = CharacterStatType.CritDamage;
|
||||
AuraPower.statType = CharacterStatType.AuraPower;
|
||||
|
||||
MaxHealth.statType = CharacterStatType.MaxHealth;
|
||||
HealthRegen.statType = CharacterStatType.HealthRegen;
|
||||
MaxMana.statType = CharacterStatType.MaxMana;
|
||||
ManaRegen.statType = CharacterStatType.ManaRegen;
|
||||
|
||||
Armor.statType = CharacterStatType.Armor;
|
||||
MagicResistance.statType = CharacterStatType.MagicResistance;
|
||||
DodgeChance.statType = CharacterStatType.DodgeChance;
|
||||
BlockChance.statType = CharacterStatType.BlockChance;
|
||||
BlockEffectiveness.statType = CharacterStatType.BlockEffectiveness;
|
||||
|
||||
AreaEffectiveness.statType = CharacterStatType.AreaEffectiveness;
|
||||
CooldownReduction.statType = CharacterStatType.CooldownReduction;
|
||||
MovementSpeed.statType = CharacterStatType.MovementSpeed;
|
||||
|
||||
ReputationGainIncrease.statType = CharacterStatType.ReputationGainIncrease;
|
||||
GoldCostReduction.statType = CharacterStatType.GoldCostReduction;
|
||||
|
||||
|
||||
primaryStatsDictionary.Add(nameof(Cunning).ToLower(), Cunning);
|
||||
primaryStatsDictionary.Add(nameof(Flow).ToLower(), Flow);
|
||||
primaryStatsDictionary.Add(nameof(Presence).ToLower(), Presence);
|
||||
|
||||
|
||||
|
||||
secondaryStatsDictionary.Add(nameof(AttackDamage).ToLower(), AttackDamage);
|
||||
secondaryStatsDictionary.Add(nameof(SpellDamage).ToLower(), SpellDamage);
|
||||
secondaryStatsDictionary.Add(nameof(AttackSpeed).ToLower(), AttackSpeed);
|
||||
|
||||
secondaryStatsDictionary.Add(nameof(CritChance).ToLower(), CritChance);
|
||||
secondaryStatsDictionary.Add(nameof(CritDamage).ToLower(), CritDamage);
|
||||
secondaryStatsDictionary.Add(nameof(AuraPower).ToLower(), AuraPower);
|
||||
|
||||
secondaryStatsDictionary.Add(nameof(HealthRegen).ToLower(), HealthRegen);
|
||||
secondaryStatsDictionary.Add(nameof(ManaRegen).ToLower(), ManaRegen);
|
||||
secondaryStatsDictionary.Add(nameof(MaxHealth).ToLower(), MaxHealth);
|
||||
secondaryStatsDictionary.Add(nameof(MaxMana).ToLower(), MaxMana);
|
||||
|
||||
secondaryStatsDictionary.Add(nameof(Armor).ToLower(), Armor);
|
||||
secondaryStatsDictionary.Add(nameof(MagicResistance).ToLower(), MagicResistance);
|
||||
secondaryStatsDictionary.Add(nameof(DodgeChance).ToLower(), DodgeChance);
|
||||
secondaryStatsDictionary.Add(nameof(BlockChance).ToLower(), BlockChance);
|
||||
secondaryStatsDictionary.Add(nameof(BlockEffectiveness).ToLower(), BlockEffectiveness);
|
||||
|
||||
secondaryStatsDictionary.Add(nameof(AreaEffectiveness).ToLower(), AreaEffectiveness);
|
||||
secondaryStatsDictionary.Add(nameof(CooldownReduction).ToLower(), CooldownReduction);
|
||||
secondaryStatsDictionary.Add(nameof(MovementSpeed).ToLower(), MovementSpeed);
|
||||
secondaryStatsDictionary.Add(nameof(ReputationGainIncrease).ToLower(), ReputationGainIncrease);
|
||||
secondaryStatsDictionary.Add(nameof(GoldCostReduction).ToLower(), GoldCostReduction);
|
||||
|
||||
InitializeStatsFromRegistry();
|
||||
onUpdateStatValues.AddListener(UpdateSecondaryStatsBasedOnPrimaryStats);
|
||||
}
|
||||
|
||||
private void InitializeStatsFromRegistry()
|
||||
{
|
||||
// Clear existing stats
|
||||
allStats.Clear();
|
||||
primaryStatsDictionary.Clear();
|
||||
secondaryStatsDictionary.Clear();
|
||||
|
||||
// Get all stat definitions from registry
|
||||
var statDefinitions = StatRegistry.Instance.GetAllStats();
|
||||
|
||||
if (statDefinitions.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"CharacterStats on {gameObject.name}: No stat definitions found in StatRegistry!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create CharacterStat for each definition
|
||||
foreach (var statDef in statDefinitions)
|
||||
{
|
||||
var characterStat = new CharacterStat(statDef.DefaultBaseValue);
|
||||
characterStat.statDefinition = statDef; // Store reference to definition
|
||||
|
||||
allStats[statDef.StatKey] = characterStat;
|
||||
|
||||
// Populate compatibility dictionaries
|
||||
string lowerKey = statDef.StatKey.ToLower();
|
||||
if (statDef.IsPrimary)
|
||||
{
|
||||
primaryStatsDictionary[lowerKey] = characterStat;
|
||||
}
|
||||
else
|
||||
{
|
||||
secondaryStatsDictionary[lowerKey] = characterStat;
|
||||
}
|
||||
|
||||
if (showDebugStats)
|
||||
{
|
||||
Debug.Log($"Initialized stat: {statDef.StatKey} (Base: {statDef.DefaultBaseValue}, Category: {statDef.Category})");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"CharacterStats on {gameObject.name}: Initialized {allStats.Count} stats");
|
||||
}
|
||||
|
||||
// Main stat access method
|
||||
public CharacterStat GetStat(string statKey)
|
||||
{
|
||||
if (allStats.TryGetValue(statKey, out CharacterStat stat))
|
||||
{
|
||||
return stat;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"CharacterStats: Stat '{statKey}' not found!");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Safe stat access that won't return null
|
||||
public CharacterStat GetStatSafe(string statKey)
|
||||
{
|
||||
var stat = GetStat(statKey);
|
||||
if (stat == null)
|
||||
{
|
||||
// Return a dummy stat to prevent null reference exceptions
|
||||
return new CharacterStat(0f);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
// Get stats by category
|
||||
public CharacterStat[] GetStatsByCategory(StatCategory category)
|
||||
{
|
||||
return allStats.Values
|
||||
.Where(stat => stat.statDefinition.Category == category)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
// Get all primary stats
|
||||
public CharacterStat[] GetPrimaryStats()
|
||||
{
|
||||
return allStats.Values
|
||||
.Where(stat => stat.statDefinition.IsPrimary)
|
||||
.ToArray();
|
||||
}
|
||||
public CharacterStat[] GetAllStats()
|
||||
{
|
||||
return allStats.Values.ToArray();
|
||||
}
|
||||
|
||||
// Get all UI-visible stats
|
||||
public CharacterStat[] GetUIVisibleStats()
|
||||
{
|
||||
return allStats.Values
|
||||
.Where(stat => stat.statDefinition.ShowInUI)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public void IncreaseAllStatPoints(int amount)
|
||||
{
|
||||
|
||||
onUpdateStatValues.Invoke();
|
||||
}
|
||||
|
||||
public void UpdateSecondaryStatsBasedOnPrimaryStats()
|
||||
{
|
||||
//Remove previous
|
||||
CritChance.RemoveAllModifiersFromSource(GameConstants.ObjectSources.CunningSource);
|
||||
CritDamage.RemoveAllModifiersFromSource(GameConstants.ObjectSources.CunningSource);
|
||||
MovementSpeed.RemoveAllModifiersFromSource(GameConstants.ObjectSources.CunningSource);
|
||||
// Get primary stats
|
||||
var cunning = GetStat("cunning");
|
||||
var flow = GetStat("flow");
|
||||
var presence = GetStat("presence");
|
||||
|
||||
//HealthRegen.RemoveAllModifiersFromSource(GameConstants.ObjectSources.FlowSource);
|
||||
MaxMana.RemoveAllModifiersFromSource(GameConstants.ObjectSources.FlowSource);
|
||||
ManaRegen.RemoveAllModifiersFromSource(GameConstants.ObjectSources.FlowSource);
|
||||
CooldownReduction.RemoveAllModifiersFromSource(GameConstants.ObjectSources.FlowSource);
|
||||
AttackSpeed.RemoveAllModifiersFromSource(GameConstants.ObjectSources.FlowSource);
|
||||
//ResourceCostReduction.RemoveAllModifiersFromSource(GameConstants.ObjectSources.FlowSource);
|
||||
if (cunning == null || flow == null || presence == null)
|
||||
{
|
||||
Debug.LogError("CharacterStats: Primary stats not found! Make sure cunning, flow, and presence StatDefinitions exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
AreaEffectiveness.RemoveAllModifiersFromSource(GameConstants.ObjectSources.PresenceSource);
|
||||
ReputationGainIncrease.RemoveAllModifiersFromSource(GameConstants.ObjectSources.PresenceSource);
|
||||
GoldCostReduction.RemoveAllModifiersFromSource(GameConstants.ObjectSources.PresenceSource);
|
||||
AuraPower.RemoveAllModifiersFromSource(GameConstants.ObjectSources.PresenceSource);
|
||||
// Remove previous modifiers from all affected stats
|
||||
RemovePrimaryStatInfluences();
|
||||
|
||||
//Add refreshed values
|
||||
CritChance.AddModifier(new StatModifier(Cunning.Value * GameConstants.CharacterStatsBalancing.CritChanceIncreasePerCunning, StatModType.Flat, GameConstants.ObjectSources.CunningSource));
|
||||
CritDamage.AddModifier(new StatModifier(Cunning.Value * GameConstants.CharacterStatsBalancing.CritDamageIncreasePerCunning, StatModType.Flat, GameConstants.ObjectSources.CunningSource));
|
||||
//DodgeChance.AddModifier(new StatModifier(Cunning.Value * GameConstants.CharacterStatInfluence.DodgeChanceIncreasePerCunning, StatModType.Flat, GameConstants.ObjectSources.CunningSource));
|
||||
MovementSpeed.AddModifier(new StatModifier(Cunning.Value * GameConstants.CharacterStatsBalancing.MovementSpeedIncreasePerCunning, StatModType.Flat, GameConstants.ObjectSources.CunningSource));
|
||||
|
||||
//HealthRegen.AddModifier(new StatModifier(Flow.Value * GameConstants.CharacterStatInfluence.HealthRegenIncreasePerFlow, StatModType.Flat, GameConstants.ObjectSources.FlowSource));
|
||||
MaxMana.AddModifier(new StatModifier(Flow.Value * GameConstants.CharacterStatsBalancing.MaxManaIncreasePerFlow, StatModType.Flat, GameConstants.ObjectSources.FlowSource));
|
||||
ManaRegen.AddModifier(new StatModifier(Flow.Value * GameConstants.CharacterStatsBalancing.ManaRegenIncreasePerFlow, StatModType.Flat, GameConstants.ObjectSources.FlowSource));
|
||||
CooldownReduction.AddModifier(new StatModifier(Flow.Value * GameConstants.CharacterStatsBalancing.CooldownReductionIncreasePerFlow, StatModType.Flat, GameConstants.ObjectSources.FlowSource));
|
||||
AttackSpeed.AddModifier(new StatModifier(Flow.Value * GameConstants.CharacterStatsBalancing.AttackSpeedIncreasePerFlow, StatModType.Flat, GameConstants.ObjectSources.FlowSource));
|
||||
//ResourceCostReduction.AddModifier(new StatModifier(Flow.Value * GameConstants.CharacterStatInfluence.ResourceCostReductionPerFlow, StatModType.Flat, GameConstants.ObjectSources.FlowSource));
|
||||
|
||||
AreaEffectiveness.AddModifier(new StatModifier(Presence.Value * GameConstants.CharacterStatsBalancing.AreaEffectivenessIncreasePerPresence, StatModType.Flat, GameConstants.ObjectSources.PresenceSource));
|
||||
|
||||
ReputationGainIncrease.AddModifier(new StatModifier(Presence.Value * GameConstants.CharacterStatsBalancing.ReputationGainIncreasePerPresence, StatModType.Flat, GameConstants.ObjectSources.PresenceSource));
|
||||
GoldCostReduction.AddModifier(new StatModifier(Presence.Value * GameConstants.CharacterStatsBalancing.GoldCostReductionPerPresence, StatModType.Flat, GameConstants.ObjectSources.PresenceSource));
|
||||
AuraPower.AddModifier(new StatModifier(Presence.Value * GameConstants.CharacterStatsBalancing.AuraPowerPerPresence, StatModType.Flat, GameConstants.ObjectSources.PresenceSource));
|
||||
|
||||
|
||||
// Apply Cunning influences
|
||||
ApplyStatInfluence("critChance", cunning.Value * GameConstants.CharacterStatsBalancing.CritChanceIncreasePerCunning, GameConstants.ObjectSources.CunningSource);
|
||||
ApplyStatInfluence("critDamage", cunning.Value * GameConstants.CharacterStatsBalancing.CritDamageIncreasePerCunning, GameConstants.ObjectSources.CunningSource);
|
||||
ApplyStatInfluence("movementSpeed", cunning.Value * GameConstants.CharacterStatsBalancing.MovementSpeedIncreasePerCunning, GameConstants.ObjectSources.CunningSource);
|
||||
|
||||
// Apply Flow influences
|
||||
ApplyStatInfluence("maxMana", flow.Value * GameConstants.CharacterStatsBalancing.MaxManaIncreasePerFlow, GameConstants.ObjectSources.FlowSource);
|
||||
ApplyStatInfluence("manaRegen", flow.Value * GameConstants.CharacterStatsBalancing.ManaRegenIncreasePerFlow, GameConstants.ObjectSources.FlowSource);
|
||||
ApplyStatInfluence("cooldownReduction", flow.Value * GameConstants.CharacterStatsBalancing.CooldownReductionIncreasePerFlow, GameConstants.ObjectSources.FlowSource);
|
||||
ApplyStatInfluence("attackSpeed", flow.Value * GameConstants.CharacterStatsBalancing.AttackSpeedIncreasePerFlow, GameConstants.ObjectSources.FlowSource);
|
||||
|
||||
// Apply Presence influences
|
||||
ApplyStatInfluence("areaEffectiveness", presence.Value * GameConstants.CharacterStatsBalancing.AreaEffectivenessIncreasePerPresence, GameConstants.ObjectSources.PresenceSource);
|
||||
ApplyStatInfluence("reputationGainIncrease", presence.Value * GameConstants.CharacterStatsBalancing.ReputationGainIncreasePerPresence, GameConstants.ObjectSources.PresenceSource);
|
||||
ApplyStatInfluence("goldCostReduction", presence.Value * GameConstants.CharacterStatsBalancing.GoldCostReductionPerPresence, GameConstants.ObjectSources.PresenceSource);
|
||||
ApplyStatInfluence("auraPower", presence.Value * GameConstants.CharacterStatsBalancing.AuraPowerPerPresence, GameConstants.ObjectSources.PresenceSource);
|
||||
|
||||
Debug.Log(this.gameObject.name + " has relative power level of: " + GetRelativePowerLevel());
|
||||
|
||||
onAllStatsUpdated.Invoke();
|
||||
}
|
||||
|
||||
public float GetRelativePowerLevel()
|
||||
private void RemovePrimaryStatInfluences()
|
||||
{
|
||||
return AttackDamage.Value * 1.1f + SpellDamage.Value * 1.1f + (CritDamage.Value * (CritChance.Value / 100f)) + MaxHealth.Value * 1f + Armor.Value * 1f + MagicResistance.Value * 1f;
|
||||
// Remove Cunning influences
|
||||
RemoveStatInfluence("critChance", GameConstants.ObjectSources.CunningSource);
|
||||
RemoveStatInfluence("critDamage", GameConstants.ObjectSources.CunningSource);
|
||||
RemoveStatInfluence("movementSpeed", GameConstants.ObjectSources.CunningSource);
|
||||
|
||||
// Remove Flow influences
|
||||
RemoveStatInfluence("maxMana", GameConstants.ObjectSources.FlowSource);
|
||||
RemoveStatInfluence("manaRegen", GameConstants.ObjectSources.FlowSource);
|
||||
RemoveStatInfluence("cooldownReduction", GameConstants.ObjectSources.FlowSource);
|
||||
RemoveStatInfluence("attackSpeed", GameConstants.ObjectSources.FlowSource);
|
||||
|
||||
// Remove Presence influences
|
||||
RemoveStatInfluence("areaEffectiveness", GameConstants.ObjectSources.PresenceSource);
|
||||
RemoveStatInfluence("reputationGainIncrease", GameConstants.ObjectSources.PresenceSource);
|
||||
RemoveStatInfluence("goldCostReduction", GameConstants.ObjectSources.PresenceSource);
|
||||
RemoveStatInfluence("auraPower", GameConstants.ObjectSources.PresenceSource);
|
||||
}
|
||||
|
||||
private void ApplyStatInfluence(string statKey, float value, object source)
|
||||
{
|
||||
var stat = GetStat(statKey);
|
||||
if (stat != null)
|
||||
{
|
||||
stat.AddModifier(new StatModifier(value, StatModType.Flat, source));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"CharacterStats: Could not apply influence to stat '{statKey}' - stat not found!");
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveStatInfluence(string statKey, object source)
|
||||
{
|
||||
var stat = GetStat(statKey);
|
||||
stat?.RemoveAllModifiersFromSource(source);
|
||||
}
|
||||
|
||||
public float GetRelativePowerLevel()
|
||||
{
|
||||
var attackDamage = GetStatSafe("attackDamage");
|
||||
var spellDamage = GetStatSafe("spellDamage");
|
||||
var critDamage = GetStatSafe("critDamage");
|
||||
var critChance = GetStatSafe("critChance");
|
||||
var maxHealth = GetStatSafe("maxHealth");
|
||||
var armor = GetStatSafe("armor");
|
||||
var magicResistance = GetStatSafe("magicResistance");
|
||||
|
||||
return attackDamage.Value * 1.1f +
|
||||
spellDamage.Value * 1.1f +
|
||||
(critDamage.Value * (critChance.Value / 100f)) +
|
||||
maxHealth.Value * 1f +
|
||||
armor.Value * 1f +
|
||||
magicResistance.Value * 1f;
|
||||
}
|
||||
|
||||
// Debug/Editor methods
|
||||
[ContextMenu("Log All Stats")]
|
||||
private void LogAllStats()
|
||||
{
|
||||
Debug.Log($"=== CharacterStats on {gameObject.name} ===");
|
||||
foreach (var kvp in allStats)
|
||||
{
|
||||
var stat = kvp.Value;
|
||||
var def = stat.statDefinition;
|
||||
Debug.Log($"{def.DisplayName} ({kvp.Key}): {stat.Value} (Base: {stat.BaseValue}, Category: {def.Category})");
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Refresh Stats From Registry")]
|
||||
private void RefreshStatsFromRegistry()
|
||||
{
|
||||
InitializeStatsFromRegistry();
|
||||
onUpdateStatValues.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Kryz.CharacterStats;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public enum WeaponType
|
||||
@ -43,6 +45,8 @@ public static class WeaponTypeExtensions
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace Kryz.CharacterStats.Examples
|
||||
{
|
||||
public enum EquipmentType
|
||||
@ -55,248 +59,9 @@ namespace Kryz.CharacterStats.Examples
|
||||
Bracers,
|
||||
Gloves,
|
||||
Boots,
|
||||
|
||||
Weapon1,
|
||||
Weapon2,
|
||||
|
||||
//Accessory,
|
||||
//Amulet,
|
||||
}
|
||||
|
||||
|
||||
[CreateAssetMenu]
|
||||
public class EquippableItem : Item
|
||||
{
|
||||
public int AttackDamageBonus;
|
||||
public int SpellDamageBonus;
|
||||
//no flat attack speed bonus, only %
|
||||
public int CritChanceBonus;
|
||||
public int CritDamageBonus;
|
||||
|
||||
public int MaxHealthBonus;
|
||||
public int HealthRegenBonus;
|
||||
public int MaxManaBonus;
|
||||
public int ManaRegenBonus;
|
||||
|
||||
public int ArmorBonus;
|
||||
public int MagicResistanceBonus;
|
||||
//no flat dodge
|
||||
//no flat block chance
|
||||
//no flat block effectiveness
|
||||
|
||||
//no flat area
|
||||
//no flat cdr
|
||||
//no flat movespeed
|
||||
|
||||
//no flat rep gains
|
||||
//no flat gold cost reduction
|
||||
|
||||
[Space]
|
||||
public float AttackDamagePercentBonus;
|
||||
public float SpellDamagePercentBonus;
|
||||
|
||||
public float AttackSpeedPercentBonus;
|
||||
|
||||
public float CritChancePercentBonus;
|
||||
public float CritDamagePercentBonus;
|
||||
|
||||
public float MaxHealthPercentBonus;
|
||||
public float HealthRegenPercentBonus;
|
||||
public float MaxManaPercentBonus;
|
||||
public float ManaRegenPercentBonus;
|
||||
|
||||
|
||||
public float ArmorPercentBonus;
|
||||
public float MagicResistancePercentBonus;
|
||||
public float DodgeChancePercentBonus;
|
||||
public float BlockChancePercentBonus;
|
||||
public float BlockEffectivenessPercentBonus;
|
||||
|
||||
|
||||
public float AreaEffectivenessPercentBonus;
|
||||
public float CooldownReductionPercentBonus;
|
||||
public float MovementSpeedPercentBonus;
|
||||
public float ReputationGainIncreasePercentBonus;
|
||||
public float GoldCostReductionPercentBonus;
|
||||
|
||||
|
||||
public EquipmentType EquipmentType;
|
||||
[Space]
|
||||
// NEW: Add WeaponType for weapon items
|
||||
public WeaponType WeaponType;
|
||||
|
||||
// Updated EquippableItemInstance helper properties
|
||||
public bool IsWeapon => EquipmentType == EquipmentType.Weapon1 || EquipmentType == EquipmentType.Weapon2;
|
||||
// NEW: Helper property to check if this weapon is two-handed
|
||||
public bool IsTwoHandedWeapon => IsWeapon && WeaponType.IsTwoHanded();
|
||||
|
||||
// NEW: Helper property to check if this weapon is one-handed
|
||||
public bool IsOneHandedWeapon => IsWeapon && WeaponType.IsOneHanded();
|
||||
|
||||
[Space]
|
||||
public bool CraftableBase = false;
|
||||
[Space(20f)]
|
||||
[Header("Crafting-ish")]
|
||||
public int MinAttackDamageBonus;
|
||||
public int MaxAttackDamageBonus;
|
||||
[Space]
|
||||
public int MinSpellDamageBonus;
|
||||
public int MaxSpellDamageBonus;
|
||||
[Space]
|
||||
public int MinCritChanceBonus;
|
||||
public int MaxCritChanceBonus;
|
||||
[Space]
|
||||
public int MinCritDamageBonus;
|
||||
public int MaxCritDamageBonus;
|
||||
[Space]
|
||||
public int MinMaxHealthBonus;
|
||||
public int MaxMaxHealthBonus;
|
||||
[Space]
|
||||
public int MinArmorBonus;
|
||||
public int MaxArmorBonus;
|
||||
[Space]
|
||||
public int MinMagicResistanceBonus;
|
||||
public int MaxMagicResistanceBonus;
|
||||
[Space]
|
||||
[Space]
|
||||
public float MinAttackDamagePercentBonus;
|
||||
public float MaxAttackDamagePercentBonus;
|
||||
[Space]
|
||||
public float MinSpellDamagePercentBonus;
|
||||
public float MaxSpellDamagePercentBonus;
|
||||
[Space]
|
||||
public float MinCritChancePercentBonus;
|
||||
public float MaxCritChancePercentBonus;
|
||||
[Space]
|
||||
public float MinCritDamagePercentBonus;
|
||||
public float MaxCritDamagePercentBonus;
|
||||
[Space]
|
||||
public float MinMaxHealthPercentBonus;
|
||||
public float MaxMaxHealthPercentBonus;
|
||||
[Space]
|
||||
public float MinArmorPercentBonus;
|
||||
public float MaxArmorPercentBonus;
|
||||
[Space]
|
||||
public float MinMagicResistancePercentBonus;
|
||||
public float MaxMagicResistancePercentBonus;
|
||||
[Space]
|
||||
[Space]
|
||||
[Tooltip("Can only increase up to this number of unique stats in a single item instance.")]
|
||||
public int MaxTotalUniqueStatsIncreasedByStones;
|
||||
|
||||
|
||||
public void Equip(PlayerCharacterStats c)
|
||||
{
|
||||
|
||||
if (AttackDamageBonus != 0)
|
||||
c.AttackDamage.AddModifier(new StatModifier(AttackDamageBonus, StatModType.Flat, this));
|
||||
if (SpellDamageBonus != 0)
|
||||
c.SpellDamage.AddModifier(new StatModifier(SpellDamageBonus, StatModType.Flat, this));
|
||||
|
||||
if (CritChanceBonus != 0)
|
||||
c.CritChance.AddModifier(new StatModifier(CritChanceBonus, StatModType.Flat, this));
|
||||
if (CritDamageBonus != 0)
|
||||
c.CritDamage.AddModifier(new StatModifier(CritDamageBonus, StatModType.Flat, this));
|
||||
|
||||
if (MaxHealthBonus != 0)
|
||||
c.MaxHealth.AddModifier(new StatModifier(MaxHealthBonus, StatModType.Flat, this));
|
||||
if (HealthRegenBonus != 0)
|
||||
c.HealthRegen.AddModifier(new StatModifier(HealthRegenBonus, StatModType.Flat, this));
|
||||
|
||||
if (MaxManaBonus != 0)
|
||||
c.MaxMana.AddModifier(new StatModifier(MaxManaBonus, StatModType.Flat, this));
|
||||
if (ManaRegenBonus != 0)
|
||||
c.ManaRegen.AddModifier(new StatModifier(ManaRegenBonus, StatModType.Flat, this));
|
||||
|
||||
|
||||
if (ArmorBonus != 0)
|
||||
c.Armor.AddModifier(new StatModifier(ArmorBonus, StatModType.Flat, this));
|
||||
if (MagicResistanceBonus != 0)
|
||||
c.MagicResistance.AddModifier(new StatModifier(MagicResistanceBonus, StatModType.Flat, this));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (AttackDamagePercentBonus != 0)
|
||||
c.AttackDamage.AddModifier(new StatModifier(AttackDamagePercentBonus, StatModType.PercentAdd, this));
|
||||
if (SpellDamagePercentBonus != 0)
|
||||
c.SpellDamage.AddModifier(new StatModifier(SpellDamagePercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
if (AttackSpeedPercentBonus != 0)
|
||||
c.AttackSpeed.AddModifier(new StatModifier(AttackSpeedPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
if (CritChancePercentBonus != 0)
|
||||
c.CritChance.AddModifier(new StatModifier(CritChancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (CritDamagePercentBonus != 0)
|
||||
c.CritDamage.AddModifier(new StatModifier(CritDamagePercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
|
||||
|
||||
if (MaxHealthPercentBonus != 0)
|
||||
c.MaxHealth.AddModifier(new StatModifier(MaxHealthPercentBonus, StatModType.PercentAdd, this));
|
||||
if (HealthRegenPercentBonus != 0)
|
||||
c.HealthRegen.AddModifier(new StatModifier(HealthRegenPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
if (MaxManaPercentBonus != 0)
|
||||
c.MaxMana.AddModifier(new StatModifier(MaxManaPercentBonus, StatModType.PercentAdd, this));
|
||||
if (ManaRegenPercentBonus != 0)
|
||||
c.ManaRegen.AddModifier(new StatModifier(ManaRegenPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
|
||||
if (ArmorPercentBonus != 0)
|
||||
c.Armor.AddModifier(new StatModifier(ArmorPercentBonus, StatModType.PercentAdd, this));
|
||||
if (MagicResistancePercentBonus != 0)
|
||||
c.MagicResistance.AddModifier(new StatModifier(MagicResistancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (DodgeChancePercentBonus != 0)
|
||||
c.DodgeChance.AddModifier(new StatModifier(DodgeChancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (BlockChancePercentBonus != 0)
|
||||
c.BlockChance.AddModifier(new StatModifier(BlockChancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (BlockEffectivenessPercentBonus != 0)
|
||||
c.BlockEffectiveness.AddModifier(new StatModifier(BlockEffectivenessPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
|
||||
if (AreaEffectivenessPercentBonus != 0)
|
||||
c.AreaEffectiveness.AddModifier(new StatModifier(AreaEffectivenessPercentBonus, StatModType.PercentAdd, this));
|
||||
if (CooldownReductionPercentBonus != 0)
|
||||
c.CooldownReduction.AddModifier(new StatModifier(CooldownReductionPercentBonus, StatModType.PercentAdd, this));
|
||||
if (MovementSpeedPercentBonus != 0)
|
||||
c.MovementSpeed.AddModifier(new StatModifier(MovementSpeedPercentBonus, StatModType.PercentAdd, this));
|
||||
if (ReputationGainIncreasePercentBonus != 0)
|
||||
c.ReputationGainIncrease.AddModifier(new StatModifier(ReputationGainIncreasePercentBonus, StatModType.PercentAdd, this));
|
||||
if (GoldCostReductionPercentBonus != 0)
|
||||
c.GoldCostReduction.AddModifier(new StatModifier(GoldCostReductionPercentBonus, StatModType.PercentAdd, this));
|
||||
}
|
||||
|
||||
public void Unequip(PlayerCharacterStats c)
|
||||
{
|
||||
|
||||
c.AttackDamage.RemoveAllModifiersFromSource(this);
|
||||
c.SpellDamage.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.AttackSpeed.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.CritChance.RemoveAllModifiersFromSource(this);
|
||||
c.CritDamage.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.MaxHealth.RemoveAllModifiersFromSource(this);
|
||||
c.HealthRegen.RemoveAllModifiersFromSource(this);
|
||||
c.MaxMana.RemoveAllModifiersFromSource(this);
|
||||
c.ManaRegen.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.Armor.RemoveAllModifiersFromSource(this);
|
||||
c.MagicResistance.RemoveAllModifiersFromSource(this);
|
||||
c.DodgeChance.RemoveAllModifiersFromSource(this);
|
||||
c.BlockChance.RemoveAllModifiersFromSource(this);
|
||||
c.BlockEffectiveness.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.AreaEffectiveness.RemoveAllModifiersFromSource(this);
|
||||
c.CooldownReduction.RemoveAllModifiersFromSource(this);
|
||||
c.MovementSpeed.RemoveAllModifiersFromSource(this);
|
||||
c.ReputationGainIncrease.RemoveAllModifiersFromSource(this);
|
||||
c.GoldCostReduction.RemoveAllModifiersFromSource(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,244 +1,190 @@
|
||||
using Kryz.CharacterStats;
|
||||
using Kryz.CharacterStats.Examples;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class ItemStatBonus
|
||||
{
|
||||
public StatDefinition statDefinition;
|
||||
public float flatValue;
|
||||
public float percentValue;
|
||||
|
||||
public bool HasFlatBonus => flatValue != 0;
|
||||
public bool HasPercentBonus => percentValue != 0;
|
||||
public bool HasAnyBonus => HasFlatBonus || HasPercentBonus;
|
||||
|
||||
public ItemStatBonus() { }
|
||||
|
||||
public ItemStatBonus(StatDefinition stat, float flat = 0f, float percent = 0f)
|
||||
{
|
||||
statDefinition = stat;
|
||||
flatValue = flat;
|
||||
percentValue = percent;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class EquippableItemInstance : ItemInstance
|
||||
{
|
||||
public int AttackDamageBonus;
|
||||
public int SpellDamageBonus;
|
||||
//no flat attack speed bonus, only %
|
||||
public int CritChanceBonus;
|
||||
public int CritDamageBonus;
|
||||
|
||||
public int MaxHealthBonus;
|
||||
public int HealthRegenBonus;
|
||||
public int MaxManaBonus;
|
||||
public int ManaRegenBonus;
|
||||
|
||||
public int ArmorBonus;
|
||||
public int MagicResistanceBonus;
|
||||
//no flat dodge
|
||||
//no flat block chance
|
||||
//no flat block effectiveness
|
||||
|
||||
//no flat area
|
||||
//no flat cdr
|
||||
//no flat movespeed
|
||||
|
||||
//no flat rep gains
|
||||
//no flat gold cost reduction
|
||||
|
||||
[Space]
|
||||
public float AttackDamagePercentBonus;
|
||||
public float SpellDamagePercentBonus;
|
||||
|
||||
public float AttackSpeedPercentBonus;
|
||||
|
||||
public float CritChancePercentBonus;
|
||||
public float CritDamagePercentBonus;
|
||||
|
||||
public float MaxHealthPercentBonus;
|
||||
public float HealthRegenPercentBonus;
|
||||
public float MaxManaPercentBonus;
|
||||
public float ManaRegenPercentBonus;
|
||||
|
||||
|
||||
public float ArmorPercentBonus;
|
||||
public float MagicResistancePercentBonus;
|
||||
public float DodgeChancePercentBonus;
|
||||
public float BlockChancePercentBonus;
|
||||
public float BlockEffectivenessPercentBonus;
|
||||
|
||||
|
||||
public float AreaEffectivenessPercentBonus;
|
||||
public float CooldownReductionPercentBonus;
|
||||
public float MovementSpeedPercentBonus;
|
||||
public float ReputationGainIncreasePercentBonus;
|
||||
public float GoldCostReductionPercentBonus;
|
||||
[Space]
|
||||
[Header("Equipment Identity")]
|
||||
public EquipmentType EquipmentType;
|
||||
[Space]
|
||||
// NEW: Add WeaponType for weapon items
|
||||
public WeaponType WeaponType;
|
||||
[Space]
|
||||
public string IconPath; // Store the icon path for serialization
|
||||
|
||||
[Header("Dynamic Stat System")]
|
||||
public List<ItemStatBonus> statBonuses = new List<ItemStatBonus>();
|
||||
|
||||
[Header("Crafting System")]
|
||||
public bool CraftableBase = false;
|
||||
[Space]
|
||||
/// <summary>
|
||||
/// Can only contain up to this number of unique stats in a single item instance.
|
||||
/// </summary>
|
||||
[Space]
|
||||
[Tooltip("Can only contain up to this number of unique stats in a single item instance.")]
|
||||
public int MaxTotalUniqueStatsIncreasedByStones;
|
||||
public List<string> AddedStoneStats = new List<string>();
|
||||
|
||||
// Updated EquippableItemInstance helper properties
|
||||
// Helper properties
|
||||
public bool IsWeapon => EquipmentType == EquipmentType.Weapon1 || EquipmentType == EquipmentType.Weapon2;
|
||||
// NEW: Helper property to check if this weapon is two-handed
|
||||
public bool IsTwoHandedWeapon => IsWeapon && WeaponType.IsTwoHanded();
|
||||
|
||||
// NEW: Helper property to check if this weapon is one-handed
|
||||
public bool IsOneHandedWeapon => IsWeapon && WeaponType.IsOneHanded();
|
||||
|
||||
public void Equip(PlayerCharacterStats c)
|
||||
public void Equip(PlayerCharacterStats characterStats)
|
||||
{
|
||||
if (AttackDamageBonus != 0)
|
||||
c.AttackDamage.AddModifier(new StatModifier(AttackDamageBonus, StatModType.Flat, this));
|
||||
if (SpellDamageBonus != 0)
|
||||
c.SpellDamage.AddModifier(new StatModifier(SpellDamageBonus, StatModType.Flat, this));
|
||||
foreach (var bonus in statBonuses)
|
||||
{
|
||||
if (bonus.statDefinition == null || !bonus.HasAnyBonus) continue;
|
||||
|
||||
if (CritChanceBonus != 0)
|
||||
c.CritChance.AddModifier(new StatModifier(CritChanceBonus, StatModType.Flat, this));
|
||||
if (CritDamageBonus != 0)
|
||||
c.CritDamage.AddModifier(new StatModifier(CritDamageBonus, StatModType.Flat, this));
|
||||
var stat = characterStats.GetStat(bonus.statDefinition.StatKey);
|
||||
if (stat != null)
|
||||
{
|
||||
// Apply flat bonus
|
||||
if (bonus.HasFlatBonus)
|
||||
{
|
||||
stat.AddModifier(new StatModifier(bonus.flatValue, StatModType.Flat, this));
|
||||
}
|
||||
|
||||
if (MaxHealthBonus != 0)
|
||||
c.MaxHealth.AddModifier(new StatModifier(MaxHealthBonus, StatModType.Flat, this));
|
||||
if (HealthRegenBonus != 0)
|
||||
c.HealthRegen.AddModifier(new StatModifier(HealthRegenBonus, StatModType.Flat, this));
|
||||
|
||||
if (MaxManaBonus != 0)
|
||||
c.MaxMana.AddModifier(new StatModifier(MaxManaBonus, StatModType.Flat, this));
|
||||
if (ManaRegenBonus != 0)
|
||||
c.ManaRegen.AddModifier(new StatModifier(ManaRegenBonus, StatModType.Flat, this));
|
||||
|
||||
|
||||
if (ArmorBonus != 0)
|
||||
c.Armor.AddModifier(new StatModifier(ArmorBonus, StatModType.Flat, this));
|
||||
if (MagicResistanceBonus != 0)
|
||||
c.MagicResistance.AddModifier(new StatModifier(MagicResistanceBonus, StatModType.Flat, this));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (AttackDamagePercentBonus != 0)
|
||||
c.AttackDamage.AddModifier(new StatModifier(AttackDamagePercentBonus, StatModType.PercentAdd, this));
|
||||
if (SpellDamagePercentBonus != 0)
|
||||
c.SpellDamage.AddModifier(new StatModifier(SpellDamagePercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
if (AttackSpeedPercentBonus != 0)
|
||||
c.AttackSpeed.AddModifier(new StatModifier(AttackSpeedPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
if (CritChancePercentBonus != 0)
|
||||
c.CritChance.AddModifier(new StatModifier(CritChancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (CritDamagePercentBonus != 0)
|
||||
c.CritDamage.AddModifier(new StatModifier(CritDamagePercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
|
||||
|
||||
if (MaxHealthPercentBonus != 0)
|
||||
c.MaxHealth.AddModifier(new StatModifier(MaxHealthPercentBonus, StatModType.PercentAdd, this));
|
||||
if (HealthRegenPercentBonus != 0)
|
||||
c.HealthRegen.AddModifier(new StatModifier(HealthRegenPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
if (MaxManaPercentBonus != 0)
|
||||
c.MaxMana.AddModifier(new StatModifier(MaxManaPercentBonus, StatModType.PercentAdd, this));
|
||||
if (ManaRegenPercentBonus != 0)
|
||||
c.ManaRegen.AddModifier(new StatModifier(ManaRegenPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
|
||||
if (ArmorPercentBonus != 0)
|
||||
c.Armor.AddModifier(new StatModifier(ArmorPercentBonus, StatModType.PercentAdd, this));
|
||||
if (MagicResistancePercentBonus != 0)
|
||||
c.MagicResistance.AddModifier(new StatModifier(MagicResistancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (DodgeChancePercentBonus != 0)
|
||||
c.DodgeChance.AddModifier(new StatModifier(DodgeChancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (BlockChancePercentBonus != 0)
|
||||
c.BlockChance.AddModifier(new StatModifier(BlockChancePercentBonus, StatModType.PercentAdd, this));
|
||||
if (BlockEffectivenessPercentBonus != 0)
|
||||
c.BlockEffectiveness.AddModifier(new StatModifier(BlockEffectivenessPercentBonus, StatModType.PercentAdd, this));
|
||||
|
||||
|
||||
if (AreaEffectivenessPercentBonus != 0)
|
||||
c.AreaEffectiveness.AddModifier(new StatModifier(AreaEffectivenessPercentBonus, StatModType.PercentAdd, this));
|
||||
if (CooldownReductionPercentBonus != 0)
|
||||
c.CooldownReduction.AddModifier(new StatModifier(CooldownReductionPercentBonus, StatModType.PercentAdd, this));
|
||||
if (MovementSpeedPercentBonus != 0)
|
||||
c.MovementSpeed.AddModifier(new StatModifier(MovementSpeedPercentBonus, StatModType.PercentAdd, this));
|
||||
if (ReputationGainIncreasePercentBonus != 0)
|
||||
c.ReputationGainIncrease.AddModifier(new StatModifier(ReputationGainIncreasePercentBonus, StatModType.PercentAdd, this));
|
||||
if (GoldCostReductionPercentBonus != 0)
|
||||
c.GoldCostReduction.AddModifier(new StatModifier(GoldCostReductionPercentBonus, StatModType.PercentAdd, this));
|
||||
// Apply percent bonus
|
||||
if (bonus.HasPercentBonus)
|
||||
{
|
||||
stat.AddModifier(new StatModifier(bonus.percentValue, StatModType.PercentAdd, this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"EquippableItemInstance: Stat '{bonus.statDefinition.StatKey}' not found in character stats!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unequip(PlayerCharacterStats c)
|
||||
public void Unequip(PlayerCharacterStats characterStats)
|
||||
{
|
||||
c.AttackDamage.RemoveAllModifiersFromSource(this);
|
||||
c.SpellDamage.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.AttackSpeed.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.CritChance.RemoveAllModifiersFromSource(this);
|
||||
c.CritDamage.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.MaxHealth.RemoveAllModifiersFromSource(this);
|
||||
c.HealthRegen.RemoveAllModifiersFromSource(this);
|
||||
c.MaxMana.RemoveAllModifiersFromSource(this);
|
||||
c.ManaRegen.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.Armor.RemoveAllModifiersFromSource(this);
|
||||
c.MagicResistance.RemoveAllModifiersFromSource(this);
|
||||
c.DodgeChance.RemoveAllModifiersFromSource(this);
|
||||
c.BlockChance.RemoveAllModifiersFromSource(this);
|
||||
c.BlockEffectiveness.RemoveAllModifiersFromSource(this);
|
||||
|
||||
c.AreaEffectiveness.RemoveAllModifiersFromSource(this);
|
||||
c.CooldownReduction.RemoveAllModifiersFromSource(this);
|
||||
c.MovementSpeed.RemoveAllModifiersFromSource(this);
|
||||
c.ReputationGainIncrease.RemoveAllModifiersFromSource(this);
|
||||
c.GoldCostReduction.RemoveAllModifiersFromSource(this);
|
||||
// Remove all modifiers from this item source across all stats
|
||||
var allStats = characterStats.GetAllStats();
|
||||
foreach (var kvp in allStats)
|
||||
{
|
||||
kvp.RemoveAllModifiersFromSource(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Stat management methods
|
||||
public void AddStatBonus(StatDefinition statDef, float flatValue = 0f, float percentValue = 0f)
|
||||
{
|
||||
var existingBonus = statBonuses.FirstOrDefault(b => b.statDefinition == statDef);
|
||||
if (existingBonus != null)
|
||||
{
|
||||
existingBonus.flatValue += flatValue;
|
||||
existingBonus.percentValue += percentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
statBonuses.Add(new ItemStatBonus(statDef, flatValue, percentValue));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStatBonus(StatDefinition statDef, float flatValue = 0f, float percentValue = 0f)
|
||||
{
|
||||
var existingBonus = statBonuses.FirstOrDefault(b => b.statDefinition == statDef);
|
||||
if (existingBonus != null)
|
||||
{
|
||||
existingBonus.flatValue = flatValue;
|
||||
existingBonus.percentValue = percentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
statBonuses.Add(new ItemStatBonus(statDef, flatValue, percentValue));
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStatBonus GetStatBonus(StatDefinition statDef)
|
||||
{
|
||||
return statBonuses.FirstOrDefault(b => b.statDefinition == statDef);
|
||||
}
|
||||
|
||||
public bool HasStat(StatDefinition statDef)
|
||||
{
|
||||
var bonus = GetStatBonus(statDef);
|
||||
return bonus != null && bonus.HasAnyBonus;
|
||||
}
|
||||
|
||||
public List<ItemStatBonus> GetAllNonZeroBonuses()
|
||||
{
|
||||
return statBonuses.Where(b => b.HasAnyBonus).ToList();
|
||||
}
|
||||
|
||||
public int GetUniqueStatCount()
|
||||
{
|
||||
return GetAllNonZeroBonuses().Count;
|
||||
}
|
||||
|
||||
// Crafting stone system (updated to use new stat system)
|
||||
public bool CanAddCraftingStone(CraftingStatStone stone)
|
||||
{
|
||||
if (!CraftableBase) return false;
|
||||
|
||||
var stoneStats = GetNonZeroStats(stone);
|
||||
var itemNonZeroStats = GetNonZeroStats(this);
|
||||
var stoneStats = GetNonZeroStatsFromStone(stone);
|
||||
var currentStats = GetAllNonZeroBonuses().Select(b => b.statDefinition.StatKey).ToList();
|
||||
|
||||
int newUniqueStats = stoneStats.Except(itemNonZeroStats).Count();
|
||||
int newUniqueStats = stoneStats.Except(currentStats).Count();
|
||||
|
||||
// Ensure we don't exceed the max unique stats cap
|
||||
if (AddedStoneStats.Count + newUniqueStats > MaxTotalUniqueStatsIncreasedByStones)
|
||||
{
|
||||
return false; // Adding the crafting stone would exceed the cap
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryAddCraftingStone(CraftingStatStone stone)
|
||||
{
|
||||
if (!CanAddCraftingStone(stone)) return false;
|
||||
|
||||
var stoneStats = GetNonZeroStats(stone);
|
||||
var itemStats = GetNonZeroStats(this);
|
||||
var stoneStats = GetNonZeroStatsFromStone(stone);
|
||||
var currentStats = GetAllNonZeroBonuses().Select(b => b.statDefinition.StatKey).ToList();
|
||||
|
||||
for (int i = 0; i < stoneStats.Count; i++)
|
||||
// Track new stats being added
|
||||
foreach (var statKey in stoneStats)
|
||||
{
|
||||
if (!itemStats.Contains(stoneStats[i]) && !AddedStoneStats.Contains(stoneStats[i]))
|
||||
AddedStoneStats.Add(stoneStats[i]);
|
||||
if (!currentStats.Contains(statKey) && !AddedStoneStats.Contains(statKey))
|
||||
{
|
||||
AddedStoneStats.Add(statKey);
|
||||
}
|
||||
}
|
||||
// Add stats from the stone to the item
|
||||
AddStats(stone);
|
||||
|
||||
// Add stats from the stone to the item (this needs to be updated based on your stone structure)
|
||||
AddStatsFromStone(stone);
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<string> GetNonZeroStats(object stats)
|
||||
private List<string> GetNonZeroStatsFromStone(CraftingStatStone stone)
|
||||
{
|
||||
var nonZeroStats = new List<string>();
|
||||
var fields = stats.GetType().GetFields();
|
||||
var fields = stone.GetType().GetFields();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (field.GetValue(stats) is int intValue && intValue != 0 && field.Name.ToLower().Contains("bonus"))
|
||||
if (field.GetValue(stone) is int intValue && intValue != 0 && field.Name.ToLower().Contains("bonus"))
|
||||
{
|
||||
nonZeroStats.Add(field.Name);
|
||||
}
|
||||
else if (field.GetValue(stats) is float floatValue && !Mathf.Approximately(floatValue, 0f) && field.Name.ToLower().Contains("bonus"))
|
||||
else if (field.GetValue(stone) is float floatValue && !Mathf.Approximately(floatValue, 0f) && field.Name.ToLower().Contains("bonus"))
|
||||
{
|
||||
nonZeroStats.Add(field.Name);
|
||||
}
|
||||
@ -247,216 +193,89 @@ public class EquippableItemInstance : ItemInstance
|
||||
return nonZeroStats;
|
||||
}
|
||||
|
||||
//TODO: Add new stats to stones too
|
||||
private void AddStats(CraftingStatStone stone)
|
||||
// This method needs to be updated based on your CraftingStatStone structure
|
||||
private void AddStatsFromStone(CraftingStatStone stone)
|
||||
{
|
||||
AttackDamageBonus += stone.AttackDamageBonus;
|
||||
SpellDamageBonus += stone.SpellDamageBonus;
|
||||
CritChanceBonus += stone.CritChanceBonus;
|
||||
CritDamageBonus += stone.CritDamageBonus;
|
||||
MaxHealthBonus += stone.MaxHealthBonus;
|
||||
//HealthRegenBonus += stone.HealthRegenBonus;
|
||||
//MaxManaBonus += stone.MaxManaBonus;
|
||||
//ManaRegenBonus += stone.ManaRegenBonus;
|
||||
ArmorBonus += stone.ArmorBonus;
|
||||
MagicResistanceBonus += stone.MagicResistanceBonus;
|
||||
|
||||
AttackDamagePercentBonus += stone.AttackDamagePercentBonus;
|
||||
SpellDamagePercentBonus += stone.SpellDamagePercentBonus;
|
||||
//AttackSpeedPercentBonus += stone.AttackSpeedPercentBonus;
|
||||
CritChancePercentBonus += stone.CritChancePercentBonus;
|
||||
CritDamagePercentBonus += stone.CritDamagePercentBonus;
|
||||
MaxHealthPercentBonus += stone.MaxHealthPercentBonus;
|
||||
//HealthRegenPercentBonus += stone.HealthRegenPercentBonus;
|
||||
//MaxManaPercentBonus += stone.MaxManaPercentBonus;
|
||||
//ManaRegenPercentBonus += stone.ManaRegenPercentBonus;
|
||||
ArmorPercentBonus += stone.ArmorPercentBonus;
|
||||
MagicResistancePercentBonus += stone.MagicResistancePercentBonus;
|
||||
//DodgeChancePercentBonus += stone.DodgeChancePercentBonus;
|
||||
//BlockChancePercentBonus += stone.BlockChancePercentBonus;
|
||||
//BlockEffectivenessPercentBonus += stone.BlockEffectivenessPercentBonus;
|
||||
//AreaEffectivenessPercentBonus += stone.AreaEffectivenessPercentBonus;
|
||||
//CooldownReductionPercentBonus += stone.CooldownReductionPercentBonus;
|
||||
//MovementSpeedPercentBonus += stone.MovementSpeedPercentBonus;
|
||||
//ReputationGainIncreasePercentBonus += stone.ReputationGainIncreasePercentBonus;
|
||||
//GoldCostReductionPercentBonus += stone.GoldCostReductionPercentBonus;
|
||||
// TODO: Update this to work with the new stat system
|
||||
// You'll need to map stone properties to StatDefinition references
|
||||
// For now, keeping the old structure as a placeholder
|
||||
Debug.LogWarning("AddStatsFromStone needs to be updated for the new stat system");
|
||||
}
|
||||
|
||||
// Constructors
|
||||
public EquippableItemInstance()
|
||||
{
|
||||
// Initialize all int stats to 0
|
||||
AttackDamageBonus = 0;
|
||||
SpellDamageBonus = 0;
|
||||
CritChanceBonus = 0;
|
||||
CritDamageBonus = 0;
|
||||
MaxHealthBonus = 0;
|
||||
HealthRegenBonus = 0;
|
||||
MaxManaBonus = 0;
|
||||
ManaRegenBonus = 0;
|
||||
ArmorBonus = 0;
|
||||
MagicResistanceBonus = 0;
|
||||
|
||||
// Initialize all float stats to 0
|
||||
AttackDamagePercentBonus = 0;
|
||||
SpellDamagePercentBonus = 0;
|
||||
AttackSpeedPercentBonus = 0;
|
||||
CritChancePercentBonus = 0;
|
||||
CritDamagePercentBonus = 0;
|
||||
MaxHealthPercentBonus = 0;
|
||||
HealthRegenPercentBonus = 0;
|
||||
MaxManaPercentBonus = 0;
|
||||
ManaRegenPercentBonus = 0;
|
||||
ArmorPercentBonus = 0;
|
||||
MagicResistancePercentBonus = 0;
|
||||
DodgeChancePercentBonus = 0;
|
||||
BlockChancePercentBonus = 0;
|
||||
BlockEffectivenessPercentBonus = 0;
|
||||
AreaEffectivenessPercentBonus = 0;
|
||||
CooldownReductionPercentBonus = 0;
|
||||
MovementSpeedPercentBonus = 0;
|
||||
ReputationGainIncreasePercentBonus = 0;
|
||||
GoldCostReductionPercentBonus = 0;
|
||||
|
||||
EquipmentType = EquipmentType.Helmet;
|
||||
WeaponType = WeaponType.Sword; // Default weapon type
|
||||
|
||||
WeaponType = WeaponType.Sword;
|
||||
CraftableBase = false;
|
||||
MaxTotalUniqueStatsIncreasedByStones = 0;
|
||||
statBonuses = new List<ItemStatBonus>();
|
||||
AddedStoneStats = new List<string>();
|
||||
templateIndex = -1;
|
||||
}
|
||||
|
||||
public EquippableItemInstance(EquippableItem template)
|
||||
// Constructor for generating from EquipmentTypeDefinition (recommended approach)
|
||||
public EquippableItemInstance(EquippableItemTypeDefinition equipmentTypeDef, string itemName, Sprite icon, string iconPath = null)
|
||||
{
|
||||
ItemName = template.ItemName;
|
||||
Icon = template.Icon;
|
||||
sellPricePlayer = template.sellPricePlayer;
|
||||
sellPriceVendor = template.sellPriceVendor;
|
||||
description = template.description;
|
||||
templateIndex = ItemIndexer.Instance.Items.IndexOf(template);
|
||||
ItemName = itemName;
|
||||
Icon = icon;
|
||||
IconPath = iconPath ?? ""; // Store the icon path
|
||||
EquipmentType = equipmentTypeDef.EquipmentType;
|
||||
WeaponType = equipmentTypeDef.WeaponType;
|
||||
CraftableBase = false; // Set based on your needs
|
||||
MaxTotalUniqueStatsIncreasedByStones = 6; // Default value
|
||||
statBonuses = new List<ItemStatBonus>();
|
||||
AddedStoneStats = new List<string>();
|
||||
templateIndex = -1;
|
||||
|
||||
// Copy all int stats
|
||||
AttackDamageBonus = template.AttackDamageBonus;
|
||||
SpellDamageBonus = template.SpellDamageBonus;
|
||||
CritChanceBonus = template.CritChanceBonus;
|
||||
CritDamageBonus = template.CritDamageBonus;
|
||||
MaxHealthBonus = template.MaxHealthBonus;
|
||||
HealthRegenBonus = template.HealthRegenBonus;
|
||||
MaxManaBonus = template.MaxManaBonus;
|
||||
ManaRegenBonus = template.ManaRegenBonus;
|
||||
ArmorBonus = template.ArmorBonus;
|
||||
MagicResistanceBonus = template.MagicResistanceBonus;
|
||||
|
||||
// Copy all float stats
|
||||
AttackDamagePercentBonus = template.AttackDamagePercentBonus;
|
||||
SpellDamagePercentBonus = template.SpellDamagePercentBonus;
|
||||
AttackSpeedPercentBonus = template.AttackSpeedPercentBonus;
|
||||
CritChancePercentBonus = template.CritChancePercentBonus;
|
||||
CritDamagePercentBonus = template.CritDamagePercentBonus;
|
||||
MaxHealthPercentBonus = template.MaxHealthPercentBonus;
|
||||
HealthRegenPercentBonus = template.HealthRegenPercentBonus;
|
||||
MaxManaPercentBonus = template.MaxManaPercentBonus;
|
||||
ManaRegenPercentBonus = template.ManaRegenPercentBonus;
|
||||
ArmorPercentBonus = template.ArmorPercentBonus;
|
||||
MagicResistancePercentBonus = template.MagicResistancePercentBonus;
|
||||
DodgeChancePercentBonus = template.DodgeChancePercentBonus;
|
||||
BlockChancePercentBonus = template.BlockChancePercentBonus;
|
||||
BlockEffectivenessPercentBonus = template.BlockEffectivenessPercentBonus;
|
||||
AreaEffectivenessPercentBonus = template.AreaEffectivenessPercentBonus;
|
||||
CooldownReductionPercentBonus = template.CooldownReductionPercentBonus;
|
||||
MovementSpeedPercentBonus = template.MovementSpeedPercentBonus;
|
||||
ReputationGainIncreasePercentBonus = template.ReputationGainIncreasePercentBonus;
|
||||
GoldCostReductionPercentBonus = template.GoldCostReductionPercentBonus;
|
||||
|
||||
EquipmentType = template.EquipmentType;
|
||||
WeaponType = template.WeaponType;
|
||||
|
||||
CraftableBase = template.CraftableBase;
|
||||
MaxTotalUniqueStatsIncreasedByStones = template.MaxTotalUniqueStatsIncreasedByStones;
|
||||
// You can set default sell prices here or pass them as parameters
|
||||
sellPricePlayer = 100;
|
||||
sellPriceVendor = 50;
|
||||
description = $"A {equipmentTypeDef.GetDisplayName()}";
|
||||
}
|
||||
|
||||
public EquippableItemInstance(EquippableItem template, bool randomizeStats)
|
||||
// Helper method to set icon with path
|
||||
public void SetIcon(Sprite icon, string iconPath)
|
||||
{
|
||||
ItemName = template.ItemName;
|
||||
Icon = template.Icon;
|
||||
sellPricePlayer = template.sellPricePlayer;
|
||||
sellPriceVendor = template.sellPriceVendor;
|
||||
description = template.description;
|
||||
templateIndex = ItemIndexer.Instance.Items.IndexOf(template);
|
||||
Icon = icon;
|
||||
IconPath = iconPath;
|
||||
}
|
||||
|
||||
if (randomizeStats)
|
||||
// Helper method to get icon path from EquipmentTypeDefinition
|
||||
public static string GetIconPathFromEquipmentType(EquippableItemTypeDefinition equipmentTypeDef, Sprite icon)
|
||||
{
|
||||
if (equipmentTypeDef.UseResourcesFolder && !string.IsNullOrEmpty(equipmentTypeDef.ResourcesPath))
|
||||
{
|
||||
// Randomize int stats
|
||||
AttackDamageBonus = Random.Range(template.MinAttackDamageBonus, template.MaxAttackDamageBonus);
|
||||
SpellDamageBonus = Random.Range(template.MinSpellDamageBonus, template.MaxSpellDamageBonus);
|
||||
CritChanceBonus = Random.Range(template.MinCritChanceBonus, template.MaxCritChanceBonus);
|
||||
CritDamageBonus = Random.Range(template.MinCritDamageBonus, template.MaxCritDamageBonus);
|
||||
MaxHealthBonus = Random.Range(template.MinMaxHealthBonus, template.MaxMaxHealthBonus);
|
||||
//HealthRegenBonus = Random.Range(template.MinHealthRegenBonus, template.MaxHealthRegenBonus);
|
||||
//MaxManaBonus = Random.Range(template.MinMaxManaBonus, template.MaxMaxManaBonus);
|
||||
//ManaRegenBonus = Random.Range(template.MinManaRegenBonus, template.MaxManaRegenBonus);
|
||||
ArmorBonus = Random.Range(template.MinArmorBonus, template.MaxArmorBonus);
|
||||
MagicResistanceBonus = Random.Range(template.MinMagicResistanceBonus, template.MaxMagicResistanceBonus);
|
||||
|
||||
// Randomize float stats with rounding
|
||||
AttackDamagePercentBonus = Mathf.Round(Random.Range(template.MinAttackDamagePercentBonus, template.MaxAttackDamagePercentBonus) * 100f) / 100f;
|
||||
SpellDamagePercentBonus = Mathf.Round(Random.Range(template.MinSpellDamagePercentBonus, template.MaxSpellDamagePercentBonus) * 100f) / 100f;
|
||||
//AttackSpeedPercentBonus = Mathf.Round(Random.Range(template.MinAttackSpeedPercentBonus, template.MaxAttackSpeedPercentBonus) * 100f) / 100f;
|
||||
CritChancePercentBonus = Mathf.Round(Random.Range(template.MinCritChancePercentBonus, template.MaxCritChancePercentBonus) * 100f) / 100f;
|
||||
CritDamagePercentBonus = Mathf.Round(Random.Range(template.MinCritDamagePercentBonus, template.MaxCritDamagePercentBonus) * 100f) / 100f;
|
||||
MaxHealthPercentBonus = Mathf.Round(Random.Range(template.MinMaxHealthPercentBonus, template.MaxMaxHealthPercentBonus) * 100f) / 100f;
|
||||
//HealthRegenPercentBonus = Mathf.Round(Random.Range(template.MinHealthRegenPercentBonus, template.MaxHealthRegenPercentBonus) * 100f) / 100f;
|
||||
//MaxManaPercentBonus = Mathf.Round(Random.Range(template.MinMaxManaPercentBonus, template.MaxMaxManaPercentBonus) * 100f) / 100f;
|
||||
//ManaRegenPercentBonus = Mathf.Round(Random.Range(template.MinManaRegenPercentBonus, template.MaxManaRegenPercentBonus) * 100f) / 100f;
|
||||
ArmorPercentBonus = Mathf.Round(Random.Range(template.MinArmorPercentBonus, template.MaxArmorPercentBonus) * 100f) / 100f;
|
||||
MagicResistancePercentBonus = Mathf.Round(Random.Range(template.MinMagicResistancePercentBonus, template.MaxMagicResistancePercentBonus) * 100f) / 100f;
|
||||
//DodgeChancePercentBonus = Mathf.Round(Random.Range(template.MinDodgeChancePercentBonus, template.MaxDodgeChancePercentBonus) * 100f) / 100f;
|
||||
//BlockChancePercentBonus = Mathf.Round(Random.Range(template.MinBlockChancePercentBonus, template.MaxBlockChancePercentBonus) * 100f) / 100f;
|
||||
//BlockEffectivenessPercentBonus = Mathf.Round(Random.Range(template.MinBlockEffectivenessPercentBonus, template.MaxBlockEffectivenessPercentBonus) * 100f) / 100f;
|
||||
//AreaEffectivenessPercentBonus = Mathf.Round(Random.Range(template.MinAreaEffectivenessPercentBonus, template.MaxAreaEffectivenessPercentBonus) * 100f) / 100f;
|
||||
//CooldownReductionPercentBonus = Mathf.Round(Random.Range(template.MinCooldownReductionPercentBonus, template.MaxCooldownReductionPercentBonus) * 100f) / 100f;
|
||||
//MovementSpeedPercentBonus = Mathf.Round(Random.Range(template.MinMovementSpeedPercentBonus, template.MaxMovementSpeedPercentBonus) * 100f) / 100f;
|
||||
//ReputationGainIncreasePercentBonus = Mathf.Round(Random.Range(template.MinReputationGainIncreasePercentBonus, template.MaxReputationGainIncreasePercentBonus) * 100f) / 100f;
|
||||
//GoldCostReductionPercentBonus = Mathf.Round(Random.Range(template.MinGoldCostReductionPercentBonus, template.MaxGoldCostReductionPercentBonus) * 100f) / 100f;
|
||||
return $"{equipmentTypeDef.ResourcesPath}/{icon.name}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy exact values from template
|
||||
AttackDamageBonus = template.AttackDamageBonus;
|
||||
SpellDamageBonus = template.SpellDamageBonus;
|
||||
CritChanceBonus = template.CritChanceBonus;
|
||||
CritDamageBonus = template.CritDamageBonus;
|
||||
MaxHealthBonus = template.MaxHealthBonus;
|
||||
HealthRegenBonus = template.HealthRegenBonus;
|
||||
MaxManaBonus = template.MaxManaBonus;
|
||||
ManaRegenBonus = template.ManaRegenBonus;
|
||||
ArmorBonus = template.ArmorBonus;
|
||||
MagicResistanceBonus = template.MagicResistanceBonus;
|
||||
return ""; // Manual icons don't have paths
|
||||
}
|
||||
|
||||
AttackDamagePercentBonus = template.AttackDamagePercentBonus;
|
||||
SpellDamagePercentBonus = template.SpellDamagePercentBonus;
|
||||
AttackSpeedPercentBonus = template.AttackSpeedPercentBonus;
|
||||
CritChancePercentBonus = template.CritChancePercentBonus;
|
||||
CritDamagePercentBonus = template.CritDamagePercentBonus;
|
||||
MaxHealthPercentBonus = template.MaxHealthPercentBonus;
|
||||
HealthRegenPercentBonus = template.HealthRegenPercentBonus;
|
||||
MaxManaPercentBonus = template.MaxManaPercentBonus;
|
||||
ManaRegenPercentBonus = template.ManaRegenPercentBonus;
|
||||
ArmorPercentBonus = template.ArmorPercentBonus;
|
||||
MagicResistancePercentBonus = template.MagicResistancePercentBonus;
|
||||
DodgeChancePercentBonus = template.DodgeChancePercentBonus;
|
||||
BlockChancePercentBonus = template.BlockChancePercentBonus;
|
||||
BlockEffectivenessPercentBonus = template.BlockEffectivenessPercentBonus;
|
||||
AreaEffectivenessPercentBonus = template.AreaEffectivenessPercentBonus;
|
||||
CooldownReductionPercentBonus = template.CooldownReductionPercentBonus;
|
||||
MovementSpeedPercentBonus = template.MovementSpeedPercentBonus;
|
||||
ReputationGainIncreasePercentBonus = template.ReputationGainIncreasePercentBonus;
|
||||
GoldCostReductionPercentBonus = template.GoldCostReductionPercentBonus;
|
||||
|
||||
|
||||
// Utility methods for debugging and UI
|
||||
public string GetStatSummary()
|
||||
{
|
||||
if (statBonuses.Count == 0) return "No stat bonuses";
|
||||
|
||||
var summary = new List<string>();
|
||||
foreach (var bonus in GetAllNonZeroBonuses())
|
||||
{
|
||||
var parts = new List<string>();
|
||||
if (bonus.HasFlatBonus)
|
||||
parts.Add($"+{bonus.flatValue:F0}");
|
||||
if (bonus.HasPercentBonus)
|
||||
parts.Add($"+{bonus.percentValue:P1}");
|
||||
|
||||
summary.Add($"{bonus.statDefinition.DisplayName}: {string.Join(" ", parts)}");
|
||||
}
|
||||
|
||||
EquipmentType = template.EquipmentType;
|
||||
WeaponType = template.WeaponType;
|
||||
return string.Join("\n", summary);
|
||||
}
|
||||
|
||||
CraftableBase = template.CraftableBase;
|
||||
MaxTotalUniqueStatsIncreasedByStones = template.MaxTotalUniqueStatsIncreasedByStones;
|
||||
[ContextMenu("Log Stat Summary")]
|
||||
private void LogStatSummary()
|
||||
{
|
||||
Debug.Log($"=== {ItemName} Stats ===\n{GetStatSummary()}");
|
||||
}
|
||||
}
|
||||
@ -14,11 +14,7 @@ namespace Kryz.CharacterStats.Examples
|
||||
|
||||
public static ItemInstance ConvertTemplateIntoInstance(Item template)
|
||||
{
|
||||
if(template is EquippableItem item)
|
||||
{
|
||||
return new EquippableItemInstance(item, item.CraftableBase);
|
||||
}
|
||||
else if(template is HiddenMap map)
|
||||
if(template is HiddenMap map)
|
||||
{
|
||||
return new HiddenMapInstance(map);
|
||||
}
|
||||
@ -30,10 +26,6 @@ namespace Kryz.CharacterStats.Examples
|
||||
}
|
||||
public static ItemInstance ConvertTemplateIntoInstance(Item template, int templateIndex)
|
||||
{
|
||||
if (template is EquippableItem item)
|
||||
{
|
||||
return new EquippableItemInstance(item, item.CraftableBase);
|
||||
}
|
||||
return new ItemInstance(template, templateIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,8 +107,8 @@ namespace Kryz.CharacterStats.Examples
|
||||
statPanel = FindObjectOfType<StatPanel>();
|
||||
|
||||
statPanel.SetPlayerStats(this);
|
||||
statPanel.SetStats(Cunning, Flow, Presence);
|
||||
statPanel.SetSecondaryStats(AttackDamage, SpellDamage, AttackSpeed, CritChance, CritDamage, AuraPower, MaxHealth, HealthRegen, MaxMana, ManaRegen, Armor, MagicResistance, DodgeChance, BlockChance, BlockEffectiveness, AreaEffectiveness, CooldownReduction, MovementSpeed, ReputationGainIncrease, GoldCostReduction);
|
||||
statPanel.SetStats(primaryStatsDictionary);
|
||||
statPanel.SetSecondaryStats(secondaryStatsDictionary);
|
||||
//TODO: statPanel set misc stats (area, cdr, movespeed, rep, gold
|
||||
statPanel.UpdateStatValues();
|
||||
statPanel.SetCharacterInfo(PlayerDataHandler.Instance.currentCharacterName.Value, level.currentLevel.ToString(), reputationLevel.currentLevel.ToString());
|
||||
@ -294,11 +294,10 @@ namespace Kryz.CharacterStats.Examples
|
||||
|
||||
public void UpdateStatsBasedOnLevel()
|
||||
{
|
||||
|
||||
MaxHealth.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource);
|
||||
GetStat("MaxHealth").RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource);
|
||||
|
||||
//Debug.Log("MAX HEALTH BASE VALUE: " + MaxHealth.BaseValue);
|
||||
MaxHealth.AddModifier(new StatModifier(MaxHealth.BaseValue * (level.currentLevel - 1) * GameConstants.CharacterStatsBalancing.BaseMaxHealthGrowthPerLevel, StatModType.Flat, GameConstants.ObjectSources.LevelSource));
|
||||
GetStat("MaxHealth").AddModifier(new StatModifier(GetStat("MaxHealth").BaseValue * (level.currentLevel - 1) * GameConstants.CharacterStatsBalancing.BaseMaxHealthGrowthPerLevel, StatModType.Flat, GameConstants.ObjectSources.LevelSource));
|
||||
|
||||
|
||||
onUpdateStatValues.Invoke();
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using TMPro;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@ -52,20 +54,23 @@ namespace Kryz.CharacterStats.Examples
|
||||
this.playerStats = playerStats;
|
||||
}
|
||||
|
||||
public void SetStats(params CharacterStat[] charStats)
|
||||
public void SetStats(Dictionary<string, CharacterStat> primaryStats)
|
||||
{
|
||||
stats = charStats;
|
||||
// Store both dictionary values as array (for compatibility with existing methods)
|
||||
stats = primaryStats.Values.ToArray();
|
||||
|
||||
if (stats.Length > statDisplays.Length)
|
||||
for (int i = 0; i < statDisplays.Length && i < primaryStats.Count; i++)
|
||||
{
|
||||
Debug.LogError("Not Enough Stat Displays!");
|
||||
return;
|
||||
var stat = primaryStats.Values.ElementAt(i);
|
||||
statDisplays[i].Stat = stat;
|
||||
statDisplays[i].NameText.text = stat.statDefinition.DisplayName; // This requires updating CharacterStat first
|
||||
statDisplays[i].gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < statDisplays.Length; i++)
|
||||
// Hide unused displays
|
||||
for (int i = primaryStats.Count; i < statDisplays.Length; i++)
|
||||
{
|
||||
statDisplays[i].Stat = i < stats.Length ? stats[i] : null;
|
||||
statDisplays[i].gameObject.SetActive(i < stats.Length);
|
||||
statDisplays[i].gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
unallocated.ValueText.text = playerStats.AvailablePointsToAllocate.ToString();
|
||||
@ -79,19 +84,25 @@ namespace Kryz.CharacterStats.Examples
|
||||
addStatButtons[2].onClick.AddListener(() => AllocateStat(2));
|
||||
resetAllocated.onClick.AddListener(ResetAllocatedStats);
|
||||
}
|
||||
public void SetSecondaryStats(params CharacterStat[] secondaryStats)
|
||||
public void SetSecondaryStats(Dictionary<string, CharacterStat> secondaryStats)
|
||||
{
|
||||
this.secondaryStats = secondaryStats;
|
||||
// Store as array for compatibility
|
||||
this.secondaryStats = secondaryStats.Values.ToArray();
|
||||
|
||||
if (secondaryStats.Length > secondaryStatDisplays.Length)
|
||||
int index = 0;
|
||||
foreach (var kvp in secondaryStats)
|
||||
{
|
||||
Debug.LogError("Not Enough Stat Displays!");
|
||||
return;
|
||||
if (index >= secondaryStatDisplays.Length) break;
|
||||
|
||||
secondaryStatDisplays[index].Stat = kvp.Value;
|
||||
secondaryStatDisplays[index].NameText.text = kvp.Value.statDefinition.DisplayName;
|
||||
index++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondaryStatDisplays.Length; i++)
|
||||
// Hide unused displays
|
||||
for (int i = index; i < secondaryStatDisplays.Length; i++)
|
||||
{
|
||||
secondaryStatDisplays[i].Stat = secondaryStats[i];
|
||||
secondaryStatDisplays[i].gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,10 +13,8 @@ public class DropTable : MonoBehaviour
|
||||
|
||||
[SerializeField] private GameEvent_Int onCoinDrop;
|
||||
|
||||
public List<EquippableItem> guaranteedItemDrop = new List<EquippableItem>();
|
||||
[Header("Only one of the following list is guaranteed to drop.")]
|
||||
public List<WeightedDrop> guaranteedOnlyOnePerKill = new List<WeightedDrop>();
|
||||
public List<EquippableItem> extraDrops = new List<EquippableItem>();
|
||||
public List<Item> nonEquippablesDrops = new List<Item>();
|
||||
|
||||
[Space]
|
||||
@ -66,17 +64,11 @@ public class DropTable : MonoBehaviour
|
||||
|
||||
onCoinDrop.Raise(finalCoinAmount);
|
||||
|
||||
for (int i = 0; i < guaranteedItemDrop.Count; i++)
|
||||
{
|
||||
instantiatedDrop = Instantiate(interactableDropPrefab, spawnPosition, this.transform.rotation);
|
||||
itemDrop = instantiatedDrop.GetComponent<EquippableItemDrop>();
|
||||
itemDrop.itemDrop = Item.ConvertTemplateIntoInstance(guaranteedItemDrop[i]);
|
||||
}
|
||||
|
||||
if (guaranteedOnlyOnePerKill.Count > 0 && WeightedDrop.HaveDropsForDifficulty(weightedDropLootTable, GameDifficultyController.Instance.GetCurrentDifficultyLevel()))
|
||||
{
|
||||
possibleItem = WeightedDrop.GetRandomDrop(guaranteedOnlyOnePerKill, GameDifficultyController.Instance.GetCurrentDifficultyLevel());
|
||||
spawnPosition = guaranteedItemDrop.Count > 0 ? this.transform.position + Vector3.one * 0.3f : this.transform.position;
|
||||
//spawnPosition = guaranteedItemDrop.Count > 0 ? this.transform.position + Vector3.one * 0.3f : this.transform.position;
|
||||
spawnPosition.y = 0f;
|
||||
instantiatedDrop = Instantiate(interactableDropPrefab, spawnPosition, this.transform.rotation);
|
||||
itemDrop = instantiatedDrop.GetComponent<EquippableItemDrop>();
|
||||
@ -109,10 +101,7 @@ public class DropTable : MonoBehaviour
|
||||
if (possibleItem == null) return;
|
||||
|
||||
spawnPosition = this.transform.position;
|
||||
if (guaranteedItemDrop.Count > 0)
|
||||
{
|
||||
spawnPosition += Vector3.one * 0.15f;
|
||||
}
|
||||
|
||||
if(guaranteedOnlyOnePerKill.Count > 0)
|
||||
{
|
||||
spawnPosition += Vector3.one * 0.15f;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user