diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index eca684a..9c3d5b8 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -29,6 +29,14 @@ export default class CharacterData extends VagabondActorBase { return { ...baseSchema, + // Reference to equipped ancestry item (UUID) + ancestryId: new fields.StringField({ + required: false, + nullable: true, + blank: true, + initial: null, + }), + // Character level (1-10) level: new fields.NumberField({ required: true, @@ -200,9 +208,15 @@ export default class CharacterData extends VagabondActorBase { fatigue: new fields.SchemaField({ value: new fields.NumberField({ integer: true, initial: 0, min: 0, max: 5 }), }), + + // Studied Dice pool (Scholar class feature - d8s that can replace d20 rolls) + studiedDice: new fields.SchemaField({ + value: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + max: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + }), }), - // Custom resources (for class-specific tracking like Studied Dice) + // Custom resources (for class-specific tracking) customResources: new fields.ArrayField( new fields.SchemaField({ name: new fields.StringField({ required: true }), @@ -211,6 +225,42 @@ export default class CharacterData extends VagabondActorBase { }) ), + // Status Effects with Countdown Dice support + // Countdown Dice: Track duration with shrinking dice (d6 -> d4 -> ends) + statusEffects: new fields.ArrayField( + new fields.SchemaField({ + // Effect name (e.g., "Burning", "Poisoned", "Blessed") + name: new fields.StringField({ required: true }), + // Effect description + description: new fields.StringField({ required: false, blank: true }), + // Source of the effect (item UUID, spell name, etc.) + source: new fields.StringField({ required: false, blank: true }), + // Icon path for display + icon: new fields.StringField({ initial: "icons/svg/aura.svg" }), + // Is this a beneficial or harmful effect? + beneficial: new fields.BooleanField({ initial: false }), + // Duration type: "countdown" (Cd4/Cd6), "rounds", "turns", "permanent" + durationType: new fields.StringField({ + initial: "countdown", + choices: ["countdown", "rounds", "turns", "permanent"], + }), + // Current countdown die size (6 = d6, 4 = d4, 0 = ended) + countdownDie: new fields.NumberField({ integer: true, initial: 6, min: 0, max: 12 }), + // For rounds/turns duration: remaining count + durationValue: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + // Active Effect changes to apply while this status is active + changes: new fields.ArrayField( + new fields.SchemaField({ + key: new fields.StringField({ required: true }), + mode: new fields.NumberField({ integer: true, initial: 2 }), + value: new fields.StringField({ required: true }), + }), + { initial: [] } + ), + }), + { initial: [] } + ), + // Armor value (from equipped armor) armor: new fields.NumberField({ integer: true, initial: 0, min: 0 }), diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index d9e9b02..aed6441 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -68,6 +68,44 @@ export default class ArmorData extends VagabondItemBase { // Special properties or enchantments properties: new fields.ArrayField(new fields.StringField(), { initial: [] }), + + // Relic System - Powerful magic items with unique abilities + relic: new fields.SchemaField({ + // Is this item a relic? + isRelic: new fields.BooleanField({ initial: false }), + + // Relic tier (determines power level) + tier: new fields.NumberField({ + integer: true, + initial: 1, + min: 1, + max: 5, + }), + + // Unique ability name + abilityName: new fields.StringField({ required: false, blank: true }), + + // Unique ability description + abilityDescription: new fields.HTMLField({ required: false, blank: true }), + + // Activation cost (mana, luck, etc.) + activationCost: new fields.StringField({ required: false, blank: true }), + + // Uses per day (0 = unlimited or passive) + usesPerDay: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + + // Current uses remaining + usesRemaining: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + + // Attunement required? + requiresAttunement: new fields.BooleanField({ initial: false }), + + // Currently attuned? + attuned: new fields.BooleanField({ initial: false }), + + // Lore/history of the relic + lore: new fields.HTMLField({ required: false, blank: true }), + }), }; } diff --git a/module/data/item/equipment.mjs b/module/data/item/equipment.mjs index db48d8b..7ea7197 100644 --- a/module/data/item/equipment.mjs +++ b/module/data/item/equipment.mjs @@ -76,6 +76,44 @@ export default class EquipmentData extends VagabondItemBase { // Tags for filtering/searching tags: new fields.ArrayField(new fields.StringField(), { initial: [] }), + + // Relic System - Powerful magic items with unique abilities + relic: new fields.SchemaField({ + // Is this item a relic? + isRelic: new fields.BooleanField({ initial: false }), + + // Relic tier (determines power level) + tier: new fields.NumberField({ + integer: true, + initial: 1, + min: 1, + max: 5, + }), + + // Unique ability name + abilityName: new fields.StringField({ required: false, blank: true }), + + // Unique ability description + abilityDescription: new fields.HTMLField({ required: false, blank: true }), + + // Activation cost (mana, luck, etc.) + activationCost: new fields.StringField({ required: false, blank: true }), + + // Uses per day (0 = unlimited or passive) + usesPerDay: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + + // Current uses remaining + usesRemaining: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + + // Attunement required? + requiresAttunement: new fields.BooleanField({ initial: false }), + + // Currently attuned? + attuned: new fields.BooleanField({ initial: false }), + + // Lore/history of the relic + lore: new fields.HTMLField({ required: false, blank: true }), + }), }; } diff --git a/module/data/item/perk.mjs b/module/data/item/perk.mjs index 618c9d2..a57eac8 100644 --- a/module/data/item/perk.mjs +++ b/module/data/item/perk.mjs @@ -72,6 +72,37 @@ export default class PerkData extends VagabondItemBase { per: new fields.StringField({ initial: "" }), // "short", "long", "day", "" }), + // Luck System Integration + // Cost in Luck points to activate this perk + luckCost: new fields.NumberField({ + integer: true, + initial: 0, + min: 0, + }), + + // Does this perk grant Luck when triggered? + grantsLuck: new fields.NumberField({ + integer: true, + initial: 0, + min: 0, + }), + + // Ritual System (specific perks are rituals with extended casting) + isRitual: new fields.BooleanField({ initial: false }), + + // Ritual duration in minutes (10, 60, etc.) + ritualDuration: new fields.NumberField({ + integer: true, + initial: 0, + min: 0, + }), + + // Ritual components required (text description) + ritualComponents: new fields.StringField({ + required: false, + blank: true, + }), + // Tags for categorization tags: new fields.ArrayField(new fields.StringField(), { initial: [] }), }; diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 6957d9f..68e6ce2 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -121,6 +121,44 @@ export default class WeaponData extends VagabondItemBase { min: 1, max: 20, }), + + // Relic System - Powerful magic items with unique abilities + relic: new fields.SchemaField({ + // Is this item a relic? + isRelic: new fields.BooleanField({ initial: false }), + + // Relic tier (determines power level) + tier: new fields.NumberField({ + integer: true, + initial: 1, + min: 1, + max: 5, + }), + + // Unique ability name + abilityName: new fields.StringField({ required: false, blank: true }), + + // Unique ability description + abilityDescription: new fields.HTMLField({ required: false, blank: true }), + + // Activation cost (mana, luck, etc.) + activationCost: new fields.StringField({ required: false, blank: true }), + + // Uses per day (0 = unlimited or passive) + usesPerDay: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + + // Current uses remaining + usesRemaining: new fields.NumberField({ integer: true, initial: 0, min: 0 }), + + // Attunement required? + requiresAttunement: new fields.BooleanField({ initial: false }), + + // Currently attuned? + attuned: new fields.BooleanField({ initial: false }), + + // Lore/history of the relic + lore: new fields.HTMLField({ required: false, blank: true }), + }), }; } diff --git a/module/helpers/effects.mjs b/module/helpers/effects.mjs index a058fec..79b2a53 100644 --- a/module/helpers/effects.mjs +++ b/module/helpers/effects.mjs @@ -41,6 +41,8 @@ export const EFFECT_KEYS = { "hp.bonus": "system.resources.hp.bonus", "mana.bonus": "system.resources.mana.bonus", "mana.castingMax": "system.resources.mana.castingMax", + "luck.max": "system.resources.luck.max", + "studiedDice.max": "system.resources.studiedDice.max", "speed.bonus": "system.speed.bonus", armor: "system.armor", "itemSlots.bonus": "system.itemSlots.bonus",