feat(content): migrate ItemType, seed Räuberabzeichen/Grenzwacht/turn-ins, zero direct monster rewards

This commit is contained in:
Bastian Wagner
2026-08-21 13:49:49 +02:00
parent 413fafd574
commit dce26e00ad
6 changed files with 208 additions and 47 deletions

View File

@@ -9,8 +9,14 @@ import { LocationMonster } from '../../monsters/entities/location-monster.entity
import { MonsterDefinition } from '../../monsters/entities/monster-definition.entity';
import { LocationConnection } from '../../world/entities/location-connection.entity';
import { LocationDefinition } from '../../world/entities/location-definition.entity';
import { ReputationFaction } from '../../reputation/entities/reputation-faction.entity';
import { TurnInDefinition } from '../../turn-in/entities/turn-in-definition.entity';
import { DEMO_CHARACTER_STARTING_WEAPON_ITEM_ID } from '../../demo/demo-character.constants';
import { ASH_RAT_LOOT_TABLE_ID, ITEM_IDS, ROAD_BANDIT_LOOT_TABLE_ID } from './item.constants';
import {
ASH_RAT_LOOT_TABLE_ID,
ITEM_IDS,
ROAD_BANDIT_LOOT_TABLE_ID,
} from './item.constants';
import { seedVisibleVerticalSlice } from './vertical-slice.seed';
type Row = Record<string, unknown>;
@@ -81,6 +87,8 @@ function createDataSource(
lootEntryRepository: InMemoryRepository = new InMemoryRepository(),
characterItemRepository: InMemoryRepository = new InMemoryRepository(),
characterEquipmentRepository: InMemoryRepository = new InMemoryRepository(),
reputationFactionRepository: InMemoryRepository = new InMemoryRepository(),
turnInDefinitionRepository: InMemoryRepository = new InMemoryRepository(),
): DataSource {
return {
getRepository: jest.fn((entity: unknown) => {
@@ -94,6 +102,8 @@ function createDataSource(
if (entity === LootTableEntry) return lootEntryRepository;
if (entity === CharacterItem) return characterItemRepository;
if (entity === CharacterEquipment) return characterEquipmentRepository;
if (entity === ReputationFaction) return reputationFactionRepository;
if (entity === TurnInDefinition) return turnInDefinitionRepository;
throw new Error('Unexpected repository');
}),
@@ -119,7 +129,7 @@ describe('seedVisibleVerticalSlice', () => {
Object.assign(characterRepository.rows[0], {
currentLocationId: BURNED_ROAD_ID,
currentHp: 57,
experience: 39,
renown: 1,
});
await seedVisibleVerticalSlice(dataSource);
@@ -158,7 +168,7 @@ describe('seedVisibleVerticalSlice', () => {
expect.objectContaining({
currentLocationId: BURNED_ROAD_ID,
currentHp: 57,
experience: 39,
renown: 1,
}),
);
@@ -173,9 +183,8 @@ describe('seedVisibleVerticalSlice', () => {
maxHp: 45,
attack: 5,
armor: 0,
experienceReward: 8,
silverMin: 4,
silverMax: 7,
silverMin: 0,
silverMax: 0,
artworkPath: '/images/monsters/ash-rat.png',
}),
expect.objectContaining({
@@ -185,9 +194,8 @@ describe('seedVisibleVerticalSlice', () => {
maxHp: 75,
attack: 9,
armor: 5,
experienceReward: 16,
silverMin: 9,
silverMax: 15,
silverMin: 0,
silverMax: 0,
artworkPath: '/images/monsters/road-bandit.png',
}),
expect.objectContaining({
@@ -400,13 +408,13 @@ describe('seedVisibleVerticalSlice', () => {
await seedVisibleVerticalSlice(dataSource);
await seedVisibleVerticalSlice(dataSource);
expect(itemRepository.rows).toHaveLength(12);
expect(itemRepository.rows).toHaveLength(13);
expect(itemRepository.rows).toEqual(
expect.arrayContaining([
expect.objectContaining({
key: 'bandit-blade',
name: 'Räuberklinge',
type: 'WEAPON',
type: 'EQUIPMENT',
equipmentSlot: 'WEAPON',
rarity: 'COMMON',
weaponDamage: 11,
@@ -417,14 +425,20 @@ describe('seedVisibleVerticalSlice', () => {
expect.objectContaining({
key: 'ash-pelt',
name: 'Aschenfell',
type: 'MATERIAL',
type: 'TRADE_GOOD',
equipmentSlot: null,
}),
expect.objectContaining({
key: 'bandit-insignia',
name: 'Räuberabzeichen',
type: 'TROPHY',
equipmentSlot: null,
}),
]),
);
expect(lootTableRepository.rows).toHaveLength(2);
expect(lootEntryRepository.rows).toHaveLength(5);
expect(lootEntryRepository.rows).toHaveLength(6);
expect(lootEntryRepository.rows).toEqual(
expect.arrayContaining([
expect.objectContaining({
@@ -451,8 +465,14 @@ describe('seedVisibleVerticalSlice', () => {
expect(monsterRepository.rows).toEqual(
expect.arrayContaining([
expect.objectContaining({ key: 'ash-rat', lootTableId: ASH_RAT_LOOT_TABLE_ID }),
expect.objectContaining({ key: 'road-bandit', lootTableId: ROAD_BANDIT_LOOT_TABLE_ID }),
expect.objectContaining({
key: 'ash-rat',
lootTableId: ASH_RAT_LOOT_TABLE_ID,
}),
expect.objectContaining({
key: 'road-bandit',
lootTableId: ROAD_BANDIT_LOOT_TABLE_ID,
}),
]),
);
});
@@ -522,7 +542,8 @@ describe('seedVisibleVerticalSlice', () => {
await seedVisibleVerticalSlice(dataSource);
// Simulate the player having equipped earned loot instead.
characterEquipmentRepository.rows[0]['characterItemId'] = 'earned-bandit-blade-item-id';
characterEquipmentRepository.rows[0]['characterItemId'] =
'earned-bandit-blade-item-id';
await seedVisibleVerticalSlice(dataSource);
@@ -577,4 +598,53 @@ describe('seedVisibleVerticalSlice', () => {
}),
);
});
it('seeds the Grenzwacht faction', async () => {
const reputationFactionRepository = new InMemoryRepository();
const dataSource = createDataSource(
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
reputationFactionRepository,
);
await seedVisibleVerticalSlice(dataSource);
const faction = await dataSource
.getRepository(ReputationFaction)
.findOneBy({ key: 'border-guard' });
expect(faction).toMatchObject({ name: 'Grenzwacht', enabled: true });
});
it('seeds both turn-in definitions', async () => {
const turnInDefinitionRepository = new InMemoryRepository();
const dataSource = createDataSource(
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
new InMemoryRepository(),
turnInDefinitionRepository,
);
await seedVisibleVerticalSlice(dataSource);
expect(
turnInDefinitionRepository.rows.map((row: Row) => row.key).sort(),
).toEqual(['ash-pelt-border-guard', 'bandit-insignia-border-guard']);
});
});