Fix weapon sheet

This commit is contained in:
2026-03-08 14:48:49 +01:00
parent 317c4990bc
commit 31318317a7
14 changed files with 135 additions and 61 deletions

View File

@@ -10,7 +10,7 @@
--oh-font-primary: "Sherwood", "Palatino Linotype", serif;
--oh-font-secondary: "BlueDragon", "Palatino Linotype", serif;
--oh-font-body: "Calibri", "Segoe UI", sans-serif;
--oh-font-size: 0.82rem;
--oh-font-size: 0.86rem;
--oh-color-blue: #084a74;
--oh-color-olive: #535128;
--oh-color-gold: #c8a84b;
@@ -21,7 +21,7 @@
}
.application.dialog.oathhammer {
font-family: "Calibri", "Segoe UI", sans-serif;
font-size: 0.82rem;
font-size: 0.86rem;
background-image: var(--oh-background-image);
background-repeat: no-repeat;
background-size: 100% 100%;
@@ -29,7 +29,7 @@
.oathhammer .character-content,
.oathhammer .npc-content {
font-family: "Calibri", "Segoe UI", sans-serif;
font-size: 0.82rem;
font-size: 0.86rem;
color: var(--color-dark-1);
background-image: var(--oh-background-image);
background-repeat: no-repeat;
@@ -66,7 +66,7 @@
.oathhammer .npc-content input[name="name"] {
height: 2.5rem;
font-family: "Sherwood", "Palatino Linotype", serif;
font-size: calc(0.82rem * 1.2);
font-size: calc(0.86rem * 1.2);
font-weight: bold;
border: none;
border-bottom: 2px solid #084a74;
@@ -81,7 +81,7 @@
.oathhammer .character-content legend,
.oathhammer .npc-content legend {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 1.1);
font-size: calc(0.86rem * 1.1);
font-weight: bold;
letter-spacing: 1px;
color: #084a74;
@@ -89,7 +89,7 @@
.oathhammer .character-content label,
.oathhammer .npc-content label {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: 0.82rem;
font-size: 0.86rem;
color: #2a1a0a;
}
.oathhammer .tab {
@@ -105,7 +105,7 @@
}
.oathhammer .skills-container .skills-group legend .attr-rank {
font-family: "Calibri", "Segoe UI", sans-serif;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
color: #535128;
}
.oathhammer .skills-container .skills-header,
@@ -117,7 +117,7 @@
}
.oathhammer .skills-container .skills-header {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
font-weight: bold;
color: #084a74;
border-bottom: 1px solid #535128;
@@ -134,13 +134,13 @@
margin-bottom: 2px;
}
.oathhammer .skills-container .skill-row label.skill-name-col {
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
}
.oathhammer .skills-container .skill-row .skill-rank-col select,
.oathhammer .skills-container .skill-row .skill-modifier-col input {
width: 100%;
text-align: center;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
padding: 1px 2px;
}
.oathhammer .skills-container .skill-row .skill-color-col {
@@ -167,14 +167,14 @@
}
.oathhammer .skills-container .skill-row .skill-color-col .color-dice-select {
flex: 1;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
padding: 1px 1px;
min-width: 0;
}
.oathhammer .skills-container .skill-row .skill-color-col input[type="number"] {
width: 2.2rem;
text-align: center;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
padding: 1px 2px;
flex-shrink: 0;
}
@@ -228,7 +228,7 @@
.oathhammer .character-main .character-name input {
flex: 1;
font-family: "Sherwood", "Palatino Linotype", serif;
font-size: calc(0.82rem * 1.1);
font-size: calc(0.86rem * 1.1);
}
.oathhammer .character-main .character-identity-bar {
display: flex;
@@ -245,7 +245,7 @@
border: 1px solid #535128;
border-radius: 3px;
background: rgba(0, 0, 0, 0.15);
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
min-width: 6rem;
min-height: 1.6rem;
}
@@ -265,17 +265,17 @@
.oathhammer .character-main .character-identity-bar .identity-slot .identity-name {
flex: 1;
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
}
.oathhammer .character-main .character-identity-bar .identity-slot .slot-icon {
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
opacity: 0.6;
}
.oathhammer .character-main .character-identity-bar .identity-slot .slot-placeholder {
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
}
.oathhammer .character-main .character-identity-bar .identity-slot a {
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
opacity: 0.7;
}
.oathhammer .character-main .character-identity-bar .identity-slot a:hover {
@@ -286,11 +286,11 @@
align-items: center;
gap: 3px;
margin-left: auto;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
}
.oathhammer .character-main .character-identity-bar .identity-xp .xp-label {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
color: #535128;
margin-left: 4px;
}
@@ -300,7 +300,7 @@
.oathhammer .character-main .character-identity-bar .identity-xp input {
width: 3rem;
text-align: center;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
padding: 1px 2px;
}
.oathhammer .character-main .character-stats-band {
@@ -332,18 +332,18 @@
.oathhammer .character-main .character-stats-band .character-resources .character-resource input {
width: 2.4rem;
text-align: center;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
padding: 1px 2px;
}
.oathhammer .character-main .character-stats-band .character-resources .character-resource .res-sep {
opacity: 0.5;
font-size: calc(0.82rem * 0.9);
font-size: calc(0.86rem * 0.9);
}
.oathhammer .character-main .character-stats-band .character-resources .resource-label {
min-width: 3.8rem;
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 0.9);
color: #535128;
font-size: calc(0.86rem * 0.9);
color: #2a1a0a;
}
.oathhammer .character-main .character-stats-band .character-attributes {
flex: 1;
@@ -365,13 +365,14 @@
}
.oathhammer .attribute-box label {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
color: #2a1a0a;
text-align: center;
}
.oathhammer .attribute-box input {
width: 2.5rem;
text-align: center;
font-size: calc(0.82rem * 1.1);
font-size: calc(0.86rem * 1.1);
}
.oathhammer .currency-bar {
margin-top: 4px;
@@ -492,7 +493,7 @@
border-bottom: 1px solid #535128;
margin-bottom: 2px;
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 0.9);
font-size: calc(0.86rem * 0.9);
color: #084a74;
}
.oathhammer .item-list-header span {
@@ -524,14 +525,14 @@
}
.oathhammer .item-entry .item-name {
font-family: "Calibri", "Segoe UI", sans-serif;
font-size: 0.82rem;
font-size: 0.86rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}
.oathhammer .item-entry .item-detail {
font-size: calc(0.82rem * 0.9);
font-size: calc(0.86rem * 0.9);
color: #535128;
text-align: center;
overflow: hidden;
@@ -539,7 +540,7 @@
white-space: nowrap;
}
.oathhammer .item-entry .item-type {
font-size: calc(0.82rem * 0.9);
font-size: calc(0.86rem * 0.9);
color: #084a74;
text-align: center;
overflow: hidden;
@@ -566,7 +567,7 @@
.oathhammer .item-entry .item-actions a {
opacity: 0.6;
transition: opacity 0.2s;
font-size: calc(0.82rem * 0.85);
font-size: calc(0.86rem * 0.85);
}
.oathhammer .item-entry .item-actions a:hover {
opacity: 1;
@@ -617,7 +618,7 @@
.oathhammer .no-items {
color: var(--color-dark-5);
font-style: italic;
font-size: calc(0.82rem * 0.9);
font-size: calc(0.86rem * 0.9);
padding: 4px;
}
.oathhammer .create-btn {
@@ -633,7 +634,7 @@
overflow: auto;
padding: 10px 20px;
font-family: "Calibri", "Segoe UI", sans-serif;
font-size: 0.82rem;
font-size: 0.86rem;
background-image: var(--oh-background-image);
background-repeat: no-repeat;
background-size: 100% 100%;
@@ -674,7 +675,7 @@
.oathhammer .item-sheet-common input[name="name"] {
height: 2.5rem;
font-family: "Sherwood", "Palatino Linotype", serif;
font-size: calc(0.82rem * 1.2);
font-size: calc(0.86rem * 1.2);
font-weight: bold;
border: none;
border-bottom: 2px solid #084a74;
@@ -682,7 +683,7 @@
}
.oathhammer .item-sheet-common label {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: 0.82rem;
font-size: 0.86rem;
color: #2a1a0a;
}
.oathhammer .item-sheet-common .form-group {
@@ -695,7 +696,7 @@
.oathhammer .item-sheet-common .form-group > label {
flex: 0 0 8rem;
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: 0.82rem;
font-size: 0.86rem;
color: #2a1a0a;
}
.oathhammer .item-sheet-common .form-group .form-fields {
@@ -723,7 +724,7 @@
}
.oathhammer .item-sheet-common legend {
font-family: "BlueDragon", "Palatino Linotype", serif;
font-size: calc(0.82rem * 1.1);
font-size: calc(0.86rem * 1.1);
font-weight: bold;
color: #084a74;
}

View File

@@ -150,11 +150,12 @@
"Trinket": "Trinket"
},
"Rarity": {
"Common": "Common",
"Uncommon": "Uncommon",
"Rare": "Rare",
"VeryRare": "Very Rare",
"Legendary": "Legendary"
"Always": "Always",
"Common": "1 Common",
"Uncommon": "2 Uncommon",
"Rare": "3 Rare",
"VeryRare": "4 Very Rare",
"Legendary": "5 Legendary"
},
"AbilityType": {
"ClassAbility": "Class Ability",

View File

@@ -172,7 +172,7 @@
min-width: 3.8rem;
font-family: @font-secondary;
font-size: @font-size-xs;
color: @color-olive;
color: @color-dark;
}
}
@@ -205,6 +205,7 @@
label {
font-family: @font-secondary;
font-size: @font-size-sm;
color: @color-dark;
text-align: center;
}

View File

@@ -6,7 +6,7 @@
@font-primary: "Sherwood", "Palatino Linotype", serif;
@font-secondary: "BlueDragon", "Palatino Linotype", serif;
@font-body: "Calibri", "Segoe UI", sans-serif;
@font-size-base: 0.82rem;
@font-size-base: 0.86rem;
// Colors — from design_rules.md (CMYK converted to RGB)
// Blue: CMYK(94, 42, 9, 50) → rgb(8, 74, 116)

View File

@@ -54,6 +54,20 @@ export default class OathHammerItemSheet extends HandlebarsApplicationMixin(foun
if (this.document.system.description !== undefined) {
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? "", { async: true })
}
// Armor-specific numeric selects
context.armorValueChoices = Object.fromEntries(
Array.from({ length: 13 }, (_, i) => [i, String(i)])
)
context.penaltyChoices = Object.fromEntries(
Array.from({ length: 6 }, (_, i) => [-i, String(-i)])
)
// Weapon-specific numeric selects
context.damageModChoices = Object.fromEntries(
Array.from({ length: 10 }, (_, i) => [i - 4, i - 4 >= 0 ? `+${i - 4}` : String(i - 4)])
)
context.apChoices = Object.fromEntries(
Array.from({ length: 7 }, (_, i) => [i, String(i)])
)
return context
}

View File

@@ -164,6 +164,7 @@ export const MAGIC_QUALITY_CHOICES = {
}
export const RARITY_CHOICES = {
always: "OATHHAMMER.Rarity.Always",
common: "OATHHAMMER.Rarity.Common",
uncommon: "OATHHAMMER.Rarity.Uncommon",
rare: "OATHHAMMER.Rarity.Rare",

View File

@@ -17,8 +17,7 @@ export default class OathHammerAmmunition extends foundry.abstract.TypeDataModel
// Quantity of individual arrows/bolts in this stack
schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 20, min: 0 })
// Rarity: DV for Fortune check when purchasing; 0 = always available
schema.rarity = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 6 })
schema.rarity = new fields.StringField({ required: true, initial: "common", choices: SYSTEM.RARITY_CHOICES })
schema.cost = new fields.NumberField({ required: true, nullable: false, initial: 0, min: 0 })
schema.currency = new fields.StringField({ required: true, initial: "sp", choices: SYSTEM.CURRENCY_CHOICES })
@@ -26,5 +25,13 @@ export default class OathHammerAmmunition extends foundry.abstract.TypeDataModel
return schema
}
static migrateData(source) {
if (typeof source.rarity === "number") {
const map = { 0: "common", 1: "uncommon", 2: "rare", 3: "very-rare", 4: "legendary", 5: "legendary", 6: "legendary" }
source.rarity = map[source.rarity] ?? "common"
}
return super.migrateData(source)
}
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Ammunition"]
}

