Add minor data model improvements from rulebook audit (16 items)
CharacterData additions: - Senses (darksight, blindsight, tremorsense, elvenEyes, witchsight, sixthSense) - Languages array (default: ["Common"]) - Rest tracking (lastRest, breathersTaken, restBonuses) - Travel tracking (milesThisDay, pace, canForage, shiftsElapsed) - Crafting projects (activeProjects with materials, shifts, bonuses) - Combat tracking (isFlanked, flankingAllies, ignoresFlankingPenalty, currentZone, isDualWielding, mainHandWeapon, offHandWeapon) - Casting tracking (equippedTrinket, canCastThroughWeapon/Instrument) - Downtime activities with type and shifts - Quest tracking (active, completed, lastQuestCompleted) - Death state (isDead, deathCause, canBeRevived, luminaryRevivifyUsed) - Summoned creatures (active array with type, HD, HP, command method) - Size mechanical effects (unitsOccupied, allowsMovementThrough) - Being type choices (humanlike, fae, cryptid, etc.) - preferredZone for class-based positioning NPCData additions: - Morale status tracking (checkedThisCombat, lastTrigger, lastResult, broken) - Senses (darksight, blindsight, tremorsense) ArmorData additions: - Medium armor type, hindersDodge, preventsRage flags WeaponData additions: - Damage type choices (blunt/piercing/slashing + elemental) - equippedHand for dual-wielding (main/off/both) EquipmentData additions: - isTrinket and canCastThrough for spell component tracking 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
466581efd5
commit
c06192f90f
@ -339,8 +339,29 @@ export default class CharacterData extends VagabondActorBase {
|
|||||||
|
|
||||||
// Character details
|
// Character details
|
||||||
details: new fields.SchemaField({
|
details: new fields.SchemaField({
|
||||||
size: new fields.StringField({ initial: "medium" }),
|
// Size category with mechanical effects
|
||||||
beingType: new fields.StringField({ initial: "humanlike" }),
|
size: new fields.StringField({
|
||||||
|
initial: "medium",
|
||||||
|
choices: ["small", "medium", "large", "huge", "giant", "colossal"],
|
||||||
|
}),
|
||||||
|
// Units occupied on grid (derived from size)
|
||||||
|
unitsOccupied: new fields.NumberField({ integer: true, initial: 1, min: 1 }),
|
||||||
|
// Small creatures don't block movement through their space
|
||||||
|
allowsMovementThrough: new fields.BooleanField({ initial: false }),
|
||||||
|
// Being type for targeting effects
|
||||||
|
beingType: new fields.StringField({
|
||||||
|
initial: "humanlike",
|
||||||
|
choices: [
|
||||||
|
"humanlike",
|
||||||
|
"fae",
|
||||||
|
"cryptid",
|
||||||
|
"artificial",
|
||||||
|
"undead",
|
||||||
|
"primordial",
|
||||||
|
"hellspawn",
|
||||||
|
"beast",
|
||||||
|
],
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Favor/Hinder tracking (d20 +/- d6 modifiers)
|
// Favor/Hinder tracking (d20 +/- d6 modifiers)
|
||||||
@ -400,6 +421,178 @@ export default class CharacterData extends VagabondActorBase {
|
|||||||
// Track which stats were increased at which level
|
// Track which stats were increased at which level
|
||||||
statIncreasesByLevel: new fields.ObjectField({ initial: {} }), // { "2": "might", "4": "dexterity" }
|
statIncreasesByLevel: new fields.ObjectField({ initial: {} }), // { "2": "might", "4": "dexterity" }
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// Senses and vision types
|
||||||
|
senses: new fields.SchemaField({
|
||||||
|
darksight: new fields.BooleanField({ initial: false }), // Dwarf, Goblin, Orc, Infravision perk
|
||||||
|
blindsight: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
||||||
|
tremorsense: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
||||||
|
// Special vision abilities from perks/ancestry
|
||||||
|
specialVision: new fields.SchemaField({
|
||||||
|
elvenEyes: new fields.BooleanField({ initial: false }), // Favor on sight Detect
|
||||||
|
witchsight: new fields.BooleanField({ initial: false }), // See Invisible, Favor vs illusions
|
||||||
|
sixthSense: new fields.BooleanField({ initial: false }), // Ignore Blinded for sight-based checks
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Known languages
|
||||||
|
languages: new fields.ArrayField(new fields.StringField(), { initial: ["Common"] }),
|
||||||
|
|
||||||
|
// Rest and breather tracking
|
||||||
|
restTracking: new fields.SchemaField({
|
||||||
|
// Timestamp of last full rest
|
||||||
|
lastRest: new fields.StringField({ required: false, blank: true }),
|
||||||
|
// Number of breathers taken in current combat/scene
|
||||||
|
breathersTaken: new fields.NumberField({ integer: true, initial: 0, min: 0 }),
|
||||||
|
// Bonuses to rest (Song of Rest, Tricksy, etc.)
|
||||||
|
restBonuses: new fields.ArrayField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
source: new fields.StringField({ required: true }), // "Song of Rest", "Tricksy"
|
||||||
|
effect: new fields.StringField({ required: true }), // "+PRS HP", "+1 Luck"
|
||||||
|
}),
|
||||||
|
{ initial: [] }
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Travel and exploration tracking
|
||||||
|
travel: new fields.SchemaField({
|
||||||
|
// Miles traveled today (for Padfoot perk)
|
||||||
|
milesThisDay: new fields.NumberField({ integer: true, initial: 0, min: 0 }),
|
||||||
|
// Current travel pace
|
||||||
|
pace: new fields.StringField({
|
||||||
|
initial: "normal",
|
||||||
|
choices: ["slow", "normal", "fast"],
|
||||||
|
}),
|
||||||
|
// Can forage at normal pace (Hunter Survivalist)
|
||||||
|
canForage: new fields.BooleanField({ initial: false }),
|
||||||
|
// Shifts elapsed (time tracking for cooldowns)
|
||||||
|
shiftsElapsed: new fields.NumberField({ integer: true, initial: 0, min: 0 }),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Crafting projects in progress
|
||||||
|
crafting: new fields.SchemaField({
|
||||||
|
activeProjects: new fields.ArrayField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
itemName: new fields.StringField({ required: true }),
|
||||||
|
targetValue: new fields.NumberField({ integer: true, initial: 0 }), // In silver
|
||||||
|
materialsCost: new fields.NumberField({ integer: true, initial: 0 }),
|
||||||
|
shiftsRequired: new fields.NumberField({ integer: true, initial: 1 }),
|
||||||
|
shiftsCompleted: new fields.NumberField({ integer: true, initial: 0 }),
|
||||||
|
bonuses: new fields.ArrayField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
source: new fields.StringField({ required: true }), // "Master Artisan"
|
||||||
|
effect: new fields.StringField({ required: true }), // "2× Shifts"
|
||||||
|
}),
|
||||||
|
{ initial: [] }
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
{ initial: [] }
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Combat positioning and flanking
|
||||||
|
combat: new fields.SchemaField({
|
||||||
|
// Is this character currently flanked?
|
||||||
|
isFlanked: new fields.BooleanField({ initial: false }),
|
||||||
|
// IDs of allies providing flanking
|
||||||
|
flankingAllies: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
// Ignores flanking penalties (Situational Awareness perk)
|
||||||
|
ignoresFlankingPenalty: new fields.BooleanField({ initial: false }),
|
||||||
|
// Current combat zone
|
||||||
|
currentZone: new fields.StringField({
|
||||||
|
initial: "",
|
||||||
|
choices: ["", "frontline", "midline", "backline"],
|
||||||
|
}),
|
||||||
|
// Is dual-wielding?
|
||||||
|
isDualWielding: new fields.BooleanField({ initial: false }),
|
||||||
|
// Main hand weapon ID
|
||||||
|
mainHandWeapon: new fields.StringField({ required: false, blank: true }),
|
||||||
|
// Off hand weapon/shield ID
|
||||||
|
offHandWeapon: new fields.StringField({ required: false, blank: true }),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Casting and spell component tracking
|
||||||
|
casting: new fields.SchemaField({
|
||||||
|
// Currently equipped trinket item ID
|
||||||
|
equippedTrinket: new fields.StringField({ required: false, blank: true }),
|
||||||
|
// Can cast through weapon (Gish perk)
|
||||||
|
canCastThroughWeapon: new fields.BooleanField({ initial: false }),
|
||||||
|
// Can cast through musical instrument (Harmonic Resonance)
|
||||||
|
canCastThroughInstrument: new fields.BooleanField({ initial: false }),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Downtime activity tracking
|
||||||
|
downtime: new fields.SchemaField({
|
||||||
|
activities: new fields.ArrayField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
type: new fields.StringField({
|
||||||
|
initial: "work",
|
||||||
|
choices: ["craft", "study", "carouse", "work", "research"],
|
||||||
|
}),
|
||||||
|
shiftsSpent: new fields.NumberField({ integer: true, initial: 0 }),
|
||||||
|
result: new fields.StringField({ required: false, blank: true }),
|
||||||
|
}),
|
||||||
|
{ initial: [] }
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Quest tracking (for cooldowns like Medium perk)
|
||||||
|
quests: new fields.SchemaField({
|
||||||
|
activeQuests: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
completedQuests: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
// For Medium perk cooldown
|
||||||
|
lastQuestCompleted: new fields.StringField({ required: false, blank: true }),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Death and dying state
|
||||||
|
death: new fields.SchemaField({
|
||||||
|
isDead: new fields.BooleanField({ initial: false }),
|
||||||
|
deathCause: new fields.StringField({
|
||||||
|
initial: "",
|
||||||
|
choices: ["", "hp-zero", "body-destroyed", "fatigue-five"],
|
||||||
|
}),
|
||||||
|
canBeRevived: new fields.BooleanField({ initial: true }),
|
||||||
|
revivedCount: new fields.NumberField({ integer: true, initial: 0, min: 0 }),
|
||||||
|
// Luminary Revivify used today?
|
||||||
|
luminaryRevivifyUsed: new fields.BooleanField({ initial: false }),
|
||||||
|
// Force of Nature used this combat?
|
||||||
|
forceOfNatureUsed: new fields.BooleanField({ initial: false }),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Summoned creatures tracking
|
||||||
|
summons: new fields.SchemaField({
|
||||||
|
active: new fields.ArrayField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
id: new fields.StringField({ required: true }),
|
||||||
|
name: new fields.StringField({ required: true }),
|
||||||
|
type: new fields.StringField({
|
||||||
|
initial: "beast",
|
||||||
|
choices: ["companion", "familiar", "primordial", "beast", "undead"],
|
||||||
|
}),
|
||||||
|
source: new fields.StringField({ required: true }), // "Animal Companion", "Familiar perk"
|
||||||
|
hd: new fields.NumberField({ integer: true, initial: 1 }),
|
||||||
|
currentHP: new fields.NumberField({ integer: true, initial: 4 }),
|
||||||
|
maxHP: new fields.NumberField({ integer: true, initial: 4 }),
|
||||||
|
usesSkill: new fields.StringField({ initial: "survival" }), // Which skill for checks
|
||||||
|
commandMethod: new fields.StringField({
|
||||||
|
initial: "action",
|
||||||
|
choices: ["action", "skip-move", "automatic"],
|
||||||
|
}),
|
||||||
|
duration: new fields.StringField({
|
||||||
|
initial: "permanent",
|
||||||
|
choices: ["permanent", "focus", "shift", "scene"],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
{ initial: [] }
|
||||||
|
),
|
||||||
|
maxConcurrent: new fields.NumberField({ integer: true, initial: 1, min: 1 }),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Preferred combat zone (from class)
|
||||||
|
preferredZone: new fields.StringField({
|
||||||
|
initial: "frontline",
|
||||||
|
choices: ["frontline", "midline", "backline", "flexible"],
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,6 +73,24 @@ export default class NPCData extends VagabondActorBase {
|
|||||||
max: 12,
|
max: 12,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// Morale check tracking
|
||||||
|
moraleStatus: new fields.SchemaField({
|
||||||
|
// Has a morale check been triggered this combat?
|
||||||
|
checkedThisCombat: new fields.BooleanField({ initial: false }),
|
||||||
|
// What triggered the last check?
|
||||||
|
lastTrigger: new fields.StringField({
|
||||||
|
initial: "",
|
||||||
|
choices: ["", "first-death", "half-hp", "half-incapacitated", "leader-death"],
|
||||||
|
}),
|
||||||
|
// Result of the last morale check
|
||||||
|
lastResult: new fields.StringField({
|
||||||
|
initial: "",
|
||||||
|
choices: ["", "passed", "failed-retreat", "failed-surrender"],
|
||||||
|
}),
|
||||||
|
// Is this NPC currently fleeing/surrendered?
|
||||||
|
broken: new fields.BooleanField({ initial: false }),
|
||||||
|
}),
|
||||||
|
|
||||||
// Number appearing (for random encounters)
|
// Number appearing (for random encounters)
|
||||||
appearing: new fields.StringField({ initial: "1d6" }),
|
appearing: new fields.StringField({ initial: "1d6" }),
|
||||||
|
|
||||||
@ -89,6 +107,13 @@ export default class NPCData extends VagabondActorBase {
|
|||||||
// Being type (for targeting by certain effects)
|
// Being type (for targeting by certain effects)
|
||||||
beingType: new fields.StringField({ initial: "beast" }),
|
beingType: new fields.StringField({ initial: "beast" }),
|
||||||
|
|
||||||
|
// Senses (vision types)
|
||||||
|
senses: new fields.SchemaField({
|
||||||
|
darksight: new fields.BooleanField({ initial: false }),
|
||||||
|
blindsight: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
||||||
|
tremorsense: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
||||||
|
}),
|
||||||
|
|
||||||
// Movement speed
|
// Movement speed
|
||||||
speed: new fields.SchemaField({
|
speed: new fields.SchemaField({
|
||||||
value: new fields.NumberField({ integer: true, initial: 30 }),
|
value: new fields.NumberField({ integer: true, initial: 30 }),
|
||||||
|
|||||||
@ -33,16 +33,22 @@ export default class ArmorData extends VagabondItemBase {
|
|||||||
min: 0,
|
min: 0,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Armor type (light, heavy, shield)
|
// Armor type (none, light, medium, heavy, shield)
|
||||||
armorType: new fields.StringField({
|
armorType: new fields.StringField({
|
||||||
required: true,
|
required: true,
|
||||||
initial: "light",
|
initial: "light",
|
||||||
choices: ["light", "heavy", "shield"],
|
choices: ["none", "light", "medium", "heavy", "shield"],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Does this armor impose a dodge penalty?
|
// Does this armor impose a dodge penalty? (auto-set based on type for heavy)
|
||||||
dodgePenalty: new fields.BooleanField({ initial: false }),
|
dodgePenalty: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
|
// Hinders dodge saves (heavy armor hinders, medium may partially)
|
||||||
|
hindersDodge: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
|
// Prevents certain abilities (Barbarian Rage requires light or no armor)
|
||||||
|
preventsRage: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
// Inventory slot cost
|
// Inventory slot cost
|
||||||
slots: new fields.NumberField({
|
slots: new fields.NumberField({
|
||||||
integer: true,
|
integer: true,
|
||||||
|
|||||||
@ -77,6 +77,12 @@ export default class EquipmentData extends VagabondItemBase {
|
|||||||
// Tags for filtering/searching
|
// Tags for filtering/searching
|
||||||
tags: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
tags: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||||
|
|
||||||
|
// Is this item a valid spell casting trinket?
|
||||||
|
isTrinket: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
|
// Can spells be cast through this item? (for Familiars, Gish weapons)
|
||||||
|
canCastThrough: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
// Relic System - Powerful magic items with unique abilities
|
// Relic System - Powerful magic items with unique abilities
|
||||||
relic: new fields.SchemaField({
|
relic: new fields.SchemaField({
|
||||||
// Is this item a relic?
|
// Is this item a relic?
|
||||||
|
|||||||
@ -33,10 +33,11 @@ export default class WeaponData extends VagabondItemBase {
|
|||||||
initial: "1d6",
|
initial: "1d6",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Damage type
|
// Damage type (physical: blunt/piercing/slashing, elemental: fire/cold/shock/acid/poison)
|
||||||
damageType: new fields.StringField({
|
damageType: new fields.StringField({
|
||||||
required: true,
|
required: true,
|
||||||
initial: "blunt",
|
initial: "blunt",
|
||||||
|
choices: ["blunt", "piercing", "slashing", "fire", "cold", "shock", "acid", "poison"],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Bonus damage (from magic, etc.)
|
// Bonus damage (from magic, etc.)
|
||||||
@ -106,6 +107,12 @@ export default class WeaponData extends VagabondItemBase {
|
|||||||
// Is this weapon equipped?
|
// Is this weapon equipped?
|
||||||
equipped: new fields.BooleanField({ initial: false }),
|
equipped: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
|
// Which hand is this weapon equipped in? (for dual-wielding)
|
||||||
|
equippedHand: new fields.StringField({
|
||||||
|
initial: "",
|
||||||
|
choices: ["", "main", "off", "both"],
|
||||||
|
}),
|
||||||
|
|
||||||
// Quantity (for ammunition, thrown weapons)
|
// Quantity (for ammunition, thrown weapons)
|
||||||
quantity: new fields.NumberField({
|
quantity: new fields.NumberField({
|
||||||
integer: true,
|
integer: true,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user