281 lines
9.2 KiB
C#
281 lines
9.2 KiB
C#
using Kryz.CharacterStats;
|
|
using Kryz.CharacterStats.Examples;
|
|
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
|
|
{
|
|
[Header("Equipment Identity")]
|
|
public EquipmentType EquipmentType;
|
|
public WeaponType WeaponType;
|
|
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;
|
|
public int MaxTotalUniqueStatsIncreasedByStones;
|
|
public List<string> AddedStoneStats = new List<string>();
|
|
|
|
// Helper properties
|
|
public bool IsWeapon => EquipmentType == EquipmentType.Weapon1 || EquipmentType == EquipmentType.Weapon2;
|
|
public bool IsTwoHandedWeapon => IsWeapon && WeaponType.IsTwoHanded();
|
|
public bool IsOneHandedWeapon => IsWeapon && WeaponType.IsOneHanded();
|
|
|
|
public void Equip(PlayerCharacterStats characterStats)
|
|
{
|
|
foreach (var bonus in statBonuses)
|
|
{
|
|
if (bonus.statDefinition == null || !bonus.HasAnyBonus) continue;
|
|
|
|
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));
|
|
}
|
|
|
|
// 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 characterStats)
|
|
{
|
|
// 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 = GetNonZeroStatsFromStone(stone);
|
|
var currentStats = GetAllNonZeroBonuses().Select(b => b.statDefinition.StatKey).ToList();
|
|
|
|
int newUniqueStats = stoneStats.Except(currentStats).Count();
|
|
|
|
// Ensure we don't exceed the max unique stats cap
|
|
if (AddedStoneStats.Count + newUniqueStats > MaxTotalUniqueStatsIncreasedByStones)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool TryAddCraftingStone(CraftingStatStone stone)
|
|
{
|
|
if (!CanAddCraftingStone(stone)) return false;
|
|
|
|
var stoneStats = GetNonZeroStatsFromStone(stone);
|
|
var currentStats = GetAllNonZeroBonuses().Select(b => b.statDefinition.StatKey).ToList();
|
|
|
|
// Track new stats being added
|
|
foreach (var statKey in stoneStats)
|
|
{
|
|
if (!currentStats.Contains(statKey) && !AddedStoneStats.Contains(statKey))
|
|
{
|
|
AddedStoneStats.Add(statKey);
|
|
}
|
|
}
|
|
|
|
// 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> GetNonZeroStatsFromStone(CraftingStatStone stone)
|
|
{
|
|
var nonZeroStats = new List<string>();
|
|
var fields = stone.GetType().GetFields();
|
|
|
|
foreach (var field in fields)
|
|
{
|
|
if (field.GetValue(stone) is int intValue && intValue != 0 && field.Name.ToLower().Contains("bonus"))
|
|
{
|
|
nonZeroStats.Add(field.Name);
|
|
}
|
|
else if (field.GetValue(stone) is float floatValue && !Mathf.Approximately(floatValue, 0f) && field.Name.ToLower().Contains("bonus"))
|
|
{
|
|
nonZeroStats.Add(field.Name);
|
|
}
|
|
}
|
|
|
|
return nonZeroStats;
|
|
}
|
|
|
|
// This method needs to be updated based on your CraftingStatStone structure
|
|
private void AddStatsFromStone(CraftingStatStone stone)
|
|
{
|
|
// 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()
|
|
{
|
|
EquipmentType = EquipmentType.Helmet;
|
|
WeaponType = WeaponType.Sword;
|
|
CraftableBase = false;
|
|
MaxTotalUniqueStatsIncreasedByStones = 0;
|
|
statBonuses = new List<ItemStatBonus>();
|
|
AddedStoneStats = new List<string>();
|
|
templateIndex = -1;
|
|
}
|
|
|
|
// Constructor for generating from EquipmentTypeDefinition (recommended approach)
|
|
public EquippableItemInstance(EquippableItemTypeDefinition equipmentTypeDef, string itemName, Sprite icon, string iconPath = null)
|
|
{
|
|
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;
|
|
|
|
// You can set default sell prices here or pass them as parameters
|
|
sellPricePlayer = 100;
|
|
sellPriceVendor = 50;
|
|
description = $"A {equipmentTypeDef.GetDisplayName()}";
|
|
}
|
|
|
|
// Helper method to set icon with path
|
|
public void SetIcon(Sprite icon, string iconPath)
|
|
{
|
|
Icon = icon;
|
|
IconPath = iconPath;
|
|
}
|
|
|
|
// Helper method to get icon path from EquipmentTypeDefinition
|
|
public static string GetIconPathFromEquipmentType(EquippableItemTypeDefinition equipmentTypeDef, Sprite icon)
|
|
{
|
|
if (equipmentTypeDef.UseResourcesFolder && !string.IsNullOrEmpty(equipmentTypeDef.ResourcesPath))
|
|
{
|
|
return $"{equipmentTypeDef.ResourcesPath}/{icon.name}";
|
|
}
|
|
return ""; // Manual icons don't have paths
|
|
}
|
|
|
|
|
|
|
|
// 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)}");
|
|
}
|
|
|
|
return string.Join("\n", summary);
|
|
}
|
|
|
|
[ContextMenu("Log Stat Summary")]
|
|
private void LogStatSummary()
|
|
{
|
|
Debug.Log($"=== {ItemName} Stats ===\n{GetStatSummary()}");
|
|
}
|
|
} |