View File

@@ -25,8 +25,7 @@ export default class OathHammerArmor extends foundry.abstract.TypeDataModel {
new fields.StringField({ choices: SYSTEM.ARMOR_TRAITS })
)
// Rarity: DV for Fortune check when purchasing; 0 = always available
schema.rarity = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 6 })
schema.rarity = new fields.StringField({ required: true, initial: "common", choices: SYSTEM.RARITY_CHOICES })
schema.equipped = new fields.BooleanField({ initial: false })
schema.cost = new fields.NumberField({ required: true, nullable: false, initial: 0, min: 0 })
@@ -45,5 +44,13 @@ export default class OathHammerArmor extends foundry.abstract.TypeDataModel {
return schema
}
static migrateData(source) {
if (typeof source.rarity === "number") {
const map = { 0: "common", 1: "uncommon", 2: "rare", 3: "very-rare", 4: "legendary", 5: "legendary", 6: "legendary" }
source.rarity = map[source.rarity] ?? "common"
}
return super.migrateData(source)
}
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Armor"]
}

View File

@@ -16,8 +16,7 @@ export default class OathHammerEquipment extends foundry.abstract.TypeDataModel
// Item slots occupied when carried. 0 = small item (no slots).
schema.slots = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
// Rarity: DV for Fortune check when purchasing; 0 = always available
schema.rarity = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 6 })
schema.rarity = new fields.StringField({ required: true, initial: "common", choices: SYSTEM.RARITY_CHOICES })
// Light radius in feet — only relevant for light-source items (Candle/Lamp/Lantern/Torch)
schema.lightRadius = new fields.NumberField({ required: false, nullable: true, initial: null, min: 0 })
@@ -28,5 +27,13 @@ export default class OathHammerEquipment extends foundry.abstract.TypeDataModel
return schema
}
static migrateData(source) {
if (typeof source.rarity === "number") {
const map = { 0: "common", 1: "uncommon", 2: "rare", 3: "very-rare", 4: "legendary", 5: "legendary", 6: "legendary" }
source.rarity = map[source.rarity] ?? "common"
}
return super.migrateData(source)
}
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Equipment"]
}

