From ce1844a070239bd43b19745331134068e5cb3229 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Wed, 8 Jan 2025 17:26:57 +0100 Subject: [PATCH] Add vehicle type --- css/fvtt-cthulhu-eternal.css | 251 ++++++++++++++++++ cthulhu-eternal.mjs | 4 +- gulpfile.js | 7 +- lang/en.json | 46 +++- module/applications/_module.mjs | 1 + .../applications/sheets/protagonist-sheet.mjs | 14 - module/applications/sheets/vehicle-sheet.mjs | 117 ++++++++ module/config/system.mjs | 15 ++ module/models/_module.mjs | 2 + module/models/gear.mjs | 1 + module/models/protagonist.mjs | 35 +-- module/models/vehicle.mjs | 34 +++ module/models/weapon.mjs | 1 + packs/skills/{000030.log => 000038.log} | 0 packs/skills/CURRENT | 2 +- packs/skills/LOG | 2 +- packs/skills/LOG.old | 2 +- packs/skills/MANIFEST-000028 | 3 - packs/skills/MANIFEST-000036 | 3 + styles/fvtt-cthulhu-eternal.less | 3 +- styles/mixins.less | 7 + styles/vehicle.less | 223 ++++++++++++++++ system.json | 3 +- templates/gear.hbs | 1 + templates/protagonist-biography.hbs | 5 +- templates/vehicle-description.hbs | 12 + templates/vehicle-equipment.hbs | 54 ++++ templates/vehicle-main.hbs | 52 ++++ templates/weapon.hbs | 2 + 29 files changed, 859 insertions(+), 43 deletions(-) create mode 100644 module/applications/sheets/vehicle-sheet.mjs create mode 100644 module/models/vehicle.mjs rename packs/skills/{000030.log => 000038.log} (100%) delete mode 100644 packs/skills/MANIFEST-000028 create mode 100644 packs/skills/MANIFEST-000036 create mode 100644 styles/vehicle.less create mode 100644 templates/vehicle-description.hbs create mode 100644 templates/vehicle-equipment.hbs create mode 100644 templates/vehicle-main.hbs diff --git a/css/fvtt-cthulhu-eternal.css b/css/fvtt-cthulhu-eternal.css index 11226d6..690b057 100644 --- a/css/fvtt-cthulhu-eternal.css +++ b/css/fvtt-cthulhu-eternal.css @@ -178,6 +178,10 @@ i.fvtt-cthulhu-eternal { font-family: var(--font-secondary); font-size: calc(var(--font-size-standard) * 1); } +.fvtt-cthulhu-eternal .vehicle-sheet-common label { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1); +} .fvtt-cthulhu-eternal .item-sheet-common .form-fields { padding-top: 4px; } @@ -776,6 +780,253 @@ i.fvtt-cthulhu-eternal { .fvtt-cthulhu-eternal .tab.protagonist-equipment prose-mirror.active { min-height: 150px; } +.fvtt-cthulhu-eternal .vehicle-content { + 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-repeat: no-repeat; + background-size: 100% 100%; + overflow: scroll; +} +.fvtt-cthulhu-eternal .vehicle-content input:disabled, +.fvtt-cthulhu-eternal .vehicle-content select:disabled { + background-color: rgba(0, 0, 0, 0.2); + border-color: transparent; + color: var(--color-dark-3); +} +.fvtt-cthulhu-eternal .vehicle-content input, +.fvtt-cthulhu-eternal .vehicle-content select { + background-color: rgba(0, 0, 0, 0.1); + border-color: var(--color-dark-6); + color: var(--color-dark-2); +} +.fvtt-cthulhu-eternal .vehicle-content input[name="name"] { + height: 40px; + margin-right: 10px; + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1); + font-weight: bold; + border: none; +} +.fvtt-cthulhu-eternal .vehicle-content fieldset { + margin-bottom: 4px; + border-radius: 4px; +} +.fvtt-cthulhu-eternal .vehicle-content .form-fields input, +.fvtt-cthulhu-eternal .vehicle-content .form-fields select { + text-align: center; + font-size: calc(var(--font-size-standard) * 1); +} +.fvtt-cthulhu-eternal .vehicle-content .form-fields select { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1); +} +.fvtt-cthulhu-eternal .vehicle-content legend { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1.2); + font-weight: bold; + letter-spacing: 1px; +} +.fvtt-cthulhu-eternal .vehicle-content label { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1); +} +.fvtt-cthulhu-eternal .sheet-tabs { + background-color: var(--color-light-1); +} +.fvtt-cthulhu-eternal .vehicle-main { + background-color: var(--color-light-1); + display: flex; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc { + display: flex; + gap: 4px; + flex: 1; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-left { + min-width: 180px; + display: flex; + flex-direction: column; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-left .vehicle-left-image { + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 8px; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-left .vehicle-left-image .vehicle-img { + height: 140px; + width: auto; + border: none; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right { + display: flex; + flex-direction: column; + gap: 5px; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-name { + display: flex; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-name input { + font-family: var(--font-title); + font-size: calc(var(--font-size-standard) * 1.4); + width: 400px; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos { + display: flex; + flex-direction: column; + gap: 4px; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos label { + min-width: 120px; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp { + display: flex; + gap: 2px; + align-items: center; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .vehicle-hp-value .form-fields input { + flex: none; + width: 50px; + margin-left: 4px; + font-size: calc(var(--font-size-standard) * 1.4); +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .vehicle-hp-max { + clear: both; + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: 3px 0; + align-items: center; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .vehicle-hp-max input { + width: 50px; + text-align: center; + font-size: calc(var(--font-size-standard) * 1.4); +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .hp-separator { + font-size: calc(var(--font-size-standard) * 1.2); + display: flex; + align-items: center; + justify-content: center; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc-play { + min-width: 500px; +} +.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc-edit { + min-width: 650px; +} +.fvtt-cthulhu-eternal .vehicle-biography { + background-color: var(--color-light-1); +} +.fvtt-cthulhu-eternal .vehicle-biography prose-mirror.inactive { + min-height: 40px; +} +.fvtt-cthulhu-eternal .vehicle-biography prose-mirror.active { + min-height: 150px; +} +.fvtt-cthulhu-eternal .vehicle-biography .field-label { + margin-left: 8px; +} +.fvtt-cthulhu-eternal .vehicle-biography .biodata { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; +} +.fvtt-cthulhu-eternal .vehicle-biography .biodata label { + min-width: 3rem; +} +.fvtt-cthulhu-eternal .vehicle-biography .biodata .feature { + display: flex; + align-items: center; + gap: 4px; + min-width: 18rem; + max-width: 18rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment { + background-color: var(--color-light-1); + display: grid; + grid-template-columns: 1fr; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment legend a { + font-size: calc(var(--font-size-standard) * 1.4); + padding-left: 5px; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 4px; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon { + display: flex; + align-items: center; + gap: 4px; + min-width: 13rem; + max-width: 13srem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .rollable:hover, +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .rollable:focus { + text-shadow: 0 0 8px var(--color-shadow-primary); + cursor: pointer; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .controls { + min-width: 2rem; + max-width: 2rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .damage { + min-width: 5rem; + max-width: 5rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .name { + min-width: 8rem; + max-width: 8rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .item-img { + width: 32px; + height: 32px; + margin: 4px 0 0 0; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 4px; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear { + display: flex; + align-items: center; + gap: 4px; + min-width: 13rem; + max-width: 13srem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .rollable:hover, +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .rollable:focus { + text-shadow: 0 0 8px var(--color-shadow-primary); + cursor: pointer; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .controls { + min-width: 2rem; + max-width: 2rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .damage { + min-width: 5rem; + max-width: 5rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .name { + min-width: 8rem; + max-width: 8rem; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .item-img { + width: 32px; + height: 32px; + margin: 4px 0 0 0; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment prose-mirror.inactive { + min-height: 40px; +} +.fvtt-cthulhu-eternal .tab.vehicle-equipment prose-mirror.active { + min-height: 150px; +} .fvtt-cthulhu-eternal .skill-content { font-family: var(--font-primary); font-size: calc(var(--font-size-standard) * 1); diff --git a/cthulhu-eternal.mjs b/cthulhu-eternal.mjs index 2984309..c96e15f 100644 --- a/cthulhu-eternal.mjs +++ b/cthulhu-eternal.mjs @@ -34,7 +34,8 @@ Hooks.once("init", function () { CONFIG.Actor.documentClass = documents.CthulhuEternalActor CONFIG.Actor.dataModels = { - protagonist: models.CthulhuEternalProtagonist + protagonist: models.CthulhuEternalProtagonist, + vehicle: models.CthulhuEternalVehicle } CONFIG.Item.documentClass = documents.CthulhuEternalItem @@ -54,6 +55,7 @@ Hooks.once("init", function () { // Register sheet application classes Actors.unregisterSheet("core", ActorSheet) Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalProtagonistSheet, { types: ["protagonist"], makeDefault: true }) + Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalVehicleSheet, { types: ["vehicle"], makeDefault: true }) Items.unregisterSheet("core", ItemSheet) Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalSkillSheet, { types: ["skill"], makeDefault: true }) diff --git a/gulpfile.js b/gulpfile.js index 39dbdfb..bbd4e90 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,12 +1,17 @@ const gulp = require('gulp'); const less = require('gulp-less'); +function onError(err) { + util.log(util.colors.red.bold('[ERROR LESS]:'),util.colors.bgRed(err.message)); + this.emit('end'); +}; + /* ----------------------------------------- */ /* Compile LESS /* ----------------------------------------- */ function compileLESS() { return gulp.src("styles/fvtt-cthulhu-eternal.less") - .pipe(less()) + .pipe(less()).on('error',console.log.bind(console)) .pipe(gulp.dest("./css")) } const css = gulp.series(compileLESS); diff --git a/lang/en.json b/lang/en.json index f8b9610..0987ab5 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1,7 +1,8 @@ { "TYPES": { "Actor": { - "protagonist": "Protagonist" + "protagonist": "Protagonist", + "vehicle": "Vehicle" }, "Item": { "skill": "Skill", @@ -149,6 +150,9 @@ "resourceLevel": { "label": "Resource level" }, + "state": { + "label": "State" + }, "settings": { "label": "Settings era" } @@ -177,6 +181,9 @@ "riflecarabine": "Rifle/Carabine" }, "FIELDS": { + "state": { + "label": "State" + }, "settings": { "label": "Settings era" }, @@ -232,6 +239,34 @@ } } }, + "Vehicle": { + "FIELDS": { + "description": { + "label": "Description" + }, + "notes": { + "label": "Notes" + }, + "surfaceSpeed": { + "label": "Surface Speed" + }, + "airSpeed": { + "label": "Air Speed" + }, + "armor": { + "label": "Armor" + }, + "settings": { + "label": "Settings era" + }, + "crew": { + "label": "Crew" + }, + "state": { + "label": "State" + } + } + }, "MentalDisorder": { "FIELDS": { "description": { @@ -288,6 +323,15 @@ "veryHarsh": "Very Harsh" }, "Label": { + "Vehicle": "Vehicle", + "Speed": "Speed", + "Slow": "Slow", + "Fast": "Fast", + "Average": "Average", + "None": "None", + "pristine": "Pristine", + "worn": "Worn", + "junk": "Junk", "resources": "Resources", "resourceChecks": "Resource Checks", "sanBPShort": "BP", diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs index e90dd4c..c7b3cc2 100644 --- a/module/applications/_module.mjs +++ b/module/applications/_module.mjs @@ -9,3 +9,4 @@ export { default as CthulhuEternalMentalDisorderSheet } from "./sheets/mentaldis export { default as CthulhuEternalGearSheet } from "./sheets/gear-sheet.mjs" export { default as CthulhuEternalMotivationSheet } from "./sheets/motivation-sheet.mjs" export { default as CthulhuEternalArchetypeSheet } from "./sheets/archetype-sheet.mjs" +export { default as CthulhuEternalVehicleSheet } from "./sheets/vehicle-sheet.mjs" diff --git a/module/applications/sheets/protagonist-sheet.mjs b/module/applications/sheets/protagonist-sheet.mjs index a43a5cb..0a5d4f9 100644 --- a/module/applications/sheets/protagonist-sheet.mjs +++ b/module/applications/sheets/protagonist-sheet.mjs @@ -85,23 +85,9 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS cha: game.i18n.localize("CTHULHUETERNAL.Characteristic.Cha") } - context.tooltipsRessources = { - } - - context.rollType = { - str: "characteristic", - dex: "characteristic", - con: "characteristic", - int: "characteristic", - pow: "characteristic", - cha: "characteristic" - } return context } - _generateTooltip(type, target) { - } - /** @override */ async _preparePartContext(partId, context) { const doc = this.document diff --git a/module/applications/sheets/vehicle-sheet.mjs b/module/applications/sheets/vehicle-sheet.mjs new file mode 100644 index 0000000..513ccef --- /dev/null +++ b/module/applications/sheets/vehicle-sheet.mjs @@ -0,0 +1,117 @@ +import CthulhuEternalActorSheet from "./base-actor-sheet.mjs" + +export default class CthulhuEternalVehicleSheet extends CthulhuEternalActorSheet { + /** @override */ + static DEFAULT_OPTIONS = { + classes: ["vehicle"], + position: { + width: 680, + height: 540, + }, + window: { + contentClasses: ["vehicle-content"], + }, + actions: { + createGear: CthulhuEternalVehicleSheet.#onCreateGear, + createWeapon: CthulhuEternalVehicleSheet.#onCreateWeapon, + }, + } + + /** @override */ + static PARTS = { + main: { + template: "systems/fvtt-cthulhu-eternal/templates/vehicle-main.hbs", + }, + tabs: { + template: "templates/generic/tab-navigation.hbs", + }, + equipment: { + template: "systems/fvtt-cthulhu-eternal/templates/vehicle-equipment.hbs", + }, + description: { + template: "systems/fvtt-cthulhu-eternal/templates/vehicle-description.hbs", + }, + } + + /** @override */ + tabGroups = { + sheet: "equipment", + } + + /** + * Prepare an array of form header tabs. + * @returns {Record>} + */ + #getTabs() { + const tabs = { + equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "CTHULHUETERNAL.Label.equipment" }, + description: { id: "description", group: "sheet", icon: "fa-solid fa-book", label: "CTHULHUETERNAL.Label.description" }, + } + for (const v of Object.values(tabs)) { + v.active = this.tabGroups[v.group] === v.id + v.cssClass = v.active ? "active" : "" + } + return tabs + } + + /** @override */ + async _prepareContext() { + const context = await super._prepareContext() + context.tabs = this.#getTabs() + + context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true }) + context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true }) + + return context + } + + _generateTooltip(type, target) { + } + + /** @override */ + async _preparePartContext(partId, context) { + const doc = this.document + switch (partId) { + case "main": + break + case "equipment": + context.tab = context.tabs.equipment + context.weapons = doc.itemTypes.weapon + context.gears = doc.itemTypes.gear + break + case "description": + context.tab = context.tabs.description + context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true }) + context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true }) + break + } + return context + } + + /** + * Creates a new attack item directly from the sheet and embeds it into the document. + * @param {Event} event The initiating click event. + * @param {HTMLElement} target The current target of the event listener. + */ + static #onCreateGear(event, target) { + this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }]) + } + + static #onCreateWeapon(event, target) { + this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newWeapon"), type: "weapon" }]) + } + + + async _onDrop(event) { + if (!this.isEditable || !this.isEditMode) return + const data = TextEditor.getDragEventData(event) + + // Handle different data types + switch (data.type) { + case "Item": + const item = await fromUuid(data.uuid) + return super._onDropItem(item) + } + } + +} diff --git a/module/config/system.mjs b/module/config/system.mjs index 9d47c41..56c8f88 100644 --- a/module/config/system.mjs +++ b/module/config/system.mjs @@ -113,6 +113,19 @@ export const RESOURCE_BREAKDOWN = [ { value: 20, hand: 6, stowed: 6, storage: 8, checks: 3} ] +export const VEHICLE_SPEED = { + "none": "CTHULHUETERNAL.Label.None", + "slow": "CTHULHUETERNAL.Label.Slow", + "average": "CTHULHUETERNAL.Label.Average", + "fast": "CTHULHUETERNAL.Label.Fast" +} + +export const EQUIPMENT_STATES = { + "pristine": "CTHULHUETERNAL.Label.Pristine", + "worn": "CTHULHUETERNAL.Label.Worn", + "junk": "CTHULHUETERNAL.Label.Junk" +} + export const MENTAL_ILLNESS_CURE_SKILL = { jazz: "CTHULHUETERNAL.Skill.Psychoanalyze", modern: "CTHULHUETERNAL.Skill.Psychoanalyze", @@ -213,6 +226,8 @@ export const SYSTEM = { MENTAL_ILLNESS_CURE_SKILL, ERA_CSS, INSANITY, + EQUIPMENT_STATES, RESOURCE_BREAKDOWN, + VEHICLE_SPEED, ASCII } diff --git a/module/models/_module.mjs b/module/models/_module.mjs index d726285..58ae6f2 100644 --- a/module/models/_module.mjs +++ b/module/models/_module.mjs @@ -9,3 +9,5 @@ export { default as CthulhuEternalBond } from "./bond.mjs" export { default as CthulhuEternalGear } from "./gear.mjs" export { default as CthulhuEternalMotivation } from "./motivation.mjs" export { default as CthulhuEternalArchetype } from "./archetype.mjs" +export { default as CthulhuEternalVehicle } from "./vehicle.mjs" + diff --git a/module/models/gear.mjs b/module/models/gear.mjs index 2dc050d..f8a1bc7 100644 --- a/module/models/gear.mjs +++ b/module/models/gear.mjs @@ -9,6 +9,7 @@ export default class CthulhuEternalGHear extends foundry.abstract.TypeDataModel schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS }) schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) + schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES }) return schema } diff --git a/module/models/protagonist.mjs b/module/models/protagonist.mjs index eef6282..7ad84d1 100644 --- a/module/models/protagonist.mjs +++ b/module/models/protagonist.mjs @@ -33,8 +33,8 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData }) schema.hp = new fields.SchemaField({ - value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), - max: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), + value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), + max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), stunned: new fields.BooleanField({ required: true, initial: false }) }) @@ -146,20 +146,23 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData updates[`system.hp.value`] = this.hp.max } - if ( this.resources.permanentRating <= 20) { - let breakdown = SYSTEM.RESOURCE_BREAKDOWN[this.resources.permanentRating] - if (this.resources.hand !== breakdown.hand) { - updates[`system.resources.hand`] = breakdown.hand - } - if (this.resources.stowed !== breakdown.stowed) { - updates[`system.resources.stowed`] = breakdown.stowed - } - if (this.resources.storage !== breakdown.storage) { - updates[`system.resources.storage`] = breakdown.storage - } - if (this.resources.nbValidChecks !== breakdown.checks) { - updates[`system.resources.nbValidChecks`] = breakdown.checks - } + if (this.resources.permanentRating < 0) { + updates[`system.resources.permanentRating`] = 0 + } + + let resourceIndex = Math.max(Math.min(this.resources.permanentRating, 20), 0) + let breakdown = SYSTEM.RESOURCE_BREAKDOWN[this.resources.resourceIndex] + if (this.resources.hand !== breakdown.hand) { + updates[`system.resources.hand`] = breakdown.hand + } + if (this.resources.stowed !== breakdown.stowed) { + updates[`system.resources.stowed`] = breakdown.stowed + } + if (this.resources.storage !== breakdown.storage) { + updates[`system.resources.storage`] = breakdown.storage + (this.resources.permanentRating - resourceIndex) + } + if (this.resources.nbValidChecks !== breakdown.checks) { + updates[`system.resources.nbValidChecks`] = breakdown.checks } if (Object.keys(updates).length > 0) { diff --git a/module/models/vehicle.mjs b/module/models/vehicle.mjs new file mode 100644 index 0000000..fa8ea6c --- /dev/null +++ b/module/models/vehicle.mjs @@ -0,0 +1,34 @@ +import { SYSTEM } from "../config/system.mjs" +import CthulhuEternalRoll from "../documents/roll.mjs" + +export default class CthulhuEternalVehicle extends foundry.abstract.TypeDataModel { + static defineSchema() { + const fields = foundry.data.fields + const requiredInteger = { required: true, nullable: false, integer: true } + const schema = {} + + schema.settings = new fields.StringField({ required: true, initial: "modern", choices: SYSTEM.AVAILABLE_SETTINGS }) + + schema.hp = new fields.SchemaField({ + value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), + max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }) + }) + + schema.armor = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) + schema.surfaceSpeed = new fields.StringField({ required: true, initial: "slow", choices: SYSTEM.VEHICLE_SPEED }) + schema.airSpeed = new fields.StringField({ required: true, initial: "none", choices: SYSTEM.VEHICLE_SPEED }) + schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES }) + + schema.crew = new fields.ArrayField(new fields.StringField(), { required: false, initial: [], min:0 }) + schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) + + schema.description = new fields.HTMLField({ required: true, textSearch: true }) + schema.notes = new fields.HTMLField({ required: true, textSearch: true }) + + return schema + } + + /** @override */ + static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Vehicle"] + +} diff --git a/module/models/weapon.mjs b/module/models/weapon.mjs index 10e4875..0a0ecb0 100644 --- a/module/models/weapon.mjs +++ b/module/models/weapon.mjs @@ -17,6 +17,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel { schema.killRadius = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.armorPiercing = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.weaponSubtype = new fields.StringField({ required: true, initial: "basicfirearm", choices: SYSTEM.WEAPON_SUBTYPE }) + schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES }) schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) diff --git a/packs/skills/000030.log b/packs/skills/000038.log similarity index 100% rename from packs/skills/000030.log rename to packs/skills/000038.log diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT index cc9df1d..e2ecb83 100644 --- a/packs/skills/CURRENT +++ b/packs/skills/CURRENT @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:444c150ee4bcfced9404f47e0cfe6f49b0e753a8c7ab597107844f156cf104fe +oid sha256:7aa2c6f4da8ee456f65b8594b2ecda649d2f8a0aa921953c3391b4e19417b3ea size 16 diff --git a/packs/skills/LOG b/packs/skills/LOG index 77c62ef..5db1309 100644 --- a/packs/skills/LOG +++ b/packs/skills/LOG @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fedef4174124848cc6168a83b21f68e266071db074121fc05d824d38ac6ad73 +oid sha256:67c5e30134419c54156d3f8cdaa1db648f7eacd2e9b9b97ae7aafd5ebf6b472e size 736 diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old index 3e91d39..cfa9d3c 100644 --- a/packs/skills/LOG.old +++ b/packs/skills/LOG.old @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6a199bd76b41a49f7f30d06e92188a355e3e664b71ba45bde1a088e866622a7 +oid sha256:7ca2d2a1d43a060b78887fe473a2a4b50a79d5a7ee7678ccf36e8146df44df30 size 736 diff --git a/packs/skills/MANIFEST-000028 b/packs/skills/MANIFEST-000028 deleted file mode 100644 index bbc19aa..0000000 --- a/packs/skills/MANIFEST-000028 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e2d31e6d9405a5b62c8746a8fb5ce9acc56f39c96dddcf24d3e976e4beb3aa9a -size 139 diff --git a/packs/skills/MANIFEST-000036 b/packs/skills/MANIFEST-000036 new file mode 100644 index 0000000..ebb04be --- /dev/null +++ b/packs/skills/MANIFEST-000036 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dba69be4c98b34b5e18672acc05ff3a00109aad8d5047df05e579eb06402b78 +size 139 diff --git a/styles/fvtt-cthulhu-eternal.less b/styles/fvtt-cthulhu-eternal.less index eb5b283..4c0019c 100644 --- a/styles/fvtt-cthulhu-eternal.less +++ b/styles/fvtt-cthulhu-eternal.less @@ -4,6 +4,7 @@ .fvtt-cthulhu-eternal { @import "mixins.less"; @import "protagonist.less"; + @import "vehicle.less"; @import "skill.less"; @import "injury.less"; @import "weapon.less"; @@ -17,4 +18,4 @@ @import "archetype.less"; } -@import "roll.less"; +@import "roll.less"; \ No newline at end of file diff --git a/styles/mixins.less b/styles/mixins.less index f60653b..614f80e 100644 --- a/styles/mixins.less +++ b/styles/mixins.less @@ -61,6 +61,13 @@ } } +.vehicle-sheet-common { + label { + font-family: var(--font-secondary); + font-size: calc(var(--font-size-standard) * 1.0); + } +} + .item-sheet-common { .form-fields { padding-top: 4px; diff --git a/styles/vehicle.less b/styles/vehicle.less new file mode 100644 index 0000000..3ca9cf1 --- /dev/null +++ b/styles/vehicle.less @@ -0,0 +1,223 @@ +.vehicle-content { + .sheet-common(); + .vehicle-sheet-common(); + overflow: scroll; +} + +.sheet-tabs { + background-color: var(--color-light-1); +} + +.vehicle-main { + background-color: var(--color-light-1); + display: flex; + + .vehicle-pc { + display: flex; + gap: 4px; + flex: 1; + + .vehicle-left { + min-width: 180px; + display: flex; + flex-direction: column; + + .vehicle-left-image { + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 8px; + .vehicle-img { + height: 140px; + width: auto; + border: none; + } + } + + } + + .vehicle-right { + display: flex; + flex-direction: column; + gap: 5px; + + .vehicle-name { + display: flex; + input { + font-family: var(--font-title); + font-size: calc(var(--font-size-standard) * 1.4); + width: 400px; + } + } + + .vehicle-infos { + display: flex; + flex-direction: column; + gap: 4px; + + label { + min-width: 120px; + } + + .vehicle-hp { + display: flex; + gap: 2px; + align-items: center; + .vehicle-hp-value { + .form-fields input { + flex: none; + width: 50px; + margin-left: 4px; + font-size: calc(var(--font-size-standard) * 1.4); + } + } + .vehicle-hp-max { + clear: both; + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: 3px 0; + align-items: center; + input { + width: 50px; + text-align: center; + font-size: calc(var(--font-size-standard) * 1.4); + } + } + .hp-separator { + font-size: calc(var(--font-size-standard) * 1.2); + display: flex; + align-items: center; + justify-content: center; + } + } + } + } + } + + .vehicle-pc-play { + min-width: 500px; + } + + .vehicle-pc-edit { + min-width: 650px; + } +} + +.vehicle-biography { + background-color: var(--color-light-1); + prose-mirror.inactive { + min-height: 40px; + } + prose-mirror.active { + min-height: 150px; + } + .field-label { + margin-left: 8px; + } + + + .biodata { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; + label { + min-width: 3.0rem; + } + .feature { + display: flex; + align-items: center; + gap: 4px; + min-width: 18rem; + max-width: 18rem; + } + } + +} + +.tab.vehicle-equipment { + background-color: var(--color-light-1); + display: grid; + grid-template-columns: 1fr; + legend { + a { + font-size: calc(var(--font-size-standard) * 1.4); + padding-left: 5px; + } + } + .weapons { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 4px; + .weapon { + display: flex; + align-items: center; + gap: 4px; + min-width: 13rem; + max-width: 13srem; + .rollable:hover, + .rollable:focus { + text-shadow: 0 0 8px var(--color-shadow-primary); + cursor: pointer; + } + .controls { + min-width: 2rem; + max-width: 2rem; + } + .damage { + min-width: 5rem; + max-width: 5rem; + } + .name { + min-width: 8rem; + max-width: 8rem; + } + .item-img { + width: 32px; + height: 32px; + margin: 4px 0 0 0; + } + } + } + .gears { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 4px; + .gear { + display: flex; + align-items: center; + gap: 4px; + min-width: 13rem; + max-width: 13srem; + .rollable:hover, + .rollable:focus { + text-shadow: 0 0 8px var(--color-shadow-primary); + cursor: pointer; + } + .controls { + min-width: 2rem; + max-width: 2rem; + } + .damage { + min-width: 5rem; + max-width: 5rem; + } + .name { + min-width: 8rem; + max-width: 8rem; + } + .item-img { + width: 32px; + height: 32px; + margin: 4px 0 0 0; + } + } + } + + prose-mirror.inactive { + min-height: 40px; + } + prose-mirror.active { + min-height: 150px; + } +} diff --git a/system.json b/system.json index f45a54b..af1efe0 100644 --- a/system.json +++ b/system.json @@ -34,7 +34,8 @@ ], "documentTypes": { "Actor": { - "protagonist": { "htmlFields": ["description", "notes"] } + "protagonist": { "htmlFields": ["description", "notes"] }, + "vehicle": { "htmlFields": ["description", "notes"] } }, "Item": { "skill": { "htmlFields": ["description"] }, diff --git a/templates/gear.hbs b/templates/gear.hbs index 414da67..670fd13 100644 --- a/templates/gear.hbs +++ b/templates/gear.hbs @@ -7,6 +7,7 @@
{{formField systemFields.settings value=system.settings localize=true}} {{formField systemFields.resourceLevel value=system.resourceLevel}} + {{formField systemFields.state value=system.state}}
diff --git a/templates/protagonist-biography.hbs b/templates/protagonist-biography.hbs index 7e6ec5e..9407d3e 100644 --- a/templates/protagonist-biography.hbs +++ b/templates/protagonist-biography.hbs @@ -9,11 +9,12 @@ {{formField systemFields.resources.fields.storage value=system.resources.storage name="system.resources.storage" localize=true disabled=true}}
{{localize "CTHULHUETERNAL.Label.resourceChecks"}} - {{#each system.resources.checks as |check idx|}} + {{#each system.resources.checks as |check idx|}} {{/each}} -
+ +
diff --git a/templates/vehicle-description.hbs b/templates/vehicle-description.hbs new file mode 100644 index 0000000..53f3759 --- /dev/null +++ b/templates/vehicle-description.hbs @@ -0,0 +1,12 @@ +
+ +
+ {{localize "CTHULHUETERNAL.Label.description"}} + {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}} +
+ +
+ {{localize "CTHULHUETERNAL.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/vehicle-equipment.hbs b/templates/vehicle-equipment.hbs new file mode 100644 index 0000000..5e9013b --- /dev/null +++ b/templates/vehicle-equipment.hbs @@ -0,0 +1,54 @@ +
+ +
+ {{localize "CTHULHUETERNAL.Label.weapons"}}{{#if isEditMode}} + {{/if}} + +
+ {{#each weapons as |item|}} + {{!log 'weapon' this}} + + {{/each}} +
+
+ +
+ {{localize "CTHULHUETERNAL.Label.gears"}}{{#if isEditMode}} + {{/if}} + +
+ {{#each gears as |item|}} + {{!log 'armor' this}} +
+ +
+ {{item.name}} +
+
+ + +
+
+ {{/each}} +
+
+ +
\ No newline at end of file diff --git a/templates/vehicle-main.hbs b/templates/vehicle-main.hbs new file mode 100644 index 0000000..4272fa2 --- /dev/null +++ b/templates/vehicle-main.hbs @@ -0,0 +1,52 @@ +
+ +
+ {{localize "CTHULHUETERNAL.Label.vehicle"}} +
+
+
+ +
+
+ {{localize "CTHULHUETERNAL.Label.HP"}} +
+ {{formField systemFields.hp.fields.value value=system.hp.value}} + / + {{formField systemFields.hp.fields.max value=system.hp.max rootId=partId disabled=true}} +
+
+ +
+ +
+
+ {{formInput fields.name value=source.name rootId=partId disabled=isPlayMode}} + + + +
+ + +
+ {{localize "CTHULHUETERNAL.Label.Speed"}} +
+ {{formField systemFields.surfaceSpeed value=system.surfaceSpeed localize=true}} + {{formField systemFields.airSpeed value=system.airSpeed localize=true}} + +
+
+ +
+ {{localize "CTHULHUETERNAL.Label.armor"}} +
+ {{formField systemFields.armor value=system.armor localize=true}} +
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/templates/weapon.hbs b/templates/weapon.hbs index 160d788..bea9e21 100644 --- a/templates/weapon.hbs +++ b/templates/weapon.hbs @@ -11,6 +11,8 @@ {{formField systemFields.weaponSubtype value=system.weaponSubtype localize=true}} {{/if}} + {{formField systemFields.state value=system.state}} + {{formField systemFields.damage value=system.damage}} {{formField systemFields.baseRange value=system.baseRange}} {{formField systemFields.rangeUnit value=system.rangeUnit localize=true}}