sb-core: constants module (WI-2, issue #2)

This commit is contained in:
Jan-Peter von Hunnius 2026-10-03 11:58:02 +02:00
parent 337e9bcf2c
commit 093012af20
6 changed files with 223 additions and 45 deletions

View file

@ -0,0 +1,131 @@
//! Game-balance constants — the single audit home for tuning scalars.
//! Static data tables (`RACES`, `CLASSES`, `BARD_SONGS`, `TRAINING_GROUNDS`)
//! stay in their modules; only tuning scalars live here.
pub use crate::character::{MAX_LEVEL, XP_FACTOR};
/// d100 attack roll bounds (origin: combat.rs:66).
pub const ATTACK_ROLL_MIN: i32 = 1;
/// d100 attack roll bounds (origin: combat.rs:66).
pub const ATTACK_ROLL_MAX: i32 = 100;
/// Open-ended roll: re-roll upward at or above this value (origin: combat.rs:68).
pub const OPEN_END_HIGH_THRESHOLD: i32 = 96;
/// Open-ended roll: re-roll downward at or below this value (origin: combat.rs:70).
pub const OPEN_END_LOW_THRESHOLD: i32 = 5;
/// Crit severity A floor (origin: combat.rs:129).
pub const CRIT_SEVERITY_A_MIN: i32 = 21;
/// Crit severity B floor (origin: combat.rs:127).
pub const CRIT_SEVERITY_B_MIN: i32 = 51;
/// Crit severity C floor (origin: combat.rs:125).
pub const CRIT_SEVERITY_C_MIN: i32 = 101;
/// Crit severity D floor (origin: combat.rs:123).
pub const CRIT_SEVERITY_D_MIN: i32 = 151;
/// Level gaps up to this value apply no crit cap (origin: combat.rs:56).
pub const CRIT_CAP_DISABLED_MAX_LEVEL_GAP: i32 = 9;
/// Crit cap tier 1 level-gap range (origin: combat.rs:57).
pub const CRIT_CAP_TIER1_MIN_GAP: i32 = 10;
/// Crit cap tier 1 level-gap range (origin: combat.rs:57).
pub const CRIT_CAP_TIER1_MAX_GAP: i32 = 19;
/// Crit cap tier 2 level-gap range (origin: combat.rs:58).
pub const CRIT_CAP_TIER2_MIN_GAP: i32 = 20;
/// Crit cap tier 2 level-gap range (origin: combat.rs:58).
pub const CRIT_CAP_TIER2_MAX_GAP: i32 = 49;
/// Crit cap tier 3 level-gap range (origin: combat.rs:59).
pub const CRIT_CAP_TIER3_MIN_GAP: i32 = 50;
/// Crit cap tier 3 level-gap range (origin: combat.rs:59).
pub const CRIT_CAP_TIER3_MAX_GAP: i32 = 99;
/// Crit cap tier 4 applies from this gap upward (origin: combat.rs:60).
pub const CRIT_CAP_TIER4_MIN_GAP: i32 = 100;
/// Crit damage cap ratio for level gaps 10–19 (origin: combat.rs:57).
pub const CRIT_CAP_TIER1_RATIO: f64 = 0.60;
/// Crit damage cap ratio for level gaps 20–49 (origin: combat.rs:58).
pub const CRIT_CAP_TIER2_RATIO: f64 = 0.40;
/// Crit damage cap ratio for level gaps 50–99 (origin: combat.rs:59).
pub const CRIT_CAP_TIER3_RATIO: f64 = 0.15;
/// Crit damage cap ratio for level gaps 100 and above (origin: combat.rs:60).
pub const CRIT_CAP_TIER4_RATIO: f64 = 0.05;
/// Constitution contributes half its stat bonus to defense (origin: combat.rs:36).
pub const DEFENSIVE_CON_BONUS_DIVISOR: i32 = 2;
/// Accuracy song offensive-bonus bonus (origin: combat.rs:246).
pub const SONG_ACCURACY_OB_BONUS: i32 = 15;
/// Damage song offensive-bonus bonus (origin: combat.rs:247).
pub const SONG_DAMAGE_OB_BONUS: i32 = 20;
/// Defense song defensive-bonus bonus (origin: combat.rs:256).
pub const SONG_DEFENSE_DB_BONUS: i32 = 10;
/// Weaken song reduces the foe's offensive bonus to this fraction (origin: combat.rs:257).
pub const SONG_WEAKEN_OB_FACTOR: f64 = 0.7;
/// Bard heal song: fraction of max HP restored per round (origin: combat.rs:230).
pub const BARD_SONG_HEAL_FRACTION: f64 = 0.03;
/// Stat bonus curve: bonus is zero at this stat value (origin: character.rs:59).
pub const STAT_BONUS_NEUTRAL: i64 = 20;
/// Stat bonus curve: bonus step size per 2 stat points (origin: character.rs:59).
pub const STAT_BONUS_STEP: i64 = 2;
/// Character creation stat roll bounds (origin: character.rs:63).
pub const STAT_ROLL_MIN: i64 = 6;
/// Character creation stat roll bounds (origin: character.rs:63).
pub const STAT_ROLL_MAX: i64 = 16;
/// Base maximum energy before the class contribution (origin: character.rs:85).
pub const BASE_MAX_ENERGY: i32 = 30;
/// Energy gains one point per this many base HP (origin: character.rs:85).
pub const MAX_ENERGY_PER_BASE_HP_DIVISOR: i32 = 3;
/// Base maximum nerve before the class contribution (origin: character.rs:90).
pub const BASE_MAX_NERVE: i32 = 100;
/// Nerve gains one point per this many base HP (origin: character.rs:90).
pub const MAX_NERVE_PER_BASE_HP_DIVISOR: i32 = 2;
/// Energy regen tick interval in milliseconds (origin: character.rs:94).
pub const ENERGY_REGEN_INTERVAL_MS: i64 = 180_000;
/// Nerve regen tick interval in milliseconds (origin: character.rs:98).
pub const NERVE_REGEN_INTERVAL_MS: i64 = 300_000;
/// HP regen tick interval in milliseconds (origin: character.rs:102).
pub const HP_REGEN_INTERVAL_MS: i64 = 300_000;
/// HP restored per regen tick, as a fraction of max HP (origin: character.rs:118).
pub const HP_REGEN_FRACTION_PER_TICK: f64 = 0.05;
/// Training cost curve base cost (origin: character.rs:126).
pub const TRAINING_BASE_COST: f64 = 5.0;
/// Training cost curve growth factor (origin: character.rs:126).
pub const TRAINING_GROWTH_FACTOR: f64 = 1.3;
/// Training cost curve stat scaler (origin: character.rs:125).
pub const TRAINING_STAT_SCALER: f64 = 10.0;
/// Energy spent per training session (origin: services.rs:85, 100).
pub const TRAINING_ENERGY_COST: i32 = 1;
/// Level assigned at character creation (origin: character.rs:157).
pub const STARTING_LEVEL: i32 = 1;
/// Gold assigned at character creation (origin: character.rs:166).
pub const STARTING_GOLD: i32 = 50;
/// XP curve coefficient: 18 · 100 · (level−1)² (origin: character.rs:196).
pub const XP_CURVE_COEFFICIENT: f64 = 100.0;
/// Gold cost per target level for level-up (origin: character.rs:200).
pub const LEVEL_UP_GOLD_PER_LEVEL: i32 = 500;
/// Caster levels per spell level: (level / 3) + 1 curve (origin: spells.rs:59).
pub const CASTER_LEVELS_PER_SPELL_LEVEL: i32 = 3;
/// Spell points granted per caster spell level (origin: spells.rs:62).
pub const SPELL_POINTS_PER_SPELL_LEVEL: i32 = 10;
/// Spell learn cost table, indexed by spell level − 1 (origin: spells.rs:44–52).
pub const SPELL_LEARN_COST_BY_LEVEL: [i32; 7] = [0, 1000, 2000, 4000, 7000, 10000, 20000];
/// Learn cost reported for spell levels outside 1..=7 (origin: spells.rs:52).
pub const SPELL_LEARN_COST_UNKNOWN_LEVEL: i32 = 999_999;
/// Lowest learn-request spell level — request validation only (origin: routes/mod.rs:1146).
pub const MIN_SPELL_LEVEL: i32 = 1;
/// Highest learn-request spell level — request validation only (origin: routes/mod.rs:1146).
pub const MAX_SPELL_LEVEL: i32 = 7;