English
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: 5Weights 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 weightsWith this pool the total is 1000:
yaml
pool:
common: 700
uncommon: 200
rare: 80
epic: 18
legendary: 2| Outcome | Weight | Probability |
|---|---|---|
| common | 700 | 70% |
| uncommon | 200 | 20% |
| rare | 80 | 8% |
| epic | 18 | 1.8% |
| legendary | 2 | 0.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: 5Conditional 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: 5With 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:
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
quality.guarantee.enabled (global config.yml) | boolean | No | true in the shipped config (code fallback false) | true, false | Whether the minimum-quality guarantee is active |
quality.guarantee.threshold (global) | integer | No | 10 | positive integer | Consecutive attempts before minimum is applied |
quality.guarantee.minimum (global) | string | No | 普通 (falls back to default_tier when the name is unknown) | a defined quality name | Minimum quality name applied once triggered |
quality.guarantee.enabled (per-recipe) | boolean | No | false | true, false | Same meaning, per recipe |
quality.guarantee.attempts (per-recipe) | integer | No | 10 | positive integer | Per-recipe counterpart of threshold |
quality.guarantee.minimum (per-recipe) | string | No | 普通 | a defined quality name | Minimum 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
- Each roll below
minimumincrements the counter - When the counter reaches the threshold (global
threshold, or per-recipeattempts), the next roll is raised tominimumor better - Rolling
minimumor 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: 10How 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