Attributes¶
A general container for the numbers a character is made of — values keyed by owner and id, with bounds, change events, and the seams that turn a stored value into a stat.
What it does¶
An AttributeSet on an owner holds attributes: authored rows in the inspector, or ids created at runtime by the first write. Consumers read effective values through IAttributeSource on the owner's chain; other systems contribute through IAttributeModifierProvider; and how contributions combine is supplied by your project through IAttributeCombiner — never by the framework.
There is no fixed stat list¶
The framework does not know what strength is. An attribute is a string id, a float base value and optional bounds; what the ids mean is your game's vocabulary. That is a decision, not an absence — a shipped stat sheet would decide what kinds of characters every game has, and it is the one decision this system refuses to take on your behalf.
Where attributes become stats¶
The consumption side already ships, spread across the systems that own it: ICraftingLevelSource, IAttackerDamageModifier, IStatusResistance and their siblings. Attributes is the supply side, and the adapters under Integrations/Attributes are the bridge — the shipped one answers Crafting's level seam from an attribute you name.
What you need installed¶
Attributes ships in the Complete package only. Its core depends on nothing: every other system can be deleted and the container still compiles, and each adapter lives in its own assembly that compiles only when both of its systems are installed.
TL;DR¶
TL;DR
- Want to understand Attributes → Overview
- Want the three ideas it is built on → Mental Model
- Want to build safely → Public API
- Want to extend cleanly → Integration Surfaces
- Want to know what it will never do → System Boundaries
- Want the behavioural contract → System Guarantees Matrix
- A modifier isn't doing anything → FAQ
The two things worth knowing before you wire one up: effective values are computed reads with no combiner shipped — until you supply one, reads return clamped base values and providers are not consulted — and change events cover base values only, carrying both the old and new value.