feat(combat): resolve victory rewards in the combat completion transaction
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,8 @@ import { Hunt } from '../hunting/entities/hunt.entity';
|
||||
import { HuntEncounter } from '../hunting/entities/hunt-encounter.entity';
|
||||
import { HuntStatus } from '../hunting/hunt-status.enum';
|
||||
import { MonsterDefinition } from '../monsters/entities/monster-definition.entity';
|
||||
import { CombatRewardService } from '../rewards/combat-reward.service';
|
||||
import type { CombatRewardDto } from '../rewards/combat-reward.service';
|
||||
import { TravelService } from '../travel/travel.service';
|
||||
import { TravelStatus } from '../travel/travel-status.enum';
|
||||
import { CombatAction } from './combat-action.enum';
|
||||
@@ -57,6 +59,7 @@ export interface CombatDto {
|
||||
player: CombatPlayerDto;
|
||||
monster: CombatMonsterDto;
|
||||
events: CombatEventDto[];
|
||||
rewards: CombatRewardDto | null;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@@ -66,6 +69,7 @@ export class CombatService {
|
||||
private readonly travelService: TravelService,
|
||||
private readonly combatEngine: CombatEngineService,
|
||||
private readonly characterCombatStats: CharacterCombatStatsService,
|
||||
private readonly combatRewards: CombatRewardService,
|
||||
) {}
|
||||
|
||||
async startCombat(
|
||||
@@ -146,7 +150,7 @@ export class CombatService {
|
||||
encounter.consumedAt = new Date();
|
||||
await encounters.save(encounter);
|
||||
|
||||
return this.toCombatDto(combat, character.name, monster, []);
|
||||
return this.toCombatDto(combat, character.name, monster, [], null);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -159,13 +163,14 @@ export class CombatService {
|
||||
throw combatNotFound();
|
||||
}
|
||||
|
||||
const [character, monster, events] = await Promise.all([
|
||||
const [character, monster, events, rewards] = await Promise.all([
|
||||
this.loadCharacter(combat.characterId),
|
||||
this.loadMonster(combat.monsterDefinitionId),
|
||||
this.loadEvents(combat.id),
|
||||
this.combatRewards.loadRewards(combat.id),
|
||||
]);
|
||||
|
||||
return this.toCombatDto(combat, character.name, monster, events);
|
||||
return this.toCombatDto(combat, character.name, monster, events, rewards);
|
||||
}
|
||||
|
||||
async getActiveCombat(characterId: string): Promise<CombatDto | null> {
|
||||
@@ -183,7 +188,7 @@ export class CombatService {
|
||||
this.loadEvents(combat.id),
|
||||
]);
|
||||
|
||||
return this.toCombatDto(combat, character.name, monster, events);
|
||||
return this.toCombatDto(combat, character.name, monster, events, null);
|
||||
}
|
||||
|
||||
async performAction(
|
||||
@@ -236,6 +241,14 @@ export class CombatService {
|
||||
await combatEvents.save(entity);
|
||||
}
|
||||
|
||||
// The engine decided the outcome; rewards are resolved here, outside it
|
||||
// (spec §30). Running inside this transaction means a reward failure
|
||||
// rolls the whole round back rather than leaving a half-granted victory.
|
||||
const rewards =
|
||||
combat.status === CombatStatus.WON
|
||||
? await this.combatRewards.grantVictoryRewards(manager, combat)
|
||||
: null;
|
||||
|
||||
const [character, monster, events] = await Promise.all([
|
||||
this.loadCharacter(
|
||||
combat.characterId,
|
||||
@@ -248,7 +261,7 @@ export class CombatService {
|
||||
this.loadEvents(combat.id, combatEvents),
|
||||
]);
|
||||
|
||||
return this.toCombatDto(combat, character.name, monster, events);
|
||||
return this.toCombatDto(combat, character.name, monster, events, rewards);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -326,6 +339,7 @@ export class CombatService {
|
||||
playerName: string,
|
||||
monster: MonsterDefinition,
|
||||
events: CombatEvent[],
|
||||
rewards: CombatRewardDto | null,
|
||||
): CombatDto {
|
||||
return {
|
||||
id: combat.id,
|
||||
@@ -352,6 +366,7 @@ export class CombatService {
|
||||
target: event.target,
|
||||
amount: event.amount ?? undefined,
|
||||
})),
|
||||
rewards,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user