462 lines
22 KiB
C#

using Kryz.CharacterStats;
using Kryz.CharacterStats.Examples;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
[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]
public EquipmentType EquipmentType;
[Space]
// NEW: Add WeaponType for weapon items
public WeaponType WeaponType;
[Space]
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
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)
{
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);
}
public bool CanAddCraftingStone(CraftingStatStone stone)
{
if (!CraftableBase) return false;
var stoneStats = GetNonZeroStats(stone);
var itemNonZeroStats = GetNonZeroStats(this);
int newUniqueStats = stoneStats.Except(itemNonZeroStats).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 true;
}
public bool TryAddCraftingStone(CraftingStatStone stone)
{
if (!CanAddCraftingStone(stone)) return false;
var stoneStats = GetNonZeroStats(stone);
var itemStats = GetNonZeroStats(this);
for (int i = 0; i < stoneStats.Count; i++)
{
if (!itemStats.Contains(stoneStats[i]) && !AddedStoneStats.Contains(stoneStats[i]))
AddedStoneStats.Add(stoneStats[i]);
}
// Add stats from the stone to the item
AddStats(stone);
return true;
}
private List<string> GetNonZeroStats(object stats)
{
var nonZeroStats = new List<string>();
var fields = stats.GetType().GetFields();
foreach (var field in fields)
{
if (field.GetValue(stats) 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"))
{
nonZeroStats.Add(field.Name);
}
}
return nonZeroStats;
}
//TODO: Add new stats to stones too
private void AddStats(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;
}
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
CraftableBase = false;
MaxTotalUniqueStatsIncreasedByStones = 0;
templateIndex = -1;
}
public EquippableItemInstance(EquippableItem template)
{
ItemName = template.ItemName;
Icon = template.Icon;
sellPricePlayer = template.sellPricePlayer;
sellPriceVendor = template.sellPriceVendor;
description = template.description;
templateIndex = ItemIndexer.Instance.Items.IndexOf(template);
// 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;
}
public EquippableItemInstance(EquippableItem template, bool randomizeStats)
{
ItemName = template.ItemName;
Icon = template.Icon;
sellPricePlayer = template.sellPricePlayer;
sellPriceVendor = template.sellPriceVendor;
description = template.description;
templateIndex = ItemIndexer.Instance.Items.IndexOf(template);
if (randomizeStats)
{
// 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;
}
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;
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;
}
}