feat(battle-xp): wire story first-clear /finish through IBattleXpService

- StoryConfig.ClassXpPerClear retired; equivalent knob moves to
  BattleXpConfig.StoryXpPerClear (falls back to XpPerWin when null).
- StoryService.FinishAsync now grants class XP via IBattleXpService with
  BattleXpMode.Story on the firstClear && isPlayShape branch. Persists
  post-grant Level/Exp to Viewer.Classes.
- Wire fields (get_class_experience, class_level) stringified as before.
- StoryConfig kept as an empty [ConfigSection] for future story-specific
  knobs. StoryServiceTests updated to reflect the new default path
  (XpPerWin=100 crosses classexp.csv L1=50 → L2 with 50 carry).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-07-04 09:06:47 -04:00
parent a03bff3ea7
commit 8199a95356
3 changed files with 45 additions and 12 deletions

View File

@@ -1,9 +1,13 @@
namespace SVSim.Database.Models.Config;
/// <summary>
/// Story-family placeholder config section. Class XP per clear moved to
/// <see cref="BattleXpConfig.StoryXpPerClear"/> (BattleXpMode.Story) as part of the
/// unified per-mode XP surface. Kept as an empty section so future story-specific
/// knobs (dialogue speed, auto-skip, etc.) have a home.
/// </summary>
[ConfigSection("Story")]
public class StoryConfig
{
public int ClassXpPerClear { get; set; } = 200;
public static StoryConfig ShippedDefaults() => new();
}