feat(rewards): remove classical XP from the combat reward pipeline

This commit is contained in:
Bastian Wagner
2026-08-21 13:23:46 +02:00
parent 6fb61792e7
commit c9d9144b5f
2 changed files with 5 additions and 18 deletions

View File

@@ -120,12 +120,11 @@ function combat(overrides: Partial<Combat> = {}): Combat {
function createState(overrides: Partial<State> = {}): State {
return {
characters: [{ id: CHARACTER_ID, experience: 12, silver: 3 } as Character],
characters: [{ id: CHARACTER_ID, silver: 3 } as Character],
monsters: [
{
id: ASH_RAT_ID,
key: 'ash-rat',
experienceReward: 8,
silverMin: 4,
silverMax: 7,
lootTableId: ASH_RAT_TABLE,
@@ -133,7 +132,6 @@ function createState(overrides: Partial<State> = {}): State {
{
id: ROAD_BANDIT_ID,
key: 'road-bandit',
experienceReward: 16,
silverMin: 9,
silverMax: 15,
lootTableId: ROAD_BANDIT_TABLE,
@@ -189,7 +187,6 @@ describe('CombatRewardService', () => {
service(state).grantVictoryRewards(fakeManager(state), combat({ status: CombatStatus.ACTIVE })),
).rejects.toMatchObject({ code: 'COMBAT_NOT_WON' });
expect(state.combatRewards).toHaveLength(0);
expect(state.characters[0].experience).toBe(12);
expect(state.characters[0].silver).toBe(3);
});
@@ -207,13 +204,13 @@ describe('CombatRewardService', () => {
const reward = await service(state).grantVictoryRewards(fakeManager(state), combat());
expect(reward).toEqual({ experience: 8, silver: 6, items: [] });
expect(reward).toEqual({ silver: 6, items: [] });
expect(state.combatRewards).toHaveLength(1);
});
});
describe('Aschenratte', () => {
it('grants 8 XP and a silver roll inside 4-7, persisted on the character', async () => {
it('grants a silver roll inside 4-7, persisted on the character', async () => {
const state = createState();
const reward = await service(state, fakeLoot(), fixedRandom(0)).grantVictoryRewards(
@@ -221,9 +218,7 @@ describe('CombatRewardService', () => {
combat(),
);
expect(reward.experience).toBe(8);
expect(reward.silver).toBe(4);
expect(state.characters[0].experience).toBe(20);
expect(state.characters[0].silver).toBe(7);
});
@@ -242,7 +237,7 @@ describe('CombatRewardService', () => {
describe('Straßenräuber', () => {
const banditCombat = combat({ monsterDefinitionId: ROAD_BANDIT_ID });
it('grants 16 XP and a silver roll inside 9-15', async () => {
it('grants a silver roll inside 9-15', async () => {
const state = createState();
const reward = await service(state, fakeLoot(), fixedRandom(0)).grantVictoryRewards(
@@ -250,7 +245,6 @@ describe('CombatRewardService', () => {
banditCombat,
);
expect(reward.experience).toBe(16);
expect(reward.silver).toBe(9);
});
@@ -336,7 +330,6 @@ describe('CombatRewardService', () => {
expect(state.combatRewardItems).toHaveLength(1);
expect(state.characterItems).toHaveLength(1);
expect(state.characterItems[0].quantity).toBe(1);
expect(state.characters[0].experience).toBe(20);
expect(state.characters[0].silver).toBe(7);
expect(loot.rollLoot).toHaveBeenCalledTimes(1);
});
@@ -395,7 +388,6 @@ describe('CombatRewardService', () => {
// Every rolled item definition is resolved before any mutation, so a
// missing one must leave no reward row and no character grant behind.
expect(state.combatRewards).toHaveLength(0);
expect(state.characters[0].experience).toBe(12);
expect(state.characters[0].silver).toBe(3);
});
});

View File

@@ -27,7 +27,6 @@ export interface CombatRewardItemDto {
}
export interface CombatRewardDto {
experience: number;
silver: number;
items: CombatRewardItemDto[];
}
@@ -76,7 +75,6 @@ export class CombatRewardService {
throw rewardStateInvalid();
}
const experience = monster.experienceReward;
const silver = rollInclusive(
this.randomSource,
monster.silverMin,
@@ -111,7 +109,6 @@ export class CombatRewardService {
if (!character) {
throw rewardStateInvalid();
}
character.experience += experience;
character.silver += silver;
await characters.save(character);
@@ -119,7 +116,6 @@ export class CombatRewardService {
rewards.create({
combatId: combat.id,
characterId: combat.characterId,
experienceGranted: experience,
silverGranted: silver,
}),
);
@@ -171,7 +167,7 @@ export class CombatRewardService {
granted.sort((a, b) => a.itemDefinitionId.localeCompare(b.itemDefinitionId));
const items = granted.map((entry) => entry.dto);
return { experience, silver, items };
return { silver, items };
}
/** Reads a persisted reward so a refresh replays it (spec §25, §48). */
@@ -217,7 +213,6 @@ export class CombatRewardService {
}
return {
experience: reward.experienceGranted,
silver: reward.silverGranted,
items,
};