neon-sprawl/docs/decomposition/modules/E2_M2_XpAwardAndLevelEngine.md

5.7 KiB
Raw Blame History

E2.M2 — XpAwardAndLevelEngine

Summary

Field Value
Module ID E2.M2
Epic Epic 2 — Skills and Progression Framework
Stage target Prototype
Status In Progress (see dependency register)

Implementation snapshot

Linear (label E2.M2): Epic 2 projectSlice 2: NEO-37 (progression read snapshot) → NEO-38 (apply grant + allowlist + level-up) → NEO-39 (data-driven LevelCurve + CI); NEO-40 (telemetry hook sites) after NEO-38, parallel with NEO-39. Slice 3 integration (multi-label where noted): NEO-41, NEO-42, NEO-43, NEO-44.

NEO-37 landed: versioned GET /game/players/{id}/skill-progression (implementation plan) — SkillProgressionSnapshotApi / SkillProgressionSnapshotDtos under server/NeonSprawl.Server/Game/Skills/; one row per ISkillDefinitionRegistry skill; 404 when the player has no position (same gate as GET …/cooldown-snapshot). Manual QA NEO-37.md; server README — Skill progression snapshot (NEO-37).

NEO-38 landed: versioned POST /game/players/{id}/skill-progression (implementation plan) — applies one grant per request with ISkillDefinitionRegistry + allowedXpSourceKinds validation, stable deny reasonCode values, dual persistence (IPlayerSkillProgressionStore: in-memory / Postgres + V003__player_skill_progression.sql), GET merges stored XP with the registry; inline SkillLevelCurvePlaceholder until NEO-39; success payload includes levelUps (see README for multi-step semantics). Bruno bruno/neon-sprawl-server/skill-progression/ (GET + POST + deny); manual QA NEO-38.md; server README — Skill progression grant (NEO-38).

Still backlog within this module: data-driven LevelCurve + CI (NEO-39); telemetry hook sites (NEO-40); callers in Slice 3 (NEO-41NEO-43). Keep this paragraph and documentation tracking in sync as Slice 2 stories merge.

Purpose

Central server-authoritative engine for non-combat skill progression: applying XP grants, resolving levels against data-driven curves, and emitting level-up events. Gathering and crafting integrate as callers for skill XP. Combat encounters advance gigs (gig XP), not SkillDef lines. Mission rewards may call this API for skill XP when the payout lists a skill grant. Callers are not hard dependencies for implementing the engine core (see Epic 2 Slice 2 vs Slice 3).

Responsibilities

  • Apply XpGrantEvent (or equivalent) per skill with validated skillId from E2.M1. Reject grants when sourceKind is not in the target SkillDef.allowedXpSourceKinds.
  • Resolve experience against LevelCurve / threshold tables.
  • Emit LevelUpEvent when thresholds are crossed.
  • Support data-driven curves; reload policy: Data reload and telemetry operations policy (boot load default; optional dev reload).

Key contracts

Contract Role
XpGrantEvent Structured XP award: skillId (must exist in registry), amount, sourceKind (must appear in that skills allowedXpSourceKinds), optional modifiers.
LevelCurve Thresholds or formula per skill or global policy.
LevelUpEvent Notification for UI, unlocks, and downstream systems.

Module dependencies

Dependents (by design)

  • E5.M1 — CombatRulesEngine: gig XP from combat (not SkillDef XP via E2.M2).
  • E3.M1 / E3.M2 — Gathering and crafting award XP when wired in Slice 3.
  • E7.M2 — RewardAndUnlockRouter routes quest rewards including XP through E2.M2.
  • E2.M3 / E2.M4 — Mastery and pacing layers build on level/XP state (pre-production).
  • Epic 2 Slice 2 — XP engine (E2.M2 core): implement contracts and tests without requiring Epic 3 or 5 modules.
  • Epic 2 Slice 3 — XP award integration: E3.M1 / E3.M2 call the skill XP API with sourceKind: activity (where allowed per skill); E7.M2 / mission rewards use mission_reward (etc.) as configured; combat resolves gig progression separately from E2.M2.

Risks and telemetry

  • Runaway leveling in one skill: diminishing returns per slice; monitor distribution via E9.M2 when available.
  • Telemetry: xp_grant, level_up, time-to-first-level-up once real activity fires.

Source anchors