From e75824cd20b1ef86268a4d022aaf702fe4a74e92 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Sat, 20 Dec 2025 17:20:01 +0100 Subject: [PATCH] First PC sheet, WIP --- css/fvtt-prism-rpg.css | 242 +++++++++----- lang/en.json | 6 +- .../applications/sheets/character-sheet.mjs | 73 +---- module/applications/sheets/monster-sheet.mjs | 8 +- module/documents/actor.mjs | 21 +- module/documents/roll.mjs | 38 ++- module/models/character.mjs | 17 - module/models/skill.mjs | 11 +- styles/character-main-v2.less | 88 ++++-- styles/character-subattributes.less | 94 +++--- styles/character.less | 146 ++++++++- templates/character-biography.hbs | 237 ++++++++------ templates/character-combat.hbs | 298 ++++++++++-------- templates/character-main.hbs | 90 ++++-- templates/character-skills.hbs | 22 -- templates/character-subattributes.hbs | 47 +-- templates/chat-message.hbs | 98 +++--- templates/roll-dialog.hbs | 12 + templates/skill.hbs | 13 + 19 files changed, 961 insertions(+), 600 deletions(-) diff --git a/css/fvtt-prism-rpg.css b/css/fvtt-prism-rpg.css index 2f8f3b4..3261d6f 100644 --- a/css/fvtt-prism-rpg.css +++ b/css/fvtt-prism-rpg.css @@ -132,16 +132,51 @@ i.prismrpg { font-family: var(--font-primary); font-size: calc(var(--font-size-standard) * 1); color: var(--color-dark-1); - background-image: var(--background-image-base); + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; background-repeat: no-repeat; - background-size: 100% 100%; overflow: scroll; } +.prismrpg .character-content nav.tabs { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 2px 0; +} .prismrpg .character-content nav.tabs [data-tab] { color: #636060; + font-size: calc(var(--font-size-standard) * 1.1); + font-family: var(--font-secondary); + font-weight: bold; + padding: 3px 16px; + background-color: rgba(255, 255, 255, 0.3); + border-radius: 4px; + text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8); + transition: all 0.2s ease; + cursor: pointer; + border: 2px solid transparent; +} +.prismrpg .character-content nav.tabs [data-tab]:hover { + background-color: rgba(255, 255, 255, 0.7); + color: #1a1a1a; + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + border-color: rgba(107, 107, 107, 0.3); } .prismrpg .character-content nav.tabs [data-tab].active { - color: #252424; + color: #000000; + background-color: rgba(255, 255, 255, 0.85); + text-shadow: 1px 1px 3px #ffffff; + border: 2px solid #6b6b6b; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.25); +} +.prismrpg .character-content nav.tabs [data-tab].active:hover { + background-color: rgba(255, 255, 255, 0.95); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.35); + transform: translateY(-2px); + border-color: #4a4a4a; } .prismrpg .character-content input:disabled, .prismrpg .character-content select:disabled { @@ -387,6 +422,14 @@ i.prismrpg { .prismrpg .character-main .character-characteristic-edit { min-width: 160px; } +.prismrpg .tab.character-biography .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; +} .prismrpg .tab.character-biography .main-div .biodata { display: grid; grid-template-columns: repeat(4, 1fr); @@ -412,6 +455,12 @@ i.prismrpg { min-height: 150px; } .prismrpg .tab.character-skills .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; display: grid; grid-template-columns: 1fr; } @@ -593,6 +642,12 @@ i.prismrpg { color: #6b3c3c; } .prismrpg .tab.character-equipment .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; display: grid; grid-template-columns: 1fr; } @@ -627,6 +682,12 @@ i.prismrpg { min-width: 12rem; } .prismrpg .tab.character-combat .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; display: grid; grid-template-columns: 1fr; } @@ -771,6 +832,12 @@ i.prismrpg { min-width: 12rem; } .prismrpg .tab.character-spells .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; display: grid; grid-template-columns: 1fr; } @@ -826,6 +893,12 @@ i.prismrpg { min-height: 150px; } .prismrpg .tab.character-miracles .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; display: grid; grid-template-columns: 1fr; } @@ -935,22 +1008,22 @@ i.prismrpg { letter-spacing: 1px; } .prismrpg .character-main-v2 .character-sheet-wrapper { - background-image: url("../assets/sheet/character-bg.png"); + background-image: url("../assets/ui/prism_rpg_background.webp"); background-size: cover; background-position: center; - padding: 8px 10px; + padding: 2px 4px; min-height: auto; } .prismrpg .character-main-v2 .character-header { position: relative; - margin-bottom: 5px; + margin-bottom: 3px; } .prismrpg .character-main-v2 .character-header .character-name-banner { background-image: url("../assets/sheet/banner-bg.png"); background-size: contain; background-repeat: no-repeat; background-position: center; - height: 60px; + height: 42px; display: flex; align-items: center; justify-content: center; @@ -960,15 +1033,16 @@ i.prismrpg { border: none; text-align: center; font-family: "Cinzel", serif; - font-size: 24px; + font-size: 20px; font-weight: bold; color: #2c2c2c; width: 500px; text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5); + padding: 2px 0; } .prismrpg .character-main-v2 .character-header .character-toggle-controls { position: absolute; - top: 10px; + top: 6px; right: 10px; } .prismrpg .character-main-v2 .character-main-grid { @@ -1074,12 +1148,14 @@ i.prismrpg { } .prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-label { font-family: "Cinzel", serif; - font-size: 14px; + font-size: 11px; font-weight: bold; color: #2c2c2c; text-transform: uppercase; margin: 0; min-width: 40px; + display: flex; + align-items: center; } .prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-label a.rollable { display: flex; @@ -1101,6 +1177,10 @@ i.prismrpg { .prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-label a.rollable:hover i { color: #2c2c2c; } +.prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-value { + display: flex; + align-items: center; +} .prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-value input { width: 45px; height: 32px; @@ -1113,6 +1193,19 @@ i.prismrpg { } .prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-save { margin-left: auto; + display: flex; + align-items: center; +} +.prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-save a.save-rollable { + display: contents; + cursor: pointer; +} +.prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-save a.save-rollable i { + margin-right: 6px; +} +.prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-save a.save-rollable:hover input { + background: rgba(200, 220, 255, 0.8); + border-color: #4a4a4a; } .prismrpg .character-main-v2 .character-left-column .character-attributes .attribute-shield .attribute-save input { width: 45px; @@ -1124,6 +1217,8 @@ i.prismrpg { border: 2px solid #6b6b6b; border-radius: 4px; color: #2c2c2c; + cursor: pointer; + transition: all 0.2s; } .prismrpg .character-main-v2 .character-right-column { display: flex; @@ -1144,20 +1239,27 @@ i.prismrpg { text-align: center; } .prismrpg .character-main-v2 .character-right-column .race-section .race-box { - padding: 10px; + padding: 6px; background: rgba(255, 255, 255, 0.5); - border: 3px solid #6b6b6b; - border-radius: 8px; - min-height: 60px; + border: 2px solid #6b6b6b; + border-radius: 6px; + min-height: 50px; +} +.prismrpg .character-main-v2 .character-right-column .race-section .race-box .race-label { + font-family: "Cinzel", serif; + font-size: 10px; + color: #6b6b6b; + text-align: center; + margin-bottom: 3px; } .prismrpg .character-main-v2 .character-right-column .race-section .race-box .section-title { font-family: "Cinzel", serif; - font-size: 12px; + font-size: 11px; font-weight: bold; color: #2c2c2c; text-transform: uppercase; - margin: 0 0 8px 0; - padding: 5px; + margin: 0 0 4px 0; + padding: 3px; background: rgba(255, 255, 255, 0.6); border: 2px solid #6b6b6b; border-radius: 4px; @@ -1166,11 +1268,11 @@ i.prismrpg { .prismrpg .character-main-v2 .character-right-column .race-section .race-box .race-item { display: flex; align-items: center; - gap: 8px; + gap: 6px; } .prismrpg .character-main-v2 .character-right-column .race-section .race-box .race-item .item-img { - width: 36px; - height: 36px; + width: 30px; + height: 30px; border: 2px solid #6b6b6b; border-radius: 4px; object-fit: cover; @@ -1202,10 +1304,10 @@ i.prismrpg { .prismrpg .character-main-v2 .character-right-column .race-section .race-box .no-race { text-align: center; font-family: "Crimson Text", serif; - font-size: 13px; + font-size: 11px; color: #6b6b6b; font-style: italic; - padding: 10px; + padding: 5px; } .prismrpg .character-main-v2 .character-right-column .race-section .race-box input { width: 100%; @@ -1218,29 +1320,29 @@ i.prismrpg { .prismrpg .character-main-v2 .character-right-column .classes-section { display: flex; flex-direction: column; - gap: 12px; + gap: 8px; } .prismrpg .character-main-v2 .character-right-column .classes-section .class-box { - padding: 10px; + padding: 6px; background: rgba(255, 255, 255, 0.5); - border: 3px solid #6b6b6b; - border-radius: 8px; + border: 2px solid #6b6b6b; + border-radius: 6px; } .prismrpg .character-main-v2 .character-right-column .classes-section .class-box .class-label { font-family: "Cinzel", serif; - font-size: 11px; + font-size: 10px; color: #6b6b6b; text-align: center; - margin-bottom: 5px; + margin-bottom: 3px; } .prismrpg .character-main-v2 .character-right-column .classes-section .class-box .class-content .class-item { display: flex; align-items: center; - gap: 8px; + gap: 6px; } .prismrpg .character-main-v2 .character-right-column .classes-section .class-box .class-content .class-item .item-img { - width: 32px; - height: 32px; + width: 28px; + height: 28px; border: 2px solid #6b6b6b; border-radius: 4px; object-fit: cover; @@ -1307,74 +1409,60 @@ i.prismrpg { } .prismrpg .character-subattributes.tab .subattributes-content .subattributes-list { display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: 1rem; + grid-template-columns: repeat(4, 1fr); + gap: 0.5rem; } .prismrpg .character-subattributes.tab .subattributes-content .subattribute-item { background: rgba(0, 0, 0, 0.1); border: 1px solid var(--color-border-dark-secondary); border-radius: 4px; - padding: 0.75rem; + padding: 0.4rem; display: flex; flex-direction: column; - gap: 0.5rem; + align-items: center; + gap: 0.15rem; + text-align: center; + cursor: pointer; + text-decoration: none; } .prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-header { display: flex; - justify-content: space-between; align-items: center; - gap: 0.5rem; + gap: 0.3rem; +} +.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-header i.fa-dice-d20 { + font-size: 1em; + color: var(--color-text-dark-primary); + opacity: 0.7; +} +.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item:hover { + background: rgba(0, 0, 0, 0.2); + border-color: var(--color-text-light-primary); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} +.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item:hover .subattribute-header i.fa-dice-d20 { + opacity: 1; + color: var(--color-text-dark-primary); } .prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-name { font-weight: bold; - font-size: 1.1em; + font-size: 0.75em; color: var(--color-text-dark-primary); + line-height: 1.2; } -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-value input { - width: 3em; - text-align: center; +.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-value { + font-size: 1em; font-weight: bold; - font-size: 1.2em; + color: var(--color-text-dark-primary); + min-width: 2em; + padding: 0.15rem 0.3rem; background: rgba(255, 255, 255, 0.1); - border: 1px solid var(--color-border-dark-tertiary); border-radius: 3px; - padding: 0.25rem; - color: var(--color-text-dark-primary); -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-value input:disabled { - opacity: 0.9; - cursor: default; -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-details { - display: flex; - flex-direction: column; - gap: 0.25rem; - font-size: 0.9em; - color: var(--color-text-dark-secondary); -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-parents { - font-style: italic; -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-parents .parent-char { - display: inline-block; - margin-right: 0.5rem; -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-parents .parent-char .parent-name { - font-weight: 600; - color: var(--color-text-dark-primary); -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-parents .parent-char .parent-value { - color: var(--color-text-dark-secondary); -} -.prismrpg .character-subattributes.tab .subattributes-content .subattribute-item .subattribute-description { - padding-top: 0.25rem; - border-top: 1px solid var(--color-border-dark-tertiary); - font-size: 0.85em; - line-height: 1.3; } @media (max-width: 768px) { .prismrpg .character-subattributes.tab .subattributes-content .subattributes-list { - grid-template-columns: 1fr; + grid-template-columns: repeat(3, 1fr); } } .prismrpg .monster-content { diff --git a/lang/en.json b/lang/en.json index 8229c42..8a13676 100644 --- a/lang/en.json +++ b/lang/en.json @@ -514,6 +514,7 @@ "skill": "Skill", "skillBonus": "Skill bonus", "skills": "Skills", + "sub-attribute": "Sub-Attribute", "subattributes": "Sub-Attributes", "spells": "Spells", "str": "STR", @@ -799,10 +800,13 @@ "coreSkills": "List of all 18 available Core Skills in Prism RPG", "advancedChecks": "Advanced checks are only available for your Core Skill", "addEquipment": "New equipment", - "addSpell": "New spells", + "addSpell": "Add new spell", + "addMiracle": "Add new miracle", "skill": "Skills list", + "skills": "Skills - Your character's skills and abilities", "racialAbilities": "Racial Abilities from your character's race and sub-race" }, + "RollSavingThrow": "Roll Saving Throw", "Message": { "selectCoreSkill": "You must select a Core Skill for your character. Each character chooses one Core Skill at creation.", "dropRace": "Drag and drop a Race item here", diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index 0428bd5..a542f66 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -7,7 +7,7 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { static DEFAULT_OPTIONS = { classes: ["character"], position: { - width: 750, + width: 780, height: 780, }, window: { @@ -15,14 +15,9 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { }, actions: { createEquipment: PrismRPGCharacterSheet.#onCreateEquipment, - rangedAttackDefense: PrismRPGCharacterSheet.#onRangedAttackDefense, rollInitiative: PrismRPGCharacterSheet.#onRollInitiative, armorHitPointsPlus: PrismRPGCharacterSheet.#onArmorHitPointsPlus, armorHitPointsMinus: PrismRPGCharacterSheet.#onArmorHitPointsMinus, - divinityPointsPlus: PrismRPGCharacterSheet.#onDivinityPointsPlus, - divinityPointsMinus: PrismRPGCharacterSheet.#onDivinityPointsMinus, - aetherPointsPlus: PrismRPGCharacterSheet.#onAetherPointsPlus, - aetherPointsMinus: PrismRPGCharacterSheet.#onAetherPointsMinus, }, } @@ -49,11 +44,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { spells: { template: "systems/fvtt-prism-rpg/templates/character-spells.hbs", }, - /* Miracles disabled - Legacy from Lethal Fantasy - miracles: { - template: "systems/fvtt-prism-rpg/templates/character-miracles.hbs", - }, - */ biography: { template: "systems/fvtt-prism-rpg/templates/character-biography.hbs", }, @@ -79,11 +69,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { if (this.actor.system.biodata.magicUser) { tabs.spells = { id: "spells", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-wand-magic-sparkles", label: "PRISMRPG.Label.spells" } } - /* Miracles disabled - Legacy from Lethal Fantasy - if (this.actor.system.biodata.clericUser) { - tabs.miracles = { id: "miracles", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-hands-praying", label: "PRISMRPG.Label.miracles" } - } - */ for (const v of Object.values(tabs)) { v.active = this.tabGroups[v.group] === v.id v.cssClass = v.active ? "active" : "" @@ -128,13 +113,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { context.spells = doc.itemTypes.spell context.hasSpells = context.spells.length > 0 break - /* Miracles disabled - Legacy from Lethal Fantasy - case "miracles": - context.tab = context.tabs.miracles - context.miracles = doc.itemTypes.miracle - context.hasMiracles = context.miracles.length > 0 - break - */ case "combat": context.tab = context.tabs.combat context.weapons = doc.itemTypes.weapon @@ -172,19 +150,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { } } - static async #onRangedAttackDefense(event, target) { - // Future use : const hasTarget = false - - let roll = await PrismRPGRoll.promptRangedDefense({ - actorId: this.actor.id, - actorName: this.actor.name, - actorImage: this.actor.img, - }) - if (!roll) return null - - await roll.toMessage({}, { rollMode: roll.options.rollMode }) - } - static async #onRollInitiative(event, target) { await this.document.system.rollInitiative() } @@ -201,34 +166,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { this.actor.update({ "system.combat.armorHitPoints": Math.max(armorHP, 0) }) } - static #onDivinityPointsPlus(event, target) { - let points = this.actor.system.divinityPoints.value - points += 1 - points = Math.min(points, this.actor.system.divinityPoints.max) - this.actor.update({ "system.divinityPoints.value": points }) - } - - static #onDivinityPointsMinus(event, target) { - let points = this.actor.system.divinityPoints.value - points -= 1 - points = Math.max(points, 0) - this.actor.update({ "system.divinityPoints.value": points }) - } - - static #onAetherPointsPlus(event, target) { - let points = this.actor.system.aetherPoints.value - points += 1 - points = Math.min(points, this.actor.system.aetherPoints.max) - this.actor.update({ "system.aetherPoints.value": points }) - } - - static #onAetherPointsMinus(event, target) { - let points = this.actor.system.aetherPoints.value - points -= 1 - points = Math.max(points, 0) - this.actor.update({ "system.aetherPoints.value": points }) - } - static #onCreateEquipment(event, target) { } @@ -269,9 +206,11 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { async _onRoll(event, target) { if (this.isEditMode) return - const rollType = event.target.dataset.rollType - let rollKey = event.target.dataset.rollKey; - let rollDice = event.target.dataset?.rollDice; + // Use closest to find the rollable element in case user clicked on a child + const rollableElement = event.target.closest('.rollable') || event.target + const rollType = rollableElement.dataset.rollType + let rollKey = rollableElement.dataset.rollKey; + let rollDice = rollableElement.dataset?.rollDice; this.actor.prepareRoll(rollType, rollKey, rollDice) diff --git a/module/applications/sheets/monster-sheet.mjs b/module/applications/sheets/monster-sheet.mjs index 4b60a1b..6ab7fcf 100644 --- a/module/applications/sheets/monster-sheet.mjs +++ b/module/applications/sheets/monster-sheet.mjs @@ -162,9 +162,11 @@ export default class PrismRPGMonsterSheet extends PrismRPGActorSheet { async _onRoll(event, target) { if (this.isEditMode) return - const rollType = event.target.dataset.rollType - let rollKey = event.target.dataset.rollKey - let rollDice = event.target.dataset?.rollDice || "0" + // Use closest to find the rollable element in case user clicked on a child + const rollableElement = event.target.closest('.rollable') || event.target + const rollType = rollableElement.dataset.rollType + let rollKey = rollableElement.dataset.rollKey + let rollDice = rollableElement.dataset?.rollDice || "0" this.actor.system.prepareMonsterRoll(rollType, rollKey, rollDice) } } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 46567a1..55aabc4 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -94,6 +94,17 @@ export default class PrismRPGActor extends Actor { name: game.i18n.localize(`PRISMRPG.Label.${rollKey}`) } break + case "sub-attribute": + if (!this.system.subAttributes || !this.system.subAttributes[rollKey]) { + ui.notifications.error(`Sub-attribute ${rollKey} not found`) + return + } + rollTarget = { + ...foundry.utils.duplicate(this.system.subAttributes[rollKey]), + rollKey: rollKey, + name: game.i18n.localize(SYSTEM.SUB_ATTRIBUTES[rollKey].label) + } + break case "granted": rollTarget = { name: rollKey, @@ -112,6 +123,10 @@ export default class PrismRPGActor extends Actor { rollTarget = foundry.utils.duplicate(this.system.saves[rollKey]) rollTarget.rollKey = rollKey rollTarget.rollDice = rollDice + // Pass the characteristic value for D&D 5e modifier calculation + rollTarget.characteristicValue = this.system.characteristics[rollKey].value + // The save bonus is the proficiency modifier (value stored in saves) + rollTarget.saveBonus = this.system.saves[rollKey].value break case "spell": rollTarget = this.items.find((i) => i.type === "spell" && i.id === rollKey) @@ -128,12 +143,16 @@ export default class PrismRPGActor extends Actor { ui.notifications.warn(game.i18n.localize("PRISMRPG.Notifications.rollFromWeapon")) return } + // Get the primary attribute for D&D 5e style rolls + const attrKey = rollTarget.system.primaryAttribute || "dex" + rollTarget.characteristicValue = this.system.characteristics[attrKey].value + rollTarget.proficiencyBonus = rollTarget.system.modifier break case "spell-attack": case "spell-power": case "miracle-attack": case "miracle-power": - rollTarget = this.items.find((i) => (i.type === "miracle" || i.type == "spell") && i.id === rollKey) + rollTarget = this.items.find((i) => (i.type === "miracle" || i.type === "spell") && i.id === rollKey) rollTarget.rollKey = rollKey break case "shield-roll": { diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index db88d53..4064d48 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -7,6 +7,15 @@ import { SYSTEM } from "../config/system.mjs" export default class PrismRPGRoll extends Roll { static CHAT_TEMPLATE = "systems/fvtt-prism-rpg/templates/chat-message.hbs" + /** + * Calculate D&D 5e style ability modifier from ability score + * @param {number} abilityScore The ability score value (3-18+) + * @returns {number} The ability modifier + */ + static getAbilityModifier(abilityScore) { + return Math.floor((abilityScore - 10) / 2) + } + // Getters for roll data get type() { return this.options.type @@ -89,17 +98,40 @@ export default class PrismRPGRoll extends Roll { switch (options.rollType) { case "characteristic": options.rollName = options.rollTarget.name - // Value already set in actor.mjs + // Calculate D&D 5e modifier from characteristic value + options.rollTarget.value = this.getAbilityModifier(options.rollTarget.value) + break + + case "sub-attribute": + options.rollName = options.rollTarget.name + // Sub-attribute value is already a modifier (calculated in prepareDerivedData) break case "challenge": - case "save": options.rollName = game.i18n.localize(`PRISMRPG.Label.${options.rollTarget.rollKey}`) break + case "save": + options.rollName = `${game.i18n.localize(`PRISMRPG.Label.${options.rollTarget.rollKey}`)} Save` + // Calculate D&D 5e saving throw: ability modifier + proficiency bonus + // Get the characteristic value from rollTarget + const charValue = options.rollTarget.characteristicValue + const abilityMod = this.getAbilityModifier(charValue) + const saveBonus = options.rollTarget.saveBonus || 0 + // Store separate values for display + options.rollTarget.abilityModifier = abilityMod + options.rollTarget.saveProficiency = saveBonus + // Add the save bonus (proficiency) stored in saves + options.rollTarget.value = abilityMod + saveBonus + break + case "skill": options.rollName = options.rollTarget.name - options.rollTarget.value = Math.floor(options.rollTarget.system.skillTotal / 10) + // D&D 5e style: ability modifier + proficiency bonus + const skillCharValue = options.rollTarget.characteristicValue + const skillAbilityMod = this.getAbilityModifier(skillCharValue) + const proficiency = options.rollTarget.proficiencyBonus || 0 + options.rollTarget.value = skillAbilityMod + proficiency break case "weapon-attack": diff --git a/module/models/character.mjs b/module/models/character.mjs index 71f1f8d..187f2d6 100644 --- a/module/models/character.mjs +++ b/module/models/character.mjs @@ -144,23 +144,6 @@ export default class PrismRPGCharacter extends foundry.abstract.TypeDataModel { }, {}), ) - // Core Skill system (Prism RPG) - schema.coreSkill = new fields.SchemaField({ - skill: new fields.StringField({ - required: false, - nullable: true, - initial: null, - choices: SYSTEM.CORE_SKILLS_CHOICES, - label: "Selected Core Skill" - }), - attributeChoice: new fields.StringField({ - required: false, - nullable: true, - initial: null, - label: "Attribute Choice for +2 Bonus" - }) - }) - return schema } diff --git a/module/models/skill.mjs b/module/models/skill.mjs index 42d1672..1a14123 100644 --- a/module/models/skill.mjs +++ b/module/models/skill.mjs @@ -36,6 +36,13 @@ export default class PrismRPGSkill extends foundry.abstract.TypeDataModel { label: "Is Core Skill" }) + // Primary attribute for this skill (str, dex, con, int, wis, cha) + schema.primaryAttribute = new fields.StringField({ + required: true, + initial: "dex", + label: "Primary Attribute" + }) + // If Core Skill, which attribute receives the +2 bonus? schema.attributeBonus = new fields.StringField({ required: true, @@ -107,9 +114,9 @@ export default class PrismRPGSkill extends foundry.abstract.TypeDataModel { prepareDerivedData() { super.prepareDerivedData() - // If this is the character's Core Skill, apply bonuses + // D&D 5e style: Core Skill gives +2 proficiency bonus if (this.isCoreSkill) { - this.modifier = CORE_SKILL_BONUS?.basic || 5 + this.modifier = 2 this.canAdvancedCheck = true } else { this.modifier = 0 diff --git a/styles/character-main-v2.less b/styles/character-main-v2.less index 2c068c4..3b9bd64 100644 --- a/styles/character-main-v2.less +++ b/styles/character-main-v2.less @@ -5,24 +5,24 @@ margin: 0; .character-sheet-wrapper { - background-image: url("../assets/sheet/character-bg.png"); + background-image: url("../assets/ui/prism_rpg_background.webp"); background-size: cover; background-position: center; - padding: 8px 10px; + padding: 2px 4px; min-height: auto; } // Character Header with Banner .character-header { position: relative; - margin-bottom: 5px; + margin-bottom: 3px; .character-name-banner { background-image: url("../assets/sheet/banner-bg.png"); background-size: contain; background-repeat: no-repeat; background-position: center; - height: 60px; + height: 42px; display: flex; align-items: center; justify-content: center; @@ -32,17 +32,18 @@ border: none; text-align: center; font-family: "Cinzel", serif; - font-size: 24px; + font-size: 20px; font-weight: bold; color: #2c2c2c; width: 500px; text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5); + padding: 2px 0; } } .character-toggle-controls { position: absolute; - top: 10px; + top: 6px; right: 10px; } } @@ -168,12 +169,14 @@ .attribute-label { font-family: "Cinzel", serif; - font-size: 14px; + font-size: 11px; font-weight: bold; color: #2c2c2c; text-transform: uppercase; margin: 0; min-width: 40px; + display: flex; + align-items: center; a.rollable { display: flex; @@ -201,6 +204,9 @@ } .attribute-value { + display: flex; + align-items: center; + input { width: 45px; height: 32px; @@ -215,6 +221,22 @@ .attribute-save { margin-left: auto; + display: flex; + align-items: center; + + a.save-rollable { + display: contents; + cursor: pointer; + + i { + margin-right: 6px; + } + + &:hover input { + background: rgba(200, 220, 255, 0.8); + border-color: #4a4a4a; + } + } input { width: 45px; @@ -226,6 +248,8 @@ border: 2px solid #6b6b6b; border-radius: 4px; color: #2c2c2c; + cursor: pointer; + transition: all 0.2s; } } } @@ -254,20 +278,28 @@ .race-section { .race-box { - padding: 10px; + padding: 6px; background: rgba(255, 255, 255, 0.5); - border: 3px solid #6b6b6b; - border-radius: 8px; - min-height: 60px; + border: 2px solid #6b6b6b; + border-radius: 6px; + min-height: 50px; + + .race-label { + font-family: "Cinzel", serif; + font-size: 10px; + color: #6b6b6b; + text-align: center; + margin-bottom: 3px; + } .section-title { font-family: "Cinzel", serif; - font-size: 12px; + font-size: 11px; font-weight: bold; color: #2c2c2c; text-transform: uppercase; - margin: 0 0 8px 0; - padding: 5px; + margin: 0 0 4px 0; + padding: 3px; background: rgba(255, 255, 255, 0.6); border: 2px solid #6b6b6b; border-radius: 4px; @@ -277,11 +309,11 @@ .race-item { display: flex; align-items: center; - gap: 8px; + gap: 6px; .item-img { - width: 36px; - height: 36px; + width: 30px; + height: 30px; border: 2px solid #6b6b6b; border-radius: 4px; object-fit: cover; @@ -320,10 +352,10 @@ .no-race { text-align: center; font-family: "Crimson Text", serif; - font-size: 13px; + font-size: 11px; color: #6b6b6b; font-style: italic; - padding: 10px; + padding: 5px; } input { @@ -340,31 +372,31 @@ .classes-section { display: flex; flex-direction: column; - gap: 12px; + gap: 8px; .class-box { - padding: 10px; + padding: 6px; background: rgba(255, 255, 255, 0.5); - border: 3px solid #6b6b6b; - border-radius: 8px; + border: 2px solid #6b6b6b; + border-radius: 6px; .class-label { font-family: "Cinzel", serif; - font-size: 11px; + font-size: 10px; color: #6b6b6b; text-align: center; - margin-bottom: 5px; + margin-bottom: 3px; } .class-content { .class-item { display: flex; align-items: center; - gap: 8px; + gap: 6px; .item-img { - width: 32px; - height: 32px; + width: 28px; + height: 28px; border: 2px solid #6b6b6b; border-radius: 4px; object-fit: cover; diff --git a/styles/character-subattributes.less b/styles/character-subattributes.less index 81cc5cc..9ddf065 100644 --- a/styles/character-subattributes.less +++ b/styles/character-subattributes.less @@ -6,82 +6,62 @@ .subattributes-list { display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: 1rem; + grid-template-columns: repeat(4, 1fr); + gap: 0.5rem; } .subattribute-item { background: rgba(0, 0, 0, 0.1); border: 1px solid var(--color-border-dark-secondary); border-radius: 4px; - padding: 0.75rem; + padding: 0.4rem; display: flex; flex-direction: column; - gap: 0.5rem; + align-items: center; + gap: 0.15rem; + text-align: center; + cursor: pointer; + text-decoration: none; .subattribute-header { display: flex; - justify-content: space-between; align-items: center; - gap: 0.5rem; + gap: 0.3rem; + + i.fa-dice-d20 { + font-size: 1em; + color: var(--color-text-dark-primary); + opacity: 0.7; + } + } + + &:hover { + background: rgba(0, 0, 0, 0.2); + border-color: var(--color-text-light-primary); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); + + .subattribute-header i.fa-dice-d20 { + opacity: 1; + color: var(--color-text-dark-primary); + } } .subattribute-name { font-weight: bold; - font-size: 1.1em; + font-size: 0.75em; color: var(--color-text-dark-primary); + line-height: 1.2; } .subattribute-value { - input { - width: 3em; - text-align: center; - font-weight: bold; - font-size: 1.2em; - background: rgba(255, 255, 255, 0.1); - border: 1px solid var(--color-border-dark-tertiary); - border-radius: 3px; - padding: 0.25rem; - color: var(--color-text-dark-primary); - - &:disabled { - opacity: 0.9; - cursor: default; - } - } - } - - .subattribute-details { - display: flex; - flex-direction: column; - gap: 0.25rem; - font-size: 0.9em; - color: var(--color-text-dark-secondary); - } - - .subattribute-parents { - font-style: italic; - - .parent-char { - display: inline-block; - margin-right: 0.5rem; - - .parent-name { - font-weight: 600; - color: var(--color-text-dark-primary); - } - - .parent-value { - color: var(--color-text-dark-secondary); - } - } - } - - .subattribute-description { - padding-top: 0.25rem; - border-top: 1px solid var(--color-border-dark-tertiary); - font-size: 0.85em; - line-height: 1.3; + font-size: 1em; + font-weight: bold; + color: var(--color-text-dark-primary); + min-width: 2em; + padding: 0.15rem 0.3rem; + background: rgba(255, 255, 255, 0.1); + border-radius: 3px; } } } @@ -92,7 +72,7 @@ .character-subattributes.tab { .subattributes-content { .subattributes-list { - grid-template-columns: 1fr; + grid-template-columns: repeat(3, 1fr); } } } diff --git a/styles/character.less b/styles/character.less index f205c61..027d912 100644 --- a/styles/character.less +++ b/styles/character.less @@ -1,7 +1,107 @@ .character-content { - .sheet-common(); - .character-sheet-common(); + font-family: var(--font-primary); + font-size: calc(var(--font-size-standard) * 1); + color: var(--color-dark-1); + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; overflow: scroll; + + nav.tabs { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 2px 0; + } + + nav.tabs [data-tab] { + color: #636060; + font-size: calc(var(--font-size-standard) * 1.1); + font-family: var(--font-secondary); + font-weight: bold; + padding: 3px 16px; + background-color: rgba(255, 255, 255, 0.3); + border-radius: 4px; + text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8); + transition: all 0.2s ease; + cursor: pointer; + border: 2px solid transparent; + + &:hover { + background-color: rgba(255, 255, 255, 0.7); + color: #1a1a1a; + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + border-color: rgba(107, 107, 107, 0.3); + } + } + + nav.tabs [data-tab].active { + color: #000000; + background-color: rgba(255, 255, 255, 0.85); + text-shadow: 1px 1px 3px rgba(255, 255, 255, 1); + border: 2px solid #6b6b6b; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.25); + + &:hover { + background-color: rgba(255, 255, 255, 0.95); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.35); + transform: translateY(-2px); + border-color: #4a4a4a; + } + } + + input:disabled, + select:disabled { + background-color: rgba(0, 0, 0, 0.2); + border-color: transparent; + color: var(--color-dark-3); + } + + input, + select { + height: 1.5rem; + background-color: rgba(0, 0, 0, 0.1); + border-color: var(--color-dark-6); + color: var(--color-dark-2); + } + + input[name="name"] { + height: 2.5rem; + margin-right: 4px; + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1.2); + font-weight: bold; + border: none; + } + + fieldset { + margin-bottom: 4px; + border-radius: 4px; + } + + .form-fields { + input, + select { + text-align: center; + font-size: calc(var(--font-size-standard) * 1); + } + select { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1); + } + } + + legend { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1.2); + font-weight: bold; + letter-spacing: 1px; + } + + .character-sheet-common(); } .character-main { @@ -223,6 +323,13 @@ } .tab.character-biography .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; + .biodata { display: grid; grid-template-columns: repeat(4, 1fr); @@ -253,6 +360,13 @@ } .tab.character-skills .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; + display: grid; grid-template-columns: 1fr; legend { @@ -462,6 +576,13 @@ } .tab.character-equipment .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; + display: grid; grid-template-columns: 1fr; legend { @@ -501,6 +622,13 @@ } .tab.character-combat .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; + display: grid; grid-template-columns: 1fr; legend { @@ -651,6 +779,13 @@ } .tab.character-spells .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; + display: grid; grid-template-columns: 1fr; legend { @@ -712,6 +847,13 @@ } .tab.character-miracles .main-div { + background-image: url("../assets/ui/prism_rpg_background.webp"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding: 8px 10px; + min-height: 100%; + display: grid; grid-template-columns: 1fr; legend { diff --git a/templates/character-biography.hbs b/templates/character-biography.hbs index d523ae2..f8dd423 100644 --- a/templates/character-biography.hbs +++ b/templates/character-biography.hbs @@ -1,97 +1,156 @@ -
+
-
- {{localize "PRISMRPG.Label.biodata"}} -
-
- Class - {{formInput systemFields.biodata.fields.class value=system.biodata.class }} -
-
- Level - {{formInput systemFields.biodata.fields.level value=system.biodata.level }} -
-
- Mortal - {{formInput systemFields.biodata.fields.mortal value=system.biodata.mortal }} -
-
- Alignment - {{formInput systemFields.biodata.fields.alignment value=system.biodata.alignment }} -
-
- Age - {{formInput systemFields.biodata.fields.age value=system.biodata.age }} -
-
- Height - {{formInput systemFields.biodata.fields.height value=system.biodata.height }} -
-
- Weight - {{formInput systemFields.biodata.fields.weight value=system.biodata.weight }} -
-
- Eyes - {{formInput systemFields.biodata.fields.eyes value=system.biodata.eyes }} -
-
- Hair - {{formInput systemFields.biodata.fields.hair value=system.biodata.hair }} -
-
- Dev. Points (Total) - {{formInput systemFields.developmentPoints.fields.total value=system.developmentPoints.total }} -
-
- Dev. Points (Rem.) - {{formInput systemFields.developmentPoints.fields.remaining value=system.developmentPoints.remaining }} -
-
- Magic User - {{formInput systemFields.biodata.fields.magicUser value=system.biodata.magicUser }} -
-
- Cleric User - {{formInput systemFields.biodata.fields.clericUser value=system.biodata.clericUser }} -
-
- Save bonus (1/5levels) - {{formInput systemFields.modifiers.fields.saveModifier value=system.modifiers.saveModifier disabled=true}} -
+
+ {{localize "PRISMRPG.Label.biodata"}} +
+
+ Class + {{formInput + systemFields.biodata.fields.class + value=system.biodata.class + }} +
+
+ Level + {{formInput + systemFields.biodata.fields.level + value=system.biodata.level + }} +
+
+ Mortal + {{formInput + systemFields.biodata.fields.mortal + value=system.biodata.mortal + }} +
+
+ Age + {{formInput systemFields.biodata.fields.age value=system.biodata.age}} +
+
+ Height + {{formInput + systemFields.biodata.fields.height + value=system.biodata.height + }} +
+
+ Weight + {{formInput + systemFields.biodata.fields.weight + value=system.biodata.weight + }} +
+
+ Eyes + {{formInput + systemFields.biodata.fields.eyes + value=system.biodata.eyes + }} +
+
+ Hair + {{formInput + systemFields.biodata.fields.hair + value=system.biodata.hair + }} +
+
+ Dev. Points (Total) + {{formInput + systemFields.developmentPoints.fields.total + value=system.developmentPoints.total + }} +
+
+ Dev. Points (Rem.) + {{formInput + systemFields.developmentPoints.fields.remaining + value=system.developmentPoints.remaining + }} +
+
+ Magic User + {{formInput + systemFields.biodata.fields.magicUser + value=system.biodata.magicUser + }} +
+
+ Cleric User + {{formInput + systemFields.biodata.fields.clericUser + value=system.biodata.clericUser + }} +
+
+ Save bonus (1/5levels) + {{formInput + systemFields.modifiers.fields.saveModifier + value=system.modifiers.saveModifier + disabled=true + }} +
+ + {{#if system.biodata.magicUser}} +
+ Spell bonus (1/5levels) + {{formInput + systemFields.modifiers.fields.levelSpellModifier + value=system.modifiers.levelSpellModifier + disabled=true + }} +
+ {{/if}} + {{#if system.biodata.clericUser}} +
+ Miracle bonus (1/5levels) + {{formInput + systemFields.modifiers.fields.levelMiracleModifier + value=system.modifiers.levelMiracleModifier + disabled=true + }} +
+ {{/if}} + +
+ Last HD roll + {{formInput + systemFields.biodata.fields.hpPerLevel + value=system.biodata.hpPerLevel + disabled=true + }} +
- {{#if system.biodata.magicUser}} -
- Spell bonus (1/5levels) - {{formInput systemFields.modifiers.fields.levelSpellModifier value=system.modifiers.levelSpellModifier disabled=true}}
- {{/if}} - {{#if system.biodata.clericUser}} -
- Miracle bonus (1/5levels) - {{formInput systemFields.modifiers.fields.levelMiracleModifier value=system.modifiers.levelMiracleModifier disabled=true}} -
- {{/if}} +
-
- Last HD roll - {{formInput systemFields.biodata.fields.hpPerLevel value=system.biodata.hpPerLevel disabled=true}} -
+
+ {{localize "PRISMRPG.Label.description"}} + {{formInput + systemFields.description + enriched=enrichedDescription + value=system.description + name="system.description" + toggled=true + }} +
- -
-
- -
- {{localize "PRISMRPG.Label.description"}} - {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" - toggled=true}} -
- -
- {{localize "PRISMRPG.Label.notes"}} - {{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}} -
+
+ {{localize "PRISMRPG.Label.notes"}} + {{formInput + systemFields.notes + enriched=enrichedNotes + value=system.notes + name="system.notes" + toggled=true + }} +
\ No newline at end of file diff --git a/templates/character-combat.hbs b/templates/character-combat.hbs index 3113923..74f87e9 100644 --- a/templates/character-combat.hbs +++ b/templates/character-combat.hbs @@ -1,108 +1,102 @@ -
+
-
- {{localize "PRISMRPG.Label.combatDetails"}} -
-
- - - - - -
- {{localize "PRISMRPG.Label.armorHitPoints"}} - {{formInput systemFields.combat.fields.armorHitPoints value=system.combat.armorHitPoints localize=true }} - - -
- -
- {{localize - "PRISMRPG.Label.grantedAttackDice"}} - {{formInput systemFields.granted.fields.attackDice value=system.granted.attackDice disabled=isPlayMode }} -
- -
- {{localize - "PRISMRPG.Label.grantedDefenseDice"}} - {{formInput systemFields.granted.fields.defenseDice value=system.granted.defenseDice disabled=isPlayMode }} -
- -
- {{localize - "PRISMRPG.Label.grantedDamageDice"}} - {{formInput systemFields.granted.fields.damageDice value=system.granted.damageDice disabled=isPlayMode }} -
- -
-
-
- -
- {{localize "PRISMRPG.Label.wounds"}} -
- {{#each system.hp.wounds as |wound idx|}} -
- Name: - Duration: - HP: -
- {{/each}} -
-
-
{{localize "PRISMRPG.Label.weapons"}}
{{#each weapons as |item|}} -
- {{#if (ne item.img "icons/svg/item-bag.svg")}} - - {{/if}} -
- {{item.name}} +
+ {{#if (ne item.img "icons/svg/item-bag.svg")}} + + {{/if}} +
+ {{item.name}} +
+
+ + + + + + + + + + + S + + + + M + + +
+ +
+ + +
-
- - - - - - - - - - - S - - - - M - - -
- -
- - -
-
{{/each}}
@@ -111,22 +105,47 @@ {{localize "PRISMRPG.Label.armors"}}
{{#each armors as |item|}} -
- -
- {{item.name}} +
+ +
+ {{item.name}} +
+
{{item.system.defense}}
+
{{item.system.maximumMovement}}
+
{{item.system.hp}}
+
{{item.system.damageReduction}}
+
+ + +
-
{{item.system.defense}}
-
{{item.system.maximumMovement}}
-
{{item.system.hp}}
-
{{item.system.damageReduction}}
-
- - -
-
{{/each}}
@@ -135,25 +154,44 @@ {{localize "PRISMRPG.Label.shields"}}
{{#each shields as |item|}} -
- -
- {{item.name}} -
-
- {{item.system.apc}} APC -
-
- {{item.system.sr}} -
+
+ +
+ {{item.name}} +
+
+ + {{item.system.apc}} + APC +
+
+ + {{item.system.sr}} +
-
- - +
+ + +
-
{{/each}}
diff --git a/templates/character-main.hbs b/templates/character-main.hbs index 3456ebc..00eac80 100644 --- a/templates/character-main.hbs +++ b/templates/character-main.hbs @@ -118,11 +118,14 @@ disabled=isPlayMode }}
-
+
+ + + {{formInput systemFields.saves.fields.str.fields.value value=system.saves.str.value - disabled=true + disabled=isPlayMode }}
@@ -140,11 +143,14 @@ disabled=isPlayMode }}
-
+
+ + + {{formInput systemFields.saves.fields.dex.fields.value value=system.saves.dex.value - disabled=true + disabled=isPlayMode }}
@@ -162,11 +168,14 @@ disabled=isPlayMode }}
-
+
+ + + {{formInput systemFields.saves.fields.con.fields.value value=system.saves.con.value - disabled=true + disabled=isPlayMode }}
@@ -184,11 +193,14 @@ disabled=isPlayMode }} -
+
+ + + {{formInput systemFields.saves.fields.int.fields.value value=system.saves.int.value - disabled=true + disabled=isPlayMode }}
@@ -206,11 +218,14 @@ disabled=isPlayMode }} -
+
+ + + {{formInput systemFields.saves.fields.wis.fields.value value=system.saves.wis.value - disabled=true + disabled=isPlayMode }}
@@ -228,11 +243,14 @@ disabled=isPlayMode }} -
+
+ + + {{formInput systemFields.saves.fields.cha.fields.value value=system.saves.cha.value - disabled=true + disabled=isPlayMode }}
@@ -244,23 +262,25 @@ {{! Race }}
-

Race

- {{#if race}} -
- -
{{race.name}}
-
- - +

Race

+
+ {{#if race}} +
+ +
{{race.name}}
+
+ + +
-
- {{else}} -
-

{{localize "PRISMRPG.Message.dropRace"}}

-
- {{/if}} + {{else}} +
+

{{localize "PRISMRPG.Message.dropRace"}}

+
+ {{/if}} +
@@ -289,6 +309,20 @@
{{/each}} + + {{! Alignment }} +
+

Alignment

+
+
+ {{formInput + systemFields.biodata.fields.alignment + value=system.biodata.alignment + disabled=isPlayMode + }} +
+
+
diff --git a/templates/character-skills.hbs b/templates/character-skills.hbs index c5d7eba..cdb558e 100644 --- a/templates/character-skills.hbs +++ b/templates/character-skills.hbs @@ -60,27 +60,5 @@ {{/each}} - -
- - {{localize "PRISMRPG.Label.vulnerabilities"}} - -
- {{#each vulnerabilities as |item|}} -
- -
- {{item.name}} -
-
- - -
-
- {{/each}} -
-
\ No newline at end of file diff --git a/templates/character-subattributes.hbs b/templates/character-subattributes.hbs index 1532d99..f204826 100644 --- a/templates/character-subattributes.hbs +++ b/templates/character-subattributes.hbs @@ -1,46 +1,23 @@
-

- - Sub-Attributes -

-

- Sub-attributes are derived from the average of two primary characteristics. -

-
{{#each (entries config.SUB_ATTRIBUTES) as |entry|}} {{#with entry.[1] as |subAttr|}} - diff --git a/templates/chat-message.hbs b/templates/chat-message.hbs index e92803c..f22d5c1 100644 --- a/templates/chat-message.hbs +++ b/templates/chat-message.hbs @@ -9,80 +9,102 @@ {{actingCharName}} - {{upperFirst rollName}} {{#if (match rollType "attack")}} - Attack roll ! + Attack roll ! {{/if}} {{#if (match rollType "defense")}} - Defense roll ! + Defense roll ! {{/if}} {{#if (eq rollData.favor "favor")}} - Favor roll + Favor roll {{/if}} {{#if (eq rollData.favor "disfavor")}} - Disfavor roll + Disfavor roll {{/if}} {{#if badResult}} - {{localize "PRISMRPG.Label.otherResult"}} : {{badResult}} + {{localize "PRISMRPG.Label.otherResult"}} + : + {{badResult}} {{/if}} {{#if rollTarget.weapon}} - {{rollTarget.weapon.name}} + {{rollTarget.weapon.name}} {{/if}} {{#if rollData.letItFly}} - Let It Fly attack ! + Let It Fly attack ! {{/if}} {{#if rollData.pointBlank}} - Point Blank Range Attack ! + Point Blank Range Attack ! {{/if}} {{#if rollData.beyondSkill}} - Beyond Skill Range Attack ! + Beyond Skill Range Attack ! {{/if}} Formula : {{titleFormula}} + {{#if (eq rollType "save")}} + {{#if rollTarget.abilityModifier}} + + (Ability Mod: + {{#if + (gt rollTarget.abilityModifier 0) + }}+{{/if}}{{rollTarget.abilityModifier}}, Save Bonus: + {{#if + (gt rollTarget.saveProficiency 0) + }}+{{/if}}{{rollTarget.saveProficiency}}) + + {{/if}} + {{/if}} + {{#each diceResults as |result|}} - {{result.dice}} : {{result.value}} + {{result.dice}} : {{result.value}} {{/each}}
{{#if isSave}} -
- {{#if (eq resultType "success")}} - {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.success"}}{{/if}} - {{else}} - {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.failure"}}{{/if}} - {{/if}} -
+
+ {{#if (eq resultType "success")}} + {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.success"}}{{/if}} + {{else}} + {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.failure"}}{{/if}} + {{/if}} +
{{/if}} {{#if isResource}} -
- {{#if (eq resultType "success")}} - {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.success"}}{{/if}} - {{else}} - {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.failure"}}{{#if isFailure}} ({{localize - "PRISMRPG.Roll.resourceLost"}}){{/if}}{{/if}} - {{/if}} -
+
+ {{#if (eq resultType "success")}} + {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.success"}}{{/if}} + {{else}} + {{#if isPrivate}}?{{else}}{{localize "PRISMRPG.Roll.failure"}}{{#if + isFailure + }} ({{localize "PRISMRPG.Roll.resourceLost"}}){{/if}}{{/if}} + {{/if}} +
{{/if}} {{#if isDamage}} -
- {{#if (and isGM hasTarget)}} - {{{localize "PRISMRPG.Roll.displayArmor" targetName=targetName targetArmor=targetArmor realDamage=realDamage}}} - {{/if}} -
+
+ {{#if (and isGM hasTarget)}} + {{{localize + "PRISMRPG.Roll.displayArmor" + targetName=targetName + targetArmor=targetArmor + realDamage=realDamage + }}} + {{/if}} +
{{/if}} {{#unless isPrivate}} -
-

{{total}}

-
- {{#if D30result}} -
-

D30 result: {{D30result}}

-
- {{/if}} +
+

{{total}}

+
+ {{#if D30result}} +
+

D30 result: {{D30result}}

+
+ {{/if}} {{/unless}} \ No newline at end of file diff --git a/templates/roll-dialog.hbs b/templates/roll-dialog.hbs index 6a11e44..4b0420d 100644 --- a/templates/roll-dialog.hbs +++ b/templates/roll-dialog.hbs @@ -12,6 +12,18 @@ + {{baseValue}} + {{#if (eq rollType "save")}} +
+ (Ability Mod: + {{#if + (gt rollTarget.abilityModifier 0) + }}+{{/if}}{{rollTarget.abilityModifier}} + + Save Bonus: + {{#if + (gt rollTarget.saveProficiency 0) + }}+{{/if}}{{rollTarget.saveProficiency}}) +
+ {{/if}} {{else}}
{{upperFirst rollName}} diff --git a/templates/skill.hbs b/templates/skill.hbs index e5f25ca..f8be526 100644 --- a/templates/skill.hbs +++ b/templates/skill.hbs @@ -11,6 +11,19 @@

{{localize "PRISMRPG.Hint.isCoreSkill"}}

+ {{!-- Primary Attribute for Skill Checks --}} +
+ + +

Primary attribute used for skill checks (D&D 5e style: ability modifier + proficiency)

+
+ {{#if system.isCoreSkill}} {{!-- Attribute Bonus Selection --}}