feat(battle-xp): BattleXpGrantResult carries LeveledUp signal
BattleXpGrantResult gains a LeveledUp bool set true iff at least one curve threshold was crossed during the grant (comparing pre-Level to post-Level after the level-up loop). Callers will gate class_level_up mission emits on this flag rather than caching pre-state themselves. No behavior change for existing callers — they read GetXp/TotalXp/Level today and never check LeveledUp yet. Tests cover: unchanged level → false, single threshold → true, multi-threshold within one grant → still true, unknown class guardrail → false. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -185,7 +185,49 @@ public class BattleXpServiceTests
|
||||
Assert.That(r.GetXp, Is.EqualTo(0));
|
||||
Assert.That(r.TotalXp, Is.EqualTo(0));
|
||||
Assert.That(r.Level, Is.EqualTo(1));
|
||||
Assert.That(r.LeveledUp, Is.False);
|
||||
Assert.That(v.Classes.Single().Exp, Is.EqualTo(0),
|
||||
"Class 1's row must not have been touched.");
|
||||
}
|
||||
|
||||
// ---- LeveledUp signal ----
|
||||
|
||||
[Test]
|
||||
public async Task LeveledUp_is_false_when_grant_stays_within_same_level()
|
||||
{
|
||||
// L1 requires 100 to reach L2; grant only 40.
|
||||
var svc = NewService(new BattleXpConfig { XpPerWin = 40 });
|
||||
var v = NewViewerWithClass(1);
|
||||
|
||||
var r = await svc.GrantAsync(v, 1, isWin: true, BattleXpMode.Rank);
|
||||
|
||||
Assert.That(r.Level, Is.EqualTo(1));
|
||||
Assert.That(r.LeveledUp, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task LeveledUp_is_true_when_grant_crosses_a_threshold()
|
||||
{
|
||||
// L1=100 → grant 130 → L2 with 30 carry.
|
||||
var svc = NewService(new BattleXpConfig { XpPerWin = 130 });
|
||||
var v = NewViewerWithClass(1);
|
||||
|
||||
var r = await svc.GrantAsync(v, 1, isWin: true, BattleXpMode.Rank);
|
||||
|
||||
Assert.That(r.Level, Is.EqualTo(2));
|
||||
Assert.That(r.LeveledUp, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task LeveledUp_stays_true_across_multiple_bumps_in_one_grant()
|
||||
{
|
||||
// Grant crosses L1→L2→L3 in one go.
|
||||
var svc = NewService(new BattleXpConfig { XpPerWin = 500 });
|
||||
var v = NewViewerWithClass(1);
|
||||
|
||||
var r = await svc.GrantAsync(v, 1, isWin: true, BattleXpMode.Rank);
|
||||
|
||||
Assert.That(r.Level, Is.EqualTo(3));
|
||||
Assert.That(r.LeveledUp, Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user