From 23027cf1b300937aa107879bc398b54bf86430af Mon Sep 17 00:00:00 2001 From: Octoturge Date: Thu, 22 Oct 2026 00:05:57 +0200 Subject: [PATCH] feat: weapon wound kind (1.5.1) Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 9 +++++++++ lang/en.json | 7 +++++++ lang/pl.json | 7 +++++++ package.json | 2 +- scripts/parsers/gear-parser.ts | 11 +++++++++++ src/constants.ts | 4 ++++ src/data/item-gear.ts | 4 +++- system.json | 2 +- templates/item/gear.hbs | 8 ++++++++ tests/parsers/gear-parser.test.ts | 17 +++++++++++++++++ 10 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 tests/parsers/gear-parser.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e0cc13..2a51fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to the **HbM RPG v3** Foundry VTT system. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.5.1] - 2026-10-22 + +### Added +- Weapons have a wound kind (`system.weapon.woundKind`: tnąca / kłująca / obuchowa, empty = unspecified), editable on the gear sheet. +- Gear parser reads `wound` / `rana` frontmatter from vault weapon notes. Missing or unknown values stay unspecified; nothing is guessed. + +### Notes +- Only cutting and piercing weapons feed passive Krew; unspecified weapons give none. Callers of `applyDamage` still need to pass the weapon's `woundKind`. + ## [1.5.0] - 2026-10-20 Vault answers (Foundry Sync Brief §17): blood magic and Runiczny Pancerz. diff --git a/lang/en.json b/lang/en.json index e2c629b..2e04e62 100644 --- a/lang/en.json +++ b/lang/en.json @@ -239,6 +239,13 @@ "physical": "Physical", "magical": "Magical", "environmental": "Environmental", + "woundKind": "Wound kind", + "wound": { + "none": "Unspecified", + "cutting": "Cutting", + "piercing": "Piercing", + "blunt": "Blunt" + }, "properties": "Properties", "damageReduction": "Damage Reduction", "damageReductionBonus": "DR Bonus", diff --git a/lang/pl.json b/lang/pl.json index 2401b1b..fd7f65e 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -259,6 +259,13 @@ "physical": "Fizyczne", "magical": "Magiczne", "environmental": "Środowiskowe", + "woundKind": "Rodzaj rany", + "wound": { + "none": "Nieokreślony", + "cutting": "Tnąca", + "piercing": "Kłująca", + "blunt": "Obuchowa" + }, "properties": "Właściwości", "damageReduction": "Redukcja Obrażeń", "damageReductionBonus": "Premia do Redukcji", diff --git a/package.json b/package.json index 40aab09..c2bae20 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hbm-rpg-v3-foundry", - "version": "1.5.0", + "version": "1.5.1", "description": "Foundry VTT system for Homebrew Magic: Role Playing Game v3", "private": true, "type": "module", diff --git a/scripts/parsers/gear-parser.ts b/scripts/parsers/gear-parser.ts index 4033453..96b4c6b 100644 --- a/scripts/parsers/gear-parser.ts +++ b/scripts/parsers/gear-parser.ts @@ -38,6 +38,15 @@ export const parseGear: ParserFn = async (ctx: ParserContext): Promise; content: string } { const fm: Record = {}; let content = raw; @@ -91,6 +100,7 @@ function buildGearDoc(name: string, fm: Record, content: string, weapon: { damage: '', damageType: 'physical', + woundKind: '', properties: [], }, armor: { @@ -105,6 +115,7 @@ function buildGearDoc(name: string, fm: Record, content: string, if (category === 'weapon') { system.weapon.damage = fm.damage || fm.obrazenia || ''; + system.weapon.woundKind = parseWoundKind(fm.wound || fm.rana); if (fm.traits || fm.cechy) { system.weapon.properties = parseList(fm.traits || fm.cechy); } diff --git a/src/constants.ts b/src/constants.ts index 11ddd53..93b3ae3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -192,6 +192,10 @@ export type GearCategory = (typeof GEAR_CATEGORIES)[number]; export const DAMAGE_TYPES = ['physical', 'magical', 'environmental'] as const; export type DamageType = (typeof DAMAGE_TYPES)[number]; +/** Weapon wound kinds ('' = unspecified). Cutting / piercing feed the passive Krew talents. */ +export const WOUND_KINDS = ['', 'cutting', 'piercing', 'blunt'] as const; +export type WoundKind = (typeof WOUND_KINDS)[number]; + /** Armor types */ export const ARMOR_TYPES = ['light', 'medium', 'heavy', 'shield'] as const; export type ArmorType = (typeof ARMOR_TYPES)[number]; diff --git a/src/data/item-gear.ts b/src/data/item-gear.ts index 00f10db..a501ae9 100644 --- a/src/data/item-gear.ts +++ b/src/data/item-gear.ts @@ -6,7 +6,7 @@ import { makeArrayField, fields, } from './fields'; -import { GEAR_CATEGORIES, DAMAGE_TYPES, ARMOR_TYPES, RARITIES } from '../constants'; +import { GEAR_CATEGORIES, DAMAGE_TYPES, ARMOR_TYPES, RARITIES, WOUND_KINDS } from '../constants'; /** * Unified Gear item - discriminated by `category`. @@ -39,6 +39,8 @@ export class GearData extends foundry.abstract.TypeDataModel { choices: DAMAGE_TYPES as unknown as readonly string[], }), properties: makeArrayField(new f.StringField({ blank: false })), + // Rodzaj rany: cutting (tnąca) / piercing (kłująca) / blunt (obuchowa); '' = not specified. + woundKind: makeStringField('', { blank: true, choices: WOUND_KINDS as unknown as readonly string[] }), }), armor: new f.SchemaField({ diff --git a/system.json b/system.json index c34ccd8..8df3091 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "hbm-rpg-v3", "title": "Homebrew Magic: RPG v3", "description": "System Foundry VTT dla Homebrew Magic: Role Playing Game v3 - autorska gra fabularna z mechaniką puli kości d6 (TS - Trudność:Sukcesy).", - "version": "1.5.0", + "version": "1.5.1", "manifest": "https://vtt-content.octoturge.com/packages/system/hbm-rpg-v3.json", "download": "https://vtt-content.octoturge.com/packages/system/hbm-rpg-v3-v1.5.0.zip", "compatibility": { diff --git a/templates/item/gear.hbs b/templates/item/gear.hbs index f19862f..aeae6e1 100644 --- a/templates/item/gear.hbs +++ b/templates/item/gear.hbs @@ -31,6 +31,14 @@ + {{/if}} diff --git a/tests/parsers/gear-parser.test.ts b/tests/parsers/gear-parser.test.ts new file mode 100644 index 0000000..6cbf81b --- /dev/null +++ b/tests/parsers/gear-parser.test.ts @@ -0,0 +1,17 @@ +import { describe, it, expect } from 'vitest'; +import { parseWoundKind } from '../../scripts/parsers/gear-parser'; + +describe('gear-parser parseWoundKind', () => { + it('maps Polish and English labels', () => { + expect(parseWoundKind('tnąca')).toBe('cutting'); + expect(parseWoundKind('Kłująca')).toBe('piercing'); + expect(parseWoundKind('obuchowa')).toBe('blunt'); + expect(parseWoundKind('piercing')).toBe('piercing'); + }); + + it('never guesses: missing or unknown stays unspecified', () => { + expect(parseWoundKind(undefined)).toBe(''); + expect(parseWoundKind('')).toBe(''); + expect(parseWoundKind('ognista')).toBe(''); + }); +});