I have this stat system that I’m using in my game, I’m currently trying to pull a reference from the stat value and apply it to my weapons, but I honestly don’t really know where to start.
These are my script that handle this:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
[Serializable]
public class CharacterStat
{
public float BaseValue;
protected bool isDirty = true;
protected float lastBaseValue;
protected float _value;
public virtual float Value {
get {
if(isDirty || lastBaseValue != BaseValue) {
lastBaseValue = BaseValue;
_value = CalculateFinalValue();
isDirty = false;
}
return _value;
}
}
protected readonly List<StatModifier> statModifiers;
public readonly ReadOnlyCollection<StatModifier> StatModifiers;
public CharacterStat()
{
statModifiers = new List<StatModifier>();
StatModifiers = statModifiers.AsReadOnly();
}
public CharacterStat(float baseValue) : this()
{
BaseValue = baseValue;
}
public virtual void AddModifier(StatModifier mod)
{
isDirty = true;
statModifiers.Add(mod);
}
public virtual bool RemoveModifier(StatModifier mod)
{
if (statModifiers.Remove(mod))
{
isDirty = true;
return true;
}
return false;
}
public virtual bool RemoveAllModifiersFromSource(object source)
{
int numRemovals = statModifiers.RemoveAll(mod => mod.Source == source);
if (numRemovals > 0)
{
isDirty = true;
return true;
}
return false;
}
protected virtual int CompareModifierOrder(StatModifier a, StatModifier b)
{
if (a.Order < b.Order)
return -1;
else if (a.Order > b.Order)
return 1;
return 0; //if (a.Order == b.Order)
}
protected virtual float CalculateFinalValue()
{
float finalValue = BaseValue;
float sumPercentAdd = 0;
statModifiers.Sort(CompareModifierOrder);
for (int i = 0; i < statModifiers.Count; i++)
{
StatModifier mod = statModifiers[i];
if (mod.Type == StatModType.Flat)
{
finalValue += mod.Value;
}
else if (mod.Type == StatModType.PercentAdd)
{
sumPercentAdd += mod.Value;
if (i + 1 >= statModifiers.Count || statModifiers[i + 1].Type != StatModType.PercentAdd)
{
finalValue *= 1 + sumPercentAdd;
sumPercentAdd = 0;
}
}
else if (mod.Type == StatModType.PercentMult)
{
finalValue *= 1 + mod.Value;
}
}
// Workaround for float calculation errors, like displaying 12.00001 instead of 12
return (float)Math.Round(finalValue, 4);
}
}
using UnityEngine;
using UnityEngine.UI;
public class Character : MonoBehaviour
{
public int Health = 50;
public CharacterStat Strength;
public CharacterStat Agility;
public CharacterStat Intelligence;
public CharacterStat Vitality;
[SerializeField] Inventory inventory;
[SerializeField] EquipmentPanel equipmentPanel;
[SerializeField] StatPanel statPanel;
[SerializeField] ItemTooltip itemTooltip;
[SerializeField] Image draggableItem;
private ItemSlot dragItemSlot;
private void OnValidate()
{
if (itemTooltip == null)
itemTooltip = FindObjectOfType<ItemTooltip>();
}
private void Awake()
{
statPanel.SetStats(Strength, Agility, Intelligence, Vitality);
statPanel.UpdateStatValues();
inventory.OnRightClickEvent += Equip;
equipmentPanel.OnRightClickEvent += Unequip;
inventory.OnPointerEnterEvent += ShowTooltip;
equipmentPanel.OnPointerEnterEvent += ShowTooltip;
inventory.OnPointerExitEvent += HideTooltip;
equipmentPanel.OnPointerExitEvent += HideTooltip;
inventory.OnBeginDragEvent += BeginDrag;
equipmentPanel.OnBeginDragEvent += BeginDrag;
inventory.OnEndDragEvent += EndDrag;
equipmentPanel.OnEndDragEvent += EndDrag;
inventory.OnDragEvent += Drag;
equipmentPanel.OnDragEvent += Drag;
inventory.OnDropEvent += Drop;
equipmentPanel.OnDropEvent += Drop;
}
private void Use(ItemSlot itemSlot)
{
if (itemSlot.Item is UsableItem)
{
UsableItem usableItem = (UsableItem)itemSlot.Item;
usableItem.Use(this);
if (usableItem.IsConsumable)
{
inventory.RemoveItem(usableItem);
usableItem.Destroy();
}
}
}
private void Equip(ItemSlot itemSlot)
{
if (itemSlot.Item is EquippableItem)
{
Equip((EquippableItem)itemSlot.Item);
}
}
private void Unequip(ItemSlot itemSlot)
{
EquippableItem equippableItem = itemSlot.Item as EquippableItem;
if (equippableItem != null)
{
Unequip(equippableItem);
}
}
private void ShowTooltip(ItemSlot itemSlot)
{
if (itemSlot.Item != null)
{
itemTooltip.ShowTooltip(itemSlot.Item);
}
if (itemSlot.Item is UsableItem)
{
UsableItem usableItem = (UsableItem)itemSlot.Item;
usableItem.Use(this);
if (usableItem.IsConsumable)
{
inventory.RemoveItem(usableItem);
usableItem.Destroy();
}
}
}
private void HideTooltip(ItemSlot itemSlot)
{
itemTooltip.HideTooltip();
}
private void BeginDrag(ItemSlot itemSlot)
{
if (itemSlot.Item != null)
{
dragItemSlot = itemSlot;
draggableItem.sprite = itemSlot.Item.Icon;
draggableItem.transform.position = Input.mousePosition;
draggableItem.enabled = true;
}
}
private void EndDrag(ItemSlot itemSlot)
{
dragItemSlot = null;
draggableItem.enabled = false;
}
private void Drag(ItemSlot itemSlot)
{
if (draggableItem.enabled)
{
draggableItem.transform.position = Input.mousePosition;
}
}
private void Drop(ItemSlot dropItemSlot)
{
if (dragItemSlot == null) return;
if (dropItemSlot.CanReceiveItem(dragItemSlot.Item) && dragItemSlot.CanReceiveItem(dropItemSlot.Item))
{
EquippableItem dragItem = dragItemSlot.Item as EquippableItem;
EquippableItem dropItem = dropItemSlot.Item as EquippableItem;
if (dragItemSlot is EquipmentSlot)
{
if (dragItem != null) dragItem.Unequip(this);
if (dropItem != null) dropItem.Equip(this);
}
if (dropItemSlot is EquipmentSlot)
{
if (dragItem != null) dragItem.Equip(this);
if (dropItem != null) dropItem.Unequip(this);
}
statPanel.UpdateStatValues();
Item draggedItem = dragItemSlot.Item;
int draggedItemAmount = dragItemSlot.Amount;
dragItemSlot.Item = dropItemSlot.Item;
dragItemSlot.Amount = dropItemSlot.Amount;
dropItemSlot.Item = draggedItem;
dropItemSlot.Amount = draggedItemAmount;
}
}
public void Equip(EquippableItem item)
{
if (inventory.RemoveItem(item))
{
EquippableItem previousItem;
if (equipmentPanel.AddItem(item, out previousItem))
{
if (previousItem != null)
{
inventory.AddItem(previousItem);
previousItem.Unequip(this);
statPanel.UpdateStatValues();
}
item.Equip(this);
statPanel.UpdateStatValues();
}
else
{
inventory.AddItem(item);
}
}
}
public void Unequip(EquippableItem item)
{
if (!inventory.IsFull() && equipmentPanel.RemoveItem(item))
{
item.Unequip(this);
statPanel.UpdateStatValues();
inventory.AddItem(item);
}
}
}
These scripts control this interface:

I’m currently trying to figure out how to apply these values to my weapon, I know it’s got to be somewhere in these two scripts but I can’t pinpoint the right language.
I’ve tried putting a public reference on my weapons public CharacterStat strength; and putting this on my weapons TakeDamage(10 + strength); but it doesn’t seem to be the correct way to reference it.
I want to pull from the value of the strength stat and add it to weapon damage so weapon damage grows with that stat but I can’t seem to get the correct terminology, can someone explain to me how this should look? I’d really appreciate any constructive help to solve this.