217 lines
5.7 KiB
TypeScript
217 lines
5.7 KiB
TypeScript
import { EquipmentSlot } from '../../items/equipment-slot.enum';
|
||
import { ItemRarity } from '../../items/item-rarity.enum';
|
||
import { ItemType } from '../../items/item-type.enum';
|
||
import {
|
||
ASH_RAT_LOOT_TABLE_ID,
|
||
ITEM_IDS,
|
||
ItemKey,
|
||
ROAD_BANDIT_LOOT_TABLE_ID,
|
||
} from './item.constants';
|
||
|
||
export interface SeedItemDefinition {
|
||
id: string;
|
||
key: ItemKey;
|
||
name: string;
|
||
description: string;
|
||
type: ItemType;
|
||
equipmentSlot: EquipmentSlot | null;
|
||
rarity: ItemRarity;
|
||
tier: number;
|
||
requiredLevel: number;
|
||
weaponDamage: number;
|
||
bonusHp: number;
|
||
bonusAttack: number;
|
||
bonusArmor: number;
|
||
sellPrice: number;
|
||
iconPath: string;
|
||
}
|
||
|
||
function item(
|
||
key: ItemKey,
|
||
name: string,
|
||
description: string,
|
||
type: ItemType,
|
||
equipmentSlot: EquipmentSlot | null,
|
||
rarity: ItemRarity,
|
||
stats: Partial<Pick<SeedItemDefinition, 'weaponDamage' | 'bonusHp' | 'bonusAttack' | 'bonusArmor'>> = {},
|
||
): SeedItemDefinition {
|
||
return {
|
||
id: ITEM_IDS[key],
|
||
key,
|
||
name,
|
||
description,
|
||
type,
|
||
equipmentSlot,
|
||
rarity,
|
||
tier: 1,
|
||
requiredLevel: 1,
|
||
weaponDamage: stats.weaponDamage ?? 0,
|
||
bonusHp: stats.bonusHp ?? 0,
|
||
bonusAttack: stats.bonusAttack ?? 0,
|
||
bonusArmor: stats.bonusArmor ?? 0,
|
||
// Always 0: no merchants exist in Slice 0.4, and the balancing doc's
|
||
// Grenzmarken table lists purchase prices, not sell prices.
|
||
sellPrice: 0,
|
||
iconPath: `/images/items/${key}.png`,
|
||
};
|
||
}
|
||
|
||
// Stats from docs/Ashen_Realms_Balancing_Items_Loot_Design_V1.md §19.
|
||
export const ITEM_DEFINITIONS: SeedItemDefinition[] = [
|
||
item(
|
||
'worn-short-sword',
|
||
'Abgenutztes Kurzschwert',
|
||
'Die Klinge eines Rekruten, öfter geschliffen als geführt.',
|
||
ItemType.WEAPON,
|
||
EquipmentSlot.WEAPON,
|
||
ItemRarity.COMMON,
|
||
{ weaponDamage: 8 },
|
||
),
|
||
item(
|
||
'bandit-blade',
|
||
'Räuberklinge',
|
||
'Eine grob gezahnte Klinge, geschmiedet für schnelle Überfälle.',
|
||
ItemType.WEAPON,
|
||
EquipmentSlot.WEAPON,
|
||
ItemRarity.COMMON,
|
||
{ weaponDamage: 11, bonusAttack: 1 },
|
||
),
|
||
item(
|
||
'ash-blade',
|
||
'Aschenklinge',
|
||
'In der Glut der Aschenfelder gehärtet; die Schneide glimmt noch.',
|
||
ItemType.WEAPON,
|
||
EquipmentSlot.WEAPON,
|
||
ItemRarity.RARE,
|
||
{ weaponDamage: 15, bonusAttack: 2 },
|
||
),
|
||
item(
|
||
'bandit-hood',
|
||
'Räuberhaube',
|
||
'Vernarbtes Leder, das Gesicht und Absicht des Trägers verbirgt.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.HEAD,
|
||
ItemRarity.COMMON,
|
||
{ bonusArmor: 3, bonusHp: 5 },
|
||
),
|
||
item(
|
||
'reinforced-leather-jacket',
|
||
'Verstärkte Lederjacke',
|
||
'Mit Eisenplatten benähtes Leder, schwer und verlässlich.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.CHEST,
|
||
ItemRarity.RARE,
|
||
{ bonusArmor: 7, bonusHp: 10 },
|
||
),
|
||
item(
|
||
'raider-gloves',
|
||
'Plündererhandschuhe',
|
||
'Beschlagene Handschuhe, abgegriffen von fremdem Gut.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.HANDS,
|
||
ItemRarity.COMMON,
|
||
{ bonusArmor: 3, bonusAttack: 1 },
|
||
),
|
||
item(
|
||
'guardsman-legs',
|
||
'Wachmannsbeinkleid',
|
||
'Beinzeug der Grenzwacht, an den Knien geflickt.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.LEGS,
|
||
ItemRarity.RARE,
|
||
{ bonusArmor: 5, bonusHp: 5 },
|
||
),
|
||
item(
|
||
'ash-boots',
|
||
'Aschenstiefel',
|
||
'Stiefel, die durch glimmende Felder getragen wurden und blieben.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.FEET,
|
||
ItemRarity.RARE,
|
||
{ bonusArmor: 4, bonusHp: 5 },
|
||
),
|
||
item(
|
||
'borderwatch-sigil',
|
||
'Zeichen der Grenzwacht',
|
||
'Das Wappen eines Turms, den es nicht mehr gibt.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.AMULET,
|
||
ItemRarity.RARE,
|
||
{ bonusAttack: 3, bonusHp: 10 },
|
||
),
|
||
item(
|
||
'burned-captain-pendant',
|
||
'Anhänger des verbrannten Hauptmanns',
|
||
'Ein Schädel aus Schlacke, in dem die Glut nie erlosch.',
|
||
ItemType.ARMOR,
|
||
EquipmentSlot.AMULET,
|
||
ItemRarity.EPIC,
|
||
{ bonusAttack: 3, bonusHp: 15, bonusArmor: 2 },
|
||
),
|
||
// Seeded as content only. Slice 0.4 implements no consumable use, and the
|
||
// Straßenräuber loot entry for it is deliberately deferred (spec §16).
|
||
item(
|
||
'small-healing-potion',
|
||
'Kleiner Heiltrank',
|
||
'Ein bitterer Sud, der Wunden für einen Atemzug vergessen lässt.',
|
||
ItemType.CONSUMABLE,
|
||
null,
|
||
ItemRarity.COMMON,
|
||
),
|
||
item(
|
||
'ash-pelt',
|
||
'Aschenfell',
|
||
'Versengtes Fell, zäh wie Leder und grau von Ascheflug.',
|
||
ItemType.MATERIAL,
|
||
null,
|
||
ItemRarity.COMMON,
|
||
),
|
||
];
|
||
|
||
export const LOOT_TABLES = [
|
||
{ 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' },
|
||
];
|
||
|
||
export interface SeedLootTableEntry {
|
||
lootTableId: string;
|
||
itemDefinitionId: string;
|
||
position: number;
|
||
dropChance: string;
|
||
minQuantity: number;
|
||
maxQuantity: number;
|
||
enabled: boolean;
|
||
}
|
||
|
||
function entry(
|
||
lootTableId: string,
|
||
key: ItemKey,
|
||
position: number,
|
||
dropChance: string,
|
||
): SeedLootTableEntry {
|
||
return {
|
||
lootTableId,
|
||
itemDefinitionId: ITEM_IDS[key],
|
||
position,
|
||
dropChance,
|
||
minQuantity: 1,
|
||
maxQuantity: 1,
|
||
enabled: true,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Drop chances from docs/Ashen_Realms_Balancing_Items_Loot_Design_V1.md §27–28.
|
||
* Every entry is an independent roll (spec §17), rolled in `position` order.
|
||
*
|
||
* DEFERRED: the Straßenräuber table also lists 10 % Kleiner Heiltrank. It is
|
||
* omitted here because Slice 0.4 implements no consumables (spec §16).
|
||
*/
|
||
export const LOOT_TABLE_ENTRIES: SeedLootTableEntry[] = [
|
||
entry(ASH_RAT_LOOT_TABLE_ID, 'ash-pelt', 1, '0.6000'),
|
||
entry(ASH_RAT_LOOT_TABLE_ID, 'worn-short-sword', 2, '0.0800'),
|
||
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, 'raider-gloves', 3, '0.0800'),
|
||
];
|