Implement complete item sheet system with Effects tab
Phase 4 (Item Sheets) complete: - Created VagabondItemSheet base class using ApplicationV2 + HandlebarsApplicationMixin - Implemented templates for all 8 item types: weapon, armor, equipment, ancestry, class, spell, perk, feature - Added Details and Effects tabs to all item sheets - Effects tab provides full CRUD for Active Effects (create, edit, toggle, delete) - Added ~150 localization strings for item fields and UI elements - Comprehensive SCSS styling matching parchment theme Key features: - Type-specific templates with appropriate fields for each item type - Array field management for traits, progression tables, features - Wider dropdowns for ancestry Being Type and Size fields - Effect controls remain clickable when effect is disabled 🤖 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
350475b331
commit
5ddd33c41c
@ -545,7 +545,7 @@
|
|||||||
"id": "4.1",
|
"id": "4.1",
|
||||||
"name": "Create base VagabondItemSheet class",
|
"name": "Create base VagabondItemSheet class",
|
||||||
"description": "Extended ItemSheet with common methods, type-specific tab handling",
|
"description": "Extended ItemSheet with common methods, type-specific tab handling",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "critical",
|
"priority": "critical",
|
||||||
"dependencies": ["2.3"]
|
"dependencies": ["2.3"]
|
||||||
@ -554,7 +554,7 @@
|
|||||||
"id": "4.2",
|
"id": "4.2",
|
||||||
"name": "Implement Ancestry item sheet",
|
"name": "Implement Ancestry item sheet",
|
||||||
"description": "Being type dropdown, size dropdown, traits editor (add/remove trait entries)",
|
"description": "Being type dropdown, size dropdown, traits editor (add/remove trait entries)",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.7"]
|
"dependencies": ["4.1", "1.7"]
|
||||||
@ -563,7 +563,7 @@
|
|||||||
"id": "4.3",
|
"id": "4.3",
|
||||||
"name": "Implement Class item sheet",
|
"name": "Implement Class item sheet",
|
||||||
"description": "Key stat, training grants, progression table editor, feature definitions",
|
"description": "Key stat, training grants, progression table editor, feature definitions",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.8"]
|
"dependencies": ["4.1", "1.8"]
|
||||||
@ -572,7 +572,7 @@
|
|||||||
"id": "4.4",
|
"id": "4.4",
|
||||||
"name": "Implement Spell item sheet",
|
"name": "Implement Spell item sheet",
|
||||||
"description": "Damage type, effect text, crit effect, delivery options checkboxes, cost formula display",
|
"description": "Damage type, effect text, crit effect, delivery options checkboxes, cost formula display",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.9"]
|
"dependencies": ["4.1", "1.9"]
|
||||||
@ -581,7 +581,7 @@
|
|||||||
"id": "4.5",
|
"id": "4.5",
|
||||||
"name": "Implement Perk item sheet",
|
"name": "Implement Perk item sheet",
|
||||||
"description": "Prerequisites editor (stat/training/spell requirements), description, effects",
|
"description": "Prerequisites editor (stat/training/spell requirements), description, effects",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.10"]
|
"dependencies": ["4.1", "1.10"]
|
||||||
@ -590,7 +590,7 @@
|
|||||||
"id": "4.6",
|
"id": "4.6",
|
||||||
"name": "Implement Weapon item sheet",
|
"name": "Implement Weapon item sheet",
|
||||||
"description": "Damage dice selector, grip type, properties checkboxes, attack skill dropdown, value/slots",
|
"description": "Damage dice selector, grip type, properties checkboxes, attack skill dropdown, value/slots",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.11"]
|
"dependencies": ["4.1", "1.11"]
|
||||||
@ -599,7 +599,7 @@
|
|||||||
"id": "4.7",
|
"id": "4.7",
|
||||||
"name": "Implement Armor item sheet",
|
"name": "Implement Armor item sheet",
|
||||||
"description": "Armor value, type dropdown, dodge penalty checkbox, value/slots",
|
"description": "Armor value, type dropdown, dodge penalty checkbox, value/slots",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.12"]
|
"dependencies": ["4.1", "1.12"]
|
||||||
@ -608,7 +608,7 @@
|
|||||||
"id": "4.8",
|
"id": "4.8",
|
||||||
"name": "Implement Equipment item sheet",
|
"name": "Implement Equipment item sheet",
|
||||||
"description": "Generic item fields: description, quantity, slots, value, consumable flag",
|
"description": "Generic item fields: description, quantity, slots, value, consumable flag",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.13"]
|
"dependencies": ["4.1", "1.13"]
|
||||||
@ -617,7 +617,7 @@
|
|||||||
"id": "4.9",
|
"id": "4.9",
|
||||||
"name": "Implement Feature item sheet",
|
"name": "Implement Feature item sheet",
|
||||||
"description": "Source class, level requirement, description, passive/active toggle, effects editor",
|
"description": "Source class, level requirement, description, passive/active toggle, effects editor",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["4.1", "1.14"]
|
"dependencies": ["4.1", "1.14"]
|
||||||
|
|||||||
153
lang/en.json
153
lang/en.json
@ -287,6 +287,18 @@
|
|||||||
"VAGABOND.TabAbilities": "Abilities",
|
"VAGABOND.TabAbilities": "Abilities",
|
||||||
"VAGABOND.TabMagic": "Magic",
|
"VAGABOND.TabMagic": "Magic",
|
||||||
"VAGABOND.TabBiography": "Biography",
|
"VAGABOND.TabBiography": "Biography",
|
||||||
|
"VAGABOND.TabDetails": "Details",
|
||||||
|
"VAGABOND.TabEffects": "Effects",
|
||||||
|
|
||||||
|
"VAGABOND.ActiveEffects": "Active Effects",
|
||||||
|
"VAGABOND.AddEffect": "Add Effect",
|
||||||
|
"VAGABOND.NewEffect": "New Effect",
|
||||||
|
"VAGABOND.EditEffect": "Edit Effect",
|
||||||
|
"VAGABOND.DeleteEffect": "Delete Effect",
|
||||||
|
"VAGABOND.DeleteEffectConfirm": "Are you sure you want to delete the effect \"{name}\"?",
|
||||||
|
"VAGABOND.ToggleEffect": "Toggle Effect",
|
||||||
|
"VAGABOND.NoEffects": "No active effects on this item.",
|
||||||
|
"VAGABOND.EffectsHint": "Effects on this item will be applied when it is equipped or added to a character.",
|
||||||
|
|
||||||
"VAGABOND.CharacterName": "Character Name",
|
"VAGABOND.CharacterName": "Character Name",
|
||||||
"VAGABOND.NPCName": "NPC Name",
|
"VAGABOND.NPCName": "NPC Name",
|
||||||
@ -379,5 +391,144 @@
|
|||||||
|
|
||||||
"VAGABOND.ItemNew": "New {type}",
|
"VAGABOND.ItemNew": "New {type}",
|
||||||
"VAGABOND.ItemDeleteTitle": "Delete {name}",
|
"VAGABOND.ItemDeleteTitle": "Delete {name}",
|
||||||
"VAGABOND.ItemDeleteConfirm": "Are you sure you want to delete {name}?"
|
"VAGABOND.ItemDeleteConfirm": "Are you sure you want to delete {name}?",
|
||||||
|
"VAGABOND.ItemName": "Item Name",
|
||||||
|
|
||||||
|
"VAGABOND.DamageTypeBlunt": "Blunt",
|
||||||
|
"VAGABOND.DamageTypePiercing": "Piercing",
|
||||||
|
"VAGABOND.DamageTypeSlashing": "Slashing",
|
||||||
|
"VAGABOND.DamageTypeFire": "Fire",
|
||||||
|
"VAGABOND.DamageTypeCold": "Cold",
|
||||||
|
"VAGABOND.DamageTypeShock": "Shock",
|
||||||
|
"VAGABOND.DamageTypeAcid": "Acid",
|
||||||
|
"VAGABOND.DamageTypePoison": "Poison",
|
||||||
|
"VAGABOND.DamageTypeNone": "None",
|
||||||
|
"VAGABOND.DamageBase": "Damage Base",
|
||||||
|
|
||||||
|
"VAGABOND.Grip": "Grip",
|
||||||
|
"VAGABOND.AttackSkill": "Attack Skill",
|
||||||
|
"VAGABOND.SkillMelee": "Melee",
|
||||||
|
"VAGABOND.SkillRanged": "Ranged",
|
||||||
|
"VAGABOND.VersatileDamage": "Versatile Damage",
|
||||||
|
"VAGABOND.BonusDamage": "Bonus Damage",
|
||||||
|
"VAGABOND.AttackBonus": "Attack Bonus",
|
||||||
|
"VAGABOND.Slots": "Slots",
|
||||||
|
"VAGABOND.Value": "Value",
|
||||||
|
"VAGABOND.Quantity": "Quantity",
|
||||||
|
|
||||||
|
"VAGABOND.WeaponProperties": "Weapon Properties",
|
||||||
|
"VAGABOND.Material": "Material",
|
||||||
|
"VAGABOND.MaterialMundane": "Mundane",
|
||||||
|
"VAGABOND.MaterialSilvered": "Silvered",
|
||||||
|
"VAGABOND.MaterialAdamantine": "Adamantine",
|
||||||
|
"VAGABOND.MaterialMagical": "Magical",
|
||||||
|
"VAGABOND.Equipped": "Equipped",
|
||||||
|
"VAGABOND.EquippedHand": "Equipped Hand",
|
||||||
|
"VAGABOND.HandMain": "Main",
|
||||||
|
"VAGABOND.HandOff": "Off",
|
||||||
|
"VAGABOND.HandBoth": "Both",
|
||||||
|
|
||||||
|
"VAGABOND.Relic": "Relic",
|
||||||
|
"VAGABOND.RelicTier": "Relic Tier",
|
||||||
|
"VAGABOND.RequiresAttunement": "Requires Attunement",
|
||||||
|
"VAGABOND.Attuned": "Attuned",
|
||||||
|
"VAGABOND.RelicAbilityName": "Ability Name",
|
||||||
|
"VAGABOND.RelicAbilityDescription": "Ability Description",
|
||||||
|
"VAGABOND.ActivationCost": "Activation Cost",
|
||||||
|
"VAGABOND.UsesPerDay": "Uses/Day",
|
||||||
|
"VAGABOND.UsesRemaining": "Uses Remaining",
|
||||||
|
"VAGABOND.RelicLore": "Lore",
|
||||||
|
|
||||||
|
"VAGABOND.ArmorValue": "Armor Value",
|
||||||
|
"VAGABOND.ArmorType": "Armor Type",
|
||||||
|
"VAGABOND.ArmorTypeNone": "None",
|
||||||
|
"VAGABOND.ArmorTypeLight": "Light",
|
||||||
|
"VAGABOND.ArmorTypeMedium": "Medium",
|
||||||
|
"VAGABOND.ArmorTypeHeavy": "Heavy",
|
||||||
|
"VAGABOND.ArmorTypeShield": "Shield",
|
||||||
|
"VAGABOND.MagicBonus": "Magic Bonus",
|
||||||
|
"VAGABOND.Penalties": "Penalties",
|
||||||
|
"VAGABOND.DodgePenalty": "Dodge Penalty",
|
||||||
|
"VAGABOND.HindersDodge": "Hinders Dodge",
|
||||||
|
"VAGABOND.PreventsRage": "Prevents Rage",
|
||||||
|
|
||||||
|
"VAGABOND.SlotsPerItem": "Slots Per Item",
|
||||||
|
"VAGABOND.Category": "Category",
|
||||||
|
"VAGABOND.CategoryGear": "Gear",
|
||||||
|
"VAGABOND.CategoryTool": "Tool",
|
||||||
|
"VAGABOND.CategoryConsumable": "Consumable",
|
||||||
|
"VAGABOND.CategoryContainer": "Container",
|
||||||
|
"VAGABOND.CategoryTreasure": "Treasure",
|
||||||
|
"VAGABOND.CategoryMisc": "Misc",
|
||||||
|
"VAGABOND.Consumable": "Consumable",
|
||||||
|
"VAGABOND.Uses": "Uses",
|
||||||
|
"VAGABOND.UsesCurrent": "Current",
|
||||||
|
"VAGABOND.UsesMax": "Max",
|
||||||
|
"VAGABOND.AutoDestroy": "Auto Destroy",
|
||||||
|
"VAGABOND.ContainerCapacity": "Container Capacity",
|
||||||
|
"VAGABOND.MagicProperties": "Magic Properties",
|
||||||
|
"VAGABOND.IsTrinket": "Is Trinket",
|
||||||
|
"VAGABOND.CanCastThrough": "Can Cast Through",
|
||||||
|
|
||||||
|
"VAGABOND.BeingTypeHumanlike": "Humanlike",
|
||||||
|
"VAGABOND.BeingTypeFae": "Fae",
|
||||||
|
"VAGABOND.BeingTypeCryptid": "Cryptid",
|
||||||
|
"VAGABOND.BeingTypeBeast": "Beast",
|
||||||
|
"VAGABOND.BeingTypeUndead": "Undead",
|
||||||
|
"VAGABOND.BeingTypeArtificial": "Artificial",
|
||||||
|
"VAGABOND.BeingTypePrimordial": "Primordial",
|
||||||
|
"VAGABOND.BeingTypeHellspawn": "Hellspawn",
|
||||||
|
"VAGABOND.SizeTiny": "Tiny",
|
||||||
|
"VAGABOND.SizeGargantuan": "Gargantuan",
|
||||||
|
"VAGABOND.TraitName": "Trait Name",
|
||||||
|
"VAGABOND.TraitDescription": "Description",
|
||||||
|
"VAGABOND.NoTraits": "No traits defined",
|
||||||
|
|
||||||
|
"VAGABOND.MaxDice": "Max Dice",
|
||||||
|
"VAGABOND.UseClassDefault": "Use Class Default",
|
||||||
|
"VAGABOND.DeliveryTypes": "Delivery Types",
|
||||||
|
"VAGABOND.DurationTypes": "Duration Types",
|
||||||
|
|
||||||
|
"VAGABOND.StatRequirements": "Stat Requirements",
|
||||||
|
"VAGABOND.TrainingRequirements": "Training Requirements",
|
||||||
|
"VAGABOND.SpellRequirements": "Spell Requirements",
|
||||||
|
"VAGABOND.PerkRequirements": "Perk Requirements",
|
||||||
|
"VAGABOND.CustomRequirements": "Custom Requirements",
|
||||||
|
"VAGABOND.CommaSeparated": "Comma separated",
|
||||||
|
"VAGABOND.IsRitual": "Is Ritual",
|
||||||
|
"VAGABOND.RitualDuration": "Ritual Duration",
|
||||||
|
"VAGABOND.RecoveryPer": "Recovery",
|
||||||
|
"VAGABOND.ShortRest": "Short Rest",
|
||||||
|
"VAGABOND.LongRest": "Long Rest",
|
||||||
|
"VAGABOND.PerDay": "Per Day",
|
||||||
|
"VAGABOND.PerEncounter": "Per Encounter",
|
||||||
|
"VAGABOND.LuckCost": "Luck Cost",
|
||||||
|
"VAGABOND.GrantsLuck": "Grants Luck",
|
||||||
|
"VAGABOND.RitualComponents": "Components",
|
||||||
|
|
||||||
|
"VAGABOND.SourceClass": "Source Class",
|
||||||
|
"VAGABOND.Activation": "Activation",
|
||||||
|
"VAGABOND.ActivationType": "Type",
|
||||||
|
"VAGABOND.Action": "Action",
|
||||||
|
"VAGABOND.BonusAction": "Bonus Action",
|
||||||
|
"VAGABOND.Reaction": "Reaction",
|
||||||
|
"VAGABOND.FreeAction": "Free Action",
|
||||||
|
"VAGABOND.Special": "Special",
|
||||||
|
"VAGABOND.Unlimited": "Unlimited",
|
||||||
|
"VAGABOND.Requirements": "Requirements",
|
||||||
|
|
||||||
|
"VAGABOND.KeyStat": "Key Stat",
|
||||||
|
"VAGABOND.IsCaster": "Is Caster",
|
||||||
|
"VAGABOND.ActionStyle": "Casting Skill",
|
||||||
|
"VAGABOND.TrainedSkills": "Trained Skills",
|
||||||
|
"VAGABOND.StartingPack": "Starting Pack",
|
||||||
|
"VAGABOND.CustomResource": "Custom Resource",
|
||||||
|
"VAGABOND.ResourceName": "Resource Name",
|
||||||
|
"VAGABOND.ResourceMax": "Max Formula",
|
||||||
|
"VAGABOND.Progression": "Progression",
|
||||||
|
"VAGABOND.SpellsKnown": "Spells Known",
|
||||||
|
"VAGABOND.ClassFeatures": "Class Features",
|
||||||
|
"VAGABOND.NoProgression": "No progression entries",
|
||||||
|
"VAGABOND.FeatureName": "Feature Name",
|
||||||
|
"VAGABOND.FeatureDescription": "Description"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,10 @@
|
|||||||
* Exports all actor and item sheet classes for the Vagabond RPG system.
|
* Exports all actor and item sheet classes for the Vagabond RPG system.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Actor sheets
|
||||||
export { default as VagabondActorSheet } from "./base-actor-sheet.mjs";
|
export { default as VagabondActorSheet } from "./base-actor-sheet.mjs";
|
||||||
export { default as VagabondCharacterSheet } from "./character-sheet.mjs";
|
export { default as VagabondCharacterSheet } from "./character-sheet.mjs";
|
||||||
export { default as VagabondNPCSheet } from "./npc-sheet.mjs";
|
export { default as VagabondNPCSheet } from "./npc-sheet.mjs";
|
||||||
|
|
||||||
|
// Item sheets
|
||||||
|
export { default as VagabondItemSheet } from "./base-item-sheet.mjs";
|
||||||
|
|||||||
447
module/sheets/base-item-sheet.mjs
Normal file
447
module/sheets/base-item-sheet.mjs
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
/**
|
||||||
|
* Base Item Sheet for Vagabond RPG
|
||||||
|
*
|
||||||
|
* Provides common functionality for all item sheets:
|
||||||
|
* - Tab navigation (for complex items)
|
||||||
|
* - Form handling with automatic updates
|
||||||
|
* - Rich text editor integration
|
||||||
|
* - Type-specific rendering via parts system
|
||||||
|
*
|
||||||
|
* Uses Foundry VTT v13 ItemSheetV2 API with HandlebarsApplicationMixin.
|
||||||
|
*
|
||||||
|
* @extends ItemSheetV2
|
||||||
|
* @mixes HandlebarsApplicationMixin
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
||||||
|
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||||
|
|
||||||
|
export default class VagabondItemSheet extends HandlebarsApplicationMixin(ItemSheetV2) {
|
||||||
|
/**
|
||||||
|
* @param {Object} options - Application options
|
||||||
|
*/
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
// Active tab tracking (for items with tabs)
|
||||||
|
this._activeTab = "details";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Static Properties */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
id: "vagabond-item-sheet-{id}",
|
||||||
|
classes: ["vagabond", "sheet", "item"],
|
||||||
|
tag: "form",
|
||||||
|
window: {
|
||||||
|
title: "VAGABOND.ItemSheet",
|
||||||
|
icon: "fa-solid fa-suitcase",
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
width: 520,
|
||||||
|
height: 480,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
handler: VagabondItemSheet.#onFormSubmit,
|
||||||
|
submitOnChange: true,
|
||||||
|
closeOnSubmit: false,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
changeTab: VagabondItemSheet.#onChangeTab,
|
||||||
|
addArrayEntry: VagabondItemSheet.#onAddArrayEntry,
|
||||||
|
deleteArrayEntry: VagabondItemSheet.#onDeleteArrayEntry,
|
||||||
|
createEffect: VagabondItemSheet.#onCreateEffect,
|
||||||
|
editEffect: VagabondItemSheet.#onEditEffect,
|
||||||
|
deleteEffect: VagabondItemSheet.#onDeleteEffect,
|
||||||
|
toggleEffect: VagabondItemSheet.#onToggleEffect,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
header: {
|
||||||
|
template: "systems/vagabond/templates/item/parts/item-header.hbs",
|
||||||
|
},
|
||||||
|
tabs: {
|
||||||
|
template: "systems/vagabond/templates/item/parts/item-tabs.hbs",
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
template: "systems/vagabond/templates/item/parts/item-body.hbs",
|
||||||
|
},
|
||||||
|
effects: {
|
||||||
|
template: "systems/vagabond/templates/item/parts/item-effects.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Getters */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenient alias for the item document.
|
||||||
|
* @returns {VagabondItem}
|
||||||
|
*/
|
||||||
|
get item() {
|
||||||
|
return this.document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
get title() {
|
||||||
|
return this.document.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the available tabs for this item type.
|
||||||
|
* All items have Details and Effects tabs.
|
||||||
|
* @returns {Object[]} Array of tab definitions
|
||||||
|
*/
|
||||||
|
get tabs() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: "details",
|
||||||
|
label: "VAGABOND.TabDetails",
|
||||||
|
icon: "fas fa-list",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "effects",
|
||||||
|
label: "VAGABOND.TabEffects",
|
||||||
|
icon: "fas fa-bolt",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this item type uses tabs.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get hasTabs() {
|
||||||
|
return this.tabs !== null && this.tabs.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Data Preparation */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext(options) {
|
||||||
|
const context = await super._prepareContext(options);
|
||||||
|
|
||||||
|
// Basic item data
|
||||||
|
context.item = this.item;
|
||||||
|
context.system = this.item.system;
|
||||||
|
context.source = this.item.toObject().system;
|
||||||
|
|
||||||
|
// Sheet state
|
||||||
|
context.hasTabs = this.hasTabs;
|
||||||
|
context.activeTab = this._activeTab;
|
||||||
|
if (this.hasTabs) {
|
||||||
|
context.tabs = this.tabs.map((tab) => ({
|
||||||
|
...tab,
|
||||||
|
active: tab.id === this._activeTab,
|
||||||
|
cssClass: tab.id === this._activeTab ? "active" : "",
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roll data for formulas in templates
|
||||||
|
context.rollData = this.item.getRollData();
|
||||||
|
|
||||||
|
// Editable state
|
||||||
|
context.editable = this.isEditable;
|
||||||
|
context.owner = this.item.isOwner;
|
||||||
|
context.limited = this.item.limited;
|
||||||
|
|
||||||
|
// System configuration
|
||||||
|
context.config = CONFIG.VAGABOND;
|
||||||
|
|
||||||
|
// Item type for conditional rendering
|
||||||
|
context.itemType = this.item.type;
|
||||||
|
|
||||||
|
// Active Effects on this item
|
||||||
|
context.effects = this._prepareEffects();
|
||||||
|
|
||||||
|
// Type-specific context
|
||||||
|
await this._prepareTypeContext(context, options);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare Active Effects for display.
|
||||||
|
* @returns {Object[]} Array of effect data for rendering
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_prepareEffects() {
|
||||||
|
return this.item.effects.map((effect) => ({
|
||||||
|
id: effect.id,
|
||||||
|
name: effect.name,
|
||||||
|
icon: effect.icon,
|
||||||
|
disabled: effect.disabled,
|
||||||
|
duration: effect.duration,
|
||||||
|
source: effect.sourceName,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare type-specific context data.
|
||||||
|
* Subclasses should override this.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The context object to augment
|
||||||
|
* @param {Object} options - Render options
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
async _prepareTypeContext(_context, _options) {
|
||||||
|
// Override in subclasses
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Rendering */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
_onRender(context, options) {
|
||||||
|
super._onRender(context, options);
|
||||||
|
|
||||||
|
// Clean up inactive tabs if using tabs
|
||||||
|
if (this.hasTabs) {
|
||||||
|
this._cleanupInactiveTabs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize rich text editors
|
||||||
|
this._initializeEditors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove tab content sections that don't match the active tab.
|
||||||
|
* ApplicationV2's parts rendering appends new parts without removing old ones.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_cleanupInactiveTabs() {
|
||||||
|
if (!this.element) return;
|
||||||
|
|
||||||
|
const activeTabClass = `${this._activeTab}-tab`;
|
||||||
|
const tabContents = this.element.querySelectorAll(".tab-content");
|
||||||
|
|
||||||
|
for (const tabContent of tabContents) {
|
||||||
|
if (!tabContent.classList.contains(activeTabClass)) {
|
||||||
|
tabContent.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize rich text editors for description fields.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_initializeEditors() {
|
||||||
|
// Foundry automatically handles ProseMirror/TinyMCE for HTMLField inputs
|
||||||
|
// Additional initialization can be added here if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Action Handlers */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle form submission.
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {HTMLFormElement} form
|
||||||
|
* @param {FormDataExtended} formData
|
||||||
|
*/
|
||||||
|
static async #onFormSubmit(event, form, formData) {
|
||||||
|
const sheet = this;
|
||||||
|
const updateData = foundry.utils.expandObject(formData.object);
|
||||||
|
|
||||||
|
// Clean up array data that may have gaps from deletions
|
||||||
|
sheet._cleanArrayData(updateData);
|
||||||
|
|
||||||
|
await sheet.item.update(updateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean array data to remove gaps from deleted entries.
|
||||||
|
* Converts { "0": {...}, "2": {...} } to [ {...}, {...} ]
|
||||||
|
* @param {Object} data - The update data object
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_cleanArrayData(data) {
|
||||||
|
// Handle system-level arrays
|
||||||
|
if (data.system) {
|
||||||
|
this._cleanArraysRecursive(data.system);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively clean arrays in an object.
|
||||||
|
* @param {Object} obj - Object to clean
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_cleanArraysRecursive(obj) {
|
||||||
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
||||||
|
// Check if this looks like an indexed object (array-like)
|
||||||
|
const keys = Object.keys(value);
|
||||||
|
const isIndexed = keys.every((k) => /^\d+$/.test(k));
|
||||||
|
|
||||||
|
if (isIndexed && keys.length > 0) {
|
||||||
|
// Convert to array, filtering out nulls/undefined
|
||||||
|
obj[key] = Object.values(value).filter((v) => v != null);
|
||||||
|
} else {
|
||||||
|
// Recurse into nested objects
|
||||||
|
this._cleanArraysRecursive(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle tab change action.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onChangeTab(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const tab = target.dataset.tab;
|
||||||
|
if (!tab) return;
|
||||||
|
|
||||||
|
this._activeTab = tab;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle adding a new entry to an array field.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onAddArrayEntry(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const field = target.dataset.field;
|
||||||
|
if (!field) return;
|
||||||
|
|
||||||
|
const currentArray = foundry.utils.getProperty(this.item, field) || [];
|
||||||
|
const template = this._getArrayEntryTemplate(field);
|
||||||
|
|
||||||
|
await this.item.update({
|
||||||
|
[field]: [...currentArray, template],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle deleting an entry from an array field.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onDeleteArrayEntry(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const field = target.dataset.field;
|
||||||
|
const index = parseInt(target.dataset.index, 10);
|
||||||
|
if (!field || isNaN(index)) return;
|
||||||
|
|
||||||
|
const currentArray = foundry.utils.getProperty(this.item, field) || [];
|
||||||
|
const newArray = [...currentArray];
|
||||||
|
newArray.splice(index, 1);
|
||||||
|
|
||||||
|
await this.item.update({
|
||||||
|
[field]: newArray,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default template for a new array entry.
|
||||||
|
* Subclasses should override for their specific array fields.
|
||||||
|
* @param {string} field - The field path
|
||||||
|
* @returns {Object} Default entry object
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_getArrayEntryTemplate(_field) {
|
||||||
|
// Default template - subclasses override for specific fields
|
||||||
|
return { name: "", description: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Active Effect Actions */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle creating a new Active Effect on this item.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onCreateEffect(event, _target) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Create a new effect with default values
|
||||||
|
const effectData = {
|
||||||
|
name: game.i18n.localize("VAGABOND.NewEffect"),
|
||||||
|
icon: "icons/svg/aura.svg",
|
||||||
|
origin: this.item.uuid,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const [created] = await this.item.createEmbeddedDocuments("ActiveEffect", [effectData]);
|
||||||
|
|
||||||
|
// Open the effect config sheet
|
||||||
|
if (created) {
|
||||||
|
created.sheet.render(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle editing an existing Active Effect.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onEditEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const effectId = target.closest("[data-effect-id]")?.dataset.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.item.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
effect.sheet.render(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle deleting an Active Effect.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onDeleteEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const effectId = target.closest("[data-effect-id]")?.dataset.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.item.effects.get(effectId);
|
||||||
|
if (!effect) return;
|
||||||
|
|
||||||
|
// Confirm deletion
|
||||||
|
const confirmed = await Dialog.confirm({
|
||||||
|
title: game.i18n.localize("VAGABOND.DeleteEffect"),
|
||||||
|
content: `<p>${game.i18n.format("VAGABOND.DeleteEffectConfirm", { name: effect.name })}</p>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (confirmed) {
|
||||||
|
await effect.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle toggling an Active Effect's disabled state.
|
||||||
|
* @param {PointerEvent} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onToggleEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const effectId = target.closest("[data-effect-id]")?.dataset.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.item.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
await effect.update({ disabled: !effect.disabled });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
* @module vagabond
|
* @module vagabond
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global Actors */
|
/* global Actors, Items */
|
||||||
|
|
||||||
// Import configuration
|
// Import configuration
|
||||||
import { VAGABOND } from "./helpers/config.mjs";
|
import { VAGABOND } from "./helpers/config.mjs";
|
||||||
@ -35,7 +35,12 @@ import {
|
|||||||
} from "./applications/_module.mjs";
|
} from "./applications/_module.mjs";
|
||||||
|
|
||||||
// Import sheet classes
|
// Import sheet classes
|
||||||
import { VagabondActorSheet, VagabondCharacterSheet, VagabondNPCSheet } from "./sheets/_module.mjs";
|
import {
|
||||||
|
VagabondActorSheet,
|
||||||
|
VagabondCharacterSheet,
|
||||||
|
VagabondNPCSheet,
|
||||||
|
VagabondItemSheet,
|
||||||
|
} from "./sheets/_module.mjs";
|
||||||
|
|
||||||
// Import test registration (for Quench)
|
// Import test registration (for Quench)
|
||||||
import { registerQuenchTests } from "./tests/quench-init.mjs";
|
import { registerQuenchTests } from "./tests/quench-init.mjs";
|
||||||
@ -64,6 +69,20 @@ async function preloadHandlebarsTemplates() {
|
|||||||
"systems/vagabond/templates/actor/npc-actions.hbs",
|
"systems/vagabond/templates/actor/npc-actions.hbs",
|
||||||
"systems/vagabond/templates/actor/npc-abilities.hbs",
|
"systems/vagabond/templates/actor/npc-abilities.hbs",
|
||||||
"systems/vagabond/templates/actor/npc-notes.hbs",
|
"systems/vagabond/templates/actor/npc-notes.hbs",
|
||||||
|
// Item sheet parts
|
||||||
|
"systems/vagabond/templates/item/parts/item-header.hbs",
|
||||||
|
"systems/vagabond/templates/item/parts/item-tabs.hbs",
|
||||||
|
"systems/vagabond/templates/item/parts/item-body.hbs",
|
||||||
|
"systems/vagabond/templates/item/parts/item-effects.hbs",
|
||||||
|
// Item type templates
|
||||||
|
"systems/vagabond/templates/item/types/weapon.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/armor.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/equipment.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/ancestry.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/class.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/spell.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/perk.hbs",
|
||||||
|
"systems/vagabond/templates/item/types/feature.hbs",
|
||||||
];
|
];
|
||||||
|
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
@ -93,6 +112,7 @@ Hooks.once("init", async () => {
|
|||||||
VagabondActorSheet,
|
VagabondActorSheet,
|
||||||
VagabondCharacterSheet,
|
VagabondCharacterSheet,
|
||||||
VagabondNPCSheet,
|
VagabondNPCSheet,
|
||||||
|
VagabondItemSheet,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,12 +151,12 @@ Hooks.once("init", async () => {
|
|||||||
label: "VAGABOND.SheetNPC",
|
label: "VAGABOND.SheetNPC",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register Item sheet classes (TODO: Phase 4)
|
// Register Item sheet classes
|
||||||
// Items.unregisterSheet("core", ItemSheet);
|
Items.unregisterSheet("core", ItemSheet);
|
||||||
// Items.registerSheet("vagabond", VagabondItemSheet, {
|
Items.registerSheet("vagabond", VagabondItemSheet, {
|
||||||
// makeDefault: true,
|
makeDefault: true,
|
||||||
// label: "VAGABOND.SheetItem"
|
label: "VAGABOND.SheetItem",
|
||||||
// });
|
});
|
||||||
|
|
||||||
// Preload Handlebars templates
|
// Preload Handlebars templates
|
||||||
await preloadHandlebarsTemplates();
|
await preloadHandlebarsTemplates();
|
||||||
|
|||||||
@ -92,6 +92,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin button-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
color: $color-text-primary;
|
||||||
|
background-color: $color-parchment-dark;
|
||||||
|
border-color: $color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 2px solid $color-accent-primary;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Form inputs
|
// Form inputs
|
||||||
@mixin input-base {
|
@mixin input-base {
|
||||||
padding: $spacing-2 $spacing-3;
|
padding: $spacing-2 $spacing-3;
|
||||||
|
|||||||
@ -1,101 +1,656 @@
|
|||||||
// Vagabond RPG - Item Sheet Styles
|
// Vagabond RPG - Item Sheet Styles
|
||||||
// =================================
|
// =================================
|
||||||
|
|
||||||
// Placeholder - will be expanded in Phase 4
|
|
||||||
.vagabond.sheet.item {
|
.vagabond.sheet.item {
|
||||||
min-width: 400px;
|
min-width: 500px;
|
||||||
min-height: 300px;
|
min-height: 400px;
|
||||||
|
|
||||||
.sheet-header {
|
// Header styling
|
||||||
|
.sheet-header.item-header {
|
||||||
@include flex-between;
|
@include flex-between;
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
background-color: $color-parchment-dark;
|
background-color: $color-parchment-dark;
|
||||||
border-bottom: 2px solid $color-border;
|
border-bottom: 2px solid $color-border;
|
||||||
|
gap: $spacing-4;
|
||||||
|
|
||||||
.item-img {
|
.item-img {
|
||||||
width: 60px;
|
width: 64px;
|
||||||
height: 60px;
|
height: 64px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid $color-border;
|
border: 2px solid $color-border;
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $color-accent-primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-fields {
|
.header-fields {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-left: $spacing-4;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
font-weight: bold;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-bottom-color: $color-accent-primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-type {
|
||||||
|
.type-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: $spacing-1 $spacing-3;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: capitalize;
|
||||||
|
background-color: $color-parchment;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
|
||||||
|
&.weapon {
|
||||||
|
background-color: mix($color-danger, $color-parchment, 15%);
|
||||||
|
}
|
||||||
|
&.armor {
|
||||||
|
background-color: mix($color-info, $color-parchment, 15%);
|
||||||
|
}
|
||||||
|
&.spell {
|
||||||
|
background-color: mix($color-reason, $color-parchment, 15%);
|
||||||
|
}
|
||||||
|
&.perk {
|
||||||
|
background-color: mix($color-success, $color-parchment, 15%);
|
||||||
|
}
|
||||||
|
&.class {
|
||||||
|
background-color: mix($color-warning, $color-parchment, 15%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sheet body
|
||||||
.sheet-body {
|
.sheet-body {
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: calc(100% - 80px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item content container
|
||||||
|
.item-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stats row
|
||||||
|
.item-stats-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: $spacing-4;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
.stat-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-1;
|
||||||
|
min-width: 80px;
|
||||||
|
|
||||||
|
&.full-width {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wide {
|
||||||
|
min-width: 140px;
|
||||||
|
|
||||||
|
select {
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
padding: $spacing-2;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: $color-accent-primary;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: $color-parchment;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
margin: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-input {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.units {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
min-height: 60px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fieldset styling
|
||||||
|
fieldset {
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
padding: $spacing-3;
|
||||||
|
margin: 0;
|
||||||
|
background-color: rgba($color-parchment-dark, 0.3);
|
||||||
|
|
||||||
|
legend {
|
||||||
|
padding: 0 $spacing-2;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include button-icon;
|
||||||
|
padding: $spacing-1;
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties grid (checkboxes)
|
||||||
|
.properties-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
.property-checkbox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relic section
|
||||||
|
.relic-section {
|
||||||
|
.relic-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.relic-fields {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-3;
|
||||||
|
margin-top: $spacing-3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description editor
|
||||||
|
.item-description {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-container {
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
min-height: 120px;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traits list (ancestry)
|
||||||
|
.traits-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-3;
|
||||||
|
|
||||||
|
.trait-entry {
|
||||||
|
padding: $spacing-3;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
|
||||||
|
.trait-header {
|
||||||
|
display: flex;
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin-bottom: $spacing-2;
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include button-icon;
|
||||||
|
color: $color-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trait-description textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-traits {
|
||||||
|
color: $color-text-secondary;
|
||||||
|
font-style: italic;
|
||||||
|
text-align: center;
|
||||||
|
padding: $spacing-4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prerequisite sections (perk)
|
||||||
|
.prerequisites-section {
|
||||||
|
.prereq-stats {
|
||||||
|
margin-bottom: $spacing-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-prereq-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6, 1fr);
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin-top: $spacing-2;
|
||||||
|
|
||||||
|
.stat-prereq {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-1;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prereq-label {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prereq-training,
|
||||||
|
.prereq-spells,
|
||||||
|
.prereq-perks,
|
||||||
|
.prereq-custom {
|
||||||
|
margin-top: $spacing-3;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: $spacing-1;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progression table (class)
|
||||||
|
.progression-section {
|
||||||
|
.progression-table {
|
||||||
|
margin-top: $spacing-3;
|
||||||
|
|
||||||
|
.progression-header {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50px 60px 80px 80px 1fr 40px;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: $color-parchment-dark;
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: $radius-sm $radius-sm 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progression-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50px 60px 80px 80px 1fr 40px;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2;
|
||||||
|
border-bottom: 1px solid $color-border;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 0 $radius-sm $radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: $spacing-1;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include button-icon;
|
||||||
|
color: $color-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-progression {
|
||||||
|
padding: $spacing-4;
|
||||||
|
text-align: center;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Features list (class)
|
||||||
|
.features-section {
|
||||||
|
.features-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-3;
|
||||||
|
margin-top: $spacing-3;
|
||||||
|
|
||||||
|
.feature-entry {
|
||||||
|
padding: $spacing-3;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
|
||||||
|
.feature-header {
|
||||||
|
display: flex;
|
||||||
|
gap: $spacing-2;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: $spacing-2;
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
flex: 1;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.passive-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-1;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include button-icon;
|
||||||
|
color: $color-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-description textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-features {
|
||||||
|
padding: $spacing-4;
|
||||||
|
text-align: center;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spell effect and crit effect
|
||||||
|
.spell-effect,
|
||||||
|
.spell-crit-effect {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-container {
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
min-height: 80px;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses section
|
||||||
|
.uses-section,
|
||||||
|
.consumable-uses {
|
||||||
|
.item-stats-row {
|
||||||
|
margin-top: $spacing-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activation section
|
||||||
|
.activation-section {
|
||||||
|
.item-stats-row {
|
||||||
|
margin-top: $spacing-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Effects tab
|
||||||
|
.effects-tab {
|
||||||
|
padding: $spacing-4;
|
||||||
|
|
||||||
|
.effects-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effects-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-effect {
|
||||||
|
@include button-primary;
|
||||||
|
padding: $spacing-1 $spacing-3;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: $spacing-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-items {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
|
||||||
|
.effect-name {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure controls remain clickable when effect is disabled
|
||||||
|
.effect-controls {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
|
||||||
|
button {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-name {
|
||||||
|
flex: 1;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-controls {
|
||||||
|
display: flex;
|
||||||
|
gap: $spacing-1;
|
||||||
|
|
||||||
|
.effect-control {
|
||||||
|
@include button-icon;
|
||||||
|
|
||||||
|
&.delete {
|
||||||
|
color: $color-danger;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba($color-danger, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-effects {
|
||||||
|
color: $color-text-secondary;
|
||||||
|
font-style: italic;
|
||||||
|
text-align: center;
|
||||||
|
padding: $spacing-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item description
|
.effects-hint {
|
||||||
.item-description {
|
|
||||||
.editor {
|
|
||||||
min-height: 150px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spell item specific
|
|
||||||
.vagabond.sheet.item.spell {
|
|
||||||
.spell-details {
|
|
||||||
@include grid(2);
|
|
||||||
margin-bottom: $spacing-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delivery-options {
|
|
||||||
margin-bottom: $spacing-4;
|
|
||||||
|
|
||||||
.option-grid {
|
|
||||||
@include grid(3, $spacing-2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perk item specific
|
|
||||||
.vagabond.sheet.item.perk {
|
|
||||||
.prerequisites {
|
|
||||||
@include panel;
|
|
||||||
padding: $spacing-3;
|
|
||||||
margin-bottom: $spacing-4;
|
|
||||||
|
|
||||||
.prereq-list {
|
|
||||||
@include flex-column;
|
|
||||||
gap: $spacing-2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Weapon item specific
|
|
||||||
.vagabond.sheet.item.weapon {
|
|
||||||
.weapon-properties {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: $spacing-2;
|
|
||||||
margin-bottom: $spacing-4;
|
|
||||||
|
|
||||||
.property-tag {
|
|
||||||
padding: $spacing-1 $spacing-2;
|
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
background-color: $color-parchment-dark;
|
color: $color-text-secondary;
|
||||||
border: 1px solid $color-border;
|
margin-top: $spacing-2;
|
||||||
border-radius: $radius-full;
|
|
||||||
|
i {
|
||||||
|
margin-right: $spacing-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type-specific additional styles
|
||||||
|
.vagabond.sheet.item.weapon {
|
||||||
|
.weapon-content {
|
||||||
|
.item-properties {
|
||||||
|
margin-top: $spacing-2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class item specific
|
|
||||||
.vagabond.sheet.item.class {
|
.vagabond.sheet.item.class {
|
||||||
.progression-table {
|
min-width: 600px;
|
||||||
width: 100%;
|
min-height: 600px;
|
||||||
margin-bottom: $spacing-4;
|
|
||||||
|
|
||||||
th {
|
.class-content {
|
||||||
position: sticky;
|
.progression-header {
|
||||||
top: 0;
|
// Adjust columns without delete button column for non-editable
|
||||||
background-color: $color-parchment-dark;
|
&.readonly {
|
||||||
|
grid-template-columns: 50px 60px 80px 80px 1fr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
templates/item/parts/item-body.hbs
Normal file
5
templates/item/parts/item-body.hbs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{{!-- Item Sheet Body - Routes to type-specific template --}}
|
||||||
|
<section class="sheet-body tab-content details-tab{{#unless (eq activeTab "details")}} hidden{{/unless}}">
|
||||||
|
{{!-- Type-specific content is injected by subclass sheets --}}
|
||||||
|
{{> (concat "systems/vagabond/templates/item/types/" itemType ".hbs") }}
|
||||||
|
</section>
|
||||||
44
templates/item/parts/item-effects.hbs
Normal file
44
templates/item/parts/item-effects.hbs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{{!-- Item Effects Tab --}}
|
||||||
|
<section class="tab-content effects-tab{{#unless (eq activeTab "effects")}} hidden{{/unless}}">
|
||||||
|
<div class="effects-list">
|
||||||
|
<header class="effects-header">
|
||||||
|
<h3>{{localize "VAGABOND.ActiveEffects"}}</h3>
|
||||||
|
{{#if editable}}
|
||||||
|
<button type="button" class="add-effect" data-action="createEffect">
|
||||||
|
<i class="fas fa-plus"></i> {{localize "VAGABOND.AddEffect"}}
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{#if effects.length}}
|
||||||
|
<ul class="effect-items">
|
||||||
|
{{#each effects}}
|
||||||
|
<li class="effect-item{{#if disabled}} disabled{{/if}}" data-effect-id="{{id}}">
|
||||||
|
<img class="effect-icon" src="{{icon}}" alt="{{name}}" />
|
||||||
|
<span class="effect-name">{{name}}</span>
|
||||||
|
<div class="effect-controls">
|
||||||
|
{{#if ../editable}}
|
||||||
|
<button type="button" class="effect-control" data-action="toggleEffect" title="{{localize 'VAGABOND.ToggleEffect'}}">
|
||||||
|
<i class="fas {{#if disabled}}fa-toggle-off{{else}}fa-toggle-on{{/if}}"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="effect-control" data-action="editEffect" title="{{localize 'VAGABOND.EditEffect'}}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="effect-control delete" data-action="deleteEffect" title="{{localize 'VAGABOND.DeleteEffect'}}">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{else}}
|
||||||
|
<p class="no-effects">{{localize "VAGABOND.NoEffects"}}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<p class="effects-hint">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
{{localize "VAGABOND.EffectsHint"}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
14
templates/item/parts/item-header.hbs
Normal file
14
templates/item/parts/item-header.hbs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{{!-- Item Sheet Header --}}
|
||||||
|
<header class="sheet-header item-header">
|
||||||
|
<img class="item-img" src="{{item.img}}" alt="{{item.name}}" data-edit="img" />
|
||||||
|
|
||||||
|
<div class="header-fields">
|
||||||
|
<h1 class="item-name">
|
||||||
|
<input type="text" name="name" value="{{item.name}}" placeholder="{{localize 'VAGABOND.ItemName'}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="item-type">
|
||||||
|
<span class="type-badge {{itemType}}">{{localize (concat "VAGABOND.ItemType" (capitalize itemType))}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
9
templates/item/parts/item-tabs.hbs
Normal file
9
templates/item/parts/item-tabs.hbs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{{!-- Item Sheet Tabs --}}
|
||||||
|
<nav class="sheet-tabs tabs{{#unless hasTabs}} hidden{{/unless}}" data-group="primary">
|
||||||
|
{{#each tabs}}
|
||||||
|
<a class="item {{cssClass}}" data-tab="{{id}}" data-action="changeTab">
|
||||||
|
{{#if icon}}<i class="{{icon}}"></i>{{/if}}
|
||||||
|
{{localize label}}
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
</nav>
|
||||||
71
templates/item/types/ancestry.hbs
Normal file
71
templates/item/types/ancestry.hbs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{{!-- Ancestry Item Sheet Body --}}
|
||||||
|
<div class="item-content ancestry-content">
|
||||||
|
{{!-- Core Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group wide">
|
||||||
|
<label>{{localize "VAGABOND.BeingType"}}</label>
|
||||||
|
<select name="system.beingType" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="humanlike" {{#if (eq system.beingType "humanlike")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeHumanlike"}}</option>
|
||||||
|
<option value="fae" {{#if (eq system.beingType "fae")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeFae"}}</option>
|
||||||
|
<option value="cryptid" {{#if (eq system.beingType "cryptid")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeCryptid"}}</option>
|
||||||
|
<option value="beast" {{#if (eq system.beingType "beast")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeBeast"}}</option>
|
||||||
|
<option value="undead" {{#if (eq system.beingType "undead")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeUndead"}}</option>
|
||||||
|
<option value="artificial" {{#if (eq system.beingType "artificial")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeArtificial"}}</option>
|
||||||
|
<option value="primordial" {{#if (eq system.beingType "primordial")}}selected{{/if}}>{{localize "VAGABOND.BeingTypePrimordial"}}</option>
|
||||||
|
<option value="hellspawn" {{#if (eq system.beingType "hellspawn")}}selected{{/if}}>{{localize "VAGABOND.BeingTypeHellspawn"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group wide">
|
||||||
|
<label>{{localize "VAGABOND.Size"}}</label>
|
||||||
|
<select name="system.size" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="tiny" {{#if (eq system.size "tiny")}}selected{{/if}}>{{localize "VAGABOND.SizeTiny"}}</option>
|
||||||
|
<option value="small" {{#if (eq system.size "small")}}selected{{/if}}>{{localize "VAGABOND.SizeSmall"}}</option>
|
||||||
|
<option value="medium" {{#if (eq system.size "medium")}}selected{{/if}}>{{localize "VAGABOND.SizeMedium"}}</option>
|
||||||
|
<option value="large" {{#if (eq system.size "large")}}selected{{/if}}>{{localize "VAGABOND.SizeLarge"}}</option>
|
||||||
|
<option value="huge" {{#if (eq system.size "huge")}}selected{{/if}}>{{localize "VAGABOND.SizeHuge"}}</option>
|
||||||
|
<option value="gargantuan" {{#if (eq system.size "gargantuan")}}selected{{/if}}>{{localize "VAGABOND.SizeGargantuan"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Traits Section --}}
|
||||||
|
<fieldset class="traits-section">
|
||||||
|
<legend>
|
||||||
|
{{localize "VAGABOND.Traits"}}
|
||||||
|
{{#if editable}}
|
||||||
|
<button type="button" class="add-trait" data-action="addArrayEntry" data-field="system.traits">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
<div class="traits-list">
|
||||||
|
{{#each system.traits as |trait index|}}
|
||||||
|
<div class="trait-entry" data-index="{{index}}">
|
||||||
|
<div class="trait-header">
|
||||||
|
<input type="text" name="system.traits.{{index}}.name" value="{{trait.name}}" placeholder="{{localize 'VAGABOND.TraitName'}}" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
{{#if ../editable}}
|
||||||
|
<button type="button" class="delete-trait" data-action="deleteArrayEntry" data-field="system.traits" data-index="{{index}}">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="trait-description">
|
||||||
|
<textarea name="system.traits.{{index}}.description" placeholder="{{localize 'VAGABOND.TraitDescription'}}" {{#unless ../editable}}disabled{{/unless}}>{{trait.description}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<p class="no-traits">{{localize "VAGABOND.NoTraits"}}</p>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
135
templates/item/types/armor.hbs
Normal file
135
templates/item/types/armor.hbs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
{{!-- Armor Item Sheet Body --}}
|
||||||
|
<div class="item-content armor-content">
|
||||||
|
{{!-- Core Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ArmorValue"}}</label>
|
||||||
|
<input type="number" name="system.armorValue" value="{{system.armorValue}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ArmorType"}}</label>
|
||||||
|
<select name="system.armorType" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="none" {{#if (eq system.armorType "none")}}selected{{/if}}>{{localize "VAGABOND.ArmorTypeNone"}}</option>
|
||||||
|
<option value="light" {{#if (eq system.armorType "light")}}selected{{/if}}>{{localize "VAGABOND.ArmorTypeLight"}}</option>
|
||||||
|
<option value="medium" {{#if (eq system.armorType "medium")}}selected{{/if}}>{{localize "VAGABOND.ArmorTypeMedium"}}</option>
|
||||||
|
<option value="heavy" {{#if (eq system.armorType "heavy")}}selected{{/if}}>{{localize "VAGABOND.ArmorTypeHeavy"}}</option>
|
||||||
|
<option value="shield" {{#if (eq system.armorType "shield")}}selected{{/if}}>{{localize "VAGABOND.ArmorTypeShield"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.MagicBonus"}}</label>
|
||||||
|
<input type="number" name="system.magicBonus" value="{{system.magicBonus}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Secondary Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Slots"}}</label>
|
||||||
|
<input type="number" name="system.slots" value="{{system.slots}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Value"}}</label>
|
||||||
|
<input type="number" name="system.value" value="{{system.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="units">c</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Equipped"}}</label>
|
||||||
|
<input type="checkbox" name="system.equipped" {{#if system.equipped}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Penalties --}}
|
||||||
|
<fieldset class="item-penalties">
|
||||||
|
<legend>{{localize "VAGABOND.Penalties"}}</legend>
|
||||||
|
<div class="properties-grid">
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.dodgePenalty" {{#if system.dodgePenalty}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DodgePenalty"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.hindersDodge" {{#if system.hindersDodge}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.HindersDodge"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.preventsRage" {{#if system.preventsRage}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PreventsRage"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Relic Section (collapsible) --}}
|
||||||
|
<fieldset class="relic-section {{#unless system.relic.isRelic}}collapsed{{/unless}}">
|
||||||
|
<legend>
|
||||||
|
<label class="relic-toggle">
|
||||||
|
<input type="checkbox" name="system.relic.isRelic" {{#if system.relic.isRelic}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.Relic"}}
|
||||||
|
</label>
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
{{#if system.relic.isRelic}}
|
||||||
|
<div class="relic-fields">
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RelicTier"}}</label>
|
||||||
|
<input type="number" name="system.relic.tier" value="{{system.relic.tier}}" min="1" max="5" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RequiresAttunement"}}</label>
|
||||||
|
<input type="checkbox" name="system.relic.requiresAttunement" {{#if system.relic.requiresAttunement}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{#if system.relic.requiresAttunement}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Attuned"}}</label>
|
||||||
|
<input type="checkbox" name="system.relic.attuned" {{#if system.relic.attuned}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicAbilityName"}}</label>
|
||||||
|
<input type="text" name="system.relic.abilityName" value="{{system.relic.abilityName}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicAbilityDescription"}}</label>
|
||||||
|
<textarea name="system.relic.abilityDescription" {{#unless editable}}disabled{{/unless}}>{{system.relic.abilityDescription}}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ActivationCost"}}</label>
|
||||||
|
<input type="text" name="system.relic.activationCost" value="{{system.relic.activationCost}}" placeholder="e.g. 1 Mana" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesPerDay"}}</label>
|
||||||
|
<input type="number" name="system.relic.usesPerDay" value="{{system.relic.usesPerDay}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{#if (gt system.relic.usesPerDay 0)}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesRemaining"}}</label>
|
||||||
|
<input type="number" name="system.relic.usesRemaining" value="{{system.relic.usesRemaining}}" min="0" max="{{system.relic.usesPerDay}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicLore"}}</label>
|
||||||
|
<textarea name="system.relic.lore" {{#unless editable}}disabled{{/unless}}>{{system.relic.lore}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
163
templates/item/types/class.hbs
Normal file
163
templates/item/types/class.hbs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
{{!-- Class Item Sheet Body --}}
|
||||||
|
<div class="item-content class-content">
|
||||||
|
{{!-- Core Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.KeyStat"}}</label>
|
||||||
|
<select name="system.keyStat" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="might" {{#if (eq system.keyStat "might")}}selected{{/if}}>{{localize "VAGABOND.StatMight"}}</option>
|
||||||
|
<option value="dexterity" {{#if (eq system.keyStat "dexterity")}}selected{{/if}}>{{localize "VAGABOND.StatDexterity"}}</option>
|
||||||
|
<option value="awareness" {{#if (eq system.keyStat "awareness")}}selected{{/if}}>{{localize "VAGABOND.StatAwareness"}}</option>
|
||||||
|
<option value="reason" {{#if (eq system.keyStat "reason")}}selected{{/if}}>{{localize "VAGABOND.StatReason"}}</option>
|
||||||
|
<option value="presence" {{#if (eq system.keyStat "presence")}}selected{{/if}}>{{localize "VAGABOND.StatPresence"}}</option>
|
||||||
|
<option value="luck" {{#if (eq system.keyStat "luck")}}selected{{/if}}>{{localize "VAGABOND.StatLuck"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Zone"}}</label>
|
||||||
|
<select name="system.zone" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="frontline" {{#if (eq system.zone "frontline")}}selected{{/if}}>{{localize "VAGABOND.ZoneFrontline"}}</option>
|
||||||
|
<option value="midline" {{#if (eq system.zone "midline")}}selected{{/if}}>{{localize "VAGABOND.ZoneMidline"}}</option>
|
||||||
|
<option value="backline" {{#if (eq system.zone "backline")}}selected{{/if}}>{{localize "VAGABOND.ZoneBackline"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.IsCaster"}}</label>
|
||||||
|
<input type="checkbox" name="system.isCaster" {{#if system.isCaster}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Casting Skill (if caster) --}}
|
||||||
|
{{#if system.isCaster}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ActionStyle"}}</label>
|
||||||
|
<select name="system.actionStyle" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="" {{#unless system.actionStyle}}selected{{/unless}}>-</option>
|
||||||
|
<option value="arcana" {{#if (eq system.actionStyle "arcana")}}selected{{/if}}>{{localize "VAGABOND.SkillArcana"}}</option>
|
||||||
|
<option value="mysticism" {{#if (eq system.actionStyle "mysticism")}}selected{{/if}}>{{localize "VAGABOND.SkillMysticism"}}</option>
|
||||||
|
<option value="influence" {{#if (eq system.actionStyle "influence")}}selected{{/if}}>{{localize "VAGABOND.SkillInfluence"}}</option>
|
||||||
|
<option value="leadership" {{#if (eq system.actionStyle "leadership")}}selected{{/if}}>{{localize "VAGABOND.SkillLeadership"}}</option>
|
||||||
|
<option value="performance" {{#if (eq system.actionStyle "performance")}}selected{{/if}}>{{localize "VAGABOND.SkillPerformance"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- Trained Skills --}}
|
||||||
|
<div class="trained-skills-section">
|
||||||
|
<label>{{localize "VAGABOND.TrainedSkills"}}</label>
|
||||||
|
<input type="text" name="system.trainedSkills" value="{{join system.trainedSkills ", "}}" placeholder="e.g. melee, brawl, detect" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="hint">{{localize "VAGABOND.CommaSeparated"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Starting Pack --}}
|
||||||
|
<div class="starting-pack-section">
|
||||||
|
<label>{{localize "VAGABOND.StartingPack"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.startingPack target="system.startingPack" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Custom Resource --}}
|
||||||
|
<fieldset class="custom-resource-section">
|
||||||
|
<legend>{{localize "VAGABOND.CustomResource"}}</legend>
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ResourceName"}}</label>
|
||||||
|
<input type="text" name="system.customResource.name" value="{{system.customResource.name}}" placeholder="e.g. Studied Dice" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ResourceMax"}}</label>
|
||||||
|
<input type="text" name="system.customResource.max" value="{{system.customResource.max}}" placeholder="e.g. @level" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Progression Table --}}
|
||||||
|
<fieldset class="progression-section">
|
||||||
|
<legend>
|
||||||
|
{{localize "VAGABOND.Progression"}}
|
||||||
|
{{#if editable}}
|
||||||
|
<button type="button" class="add-progression" data-action="addArrayEntry" data-field="system.progression">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
<div class="progression-table">
|
||||||
|
<div class="progression-header">
|
||||||
|
<span class="col-level">{{localize "VAGABOND.Level"}}</span>
|
||||||
|
<span class="col-mana">{{localize "VAGABOND.Mana"}}</span>
|
||||||
|
<span class="col-casting">{{localize "VAGABOND.CastingMax"}}</span>
|
||||||
|
<span class="col-spells">{{localize "VAGABOND.SpellsKnown"}}</span>
|
||||||
|
<span class="col-features">{{localize "VAGABOND.Features"}}</span>
|
||||||
|
{{#if editable}}<span class="col-actions"></span>{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#each system.progression as |prog index|}}
|
||||||
|
<div class="progression-row" data-index="{{index}}">
|
||||||
|
<input type="number" class="col-level" name="system.progression.{{index}}.level" value="{{prog.level}}" min="1" max="10" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
<input type="number" class="col-mana" name="system.progression.{{index}}.mana" value="{{prog.mana}}" min="0" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
<input type="number" class="col-casting" name="system.progression.{{index}}.castingMax" value="{{prog.castingMax}}" min="0" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
<input type="number" class="col-spells" name="system.progression.{{index}}.spellsKnown" value="{{prog.spellsKnown}}" min="0" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
<input type="text" class="col-features" name="system.progression.{{index}}.features" value="{{join prog.features ", "}}" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
{{#if ../editable}}
|
||||||
|
<button type="button" class="col-actions delete-progression" data-action="deleteArrayEntry" data-field="system.progression" data-index="{{index}}">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<p class="no-progression">{{localize "VAGABOND.NoProgression"}}</p>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Features --}}
|
||||||
|
<fieldset class="features-section">
|
||||||
|
<legend>
|
||||||
|
{{localize "VAGABOND.ClassFeatures"}}
|
||||||
|
{{#if editable}}
|
||||||
|
<button type="button" class="add-feature" data-action="addArrayEntry" data-field="system.features">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
<div class="features-list">
|
||||||
|
{{#each system.features as |feature index|}}
|
||||||
|
<div class="feature-entry" data-index="{{index}}">
|
||||||
|
<div class="feature-header">
|
||||||
|
<input type="text" name="system.features.{{index}}.name" value="{{feature.name}}" placeholder="{{localize 'VAGABOND.FeatureName'}}" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
<input type="number" name="system.features.{{index}}.level" value="{{feature.level}}" min="1" max="10" title="{{localize 'VAGABOND.Level'}}" {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
<label class="passive-toggle">
|
||||||
|
<input type="checkbox" name="system.features.{{index}}.passive" {{#if feature.passive}}checked{{/if}} {{#unless ../editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.Passive"}}
|
||||||
|
</label>
|
||||||
|
{{#if ../editable}}
|
||||||
|
<button type="button" class="delete-feature" data-action="deleteArrayEntry" data-field="system.features" data-index="{{index}}">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="feature-description">
|
||||||
|
<textarea name="system.features.{{index}}.description" placeholder="{{localize 'VAGABOND.FeatureDescription'}}" {{#unless ../editable}}disabled{{/unless}}>{{feature.description}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<p class="no-features">{{localize "VAGABOND.NoFeatures"}}</p>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
169
templates/item/types/equipment.hbs
Normal file
169
templates/item/types/equipment.hbs
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
{{!-- Equipment Item Sheet Body --}}
|
||||||
|
<div class="item-content equipment-content">
|
||||||
|
{{!-- Core Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Quantity"}}</label>
|
||||||
|
<input type="number" name="system.quantity" value="{{system.quantity}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Slots"}}</label>
|
||||||
|
<input type="number" name="system.slots" value="{{system.slots}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.SlotsPerItem"}}</label>
|
||||||
|
<input type="checkbox" name="system.slotsPerItem" {{#if system.slotsPerItem}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Value"}}</label>
|
||||||
|
<input type="number" name="system.value" value="{{system.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="units">c</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Category and Flags --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Category"}}</label>
|
||||||
|
<select name="system.category" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="gear" {{#if (eq system.category "gear")}}selected{{/if}}>{{localize "VAGABOND.CategoryGear"}}</option>
|
||||||
|
<option value="tool" {{#if (eq system.category "tool")}}selected{{/if}}>{{localize "VAGABOND.CategoryTool"}}</option>
|
||||||
|
<option value="consumable" {{#if (eq system.category "consumable")}}selected{{/if}}>{{localize "VAGABOND.CategoryConsumable"}}</option>
|
||||||
|
<option value="container" {{#if (eq system.category "container")}}selected{{/if}}>{{localize "VAGABOND.CategoryContainer"}}</option>
|
||||||
|
<option value="treasure" {{#if (eq system.category "treasure")}}selected{{/if}}>{{localize "VAGABOND.CategoryTreasure"}}</option>
|
||||||
|
<option value="misc" {{#if (eq system.category "misc")}}selected{{/if}}>{{localize "VAGABOND.CategoryMisc"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Equipped"}}</label>
|
||||||
|
<input type="checkbox" name="system.equipped" {{#if system.equipped}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Consumable"}}</label>
|
||||||
|
<input type="checkbox" name="system.consumable" {{#if system.consumable}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Consumable Uses (if consumable) --}}
|
||||||
|
{{#if system.consumable}}
|
||||||
|
<fieldset class="consumable-uses">
|
||||||
|
<legend>{{localize "VAGABOND.Uses"}}</legend>
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesCurrent"}}</label>
|
||||||
|
<input type="number" name="system.uses.value" value="{{system.uses.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesMax"}}</label>
|
||||||
|
<input type="number" name="system.uses.max" value="{{system.uses.max}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.AutoDestroy"}}</label>
|
||||||
|
<input type="checkbox" name="system.uses.autoDestroy" {{#if system.uses.autoDestroy}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- Container Capacity (if container) --}}
|
||||||
|
{{#if (eq system.category "container")}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ContainerCapacity"}}</label>
|
||||||
|
<input type="number" name="system.containerCapacity" value="{{system.containerCapacity}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="units">{{localize "VAGABOND.Slots"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- Magic Properties --}}
|
||||||
|
<fieldset class="item-properties">
|
||||||
|
<legend>{{localize "VAGABOND.MagicProperties"}}</legend>
|
||||||
|
<div class="properties-grid">
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.isTrinket" {{#if system.isTrinket}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.IsTrinket"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.canCastThrough" {{#if system.canCastThrough}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.CanCastThrough"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Relic Section (collapsible) --}}
|
||||||
|
<fieldset class="relic-section {{#unless system.relic.isRelic}}collapsed{{/unless}}">
|
||||||
|
<legend>
|
||||||
|
<label class="relic-toggle">
|
||||||
|
<input type="checkbox" name="system.relic.isRelic" {{#if system.relic.isRelic}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.Relic"}}
|
||||||
|
</label>
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
{{#if system.relic.isRelic}}
|
||||||
|
<div class="relic-fields">
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RelicTier"}}</label>
|
||||||
|
<input type="number" name="system.relic.tier" value="{{system.relic.tier}}" min="1" max="5" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RequiresAttunement"}}</label>
|
||||||
|
<input type="checkbox" name="system.relic.requiresAttunement" {{#if system.relic.requiresAttunement}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{#if system.relic.requiresAttunement}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Attuned"}}</label>
|
||||||
|
<input type="checkbox" name="system.relic.attuned" {{#if system.relic.attuned}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicAbilityName"}}</label>
|
||||||
|
<input type="text" name="system.relic.abilityName" value="{{system.relic.abilityName}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicAbilityDescription"}}</label>
|
||||||
|
<textarea name="system.relic.abilityDescription" {{#unless editable}}disabled{{/unless}}>{{system.relic.abilityDescription}}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ActivationCost"}}</label>
|
||||||
|
<input type="text" name="system.relic.activationCost" value="{{system.relic.activationCost}}" placeholder="e.g. 1 Mana" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesPerDay"}}</label>
|
||||||
|
<input type="number" name="system.relic.usesPerDay" value="{{system.relic.usesPerDay}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{#if (gt system.relic.usesPerDay 0)}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesRemaining"}}</label>
|
||||||
|
<input type="number" name="system.relic.usesRemaining" value="{{system.relic.usesRemaining}}" min="0" max="{{system.relic.usesPerDay}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicLore"}}</label>
|
||||||
|
<textarea name="system.relic.lore" {{#unless editable}}disabled{{/unless}}>{{system.relic.lore}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
83
templates/item/types/feature.hbs
Normal file
83
templates/item/types/feature.hbs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
{{!-- Feature Item Sheet Body --}}
|
||||||
|
<div class="item-content feature-content">
|
||||||
|
{{!-- Core Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.SourceClass"}}</label>
|
||||||
|
<input type="text" name="system.sourceClass" value="{{system.sourceClass}}" placeholder="e.g. Fighter" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Level"}}</label>
|
||||||
|
<input type="number" name="system.level" value="{{system.level}}" min="1" max="10" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Passive"}}</label>
|
||||||
|
<input type="checkbox" name="system.passive" {{#if system.passive}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Activation (for active features) --}}
|
||||||
|
{{#unless system.passive}}
|
||||||
|
<fieldset class="activation-section">
|
||||||
|
<legend>{{localize "VAGABOND.Activation"}}</legend>
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ActivationType"}}</label>
|
||||||
|
<select name="system.activation.type" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="" {{#unless system.activation.type}}selected{{/unless}}>-</option>
|
||||||
|
<option value="action" {{#if (eq system.activation.type "action")}}selected{{/if}}>{{localize "VAGABOND.Action"}}</option>
|
||||||
|
<option value="bonus" {{#if (eq system.activation.type "bonus")}}selected{{/if}}>{{localize "VAGABOND.BonusAction"}}</option>
|
||||||
|
<option value="reaction" {{#if (eq system.activation.type "reaction")}}selected{{/if}}>{{localize "VAGABOND.Reaction"}}</option>
|
||||||
|
<option value="free" {{#if (eq system.activation.type "free")}}selected{{/if}}>{{localize "VAGABOND.FreeAction"}}</option>
|
||||||
|
<option value="special" {{#if (eq system.activation.type "special")}}selected{{/if}}>{{localize "VAGABOND.Special"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ActivationCost"}}</label>
|
||||||
|
<input type="text" name="system.activation.cost" value="{{system.activation.cost}}" placeholder="e.g. 1 Mana" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
{{/unless}}
|
||||||
|
|
||||||
|
{{!-- Uses (if limited) --}}
|
||||||
|
<fieldset class="uses-section">
|
||||||
|
<legend>{{localize "VAGABOND.Uses"}}</legend>
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesCurrent"}}</label>
|
||||||
|
<input type="number" name="system.uses.value" value="{{system.uses.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesMax"}}</label>
|
||||||
|
<input type="number" name="system.uses.max" value="{{system.uses.max}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RecoveryPer"}}</label>
|
||||||
|
<select name="system.uses.per" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="" {{#unless system.uses.per}}selected{{/unless}}>{{localize "VAGABOND.Unlimited"}}</option>
|
||||||
|
<option value="short" {{#if (eq system.uses.per "short")}}selected{{/if}}>{{localize "VAGABOND.ShortRest"}}</option>
|
||||||
|
<option value="long" {{#if (eq system.uses.per "long")}}selected{{/if}}>{{localize "VAGABOND.LongRest"}}</option>
|
||||||
|
<option value="day" {{#if (eq system.uses.per "day")}}selected{{/if}}>{{localize "VAGABOND.PerDay"}}</option>
|
||||||
|
<option value="encounter" {{#if (eq system.uses.per "encounter")}}selected{{/if}}>{{localize "VAGABOND.PerEncounter"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Requirements --}}
|
||||||
|
<div class="requirements-section">
|
||||||
|
<label>{{localize "VAGABOND.Requirements"}}</label>
|
||||||
|
<input type="text" name="system.requirements" value="{{system.requirements}}" placeholder="e.g. Chose Path of Rage" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
140
templates/item/types/perk.hbs
Normal file
140
templates/item/types/perk.hbs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
{{!-- Perk Item Sheet Body --}}
|
||||||
|
<div class="item-content perk-content">
|
||||||
|
{{!-- Prerequisites Section --}}
|
||||||
|
<fieldset class="prerequisites-section">
|
||||||
|
<legend>{{localize "VAGABOND.Prerequisites"}}</legend>
|
||||||
|
|
||||||
|
{{!-- Stat Requirements --}}
|
||||||
|
<div class="prereq-stats">
|
||||||
|
<label class="prereq-label">{{localize "VAGABOND.StatRequirements"}}</label>
|
||||||
|
<div class="stat-prereq-grid">
|
||||||
|
<div class="stat-prereq">
|
||||||
|
<label>MIT</label>
|
||||||
|
<input type="number" name="system.prerequisites.stats.might" value="{{system.prerequisites.stats.might}}" min="0" max="7" placeholder="-" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-prereq">
|
||||||
|
<label>DEX</label>
|
||||||
|
<input type="number" name="system.prerequisites.stats.dexterity" value="{{system.prerequisites.stats.dexterity}}" min="0" max="7" placeholder="-" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-prereq">
|
||||||
|
<label>AWR</label>
|
||||||
|
<input type="number" name="system.prerequisites.stats.awareness" value="{{system.prerequisites.stats.awareness}}" min="0" max="7" placeholder="-" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-prereq">
|
||||||
|
<label>RSN</label>
|
||||||
|
<input type="number" name="system.prerequisites.stats.reason" value="{{system.prerequisites.stats.reason}}" min="0" max="7" placeholder="-" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-prereq">
|
||||||
|
<label>PRS</label>
|
||||||
|
<input type="number" name="system.prerequisites.stats.presence" value="{{system.prerequisites.stats.presence}}" min="0" max="7" placeholder="-" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-prereq">
|
||||||
|
<label>LUK</label>
|
||||||
|
<input type="number" name="system.prerequisites.stats.luck" value="{{system.prerequisites.stats.luck}}" min="0" max="7" placeholder="-" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Training Requirements --}}
|
||||||
|
<div class="prereq-training">
|
||||||
|
<label>{{localize "VAGABOND.TrainingRequirements"}}</label>
|
||||||
|
<input type="text" name="system.prerequisites.trainedSkills" value="{{join system.prerequisites.trainedSkills ", "}}" placeholder="e.g. melee, arcana" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="hint">{{localize "VAGABOND.CommaSeparated"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Spell Requirements --}}
|
||||||
|
<div class="prereq-spells">
|
||||||
|
<label>{{localize "VAGABOND.SpellRequirements"}}</label>
|
||||||
|
<input type="text" name="system.prerequisites.spells" value="{{join system.prerequisites.spells ", "}}" placeholder="e.g. Light, Charm" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="hint">{{localize "VAGABOND.CommaSeparated"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Perk Requirements --}}
|
||||||
|
<div class="prereq-perks">
|
||||||
|
<label>{{localize "VAGABOND.PerkRequirements"}}</label>
|
||||||
|
<input type="text" name="system.prerequisites.perks" value="{{join system.prerequisites.perks ", "}}" placeholder="e.g. Tough, Familiar" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="hint">{{localize "VAGABOND.CommaSeparated"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Custom Requirements --}}
|
||||||
|
<div class="prereq-custom">
|
||||||
|
<label>{{localize "VAGABOND.CustomRequirements"}}</label>
|
||||||
|
<input type="text" name="system.prerequisites.custom" value="{{system.prerequisites.custom}}" placeholder="e.g. Maximum Mana 7+" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Usage & Activation --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Passive"}}</label>
|
||||||
|
<input type="checkbox" name="system.passive" {{#if system.passive}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.IsRitual"}}</label>
|
||||||
|
<input type="checkbox" name="system.isRitual" {{#if system.isRitual}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if system.isRitual}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RitualDuration"}}</label>
|
||||||
|
<input type="number" name="system.ritualDuration" value="{{system.ritualDuration}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="units">min</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Uses (if not passive) --}}
|
||||||
|
{{#unless system.passive}}
|
||||||
|
<fieldset class="uses-section">
|
||||||
|
<legend>{{localize "VAGABOND.Uses"}}</legend>
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesCurrent"}}</label>
|
||||||
|
<input type="number" name="system.uses.value" value="{{system.uses.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesMax"}}</label>
|
||||||
|
<input type="number" name="system.uses.max" value="{{system.uses.max}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RecoveryPer"}}</label>
|
||||||
|
<select name="system.uses.per" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="" {{#unless system.uses.per}}selected{{/unless}}>-</option>
|
||||||
|
<option value="short" {{#if (eq system.uses.per "short")}}selected{{/if}}>{{localize "VAGABOND.ShortRest"}}</option>
|
||||||
|
<option value="long" {{#if (eq system.uses.per "long")}}selected{{/if}}>{{localize "VAGABOND.LongRest"}}</option>
|
||||||
|
<option value="day" {{#if (eq system.uses.per "day")}}selected{{/if}}>{{localize "VAGABOND.PerDay"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
{{/unless}}
|
||||||
|
|
||||||
|
{{!-- Luck Integration --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.LuckCost"}}</label>
|
||||||
|
<input type="number" name="system.luckCost" value="{{system.luckCost}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.GrantsLuck"}}</label>
|
||||||
|
<input type="number" name="system.grantsLuck" value="{{system.grantsLuck}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Ritual Components --}}
|
||||||
|
{{#if system.isRitual}}
|
||||||
|
<div class="ritual-components">
|
||||||
|
<label>{{localize "VAGABOND.RitualComponents"}}</label>
|
||||||
|
<input type="text" name="system.ritualComponents" value="{{system.ritualComponents}}" placeholder="e.g. a corpse, herbs" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
134
templates/item/types/spell.hbs
Normal file
134
templates/item/types/spell.hbs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
{{!-- Spell Item Sheet Body --}}
|
||||||
|
<div class="item-content spell-content">
|
||||||
|
{{!-- Damage Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.DamageType"}}</label>
|
||||||
|
<select name="system.damageType" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="" {{#unless system.damageType}}selected{{/unless}}>{{localize "VAGABOND.DamageTypeNone"}}</option>
|
||||||
|
<option value="fire" {{#if (eq system.damageType "fire")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeFire"}}</option>
|
||||||
|
<option value="cold" {{#if (eq system.damageType "cold")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeCold"}}</option>
|
||||||
|
<option value="shock" {{#if (eq system.damageType "shock")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeShock"}}</option>
|
||||||
|
<option value="acid" {{#if (eq system.damageType "acid")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeAcid"}}</option>
|
||||||
|
<option value="poison" {{#if (eq system.damageType "poison")}}selected{{/if}}>{{localize "VAGABOND.DamageTypePoison"}}</option>
|
||||||
|
<option value="blunt" {{#if (eq system.damageType "blunt")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeBlunt"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.DamageBase"}}</label>
|
||||||
|
<input type="text" name="system.damageBase" value="{{system.damageBase}}" placeholder="d6" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.MaxDice"}}</label>
|
||||||
|
<input type="number" name="system.maxDice" value="{{system.maxDice}}" min="0" placeholder="0 = no limit" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.CastingSkill"}}</label>
|
||||||
|
<select name="system.castingSkill" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="" {{#unless system.castingSkill}}selected{{/unless}}>{{localize "VAGABOND.UseClassDefault"}}</option>
|
||||||
|
<option value="arcana" {{#if (eq system.castingSkill "arcana")}}selected{{/if}}>{{localize "VAGABOND.SkillArcana"}}</option>
|
||||||
|
<option value="mysticism" {{#if (eq system.castingSkill "mysticism")}}selected{{/if}}>{{localize "VAGABOND.SkillMysticism"}}</option>
|
||||||
|
<option value="influence" {{#if (eq system.castingSkill "influence")}}selected{{/if}}>{{localize "VAGABOND.SkillInfluence"}}</option>
|
||||||
|
<option value="leadership" {{#if (eq system.castingSkill "leadership")}}selected{{/if}}>{{localize "VAGABOND.SkillLeadership"}}</option>
|
||||||
|
<option value="performance" {{#if (eq system.castingSkill "performance")}}selected{{/if}}>{{localize "VAGABOND.SkillPerformance"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Delivery Types --}}
|
||||||
|
<fieldset class="delivery-types">
|
||||||
|
<legend>{{localize "VAGABOND.DeliveryTypes"}}</legend>
|
||||||
|
<div class="properties-grid">
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.touch" {{#if system.deliveryTypes.touch}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryTouch"}} (0)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.remote" {{#if system.deliveryTypes.remote}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryRemote"}} (0)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.imbue" {{#if system.deliveryTypes.imbue}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryImbue"}} (0)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.cube" {{#if system.deliveryTypes.cube}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryCube"}} (1)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.aura" {{#if system.deliveryTypes.aura}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryAura"}} (2)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.cone" {{#if system.deliveryTypes.cone}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryCone"}} (2)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.glyph" {{#if system.deliveryTypes.glyph}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryGlyph"}} (2)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.line" {{#if system.deliveryTypes.line}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliveryLine"}} (2)
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.deliveryTypes.sphere" {{#if system.deliveryTypes.sphere}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DeliverySphere"}} (2)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Duration Types --}}
|
||||||
|
<fieldset class="duration-types">
|
||||||
|
<legend>{{localize "VAGABOND.DurationTypes"}}</legend>
|
||||||
|
<div class="properties-grid">
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.durationTypes.instant" {{#if system.durationTypes.instant}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DurationInstant"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.durationTypes.focus" {{#if system.durationTypes.focus}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DurationFocus"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.durationTypes.continual" {{#if system.durationTypes.continual}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.DurationContinual"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Focus Tracking --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.CurrentlyFocusing"}}</label>
|
||||||
|
<input type="checkbox" name="system.focusing" {{#if system.focusing}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Effect --}}
|
||||||
|
<div class="spell-effect">
|
||||||
|
<label>{{localize "VAGABOND.Effect"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.effect target="system.effect" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Crit Effect --}}
|
||||||
|
<div class="spell-crit-effect">
|
||||||
|
<label>{{localize "VAGABOND.CritEffect"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.critEffect target="system.critEffect" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
235
templates/item/types/weapon.hbs
Normal file
235
templates/item/types/weapon.hbs
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
{{!-- Weapon Item Sheet Body --}}
|
||||||
|
<div class="item-content weapon-content">
|
||||||
|
{{!-- Core Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Damage"}}</label>
|
||||||
|
<input type="text" name="system.damage" value="{{system.damage}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.DamageType"}}</label>
|
||||||
|
<select name="system.damageType" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="blunt" {{#if (eq system.damageType "blunt")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeBlunt"}}</option>
|
||||||
|
<option value="piercing" {{#if (eq system.damageType "piercing")}}selected{{/if}}>{{localize "VAGABOND.DamageTypePiercing"}}</option>
|
||||||
|
<option value="slashing" {{#if (eq system.damageType "slashing")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeSlashing"}}</option>
|
||||||
|
<option value="fire" {{#if (eq system.damageType "fire")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeFire"}}</option>
|
||||||
|
<option value="cold" {{#if (eq system.damageType "cold")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeCold"}}</option>
|
||||||
|
<option value="shock" {{#if (eq system.damageType "shock")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeShock"}}</option>
|
||||||
|
<option value="acid" {{#if (eq system.damageType "acid")}}selected{{/if}}>{{localize "VAGABOND.DamageTypeAcid"}}</option>
|
||||||
|
<option value="poison" {{#if (eq system.damageType "poison")}}selected{{/if}}>{{localize "VAGABOND.DamageTypePoison"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Grip"}}</label>
|
||||||
|
<select name="system.grip" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="1h" {{#if (eq system.grip "1h")}}selected{{/if}}>{{localize "VAGABOND.Grip1H"}}</option>
|
||||||
|
<option value="2h" {{#if (eq system.grip "2h")}}selected{{/if}}>{{localize "VAGABOND.Grip2H"}}</option>
|
||||||
|
<option value="versatile" {{#if (eq system.grip "versatile")}}selected{{/if}}>{{localize "VAGABOND.GripVersatile"}}</option>
|
||||||
|
<option value="fist" {{#if (eq system.grip "fist")}}selected{{/if}}>{{localize "VAGABOND.GripFist"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.AttackSkill"}}</label>
|
||||||
|
<select name="system.attackType" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="melee" {{#if (eq system.attackType "melee")}}selected{{/if}}>{{localize "VAGABOND.SkillMelee"}}</option>
|
||||||
|
<option value="brawl" {{#if (eq system.attackType "brawl")}}selected{{/if}}>{{localize "VAGABOND.SkillBrawl"}}</option>
|
||||||
|
<option value="ranged" {{#if (eq system.attackType "ranged")}}selected{{/if}}>{{localize "VAGABOND.SkillRanged"}}</option>
|
||||||
|
<option value="finesse" {{#if (eq system.attackType "finesse")}}selected{{/if}}>{{localize "VAGABOND.SkillFinesse"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Secondary Stats Row --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
{{#if (eq system.grip "versatile")}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.VersatileDamage"}}</label>
|
||||||
|
<input type="text" name="system.versatileDamage" value="{{system.versatileDamage}}" placeholder="e.g. 1d8" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.BonusDamage"}}</label>
|
||||||
|
<input type="number" name="system.bonusDamage" value="{{system.bonusDamage}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.AttackBonus"}}</label>
|
||||||
|
<input type="number" name="system.attackBonus" value="{{system.attackBonus}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.CritThreshold"}}</label>
|
||||||
|
<input type="number" name="system.critThreshold" value="{{system.critThreshold}}" min="1" max="20" placeholder="20" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Range (for ranged/thrown) --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Range"}}</label>
|
||||||
|
<div class="range-input">
|
||||||
|
<input type="number" name="system.range.value" value="{{system.range.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="units">{{system.range.units}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Slots"}}</label>
|
||||||
|
<input type="number" name="system.slots" value="{{system.slots}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Value"}}</label>
|
||||||
|
<input type="number" name="system.value" value="{{system.value}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
<span class="units">c</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Quantity"}}</label>
|
||||||
|
<input type="number" name="system.quantity" value="{{system.quantity}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Properties --}}
|
||||||
|
<fieldset class="item-properties">
|
||||||
|
<legend>{{localize "VAGABOND.WeaponProperties"}}</legend>
|
||||||
|
<div class="properties-grid">
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.finesse" {{#if system.properties.finesse}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyFinesse"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.thrown" {{#if system.properties.thrown}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyThrown"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.cleave" {{#if system.properties.cleave}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyCleave"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.reach" {{#if system.properties.reach}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyReach"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.loading" {{#if system.properties.loading}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyLoading"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.brawl" {{#if system.properties.brawl}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyBrawl"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.crude" {{#if system.properties.crude}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyCrude"}}
|
||||||
|
</label>
|
||||||
|
<label class="property-checkbox">
|
||||||
|
<input type="checkbox" name="system.properties.versatile" {{#if system.properties.versatile}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.PropertyVersatile"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Material --}}
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Material"}}</label>
|
||||||
|
<select name="system.material" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="mundane" {{#if (eq system.material "mundane")}}selected{{/if}}>{{localize "VAGABOND.MaterialMundane"}}</option>
|
||||||
|
<option value="silvered" {{#if (eq system.material "silvered")}}selected{{/if}}>{{localize "VAGABOND.MaterialSilvered"}}</option>
|
||||||
|
<option value="adamantine" {{#if (eq system.material "adamantine")}}selected{{/if}}>{{localize "VAGABOND.MaterialAdamantine"}}</option>
|
||||||
|
<option value="magical" {{#if (eq system.material "magical")}}selected{{/if}}>{{localize "VAGABOND.MaterialMagical"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Equipped"}}</label>
|
||||||
|
<input type="checkbox" name="system.equipped" {{#if system.equipped}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if system.equipped}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.EquippedHand"}}</label>
|
||||||
|
<select name="system.equippedHand" {{#unless editable}}disabled{{/unless}}>
|
||||||
|
<option value="main" {{#if (eq system.equippedHand "main")}}selected{{/if}}>{{localize "VAGABOND.HandMain"}}</option>
|
||||||
|
<option value="off" {{#if (eq system.equippedHand "off")}}selected{{/if}}>{{localize "VAGABOND.HandOff"}}</option>
|
||||||
|
<option value="both" {{#if (eq system.equippedHand "both")}}selected{{/if}}>{{localize "VAGABOND.HandBoth"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Relic Section (collapsible) --}}
|
||||||
|
<fieldset class="relic-section {{#unless system.relic.isRelic}}collapsed{{/unless}}">
|
||||||
|
<legend>
|
||||||
|
<label class="relic-toggle">
|
||||||
|
<input type="checkbox" name="system.relic.isRelic" {{#if system.relic.isRelic}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
{{localize "VAGABOND.Relic"}}
|
||||||
|
</label>
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
{{#if system.relic.isRelic}}
|
||||||
|
<div class="relic-fields">
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RelicTier"}}</label>
|
||||||
|
<input type="number" name="system.relic.tier" value="{{system.relic.tier}}" min="1" max="5" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.RequiresAttunement"}}</label>
|
||||||
|
<input type="checkbox" name="system.relic.requiresAttunement" {{#if system.relic.requiresAttunement}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{#if system.relic.requiresAttunement}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.Attuned"}}</label>
|
||||||
|
<input type="checkbox" name="system.relic.attuned" {{#if system.relic.attuned}}checked{{/if}} {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicAbilityName"}}</label>
|
||||||
|
<input type="text" name="system.relic.abilityName" value="{{system.relic.abilityName}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicAbilityDescription"}}</label>
|
||||||
|
<textarea name="system.relic.abilityDescription" {{#unless editable}}disabled{{/unless}}>{{system.relic.abilityDescription}}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-stats-row">
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.ActivationCost"}}</label>
|
||||||
|
<input type="text" name="system.relic.activationCost" value="{{system.relic.activationCost}}" placeholder="e.g. 1 Mana" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesPerDay"}}</label>
|
||||||
|
<input type="number" name="system.relic.usesPerDay" value="{{system.relic.usesPerDay}}" min="0" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{#if (gt system.relic.usesPerDay 0)}}
|
||||||
|
<div class="stat-group">
|
||||||
|
<label>{{localize "VAGABOND.UsesRemaining"}}</label>
|
||||||
|
<input type="number" name="system.relic.usesRemaining" value="{{system.relic.usesRemaining}}" min="0" max="{{system.relic.usesPerDay}}" {{#unless editable}}disabled{{/unless}} />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-group full-width">
|
||||||
|
<label>{{localize "VAGABOND.RelicLore"}}</label>
|
||||||
|
<textarea name="system.relic.lore" {{#unless editable}}disabled{{/unless}}>{{system.relic.lore}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{{!-- Description --}}
|
||||||
|
<div class="item-description">
|
||||||
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
|
<div class="editor-container">
|
||||||
|
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Loading…
Reference in New Issue
Block a user