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
|
||||
details: new fields.SchemaField({
|
||||
size: new fields.StringField({ initial: "medium" }),
|
||||
beingType: new fields.StringField({ initial: "humanlike" }),
|
||||
// Size category with mechanical effects
|
||||
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)
|
||||
@ -400,6 +421,178 @@ export default class CharacterData extends VagabondActorBase {
|
||||
// Track which stats were increased at which level
|
||||
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,
|
||||
}),
|
||||
|
||||
// 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)
|
||||
appearing: new fields.StringField({ initial: "1d6" }),
|
||||
|
||||
@ -89,6 +107,13 @@ export default class NPCData extends VagabondActorBase {
|
||||
// Being type (for targeting by certain effects)
|
||||
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
|
||||
speed: new fields.SchemaField({
|
||||
value: new fields.NumberField({ integer: true, initial: 30 }),
|
||||
|
||||
@ -33,16 +33,22 @@ export default class ArmorData extends VagabondItemBase {
|
||||
min: 0,
|
||||
}),
|
||||
|
||||
// Armor type (light, heavy, shield)
|
||||
// Armor type (none, light, medium, heavy, shield)
|
||||
armorType: new fields.StringField({
|
||||
required: true,
|
||||
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 }),
|
||||
|
||||
// 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
|
||||
slots: new fields.NumberField({
|
||||
integer: true,
|
||||
|
||||
@ -77,6 +77,12 @@ export default class EquipmentData extends VagabondItemBase {
|
||||
// Tags for filtering/searching
|
||||
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: new fields.SchemaField({
|
||||
// Is this item a relic?
|
||||
|
||||
@ -33,10 +33,11 @@ export default class WeaponData extends VagabondItemBase {
|
||||
initial: "1d6",
|
||||
}),
|
||||
|
||||
// Damage type
|
||||
// Damage type (physical: blunt/piercing/slashing, elemental: fire/cold/shock/acid/poison)
|
||||
damageType: new fields.StringField({
|
||||
required: true,
|
||||
initial: "blunt",
|
||||
choices: ["blunt", "piercing", "slashing", "fire", "cold", "shock", "acid", "poison"],
|
||||
}),
|
||||
|
||||
// Bonus damage (from magic, etc.)
|
||||
@ -106,6 +107,12 @@ export default class WeaponData extends VagabondItemBase {
|
||||
// Is this weapon equipped?
|
||||
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: new fields.NumberField({
|
||||
integer: true,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user