Latest fixes for Oath Hammer

This commit is contained in:
2026-03-12 17:29:43 +01:00
parent e8d84615c5
commit 82fddb0cb3
20 changed files with 376 additions and 97 deletions

View File

@@ -703,6 +703,19 @@
text-overflow: ellipsis;
white-space: nowrap;
}
.oathhammer .item-entry .item-group {
font-size: calc(0.86rem * 0.9);
color: #535128;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.oathhammer .item-entry .item-magic {
text-align: center;
font-size: calc(0.86rem * 0.9);
color: #8e44ad;
}
.oathhammer .item-entry .item-type {
font-size: calc(0.86rem * 0.9);
color: #084a74;
@@ -741,11 +754,11 @@
}
.oathhammer .item-list--weapon .item-list-header,
.oathhammer .item-list--weapon .item-entry {
grid-template-columns: 24px 1fr 5.5rem 3rem 1.8rem 3.5rem;
grid-template-columns: 24px 1fr 4.5rem 3.5rem 2rem 1.5rem 1.8rem 3.5rem;
}
.oathhammer .item-list--armor .item-list-header,
.oathhammer .item-list--armor .item-entry {
grid-template-columns: 24px 1fr 3.5rem 5rem 1.8rem 3.5rem;
grid-template-columns: 24px 1fr 3.5rem 2.5rem 3.5rem 1.5rem 1.8rem 3.5rem;
}
.oathhammer .item-list--ammo .item-list-header,
.oathhammer .item-list--ammo .item-entry {
@@ -771,13 +784,37 @@
.oathhammer .item-list--condition .item-entry {
grid-template-columns: 24px 1fr 5.5rem 3.5rem;
}
.oathhammer .item-list--ability .item-list-header,
.oathhammer .item-list--ability .item-entry {
grid-template-columns: 24px 1fr 6rem 3.5rem;
.oathhammer .item-list--trait .item-list-header,
.oathhammer .item-list--trait .item-entry {
grid-template-columns: 24px 1fr 6rem 6rem 3.5rem;
}
.oathhammer .item-list--oath .item-list-header,
.oathhammer .item-list--oath .item-entry {
grid-template-columns: 24px 1fr 5.5rem 3.5rem;
grid-template-columns: 24px 1fr 7rem 3.5rem 3.5rem;
}
.oathhammer .item-usage {
font-size: calc(0.86rem * 0.9);
color: #535128;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.oathhammer .item-violated {
text-align: center;
font-size: calc(0.86rem * 0.85);
}
.oathhammer .item-violated i.fa-circle-xmark {
color: #c0392b;
}
.oathhammer .item-violated i.fa-circle-check {
color: #27ae60;
}
.oathhammer .oath--violated {
background-color: rgba(192, 57, 43, 0.08);
}
.oathhammer .oath--violated .item-name {
color: #c0392b;
}
.oathhammer .no-items {
color: var(--color-dark-5);

View File

@@ -10,11 +10,12 @@
"Spell": "Oath Hammer Spell Sheet",
"Miracle": "Oath Hammer Miracle Sheet",
"MagicItem": "Oath Hammer Magic Item Sheet",
"Ability": "Oath Hammer Ability Sheet",
"Trait": "Oath Hammer Trait Sheet",
"Oath": "Oath Hammer Oath Sheet",
"Condition": "Oath Hammer Condition Sheet",
"Lineage": "Oath Hammer Lineage Sheet",
"Class": "Oath Hammer Class Sheet"
"Class": "Oath Hammer Class Sheet",
"Building": "Oath Hammer Building Sheet"
},
"Tab": {
"Identity": "Identity",
@@ -116,6 +117,22 @@
"Runic": "Runic",
"Stygian": "Stygian"
},
"BuildingSkill": {
"Carpentry": "Carpentry",
"Masonry": "Masonry"
},
"Building": {
"FIELDS": {
"skillCheck": { "label": "Skill Check" },
"cost": { "label": "Cost (gp)" },
"buildTime": { "label": "Build Time" },
"taxRevenue": { "label": "Tax Revenue / month" },
"constructed":{ "label": "Constructed" },
"settlement": { "label": "Settlement" },
"description":{ "label": "Description" },
"notes": { "label": "Notes" }
}
},
"ArmorType": {
"Light": "Light",
"Medium": "Medium",
@@ -157,9 +174,9 @@
"VeryRare": "4 Very Rare",
"Legendary": "5 Legendary"
},
"AbilityType": {
"ClassAbility": "Class Ability",
"LineageTrait": "Lineage Trait"
"TraitType": {
"SpecialTrait": "Special Trait",
"ClassTrait": "Class Trait"
},
"Condition": {
"Blinded": "Blinded",
@@ -212,7 +229,7 @@
"Level": "Level",
"XP": "Current XP",
"TotalXP": "Total XP",
"Abilities": "Abilities & Traits",
"Traits": "Special Traits",
"Oaths": "Oaths",
"Weapons": "Weapons",
"Armor": "Armor & Shields",
@@ -253,6 +270,10 @@
"Features": "Features",
"Name": "Name",
"Type": "Type",
"Usage": "Usage",
"Violated": "Violated",
"Group": "Group",
"Magic": "Magic",
"Damage": "Damage",
"Tradition": "Tradition",
"Piety": "Piety",
@@ -271,7 +292,8 @@
"Weapon": "New Weapon",
"Spell": "New Spell",
"Miracle": "New Miracle",
"Equipment": "New Equipment"
"Equipment": "New Equipment",
"Building": "New Building"
},
"ToggleSheet": "Toggle Edit/Play Mode",
"Character": {
@@ -638,9 +660,9 @@
}
}
},
"Ability": {
"Trait": {
"FIELDS": {
"abilityType": {
"traitType": {
"label": "Type"
},
"source": {
@@ -775,7 +797,7 @@
"miracle": "Miracle",
"magic_item": "Magic Item",
"magic-item": "Magic Item",
"ability": "Ability",
"trait": "Trait",
"oath": "Oath",
"lineage": "Lineage",
"class": "Class"

View File

@@ -63,6 +63,21 @@
white-space: nowrap;
}
.item-group {
font-size: @font-size-xs;
color: @color-olive;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.item-magic {
text-align: center;
font-size: @font-size-xs;
color: #8e44ad;
}
.item-type {
font-size: @font-size-xs;
color: @color-blue;
@@ -102,13 +117,13 @@
.item-list--weapon {
.item-list-header, .item-entry {
grid-template-columns: @item-img-size 1fr 5.5rem 3rem 1.8rem 3.5rem;
grid-template-columns: @item-img-size 1fr 4.5rem 3.5rem 2rem 1.5rem 1.8rem 3.5rem;
}
}
.item-list--armor {
.item-list-header, .item-entry {
grid-template-columns: @item-img-size 1fr 3.5rem 5rem 1.8rem 3.5rem;
grid-template-columns: @item-img-size 1fr 3.5rem 2.5rem 3.5rem 1.5rem 1.8rem 3.5rem;
}
}
@@ -148,18 +163,39 @@
}
}
.item-list--ability {
.item-list--trait {
.item-list-header, .item-entry {
grid-template-columns: @item-img-size 1fr 6rem 3.5rem;
grid-template-columns: @item-img-size 1fr 6rem 6rem 3.5rem;
}
}
.item-list--oath {
.item-list-header, .item-entry {
grid-template-columns: @item-img-size 1fr 5.5rem 3.5rem;
grid-template-columns: @item-img-size 1fr 7rem 3.5rem 3.5rem;
}
}
.item-usage {
font-size: @font-size-xs;
color: @color-olive;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.item-violated {
text-align: center;
font-size: @font-size-sm;
i.fa-circle-xmark { color: #c0392b; }
i.fa-circle-check { color: #27ae60; }
}
.oath--violated {
background-color: fade(#c0392b, 8%);
.item-name { color: #c0392b; }
}
.no-items {
color: var(--color-dark-5);
font-style: italic;

View File

@@ -7,7 +7,8 @@ export { default as OathHammerEquipmentSheet } from "./sheets/equipment-sheet.mj
export { default as OathHammerSpellSheet } from "./sheets/spell-sheet.mjs"
export { default as OathHammerMiracleSheet } from "./sheets/miracle-sheet.mjs"
export { default as OathHammerMagicItemSheet } from "./sheets/magic-item-sheet.mjs"
export { default as OathHammerAbilitySheet } from "./sheets/ability-sheet.mjs"
export { default as OathHammerTraitSheet } from "./sheets/trait-sheet.mjs"
export { default as OathHammerOathSheet } from "./sheets/oath-sheet.mjs"
export { default as OathHammerLineageSheet } from "./sheets/lineage-sheet.mjs"
export { default as OathHammerClassSheet } from "./sheets/class-sheet.mjs"
export { default as OathHammerBuildingSheet } from "./sheets/building-sheet.mjs"

View File

@@ -0,0 +1,28 @@
import OathHammerItemSheet from "./base-item-sheet.mjs"
export default class OathHammerBuildingSheet extends OathHammerItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["building"],
position: {
width: 640,
},
window: {
contentClasses: ["building-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-oath-hammer/templates/item/building-sheet.hbs",
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.notes ?? "", { async: true })
return context
}
}

View File

@@ -72,8 +72,26 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
break
case "identity":
context.tab = context.tabs.identity
context.abilities = doc.itemTypes.ability
context.oaths = doc.itemTypes.oath
context.traits = doc.itemTypes.trait.map(a => {
const typeKey = SYSTEM.TRAIT_TYPE_CHOICES[a.system.traitType]
const periodKey = SYSTEM.TRAIT_USAGE_PERIOD[a.system.usagePeriod]
const isPassive = a.system.usagePeriod === "none"
return {
id: a.id, uuid: a.uuid, img: a.img, name: a.name, system: a.system,
_typeLabel: typeKey ? game.i18n.localize(typeKey) : a.system.traitType,
_usageLabel: isPassive
? game.i18n.localize("OATHHAMMER.UsagePeriod.None")
: `${a.system.maxUses > 0 ? a.system.maxUses + " / " : ""}${game.i18n.localize(periodKey)}`
}
})
context.oaths = doc.itemTypes.oath.map(o => {
const typeEntry = SYSTEM.OATH_TYPES[o.system.oathType]
return {
id: o.id, uuid: o.uuid, img: o.img, name: o.name, system: o.system,
_typeLabel: typeEntry ? game.i18n.localize(typeEntry.label) : o.system.oathType,
_violated: o.system.violated
}
})
break
case "skills": {
context.tab = context.tabs.skills
@@ -116,8 +134,32 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
}
case "combat":
context.tab = context.tabs.combat
context.weapons = doc.itemTypes.weapon
context.armors = doc.itemTypes.armor
context.weapons = doc.itemTypes.weapon.map(w => {
const groupKey = SYSTEM.WEAPON_PROFICIENCY_GROUPS[w.system.proficiencyGroup]
const traitsLabel = [...w.system.traits].map(t => {
const tk = SYSTEM.WEAPON_TRAITS[t]
return tk ? game.i18n.localize(tk) : t
}).join(", ")
return {
id: w.id, uuid: w.uuid, img: w.img, name: w.name, system: w.system,
_groupLabel: groupKey ? game.i18n.localize(groupKey) : w.system.proficiencyGroup,
_traitsTooltip: traitsLabel || null,
_isMagic: w.system.isMagic
}
})
context.armors = doc.itemTypes.armor.map(a => {
const typeKey = SYSTEM.ARMOR_TYPE_CHOICES[a.system.armorType]
const traitsLabel = [...a.system.traits].map(t => {
const tk = SYSTEM.ARMOR_TRAITS[t]
return tk ? game.i18n.localize(tk) : t
}).join(", ")
return {
id: a.id, uuid: a.uuid, img: a.img, name: a.name, system: a.system,
_typeLabel: typeKey ? game.i18n.localize(typeKey) : a.system.armorType,
_traitsTooltip: traitsLabel || null,
_isMagic: a.system.isMagic
}
})
context.ammunition = doc.itemTypes.ammunition
break
case "magic":

View File

@@ -1,21 +1,21 @@
import OathHammerItemSheet from "./base-item-sheet.mjs"
export default class OathHammerAbilitySheet extends OathHammerItemSheet {
export default class OathHammerTraitSheet extends OathHammerItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["ability"],
classes: ["trait"],
position: {
width: 620,
},
window: {
contentClasses: ["ability-content"],
contentClasses: ["trait-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-oath-hammer/templates/item/ability-sheet.hbs",
template: "systems/fvtt-oath-hammer/templates/item/trait-sheet.hbs",
},
}

View File

@@ -172,14 +172,14 @@ export const RARITY_CHOICES = {
legendary: "OATHHAMMER.Rarity.Legendary"
}
// Two types of ability: class traits and lineage traits. No feats in Oath Hammer.
export const ABILITY_TYPE_CHOICES = {
"class-ability": "OATHHAMMER.AbilityType.ClassAbility",
"lineage-trait": "OATHHAMMER.AbilityType.LineageTrait"
// Two types of trait per the rulebook terminology
export const TRAIT_TYPE_CHOICES = {
"special-trait": "OATHHAMMER.TraitType.SpecialTrait",
"class-trait": "OATHHAMMER.TraitType.ClassTrait"
}
// When an ability's uses reset (none = passive/always on)
export const ABILITY_USAGE_PERIOD = {
// When a trait's uses reset (none = passive/always on)
export const TRAIT_USAGE_PERIOD = {
none: "OATHHAMMER.UsagePeriod.None",
encounter: "OATHHAMMER.UsagePeriod.Encounter",
day: "OATHHAMMER.UsagePeriod.Day"
@@ -331,6 +331,11 @@ export const ASCII = `
·················································
`
export const BUILDING_SKILL_CHOICES = {
carpentry: "OATHHAMMER.BuildingSkill.Carpentry",
masonry: "OATHHAMMER.BuildingSkill.Masonry"
}
export const SYSTEM = {
id: SYSTEM_ID,
ATTRIBUTES,
@@ -353,8 +358,9 @@ export const SYSTEM = {
MAGIC_ITEM_TYPE_CHOICES,
MAGIC_QUALITY_CHOICES,
RARITY_CHOICES,
ABILITY_TYPE_CHOICES,
ABILITY_USAGE_PERIOD,
TRAIT_TYPE_CHOICES,
TRAIT_USAGE_PERIOD,
BUILDING_SKILL_CHOICES,
STATUS_EFFECTS,
ATTRIBUTE_RANK_CHOICES,
ASCII

View File

@@ -6,7 +6,7 @@ const defaultItemImg = {
spell: "systems/fvtt-oath-hammer/assets/icons/icon_spell.webp",
miracle: "systems/fvtt-oath-hammer/assets/icons/icon_miracle.webp",
"magic-item": "systems/fvtt-oath-hammer/assets/icons/icon_magic_item.webp",
ability: "systems/fvtt-oath-hammer/assets/icons/icon_ability.webp",
trait: "systems/fvtt-oath-hammer/assets/icons/icon_ability.webp",
oath: "systems/fvtt-oath-hammer/assets/icons/icon_oath.webp"
}

View File

@@ -7,7 +7,8 @@ export { default as OathHammerEquipment } from "./equipment.mjs"
export { default as OathHammerSpell } from "./spell.mjs"
export { default as OathHammerMiracle } from "./miracle.mjs"
export { default as OathHammerMagicItem } from "./magic-item.mjs"
export { default as OathHammerAbility } from "./ability.mjs"
export { default as OathHammerTrait } from "./trait.mjs"
export { default as OathHammerOath } from "./oath.mjs"
export { default as OathHammerLineage } from "./lineage.mjs"
export { default as OathHammerClass } from "./class.mjs"
export { default as OathHammerBuilding } from "./building.mjs"

View File

@@ -1,33 +0,0 @@
import { SYSTEM } from "../config/system.mjs"
export default class OathHammerAbility extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
// lineage-trait (racial) or class-ability (starting or advancement trait)
schema.abilityType = new fields.StringField({
required: true, initial: "class-ability", choices: SYSTEM.ABILITY_TYPE_CHOICES
})
// Which class or lineage this trait belongs to (e.g. "Berserker", "Wood Elf")
schema.source = new fields.StringField({ required: true, nullable: false, initial: "" })
// When uses reset: none = passive (always on), encounter, day
schema.usagePeriod = new fields.StringField({
required: true, initial: "none", choices: SYSTEM.ABILITY_USAGE_PERIOD
})
// Maximum uses per period. 0 = passive / unlimited.
// Use a descriptive string when the limit is formula-based
// (e.g. "equal to Fate ranks") — store the note in the description.
schema.maxUses = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
return schema
}
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Ability"]
}

View File

@@ -0,0 +1,44 @@
import { SYSTEM } from "../config/system.mjs"
export default class OathHammerBuilding extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
// Narrative description and special effects
schema.description = new fields.HTMLField({ required: true, textSearch: true })
// Skill required to build (Carpentry or Masonry)
schema.skillCheck = new fields.StringField({
required: true, initial: "carpentry", choices: SYSTEM.BUILDING_SKILL_CHOICES
})
// Cost in gold pieces (after skill check SV negotiation)
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
// Construction duration (free text: "3 weeks", "6 months", etc.)
schema.buildTime = new fields.StringField({ required: true, nullable: false, initial: "" })
// Monthly tax revenue formula ("3d6", "2d6", "1d3", "" = none)
schema.taxRevenue = new fields.StringField({ required: true, nullable: false, initial: "" })
// Is this building currently constructed in the settlement?
schema.constructed = new fields.BooleanField({ required: true, initial: false })
// Which settlement this building belongs to (free text or settlement name)
schema.settlement = new fields.StringField({ required: true, nullable: false, initial: "" })
// Additional GM notes (special conditions, upgrades, damage, etc.)
schema.notes = new fields.HTMLField({ required: false, textSearch: true })
return schema
}
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Building"]
/** Returns true if this building generates tax income */
get hasTaxRevenue() {
return this.taxRevenue.trim().length > 0
}
}

View File

@@ -31,7 +31,7 @@ export default class OathHammerMagicItem extends foundry.abstract.TypeDataModel
// Limited-use items (e.g. "once per day"); none = always active
schema.usagePeriod = new fields.StringField({
required: true, initial: "none", choices: SYSTEM.ABILITY_USAGE_PERIOD
required: true, initial: "none", choices: SYSTEM.TRAIT_USAGE_PERIOD
})
schema.maxUses = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })

43
module/models/trait.mjs Normal file
View File

@@ -0,0 +1,43 @@
import { SYSTEM } from "../config/system.mjs"
export default class OathHammerTrait extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
// class-trait (class-exclusive, acquirable) or special-trait (starting class trait)
schema.traitType = new fields.StringField({
required: true, initial: "special-trait", choices: SYSTEM.TRAIT_TYPE_CHOICES
})
// Which class or lineage this trait belongs to (e.g. "Berserker", "Wood Elf")
schema.source = new fields.StringField({ required: true, nullable: false, initial: "" })
// When uses reset: none = passive (always on), encounter, day
schema.usagePeriod = new fields.StringField({
required: true, initial: "none", choices: SYSTEM.TRAIT_USAGE_PERIOD
})
// Maximum uses per period. 0 = passive / unlimited.
schema.maxUses = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
return schema
}
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Trait"]
static migrateData(source) {
// Migrate old abilityType field → traitType
if (source.abilityType !== undefined && source.traitType === undefined) {
const map = { "class-ability": "class-trait", "lineage-trait": "special-trait" }
source.traitType = map[source.abilityType] ?? "special-trait"
}
// Migrate old traitType values
if (source.traitType === "lineage-trait") source.traitType = "special-trait"
if (source.traitType === "class-ability") source.traitType = "class-trait"
return super.migrateData(source)
}
}

View File

@@ -30,10 +30,11 @@ Hooks.once("init", function () {
spell: models.OathHammerSpell,
miracle: models.OathHammerMiracle,
"magic-item": models.OathHammerMagicItem,
ability: models.OathHammerAbility,
trait: models.OathHammerTrait,
oath: models.OathHammerOath,
lineage: models.OathHammerLineage,
"class": models.OathHammerClass
"class": models.OathHammerClass,
building: models.OathHammerBuilding
}
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet)
@@ -56,10 +57,11 @@ Hooks.once("init", function () {
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerSpellSheet, { types: ["spell"], makeDefault: true, label: "OATHHAMMER.Sheet.Spell" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerMiracleSheet, { types: ["miracle"], makeDefault: true, label: "OATHHAMMER.Sheet.Miracle" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerMagicItemSheet, { types: ["magic-item"], makeDefault: true, label: "OATHHAMMER.Sheet.MagicItem" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerAbilitySheet, { types: ["ability"], makeDefault: true, label: "OATHHAMMER.Sheet.Ability" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerTraitSheet, { types: ["trait"], makeDefault: true, label: "OATHHAMMER.Sheet.Trait" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerOathSheet, { types: ["oath"], makeDefault: true, label: "OATHHAMMER.Sheet.Oath" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerLineageSheet, { types: ["lineage"], makeDefault: true, label: "OATHHAMMER.Sheet.Lineage" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerClassSheet, { types: ["class"], makeDefault: true, label: "OATHHAMMER.Sheet.Class" })
foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerBuildingSheet, { types: ["building"], makeDefault: true, label: "OATHHAMMER.Sheet.Building" })
CONFIG.statusEffects = STATUS_EFFECTS

View File

@@ -73,7 +73,7 @@
"effect"
]
},
"ability": {
"trait": {
"htmlFields": [
"description"
]
@@ -96,6 +96,12 @@
"description",
"features"
]
},
"building": {
"htmlFields": [
"description",
"notes"
]
}
}
},
@@ -105,7 +111,7 @@
},
"primaryTokenAttribute": "grit",
"socket": true,
"background": "systems/fvtt-oath-hammer/assets/ui/oath_hammer_paper.webp",
"background": "systems/fvtt-oath-hammer/assets/images/cover_art.webp",
"flags": {
"hotReload": {
"extensions": [

View File

@@ -25,17 +25,21 @@
<li class="item-list-header">
<span></span>
<span class="col-name">{{localize "OATHHAMMER.Label.Name"}}</span>
<span>{{localize "OATHHAMMER.Label.Group"}}</span>
<span>{{localize "OATHHAMMER.Label.Damage"}}</span>
<span>AP</span>
<span title="Armor Penetration">AP</span>
<span title="{{localize "OATHHAMMER.Label.Magic"}}"><i class="fa-solid fa-wand-sparkles"></i></span>
<span title="{{localize "OATHHAMMER.Label.Equipped"}}"><i class="fa-solid fa-shield-halved"></i></span>
<span></span>
</li>
{{#each weapons as |weapon|}}
<li class="item-entry" data-item-id="{{weapon.id}}" data-item-uuid="{{weapon.uuid}}">
<img src="{{weapon.img}}" class="item-img" />
<span class="item-name">{{weapon.name}}</span>
<span class="item-name" {{#if weapon._traitsTooltip}}title="{{weapon._traitsTooltip}}"{{/if}}>{{weapon.name}}</span>
<span class="item-group">{{weapon._groupLabel}}</span>
<span class="item-detail">{{weapon.system.damageLabel}}</span>
<span class="item-detail">{{weapon.system.ap}}</span>
<span class="item-detail">{{#if weapon.system.ap}}{{weapon.system.ap}}{{else}}{{/if}}</span>
<span class="item-magic">{{#if weapon._isMagic}}<i class="fa-solid fa-wand-sparkles"></i>{{/if}}</span>
<div class="item-equipped">
<input type="checkbox" class="item-equipped-cb" data-item-id="{{weapon.id}}" {{checked weapon.system.equipped}} {{#if ../isPlayMode}}disabled{{/if}}>
</div>
@@ -60,17 +64,21 @@
<li class="item-list-header">
<span></span>
<span class="col-name">{{localize "OATHHAMMER.Label.Name"}}</span>
<span>{{localize "OATHHAMMER.Label.Type"}}</span>
<span>AV</span>
<span>{{localize "OATHHAMMER.Label.Penalty"}}</span>
<span title="{{localize "OATHHAMMER.Label.Magic"}}"><i class="fa-solid fa-wand-sparkles"></i></span>
<span title="{{localize "OATHHAMMER.Label.Equipped"}}"><i class="fa-solid fa-shield-halved"></i></span>
<span></span>
</li>
{{#each armors as |armor|}}
<li class="item-entry" data-item-id="{{armor.id}}" data-item-uuid="{{armor.uuid}}">
<img src="{{armor.img}}" class="item-img" />
<span class="item-name">{{armor.name}}</span>
<span class="item-name" {{#if armor._traitsTooltip}}title="{{armor._traitsTooltip}}"{{/if}}>{{armor.name}}</span>
<span class="item-type">{{armor._typeLabel}}</span>
<span class="item-detail">{{armor.system.armorValue}}</span>
<span class="item-detail">{{#if armor.system.penalty}}{{armor.system.penalty}}{{else}}{{/if}}</span>
<span class="item-magic">{{#if armor._isMagic}}<i class="fa-solid fa-wand-sparkles"></i>{{/if}}</span>
<div class="item-equipped">
<input type="checkbox" class="item-equipped-cb" data-item-id="{{armor.id}}" {{checked armor.system.equipped}} {{#if ../isPlayMode}}disabled{{/if}}>
</div>

View File

@@ -3,25 +3,27 @@
<legend>{{localize "OATHHAMMER.Label.Background"}}</legend>
{{formInput systemFields.background enriched=enrichedBackground value=system.background name="system.background" toggled=true}}
</fieldset>
{{#if abilities.length}}
{{#if traits.length}}
<fieldset>
<legend>{{localize "OATHHAMMER.Label.Abilities"}}</legend>
<ul class="item-list item-list--ability">
<legend>{{localize "OATHHAMMER.Label.Traits"}}</legend>
<ul class="item-list item-list--trait">
<li class="item-list-header">
<span></span>
<span class="col-name">{{localize "OATHHAMMER.Label.Name"}}</span>
<span>{{localize "OATHHAMMER.Label.Type"}}</span>
<span>{{localize "OATHHAMMER.Label.Usage"}}</span>
<span></span>
</li>
{{#each abilities as |ability|}}
<li class="item-entry" data-item-id="{{ability.id}}" data-item-uuid="{{ability.uuid}}">
<img src="{{ability.img}}" class="item-img" />
<span class="item-name">{{ability.name}}</span>
<span class="item-type">{{localize ability.system.abilityType}}</span>
{{#each traits as |trait|}}
<li class="item-entry" data-item-id="{{trait.id}}" data-item-uuid="{{trait.uuid}}">
<img src="{{trait.img}}" class="item-img" />
<span class="item-name">{{trait.name}}</span>
<span class="item-type">{{trait._typeLabel}}</span>
<span class="item-usage">{{trait._usageLabel}}</span>
<div class="item-actions">
{{#unless ../isPlayMode}}
<a data-action="edit" data-item-id="{{ability.id}}" data-item-uuid="{{ability.uuid}}"><i class="fa-solid fa-edit"></i></a>
<a data-action="delete" data-item-id="{{ability.id}}" data-item-uuid="{{ability.uuid}}"><i class="fa-solid fa-trash"></i></a>
<a data-action="edit" data-item-id="{{trait.id}}" data-item-uuid="{{trait.uuid}}"><i class="fa-solid fa-edit"></i></a>
<a data-action="delete" data-item-id="{{trait.id}}" data-item-uuid="{{trait.uuid}}"><i class="fa-solid fa-trash"></i></a>
{{/unless}}
</div>
</li>
@@ -37,13 +39,15 @@
<span></span>
<span class="col-name">{{localize "OATHHAMMER.Label.Name"}}</span>
<span>{{localize "OATHHAMMER.Label.Type"}}</span>
<span>{{localize "OATHHAMMER.Label.Violated"}}</span>
<span></span>
</li>
{{#each oaths as |oath|}}
<li class="item-entry" data-item-id="{{oath.id}}" data-item-uuid="{{oath.uuid}}">
<li class="item-entry {{#if oath._violated}}oath--violated{{/if}}" data-item-id="{{oath.id}}" data-item-uuid="{{oath.uuid}}">
<img src="{{oath.img}}" class="item-img" />
<span class="item-name">{{oath.name}}</span>
<span class="item-type">{{localize oath.system.oathType}}</span>
<span class="item-type">{{oath._typeLabel}}</span>
<span class="item-violated">{{#if oath._violated}}<i class="fa-solid fa-circle-xmark"></i>{{else}}<i class="fa-regular fa-circle-check"></i>{{/if}}</span>
<div class="item-actions">
{{#unless ../isPlayMode}}
<a data-action="edit" data-item-id="{{oath.id}}" data-item-uuid="{{oath.uuid}}"><i class="fa-solid fa-edit"></i></a>

View File

@@ -0,0 +1,32 @@
<section class="item-sheet-common">
<div class="header">
<img class="item-img" src="{{item.img}}" data-edit="img" data-action="editImage" data-tooltip="{{item.name}}" />
{{formInput fields.name value=source.name}}
</div>
<div class="building-meta flexrow">
<div class="building-col">
{{formField systemFields.skillCheck value=system.skillCheck name="system.skillCheck" localize=true}}
{{formField systemFields.cost value=system.cost name="system.cost"}}
{{formField systemFields.buildTime value=system.buildTime name="system.buildTime"}}
{{formField systemFields.settlement value=system.settlement name="system.settlement"}}
</div>
<div class="building-col">
{{formField systemFields.taxRevenue value=system.taxRevenue name="system.taxRevenue"}}
<div class="form-group building-constructed">
<label>{{localize "OATHHAMMER.Building.FIELDS.constructed.label"}}</label>
{{formInput systemFields.constructed value=system.constructed name="system.constructed"}}
</div>
</div>
</div>
<fieldset>
<legend>{{localize "OATHHAMMER.Label.Description"}}</legend>
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
</fieldset>
<fieldset>
<legend>{{localize "OATHHAMMER.Label.Notes"}}</legend>
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
</fieldset>
</section>

View File

@@ -5,7 +5,7 @@
</div>
<div class="flexrow">
<div class="align-top">
{{formField systemFields.abilityType value=system.abilityType name="system.abilityType" localize=true}}
{{formField systemFields.traitType value=system.traitType name="system.traitType" localize=true}}
{{formField systemFields.source value=system.source name="system.source"}}
{{formField systemFields.usagePeriod value=system.usagePeriod name="system.usagePeriod" localize=true}}
{{#unless (eq system.usagePeriod "none")}}