Skip to content

Configurable level and stat/experience gain charts#590

Merged
Volte6 merged 1 commit into
masterfrom
stats-progression
May 29, 2026
Merged

Configurable level and stat/experience gain charts#590
Volte6 merged 1 commit into
masterfrom
stats-progression

Conversation

@Volte6
Copy link
Copy Markdown
Member

@Volte6 Volte6 commented May 29, 2026

Configurable Character Progression + Admin Visual Editor

Replaces all hardcoded character progression constants with a fully configurable system and adds a new /admin/progression page with live charts, interactive controls, and hover tooltips.


Config (GamePlay.Progression.*)

  • New ProgressionConfig struct under GamePlay exposes every previously hardcoded progression constant as a named config key
  • Stat gainsBaseModFactor, BaseModExponent, NaturalGainsModFactor, NaturalGainsExponent control the racial and flat per-level stat growth curves; exponent fields allow linear, diminishing-returns, or accelerating shapes
  • HP/Mana formulasHPBase, HPPerLevel, HPPerVitality, ManaBase, ManaPerLevel, ManaPerMysticism
  • Level-up rewardsTrainingPointsPerLevel, TrainingPointsEveryNLevels, StatPointsPerLevel, StatPointsEveryNLevels; the EveryNLevels fields allow burst-style rewards (e.g. 3 points every 2 levels)
  • XP curveXPBase, XPLevelFactor, XPLevelPower (capped at 5.0 to prevent integer overflow)
  • Stat cap compressionStatCapThreshold, StatCapAnchor, StatCapExponent, StatCapScale, StatCapExemptBonus; when StatCapExemptBonus is enabled, only racial gains are compressed and training/equipment bonuses land on top at full value
  • DisplayMaxLevel for chart range
  • All defaults reproduce the previous hardcoded behavior exactly; existing characters are unaffected by the migration

Engine changes

  • internal/stats/stats.goGainsForLevel now uses math.Pow with the exponent knobs; Recalculate applies the configurable cap formula; new NoCap bool field on StatInfo lets HealthMax/ManaMax bypass the stat cap (previously they were incorrectly subject to it)
  • internal/characters/character.goXPTL, LevelUp, and RecalculateStats all read from GetProgressionConfig(); XPTL now uses float64 throughout (removing a float32 cast that caused negative XP display at high levels) and clamps the result to math.MaxInt64 before the int conversion
  • internal/users/userrecord.go — level-up event accumulator now snapshots TrainingPoints/StatPoints before and after each LevelUp() call and diffs them, replacing hardcoded += 1 that ignored config
  • internal/usercommands/experience.goexperience chart command now uses ValueAdj (compressed effective stat) instead of raw GainsForLevel, so the table matches what the game actually uses

Admin page (/admin/progression)

  • New page at /admin/progression with a sticky left control panel and a live chart column
  • Controls — sliders and number inputs for every ProgressionConfig field, grouped into four sections (Stat Gains, HP & Mana, XP Curve, Level-Up Rewards); charts update 150ms after any change without saving
  • Level-Up Rewards UX — each reward type is a self-contained card with an inline "Give N points every N levels" sentence and a live plain-English summary (e.g. "1 training point awarded every 3 levels (levels 3, 6, 9…)")
  • ? tooltips — every control has a styled CSS tooltip explaining its intended effect and example use cases; tooltips are not clipped by the panel (overflow: hidden removed and replaced with targeted border-radius on first/last children)
  • Four canvas charts — Stat Gains per Level (solid = raw Value, dashed = ValueAdj after cap), HP & Mana at Level, XP Required per Level, XP Cumulative; all redrawn on resize via ResizeObserver; data is computed server-side so charts are guaranteed to match the engine
  • Chart interactivity — hovering any chart shows a vertical crosshair, dots on each series, and a floating tooltip with all series values at that level
  • Save / Reset / Restore Defaults — Save patches the live config; Reset reverts unsaved slider changes; Restore Defaults opens a confirmation modal then saves all fields back to their hardcoded defaults
  • Warning banner at the top of the page noting that changes are immediate, server-wide, and cannot be automatically reversed
  • Preview APIGET /admin/api/v1/progression/preview accepts all config fields as query params, runs the actual Go formulas, and returns precomputed chart series (downsampled to ≤100 points regardless of MaxLevel)

Bug fixes

  • HealthMax and ManaMax were incorrectly subject to the stat cap compression formula; fixed via StatInfo.NoCap
  • Level-up event TrainingPoints/StatPoints counts were hardcoded to 1 regardless of config
  • experience chart command showed raw Value instead of compressed ValueAdj
  • XPTL used a float32 cast that caused precision loss and negative XP display above ~level 150; now fully float64
  • XPLevelPower validation cap lowered from 10.0 to 5.0 to prevent integer overflow at high levels with steep curves

@Volte6 Volte6 merged commit 322829c into master May 29, 2026
8 checks passed
@Volte6 Volte6 deleted the stats-progression branch May 29, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant