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

@@ -17,7 +17,6 @@ export interface SeedItemDefinition {
equipmentSlot: EquipmentSlot | null; equipmentSlot: EquipmentSlot | null;
rarity: ItemRarity; rarity: ItemRarity;
tier: number; tier: number;
requiredLevel: number;
weaponDamage: number; weaponDamage: number;
bonusHp: number; bonusHp: number;
bonusAttack: number; bonusAttack: number;
@@ -33,7 +32,12 @@ function item(
type: ItemType, type: ItemType,
equipmentSlot: EquipmentSlot | null, equipmentSlot: EquipmentSlot | null,
rarity: ItemRarity, rarity: ItemRarity,
stats: Partial<Pick<SeedItemDefinition, 'weaponDamage' | 'bonusHp' | 'bonusAttack' | 'bonusArmor'>> = {}, stats: Partial<
Pick<
SeedItemDefinition,
'weaponDamage' | 'bonusHp' | 'bonusAttack' | 'bonusArmor'
>
> = {},
): SeedItemDefinition { ): SeedItemDefinition {
return { return {
id: ITEM_IDS[key], id: ITEM_IDS[key],
@@ -44,7 +48,6 @@ function item(
equipmentSlot, equipmentSlot,
rarity, rarity,
tier: 1, tier: 1,
requiredLevel: 1,
weaponDamage: stats.weaponDamage ?? 0, weaponDamage: stats.weaponDamage ?? 0,
bonusHp: stats.bonusHp ?? 0, bonusHp: stats.bonusHp ?? 0,
bonusAttack: stats.bonusAttack ?? 0, bonusAttack: stats.bonusAttack ?? 0,
@@ -62,7 +65,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'worn-short-sword', 'worn-short-sword',
'Abgenutztes Kurzschwert', 'Abgenutztes Kurzschwert',
'Die Klinge eines Rekruten, öfter geschliffen als geführt.', 'Die Klinge eines Rekruten, öfter geschliffen als geführt.',
ItemType.WEAPON, ItemType.EQUIPMENT,
EquipmentSlot.WEAPON, EquipmentSlot.WEAPON,
ItemRarity.COMMON, ItemRarity.COMMON,
{ weaponDamage: 8 }, { weaponDamage: 8 },
@@ -71,7 +74,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'bandit-blade', 'bandit-blade',
'Räuberklinge', 'Räuberklinge',
'Eine grob gezahnte Klinge, geschmiedet für schnelle Überfälle.', 'Eine grob gezahnte Klinge, geschmiedet für schnelle Überfälle.',
ItemType.WEAPON, ItemType.EQUIPMENT,
EquipmentSlot.WEAPON, EquipmentSlot.WEAPON,
ItemRarity.COMMON, ItemRarity.COMMON,
{ weaponDamage: 11, bonusAttack: 1 }, { weaponDamage: 11, bonusAttack: 1 },
@@ -80,7 +83,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'ash-blade', 'ash-blade',
'Aschenklinge', 'Aschenklinge',
'In der Glut der Aschenfelder gehärtet; die Schneide glimmt noch.', 'In der Glut der Aschenfelder gehärtet; die Schneide glimmt noch.',
ItemType.WEAPON, ItemType.EQUIPMENT,
EquipmentSlot.WEAPON, EquipmentSlot.WEAPON,
ItemRarity.RARE, ItemRarity.RARE,
{ weaponDamage: 15, bonusAttack: 2 }, { weaponDamage: 15, bonusAttack: 2 },
@@ -89,7 +92,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'bandit-hood', 'bandit-hood',
'Räuberhaube', 'Räuberhaube',
'Vernarbtes Leder, das Gesicht und Absicht des Trägers verbirgt.', 'Vernarbtes Leder, das Gesicht und Absicht des Trägers verbirgt.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.HEAD, EquipmentSlot.HEAD,
ItemRarity.COMMON, ItemRarity.COMMON,
{ bonusArmor: 3, bonusHp: 5 }, { bonusArmor: 3, bonusHp: 5 },
@@ -98,7 +101,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'reinforced-leather-jacket', 'reinforced-leather-jacket',
'Verstärkte Lederjacke', 'Verstärkte Lederjacke',
'Mit Eisenplatten benähtes Leder, schwer und verlässlich.', 'Mit Eisenplatten benähtes Leder, schwer und verlässlich.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.CHEST, EquipmentSlot.CHEST,
ItemRarity.RARE, ItemRarity.RARE,
{ bonusArmor: 7, bonusHp: 10 }, { bonusArmor: 7, bonusHp: 10 },
@@ -107,7 +110,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'raider-gloves', 'raider-gloves',
'Plündererhandschuhe', 'Plündererhandschuhe',
'Beschlagene Handschuhe, abgegriffen von fremdem Gut.', 'Beschlagene Handschuhe, abgegriffen von fremdem Gut.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.HANDS, EquipmentSlot.HANDS,
ItemRarity.COMMON, ItemRarity.COMMON,
{ bonusArmor: 3, bonusAttack: 1 }, { bonusArmor: 3, bonusAttack: 1 },
@@ -116,7 +119,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'guardsman-legs', 'guardsman-legs',
'Wachmannsbeinkleid', 'Wachmannsbeinkleid',
'Beinzeug der Grenzwacht, an den Knien geflickt.', 'Beinzeug der Grenzwacht, an den Knien geflickt.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.LEGS, EquipmentSlot.LEGS,
ItemRarity.RARE, ItemRarity.RARE,
{ bonusArmor: 5, bonusHp: 5 }, { bonusArmor: 5, bonusHp: 5 },
@@ -125,7 +128,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'ash-boots', 'ash-boots',
'Aschenstiefel', 'Aschenstiefel',
'Stiefel, die durch glimmende Felder getragen wurden und blieben.', 'Stiefel, die durch glimmende Felder getragen wurden und blieben.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.FEET, EquipmentSlot.FEET,
ItemRarity.RARE, ItemRarity.RARE,
{ bonusArmor: 4, bonusHp: 5 }, { bonusArmor: 4, bonusHp: 5 },
@@ -134,7 +137,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'borderwatch-sigil', 'borderwatch-sigil',
'Zeichen der Grenzwacht', 'Zeichen der Grenzwacht',
'Das Wappen eines Turms, den es nicht mehr gibt.', 'Das Wappen eines Turms, den es nicht mehr gibt.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.AMULET, EquipmentSlot.AMULET,
ItemRarity.RARE, ItemRarity.RARE,
{ bonusAttack: 3, bonusHp: 10 }, { bonusAttack: 3, bonusHp: 10 },
@@ -143,7 +146,7 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
'burned-captain-pendant', 'burned-captain-pendant',
'Anhänger des verbrannten Hauptmanns', 'Anhänger des verbrannten Hauptmanns',
'Ein Schädel aus Schlacke, in dem die Glut nie erlosch.', 'Ein Schädel aus Schlacke, in dem die Glut nie erlosch.',
ItemType.ARMOR, ItemType.EQUIPMENT,
EquipmentSlot.AMULET, EquipmentSlot.AMULET,
ItemRarity.EPIC, ItemRarity.EPIC,
{ bonusAttack: 3, bonusHp: 15, bonusArmor: 2 }, { bonusAttack: 3, bonusHp: 15, bonusArmor: 2 },
@@ -158,11 +161,21 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
null, null,
ItemRarity.COMMON, ItemRarity.COMMON,
), ),
// A Trade Good (spec §17): turned in to the Grenzwacht for Silver and
// reputation rather than crafted with.
item( item(
'ash-pelt', 'ash-pelt',
'Aschenfell', 'Aschenfell',
'Versengtes Fell, zäh wie Leder und grau von Ascheflug.', 'Versengtes Fell, zäh wie Leder und grau von Ascheflug.',
ItemType.MATERIAL, ItemType.TRADE_GOOD,
null,
ItemRarity.COMMON,
),
item(
'bandit-insignia',
'Räuberabzeichen',
'Ein grob geprägtes Zeichen, das einen Straßenräuber als Mitglied seiner Bande auswies.',
ItemType.TROPHY,
null, null,
ItemRarity.COMMON, ItemRarity.COMMON,
), ),
@@ -170,7 +183,11 @@ export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
export const LOOT_TABLES = [ export const LOOT_TABLES = [
{ id: ASH_RAT_LOOT_TABLE_ID, key: 'ash-rat-loot', name: 'Aschenratte Beute' }, { id: ASH_RAT_LOOT_TABLE_ID, key: 'ash-rat-loot', name: 'Aschenratte Beute' },
{ id: ROAD_BANDIT_LOOT_TABLE_ID, key: 'road-bandit-loot', name: 'Straßenräuber Beute' }, {
id: ROAD_BANDIT_LOOT_TABLE_ID,
key: 'road-bandit-loot',
name: 'Straßenräuber Beute',
},
]; ];
export interface SeedLootTableEntry { export interface SeedLootTableEntry {
@@ -213,4 +230,5 @@ export const LOOT_TABLE_ENTRIES: SeedLootTableEntry[] = [
entry(ROAD_BANDIT_LOOT_TABLE_ID, 'bandit-blade', 1, '0.1800'), entry(ROAD_BANDIT_LOOT_TABLE_ID, 'bandit-blade', 1, '0.1800'),
entry(ROAD_BANDIT_LOOT_TABLE_ID, 'bandit-hood', 2, '0.1200'), entry(ROAD_BANDIT_LOOT_TABLE_ID, 'bandit-hood', 2, '0.1200'),
entry(ROAD_BANDIT_LOOT_TABLE_ID, 'raider-gloves', 3, '0.0800'), entry(ROAD_BANDIT_LOOT_TABLE_ID, 'raider-gloves', 3, '0.0800'),
entry(ROAD_BANDIT_LOOT_TABLE_ID, 'bandit-insignia', 4, '0.4000'),
]; ];

View File

@@ -12,6 +12,7 @@ export const ITEM_IDS = {
'burned-captain-pendant': '50000000-0000-4000-8000-00000000000a', 'burned-captain-pendant': '50000000-0000-4000-8000-00000000000a',
'small-healing-potion': '50000000-0000-4000-8000-00000000000b', 'small-healing-potion': '50000000-0000-4000-8000-00000000000b',
'ash-pelt': '50000000-0000-4000-8000-00000000000c', 'ash-pelt': '50000000-0000-4000-8000-00000000000c',
'bandit-insignia': '50000000-0000-4000-8000-00000000000d',
} as const; } as const;
export type ItemKey = keyof typeof ITEM_IDS; export type ItemKey = keyof typeof ITEM_IDS;

View File

@@ -0,0 +1,25 @@
export const BORDER_GUARD_FACTION_ID = '80000000-0000-4000-8000-000000000001';
export interface SeedReputationFaction {
id: string;
key: string;
name: string;
description: string;
regionKey: string;
enabled: boolean;
}
// Only Grenzwacht is seeded and usable in Slice 0.6.5 (spec §8). Dämmerjäger
// ('dusk-hunters') and Letzte Wacht ('last-watch') are future-region keys,
// intentionally not seeded yet.
export const REPUTATION_FACTIONS: SeedReputationFaction[] = [
{
id: BORDER_GUARD_FACTION_ID,
key: 'border-guard',
name: 'Grenzwacht',
description:
'Die letzten organisierten Wächter der Aschenfelder, die verbliebene Handelsrouten und Außenposten schützen.',
regionKey: 'ashen-fields',
enabled: true,
},
];

View File

@@ -0,0 +1,38 @@
import { ITEM_IDS } from './item.constants';
import { BORDER_GUARD_FACTION_ID } from './reputation-content';
export interface SeedTurnInDefinition {
id: string;
key: string;
itemDefinitionId: string;
factionId: string;
silverRewardPerItem: number;
reputationRewardPerItem: number;
repeatable: boolean;
enabled: boolean;
}
// Initial development values (spec §21), kept in content so they can be
// tuned without touching TurnInService's logic (spec §42).
export const TURN_IN_DEFINITIONS: SeedTurnInDefinition[] = [
{
id: '90000000-0000-4000-8000-000000000001',
key: 'ash-pelt-border-guard',
itemDefinitionId: ITEM_IDS['ash-pelt'],
factionId: BORDER_GUARD_FACTION_ID,
silverRewardPerItem: 4,
reputationRewardPerItem: 1,
repeatable: true,
enabled: true,
},
{
id: '90000000-0000-4000-8000-000000000002',
key: 'bandit-insignia-border-guard',
itemDefinitionId: ITEM_IDS['bandit-insignia'],
factionId: BORDER_GUARD_FACTION_ID,
silverRewardPerItem: 12,
reputationRewardPerItem: 4,
repeatable: true,
enabled: true,
},
];

View File

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

View File

@@ -16,7 +16,13 @@ import { LocationMonster } from '../../monsters/entities/location-monster.entity
import { MonsterDefinition } from '../../monsters/entities/monster-definition.entity'; import { MonsterDefinition } from '../../monsters/entities/monster-definition.entity';
import { LocationConnection } from '../../world/entities/location-connection.entity'; import { LocationConnection } from '../../world/entities/location-connection.entity';
import { LocationDefinition } from '../../world/entities/location-definition.entity'; import { LocationDefinition } from '../../world/entities/location-definition.entity';
import { ITEM_DEFINITIONS, LOOT_TABLES, LOOT_TABLE_ENTRIES } from './item-content'; import { ReputationFaction } from '../../reputation/entities/reputation-faction.entity';
import { TurnInDefinition } from '../../turn-in/entities/turn-in-definition.entity';
import {
ITEM_DEFINITIONS,
LOOT_TABLES,
LOOT_TABLE_ENTRIES,
} from './item-content';
import { import {
ASH_RAT_LOOT_TABLE_ID, ASH_RAT_LOOT_TABLE_ID,
ITEM_IDS, ITEM_IDS,
@@ -26,6 +32,8 @@ import {
BURNED_ROAD_LOCAL_CONTENT, BURNED_ROAD_LOCAL_CONTENT,
SOUTH_GATE_LOCAL_CONTENT, SOUTH_GATE_LOCAL_CONTENT,
} from './local-location.content'; } from './local-location.content';
import { REPUTATION_FACTIONS } from './reputation-content';
import { TURN_IN_DEFINITIONS } from './turn-in-content';
import { import {
ASH_RAT_MONSTER_ID, ASH_RAT_MONSTER_ID,
BURNED_ROAD_ID, BURNED_ROAD_ID,
@@ -46,6 +54,9 @@ export async function seedVisibleVerticalSlice(
const itemRepository = dataSource.getRepository(ItemDefinition); const itemRepository = dataSource.getRepository(ItemDefinition);
const lootTableRepository = dataSource.getRepository(LootTable); const lootTableRepository = dataSource.getRepository(LootTable);
const lootEntryRepository = dataSource.getRepository(LootTableEntry); const lootEntryRepository = dataSource.getRepository(LootTableEntry);
const reputationFactionRepository =
dataSource.getRepository(ReputationFaction);
const turnInDefinitionRepository = dataSource.getRepository(TurnInDefinition);
const locations = [ const locations = [
{ {
@@ -125,6 +136,8 @@ export async function seedVisibleVerticalSlice(
'lootTableId', 'lootTableId',
'itemDefinitionId', 'itemDefinitionId',
]); ]);
await reputationFactionRepository.upsert(REPUTATION_FACTIONS, ['key']);
await turnInDefinitionRepository.upsert(TURN_IN_DEFINITIONS, ['key']);
const monsters = [ const monsters = [
{ {
@@ -135,9 +148,8 @@ export async function seedVisibleVerticalSlice(
maxHp: 45, maxHp: 45,
attack: 5, attack: 5,
armor: 0, armor: 0,
experienceReward: 8, silverMin: 0,
silverMin: 4, silverMax: 0,
silverMax: 7,
artworkPath: '/images/monsters/ash-rat.png', artworkPath: '/images/monsters/ash-rat.png',
iconPath: '/images/combat/icons/ash-rat-128.png', iconPath: '/images/combat/icons/ash-rat-128.png',
lootTableId: ASH_RAT_LOOT_TABLE_ID, lootTableId: ASH_RAT_LOOT_TABLE_ID,
@@ -150,9 +162,8 @@ export async function seedVisibleVerticalSlice(
maxHp: 55, maxHp: 55,
attack: 7, attack: 7,
armor: 0, armor: 0,
experienceReward: 11, silverMin: 0,
silverMin: 5, silverMax: 0,
silverMax: 9,
artworkPath: '/images/monsters/wild-road-dog.png', artworkPath: '/images/monsters/wild-road-dog.png',
iconPath: '/images/combat/icons/wild-road-dog-128.png', iconPath: '/images/combat/icons/wild-road-dog-128.png',
// Shares the beast table: both are scorched road animals that leave a // Shares the beast table: both are scorched road animals that leave a
@@ -167,9 +178,8 @@ export async function seedVisibleVerticalSlice(
maxHp: 75, maxHp: 75,
attack: 9, attack: 9,
armor: 5, armor: 5,
experienceReward: 16, silverMin: 0,
silverMin: 9, silverMax: 0,
silverMax: 15,
artworkPath: '/images/monsters/road-bandit.png', artworkPath: '/images/monsters/road-bandit.png',
iconPath: '/images/combat/icons/road-bandit-128.png', iconPath: '/images/combat/icons/road-bandit-128.png',
lootTableId: ROAD_BANDIT_LOOT_TABLE_ID, lootTableId: ROAD_BANDIT_LOOT_TABLE_ID,
@@ -182,9 +192,8 @@ export async function seedVisibleVerticalSlice(
maxHp: 85, maxHp: 85,
attack: 11, attack: 11,
armor: 6, armor: 6,
experienceReward: 20, silverMin: 0,
silverMin: 12, silverMax: 0,
silverMax: 19,
artworkPath: '/images/monsters/charred-looter.png', artworkPath: '/images/monsters/charred-looter.png',
iconPath: '/images/combat/icons/charred-looter-128.png', iconPath: '/images/combat/icons/charred-looter-128.png',
// Shares the raider table: same gear, taken from the same caravans. // Shares the raider table: same gear, taken from the same caravans.
@@ -237,8 +246,7 @@ export async function seedVisibleVerticalSlice(
await characterRepository.insert({ await characterRepository.insert({
id: DEMO_CHARACTER_ID, id: DEMO_CHARACTER_ID,
name: 'Aric Duskwalker', name: 'Aric Duskwalker',
level: 1, renown: 1,
experience: 0,
silver: 0, silver: 0,
baseHp: 100, baseHp: 100,
baseAttack: 6, baseAttack: 6,
@@ -248,7 +256,8 @@ export async function seedVisibleVerticalSlice(
} }
const characterItemRepository = dataSource.getRepository(CharacterItem); const characterItemRepository = dataSource.getRepository(CharacterItem);
const characterEquipmentRepository = dataSource.getRepository(CharacterEquipment); const characterEquipmentRepository =
dataSource.getRepository(CharacterEquipment);
// Starting loadout is weapon-only -- no starter armor piece exists in // Starting loadout is weapon-only -- no starter armor piece exists in
// content yet -- so the demo character's effective armor (sum of equipped // content yet -- so the demo character's effective armor (sum of equipped