View File

@@ -38,8 +38,7 @@ export default class OathHammerWeapon extends foundry.abstract.TypeDataModel {
// Item slots (when stowed; 0 = does not occupy slots)
schema.slots = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
// Rarity (DV for Fortune check to find item for sale)
schema.rarity = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 5 })
schema.rarity = new fields.StringField({ required: true, initial: "common", choices: SYSTEM.RARITY_CHOICES })
schema.equipped = new fields.BooleanField({ required: true, initial: false })
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
@@ -61,6 +60,14 @@ export default class OathHammerWeapon extends foundry.abstract.TypeDataModel {
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Weapon"]
static migrateData(source) {
if (typeof source.rarity === "number") {
const map = { 0: "common", 1: "uncommon", 2: "rare", 3: "very-rare", 4: "legendary", 5: "legendary", 6: "legendary" }
source.rarity = map[source.rarity] ?? "common"
}
return super.migrateData(source)
}
/**
* Human-readable damage formula for display, e.g. "M+2", "M-1", "6"
*/

View File

@@ -7,7 +7,7 @@
<div class="align-top">
{{formField systemFields.ammoType value=system.ammoType name="system.ammoType" localize=true}}
{{formField systemFields.quantity value=system.quantity name="system.quantity"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity" localize=true}}
</div>
<div class="align-top">
{{formField systemFields.cost value=system.cost name="system.cost"}}

View File

@@ -6,13 +6,27 @@
<div class="flexrow">
<div class="align-top">
{{formField systemFields.armorType value=system.armorType name="system.armorType" localize=true}}
{{formField systemFields.armorValue value=system.armorValue name="system.armorValue"}}
{{formField systemFields.penalty value=system.penalty name="system.penalty"}}
<div class="form-group">
<label>{{localize "OATHHAMMER.Armor.FIELDS.armorValue.label"}}</label>
<div class="form-fields">
<select name="system.armorValue">
{{selectOptions armorValueChoices selected=system.armorValue}}
</select>
</div>
</div>
<div class="form-group">
<label>{{localize "OATHHAMMER.Armor.FIELDS.penalty.label"}}</label>
<div class="form-fields">
<select name="system.penalty">
{{selectOptions penaltyChoices selected=system.penalty}}
</select>
</div>
</div>
{{formField systemFields.slots value=system.slots name="system.slots"}}
{{formField systemFields.traits value=system.traits name="system.traits" localize=true}}
</div>
<div class="align-top">
{{formField systemFields.rarity value=system.rarity name="system.rarity"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity" localize=true}}
{{formField systemFields.isMagic value=system.isMagic name="system.isMagic"}}
{{formField systemFields.equipped value=system.equipped name="system.equipped"}}
{{formField systemFields.cost value=system.cost name="system.cost"}}

View File

@@ -8,7 +8,7 @@
{{formField systemFields.itemType value=system.itemType name="system.itemType" localize=true}}
{{formField systemFields.quantity value=system.quantity name="system.quantity"}}
{{formField systemFields.slots value=system.slots name="system.slots"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity" localize=true}}
{{#if system.lightRadius}}
{{formField systemFields.lightRadius value=system.lightRadius name="system.lightRadius"}}
{{/if}}

View File

@@ -7,8 +7,22 @@
<div class="align-top">
{{formField systemFields.proficiencyGroup value=system.proficiencyGroup name="system.proficiencyGroup" localize=true}}
{{formField systemFields.usesMight value=system.usesMight name="system.usesMight"}}
{{formField systemFields.damageMod value=system.damageMod name="system.damageMod"}}
{{formField systemFields.ap value=system.ap name="system.ap"}}
<div class="form-group">
<label>{{localize "OATHHAMMER.Weapon.FIELDS.damageMod.label"}}</label>
<div class="form-fields">
<select name="system.damageMod">
{{selectOptions damageModChoices selected=system.damageMod}}
</select>
</div>
</div>
<div class="form-group">
<label>{{localize "OATHHAMMER.Weapon.FIELDS.ap.label"}}</label>
<div class="form-fields">
<select name="system.ap">
{{selectOptions apChoices selected=system.ap}}
</select>
</div>
</div>
{{formField systemFields.reach value=system.reach name="system.reach"}}
{{formField systemFields.shortRange value=system.shortRange name="system.shortRange"}}
{{formField systemFields.longRange value=system.longRange name="system.longRange"}}
@@ -16,7 +30,7 @@
<div class="align-top">
{{formField systemFields.traits value=system.traits name="system.traits" localize=true}}
{{formField systemFields.slots value=system.slots name="system.slots"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity"}}
{{formField systemFields.rarity value=system.rarity name="system.rarity" localize=true}}
{{formField systemFields.isMagic value=system.isMagic name="system.isMagic"}}
{{formField systemFields.equipped value=system.equipped name="system.equipped"}}
{{formField systemFields.cost value=system.cost name="system.cost"}}