TrimKit.StatDictionary 1.1.0

dotnet add package TrimKit.StatDictionary --version 1.1.0
                    
NuGet\Install-Package TrimKit.StatDictionary -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TrimKit.StatDictionary" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TrimKit.StatDictionary" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="TrimKit.StatDictionary" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TrimKit.StatDictionary --version 1.1.0
                    
#r "nuget: TrimKit.StatDictionary, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TrimKit.StatDictionary@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TrimKit.StatDictionary&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=TrimKit.StatDictionary&version=1.1.0
                    
Install as a Cake Tool

TrimKit.StatDictionary

StatDictionary is a simple, type-safe stat container designed for games that rely on numerical attributes - whether for character attributes, item properties, or entire gameplay systems.

It provides a lightweight, deterministic way to manage values and modifiers in a clean, unified manner. Instead of manually tracking fields like health, damage, or experience across different objects, you can store and manipulate them all through a single API that supports direct values, percentage-based modifiers, computed formulas, and value clamping - all with built-in validation and safety checks.

Some use cases:

  • Character stats in an RPG (health, strength, defense, etc.)
  • Item attributes (damage, accuracy, etc.)
  • Procedural generation or balancing tools (scalable numeric profiles)
  • Buff/Debuff systems (temporary modifiers)
  • Basically any system where values need to be dynamically modified

Use it as a drop-in stat core for RPGs, shooters, roguelikes, strategy games, or a general-purpose numeric container for managing large number of values.

Features

  • Strongly typed via generics (StatDictionary<T> where T : Enum)
  • Clean separation between base values and modifiers, which can be applied separately at any time
  • Computed stats via registered formulas (RegisterFormula, RecalculateFormulas)
  • Per-stat clamping with configurable min-max ranges
  • Ability to work with stat containers as a whole (merge, clone, scale)
  • Adjustable precision (eliminates epsilon problem)
  • Simple, expressive API covering most use cases
  • Fully deterministic and side-effect free
  • Optional locking system to prevent modification after initialization
  • No external dependencies

Installation

Use provided nuget package or download the source.

NuGet

🔧 dotnet add package TrimKit.StatDictionary

Quick start

Decide on your stats enum:

public enum Stats
{
    Health,
    Stamina,
    Strength,
    Agility,
    Intelligence
    // etc.
}

Create and manipulate your stats:

// create a stat dictionary with precision up to 8 digits
var stats = new StatDictionary<Stats>(precision: 8);

// set base values
stats.SetValue(Stats.Health, 100);
stats.SetValue(Stats.Strength, 20);

// add modifiers
stats.AddValue(Stats.Health, 100);     // now 200
stats.AddPercent(Stats.Health, 10);   // will be +10%

// apply all percentage modifiers
stats.ApplyPercentages(); // now Health = 220

// etc.

Use stored formulas to calculate derived stats:

// register a computed formula
stats.RegisterFormula(Stats.Health, ctx => ctx.Values[Stats.Strength] * 2);
stats.RegisterFormula(Stats.Stamina, ctx => ctx.Values[Stats.Agility] * 5);

// and recalculate at any time
stats.RecalculateFormulas();

Use value clamps:

// defines a clamp for Health to be between 0 and 100
stats.SetClamp(Stats.Health, 0, 100);

// apply when needed
stats.ApplyClamps();

Merge, clone, or reset:

var other = new StatDictionary<Stats>();
other.SetValue(Stats.Health, 25);
other.SetPercent(Stats.Health, 5);

// combine two dictionaries
stats.Merge(other);

// clone
var copy = stats.Clone();

// reset what isn't needed
stats.ClearValues();
stats.ClearPercentages();
stats.ClearFormulas();
stats.ClearClamps();

Notes

  • This library uses double to store all values, so you will inevitably encounter epsilon problem (i.e. stuff like 100.000000000000003) at some point unless you enable rounding in the constructor, which is recommended.
  • StatDictionary is not thread-safe by design. If you need to share it between threads, wrap access in your own synchronization mechanism.
  • When first instantiated, StatDictionary<T> validates that your enum does not contain duplicate values (aliases). If duplicates exist, it throws an exception at startup to prevent logic bugs.
  • Formulas are recalculated using a snapshot of current values, ensuring formula order doesn't affect results.

API Overview

Constructors

Constructor Description
StatDictionary(int precision = -1) Creates StatDictionary with a given precision. Use 0�15 to enable or -1 disables rounding.

Base Values

Method / Property Description
void SetValue(T stat, double amount) Sets base value for a stat.
void AddValue(T stat, double amount) Adds to base value.
double GetValue(T stat) Gets current base value.
bool HasValue(T stat) Returns true if the given stat has a stored value.
bool TryGetValue(T stat, out double value) Attempts to get a stat value safely.
double this[T stat] Indexer for direct access.
void ScaleValues(double factor) Multiplies all base values by a factor.
void ClearValues() Clears all base values.

Percentage Modifiers

Method / Property Description
void SetPercent(T stat, double amount) Sets a percentage modifier.
void AddPercent(T stat, double amount) Adds to a percentage modifier.
double GetPercent(T stat) Gets the current percentage modifier.
bool HasPercent(T stat) Returns true if the given stat has a percentage modifier.
bool TryGetPercent(T stat, out double value) Attempts to get a percentage safely.
void ApplyPercentages(bool discardUnused = false) Applies (bakes in) percentage modifiers.
void ScalePercentages(double factor) Scales all percentages by a factor.
void ClearPercentages() Clears all percentage modifiers.

Computed Formulas

Method / Property Description
void RegisterFormula(T stat, Func<StatContext, double> formula) Registers or replaces a formula used to calculate a stat dynamically.
bool UnregisterFormula(T stat) Removes a formula from a stat.
bool HasFormula(T stat) Returns true if a formula is registered for the stat.
void RecalculateFormulas() Recalculates values using registered formulas.
void ClearFormulas() Removes all formulas.

Clamps

Method / Property Description
void SetClamp(T stat, double min, double max) Defines a min-max range for a stat.
bool RemoveClamp(T stat) Removes a clamp if present.
bool HasClamp(T stat) Returns true if a clamp is defined for the stat.
void ApplyClamps(bool enforceForMissingStats = false) Applies clamps to ensure values stay within defined ranges.
void ClearClamps() Removes all clamps.

Misc

Method / Property Description
StatDictionary<T> Merge(StatDictionary<T> other, bool mergeFormulas = false, bool mergeClamps = false) Merges another dictionary into this one.
StatDictionary<T> Clone() Creates a copy.
bool IsLocked Returns true if the container is locked.
void Lock() Prevents further modifications.
bool IsEmpty Returns true if no stats, percentages, formulas, or clamps are stored.

Changes

  • v1.1 - Expanded API with additional helper methods (Has*, TryGet*, IsEmpty, etc.)
  • v1.0 - Initial release.

TrimKit Collection

This library is part of the TrimKit collection - a set of small, focused C# libraries that make game development more enjoyable by reducing the need for boilerplate code and providing simple reusable building blocks that can be dropped into any project.

Each module is independent and can be used standalone or combined with others for a complete lightweight foundation.

Contribution

Contributions are welcome!

You can start with submitting an issue on GitHub.

License

This library is released under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 189 11/2/2025
1.0.0 166 10/16/2025