From dfe4e1d18968c4750e6786090b0a6f6d72ce2426 Mon Sep 17 00:00:00 2001 From: Drew Malzahn Date: Sun, 28 Jun 2026 12:13:33 -0400 Subject: [PATCH] feat: Add armor and shields to equipment picker Import armor_shields.yml and merge it with weapons in the '+ Add Equipment' picker. Armor/shield entries are formatted with DEF/MDEF/Init fields. Adds armor and shield filter categories alongside existing weapon categories. Co-Authored-By: Claude Sonnet 4.6 --- data/armor_shields.yml | 8 ++++---- src/CharacterSheet.tsx | 33 ++++++++++++++++++++++++++------- src/globals.d.ts | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/data/armor_shields.yml b/data/armor_shields.yml index 5eb9933..940d37b 100644 --- a/data/armor_shields.yml +++ b/data/armor_shields.yml @@ -48,7 +48,7 @@ armor_shields: category: armor description: No Quality. - - name: Bronze Plate (E) + - name: Bronze Plate ✦ cost: 200 defense: "11" magic_defense: "INS size" @@ -56,7 +56,7 @@ armor_shields: category: armor description: No Quality. - - name: Runic Plate (E) + - name: Runic Plate ✦ cost: 250 defense: "11" magic_defense: "INS size +1" @@ -64,7 +64,7 @@ armor_shields: category: armor description: No Quality. - - name: Steel Plate (E) + - name: Steel Plate ✦ cost: 300 defense: "12" magic_defense: "INS size" @@ -80,7 +80,7 @@ armor_shields: category: shield description: No Quality. - - name: Runic Shield (E) + - name: Runic Shield ✦ cost: 150 defense: "+2" magic_defense: "+2" diff --git a/src/CharacterSheet.tsx b/src/CharacterSheet.tsx index a02900e..cde06e4 100644 --- a/src/CharacterSheet.tsx +++ b/src/CharacterSheet.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback, useRef } from "react"; import "./fabula-ultima-sheet.css"; import spellsFile from "../data/spells.yml"; import weaponsFile from "../data/weapons.yml"; +import armorShieldsFile from "../data/armor_shields.yml"; const STATUSES = ["Slow", "Enraged", "Dazed", "Weak", "Poisoned", "Shaken"]; const FEELINGS = [ @@ -1165,13 +1166,31 @@ export default function CharacterSheet() { {weaponPickerOpen && (() => { const allWeapons = (weaponsFile as WeaponsFile).weapons; - const categories = ["all", ...Array.from(new Set(allWeapons.map(w => w.category))).sort()]; - const visible = weaponCategory === "all" ? allWeapons : allWeapons.filter(w => w.category === weaponCategory); + const allArmorShields = (armorShieldsFile as ArmorShieldsFile).armor_shields; + type PickerItem = + | { kind: "weapon"; data: WeaponTemplate } + | { kind: "armor"; data: ArmorShieldTemplate }; + const allItems: PickerItem[] = [ + ...allWeapons.map(w => ({ kind: "weapon" as const, data: w })), + ...allArmorShields.map(a => ({ kind: "armor" as const, data: a })), + ]; + const categories = ["all", ...Array.from(new Set(allItems.map(i => i.data.category))).sort()]; + const visible = weaponCategory === "all" ? allItems : allItems.filter(i => i.data.category === weaponCategory); + const formatLine = (item: PickerItem) => { + if (item.kind === "weapon") { + const w = item.data; + return `• ${w.name}: Acc ${w.accuracy}, Dmg ${w.damage}${w.description ? ` | ${w.description}` : ""}${w.cost > 0 ? ` (${w.cost}z)` : ""}`; + } else { + const a = item.data; + const init = a.initiative ?? a.initative ?? 0; + return `• ${a.name}: DEF ${a.defense}, MDEF ${a.magic_defense}, Init ${init}${a.description ? ` | ${a.description}` : ""}${a.cost > 0 ? ` (${a.cost}z)` : ""}`; + } + }; return (
setWeaponPickerOpen(false)}>
e.stopPropagation()}>
- Choose a weapon + Choose equipment
@@ -1187,18 +1206,18 @@ export default function CharacterSheet() { ))}
    - {visible.map((w, i) => ( + {visible.map((item, i) => (
  • { - const line = `• ${w.name}: Acc ${w.accuracy}, Dmg ${w.damage}${w.description ? ` | ${w.description}` : ""}${w.cost > 0 ? ` (${w.cost}z)` : ""}`; + const line = formatLine(item); f("backpack", fields.backpack ? fields.backpack + "\n" + line : line); setWeaponPickerOpen(false); }} > - {w.name} - {w.category} + {item.data.name} + {item.data.category}
  • ))}
diff --git a/src/globals.d.ts b/src/globals.d.ts index 0ca271c..df213c2 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -18,6 +18,21 @@ interface WeaponsFile { weapons: WeaponTemplate[]; } +interface ArmorShieldTemplate { + name: string; + cost: number; + defense: string; + magic_defense: string; + initiative?: number; + initative?: number; // typo present in source YAML + category: string; + description?: string; +} + +interface ArmorShieldsFile { + armor_shields: ArmorShieldTemplate[]; +} + interface SpellTemplate { name: string; cost: string;