🎛️ Crafting — Modifiers¶
The Modifiers folder contains runtime components that implement ICraftingModifier.
Attach them to GameObjects (typically the crafter/owner or a parent in its hierarchy)
to dynamically influence crafting behaviour.
Modifiers mutate CraftAdjustments, not the recipe itself.
Truth-pass note: This README describes the modifier behaviour implemented by the current Crafting service. Where behaviour depends on service settings, that dependency is stated explicitly.
🎯 Purpose¶
Modifiers allow runtime changes to craft behaviour by adjusting:
- Craft duration (
durationSeconds) - Currency cost scaling (
currencyMultiplier) - Output multipliers (
outputMultiplier) - Additional bonus outputs (deterministic or chance-based)
- Any other property reachable through
CraftAdjustments
Modifiers do not modify RecipeCore data and do not perform side effects.
⏱ When modifiers run¶
When modifiers are enabled on the service (EnableModifiers == true), adjustments are computed:
- During preflight evaluation (used for duration, cost, output, and space budgeting)
- During accept/enqueue
- Again at delivery time (so mid-craft changes can affect delivery-time outcomes)
This is service behaviour; modifiers must not assume a single invocation per craft attempt and should be idempotent.
Important: Modifiers do not change input requirements or currency definitions. Inputs are consumed exactly as defined by the recipe; currency is only scaled via multipliers.
⚙️ Modifier pipeline (current service behaviour)¶
Modifiers are applied in two layers inside the service:
1) Component modifiers (owner hierarchy)¶
- The service collects
ICraftingModifiercomponents from the owner and its parents usingGetComponentsInParent(true, list). - Discovery is cached per frame to reduce allocations.
- Use
ctx.stationTagto gate station/bench-specific behaviour.
2) Service-registered modifier hooks (internal)¶
The service also supports internal modifier hooks registered via AddModifier/RemoveModifier.
These are not a public consumer extension surface; external consumers should prefer
component modifiers.
🔒 Clamping rules (enforced by the service)¶
After modifier application, the service defensively clamps:
durationSeconds >= 0currencyMultiplier >= 0outputMultiplier >= 1
This prevents invalid adjustment values from propagating into job timing and cost math.
📦 Included modifiers¶
AddChanceOutputModifier¶
Adds a probabilistic extra output by appending to adj.chanceOutputs.
Notes:
- Uses EnsureChanceOutputs() before adding entries.
- Chance entries are rolled by the service (once per craft; batched crafts may use approximation when enabled).
- Optional station-tag filter (trimmed, case-insensitive).
SimpleStationBonus¶
Station-gated modifier that:
- multiplies adj.durationSeconds, and
- optionally adds a deterministic extra output (+1 of the recipe’s first output) per craft.
Notes:
- Uses EnsureExtraOutputs() before adding entries.
- Optional station-tag filter (trimmed, case-insensitive).
🧩 Writing your own modifier¶
Implement:
public interface ICraftingModifier
{
void Apply(ref CraftContext ctx, ref CraftAdjustments adj);
}
Example — 50% currency discount:
[DisallowMultipleComponent]
public sealed class DiscountModifier : MonoBehaviour, ICraftingModifier
{
[Range(0f, 1f)] public float discount = 0.5f;
public void Apply(ref CraftContext ctx, ref CraftAdjustments adj)
{
adj.currencyMultiplier *= Mathf.Clamp01(discount);
}
}
💡 Best practices¶
- Call
adj.EnsureExtraOutputs()/adj.EnsureChanceOutputs()before adding outputs. - Use
ctx.stationTagto restrict effects to specific benches or stations. - Keep logic allocation-light — modifiers may be invoked multiple times.
- Avoid relying on execution order; modifiers should be composable.
- Keep any cross-craft state (“every N crafts”) outside modifiers unless you manage it explicitly.
📁 Folder contents¶
| File | Description |
|---|---|
AddChanceOutputModifier.cs |
Probabilistic bonus output modifier |
SimpleStationBonus.cs |
Station-based duration and per-craft output bonus |
| (your modifiers) | Any component implementing ICraftingModifier |
Summary¶
Modifiers are the recommended runtime layer for perks, buffs, station effects, and tuning. They are adapter-friendly, composable, and integrated into the service’s preflight and delivery flow.