Skip to content

Weights ​

Weights give every outcome a number and roll by its share of the total. Weights are used for random pools, quality pools, rewards, and guarantee systems

Example ​

yaml
pool:
  common: 80
  rare: 15
  epic: 5

Weights are relative. They do not have to add up to 100

Probability formula ​

A single outcome's real probability is:

text
probability = that outcome's weight / sum of all weights

With this pool the total is 1000:

yaml
pool:
  common: 700
  uncommon: 200
  rare: 80
  epic: 18
  legendary: 2
OutcomeWeightProbability
common70070%
uncommon20020%
rare808%
epic181.8%
legendary20.2%

An entry whose weight is zero or negative is dropped from the pool, and a pool whose total weight is not positive rolls nothing at all

Pool forms ​

Plain map ​

The simplest pool is a key-value map:

yaml
quality:
  enabled: true
  custom_pool:
    common: 70
    rare: 25
    epic: 5

Conditional bonuses ​

Some modules adjust weights based on the inputs:

yaml
quality:
  enabled: true
  custom_pool:
    common: 70
    rare: 25
    epic: 5
  material_bonus:
    rare_material:
      rare: 10
      epic: 5

With a rare material, rare goes from 25 to 35 and epic from 5 to 10

Expression weights ​

Some modules allow expressions as weight values:

yaml
quality:
  custom_pool:
    common: '100 - %material_score%'
    rare: '%material_score% * 0.5'
    epic: '%material_score% * 0.2'

Whether expressions are accepted depends on the calling module

Guarantee rules are not a CoreLib feature ​

CoreLib's own WeightedPool implements weighted rolling only: it has no guarantee, counter, or pity logic. The guarantee fields below are implemented by EmakiForge, so they are only available where Forge reads them; do not expect them in other modules' pools. Forge uses a different key name at each level:

FieldTypeRequiredDefaultRangeDescription
quality.guarantee.enabled (global config.yml)booleanNotrue in the shipped config (code fallback false)true, falseWhether the minimum-quality guarantee is active
quality.guarantee.threshold (global)integerNo10positive integerConsecutive attempts before minimum is applied
quality.guarantee.minimum (global)stringNo普通 (falls back to default_tier when the name is unknown)a defined quality nameMinimum quality name applied once triggered
quality.guarantee.enabled (per-recipe)booleanNofalsetrue, falseSame meaning, per recipe
quality.guarantee.attempts (per-recipe)integerNo10positive integerPer-recipe counterpart of threshold
quality.guarantee.minimum (per-recipe)stringNo普通a defined quality nameMinimum quality name for this recipe

Writing attempts in the global config, or threshold in a recipe, silently falls back to the default of 10

Guarantee configuration example ​

yaml
# Per-recipe form: after 60 consecutive misses, raise to "无暇"
quality:
  enabled: true
  custom_pool: []
  guarantee:
    enabled: true
    attempts: 60
    minimum: "无暇"

How the guarantee works ​

  1. Each roll below minimum increments the counter
  2. When the counter reaches the threshold (global threshold, or per-recipe attempts), the next roll is raised to minimum or better
  3. Rolling minimum or better resets the counter to 0

Only modules that implement it read guarantee; other modules' pools are unaffected. The keys, defaults, and scope are owned by EmakiForge quality

Multiple and nested pools ​

Some modules layer pools, rolling a category first and then an outcome inside it:

yaml
reward:
  category_pool:
    equipment: 30
    material: 50
    currency: 20
  equipment_pool:
    sword: 40
    armor: 35
    accessory: 25
  material_pool:
    common_ore: 60
    rare_ore: 30
    gem_fragment: 10

How nesting works is decided by the calling module

Verifying a distribution ​

Roll a large sample on a test server using whatever batch command the module provides, then compare against the theoretical share. With common=70, rare=25, epic=5, 1000 rolls should land near 700 / 250 / 50. Real results fluctuate; larger samples converge closer to the theoretical probability

Advice ​

Avoid negative weights and all-zero pools. For rare outcomes, consider guarantee rules to improve player experience