Skip to main content

Stat Modifier

AchUtils includes a stat calculation pipeline for RPGs, idle games, strategy games, and any game with additive and percentage modifiers. Final values are calculated in this order: Flat -> PercentAdd -> PercentMultiply.

Formula

Final = (Base + sum(Flat)) * (1 + sum(PercentAdd)) * product(PercentMultiply)

Example:

Base Attack : 100
Weapon : +20 (Flat)
Buff : +30% (PercentAdd)
Passive : x1.15 (PercentMultiply)

Final = (100 + 20) * (1 + 0.30) * 1.15
= 179.4

Structure

StatSheet - Stat container (pure C#)
└── Dictionary<string, StatValue>

StatValue - Single stat and modifier list
└── List<StatModifier>

StatSheetComponent - MonoBehaviour wrapper for GameObjects

Quick Start

using AchUtils.StatModifier;

var sheet = new StatSheet();

sheet.SetBase("Attack", 100f);
sheet.SetBase("Defense", 50f);

sheet.AddModifier("Attack", new StatModifier("weapon_sword", ModifierType.Flat, 20f));
sheet.AddModifier("Attack", new StatModifier("buff_rage", ModifierType.PercentAdd, 0.3f));
sheet.AddModifier("Attack", new StatModifier("passive_might", ModifierType.PercentMultiply, 0.15f));

float finalAtk = sheet.GetFinal("Attack"); // 179.4

StatModifier Constructor

new StatModifier(
source: "weapon_sword",
type: ModifierType.Flat,
value: 20f,
priority: 0
)

API

StatSheet

void SetBase(string key, float value)
float GetFinal(string key)
StatValue GetStat(string key)

void AddModifier(string key, StatModifier modifier)
void RemoveModifier(string key, string source)
void RemoveAllModifiers(string key)

bool HasStat(string key)
event Action<string> OnStatChanged

StatValue

float BaseValue { get; set; }
float FinalValue { get; }

void AddModifier(StatModifier modifier)
bool RemoveModifier(string source)
void RemoveAllModifiers()

event Action OnChanged

Use With MonoBehaviour

var sheetComp = GetComponent<StatSheetComponent>();
sheetComp.Sheet.SetBase("HP", 500f);
sheetComp.Sheet.SetBase("Attack", 100f);

sheetComp.Sheet.AddModifier("Attack",
new StatModifier("equip_sword", ModifierType.Flat, 35f));

sheetComp.Sheet.RemoveModifier("Attack", "equip_sword");

Observe Stat Changes

sheet.OnStatChanged += statKey =>
{
if (statKey == "HP") UpdateHPBar(sheet.GetFinal("HP"));
};

Source Naming

"base" - Base value
"equip_{id}" - Equipment
"buff_{id}" - Buff system integration
"passive_{id}" - Passive skill
"set_{id}" - Set effect

::: tip Buff integration StatModifyEffect updates StatSheet automatically when a buff is applied or removed.

See Buff / Debuff. :::