diff --git a/LICENSE.txt b/LICENSE.txt index 740121c9..515e8f90 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2020 Foundry Network - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2020 Foundry Network + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 89eb0cc1..9dcbe040 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,9 @@ NICE TO HAVE: # Changelog +- 02/06/2020 - Esrin - Temporary display fixes to Minion and Vehicle sheets awaiting CStadther's eventual restyle. +- 02/06/2020 - Esrin - Minor bugfix to character sheet, soak value set to disabled for auto-calculation, encumbrance max and current values swapped to correct fields and current set to disabled for auto-calculation. +- 02/06/2020 - CStadther - Major sheet restyling - 02/06/2020 - Jaxxa - Added Icons in the Dice roller, visually indicating the dice types. - 31/05/2020 - Esrin - Work in progress on the group management GM tool. Destiny Pool now working (will reset on page refresh). Player Character list under construction. - 31/05/2020 - Esrin - Bugfix to localisation hook for Gear Quantity on Character Sheet (thanks Alex | HDScurox for the bug report). diff --git a/lang/en.json b/lang/en.json index 3547cb0d..771070f3 100644 --- a/lang/en.json +++ b/lang/en.json @@ -14,7 +14,7 @@ "SWFFG.ForcePool": "Force Pool", "SWFFG.ForcePoolCommitted": "Committed", "SWFFG.ForcePoolAvailable": "Available", - "SWFFG.Encumbrance": "Encum", + "SWFFG.Encumbrance": "Encumbrance", "SWFFG.TabCharacteristics": "Characteristics", "SWFFG.TabGear": "Gear & Equipment", "SWFFG.TabTalents": "Talents", @@ -25,9 +25,9 @@ "SWFFG.CharacteristicCunning": "Cunning", "SWFFG.CharacteristicWillpower": "Willpower", "SWFFG.CharacteristicPresence": "Presence", - "SWFFG.SkillsGeneral": "General", - "SWFFG.SkillsCombat": "Combat", - "SWFFG.SkillsKnowledge": "Knowledge", + "SWFFG.SkillsGeneral": "General Skills", + "SWFFG.SkillsCombat": "Combat Skills", + "SWFFG.SkillsKnowledge": "Knowledge Skills", "SWFFG.SkillsName": "Name", "SWFFG.SkillsCS": "CS", "SWFFG.SkillsCareerSkill": "Career Skill", @@ -61,5 +61,17 @@ "SWFFG.DescriptionObligation": "Obligation", "SWFFG.DescriptionDuty": "Duty", "SWFFG.DescriptionMorality": "Morality", - "SWFFG.DescriptionConflict": "Conflict" + "SWFFG.DescriptionConflict": "Conflict", + "SWFFG.ItemWeaponDamage": "Dmg", + "SWFFG.ItemWeaponCritical": "Crit", + "SWFFG.ItemWeaponEncumbrance": "Encum", + "SWFFG.ItemWeaponHardPoints": "HP", + "SWFFG.ItemWeaponRarity": "Rarity", + "SWFFG.ItemWeaponSkill": "Skill", + "SWFFG.ItemWeaponRange": "Range", + "SWFFG.ItemWeaponPrice": "Price", + "SWFFG.ItemWeaponQuantity": "Qty", + "SWFFG.ItemWeaponSpecial": "Special", + "SWFFG.ItemArmorDefense": "Def", + "SWFFG.ItemTalentRanked": "Ranked?" } diff --git a/modules/actors/actor-ffg.js b/modules/actors/actor-ffg.js index db26ab73..ae8d0b95 100644 --- a/modules/actors/actor-ffg.js +++ b/modules/actors/actor-ffg.js @@ -1,110 +1,110 @@ -/** - * Extend the base Actor entity. - * @extends {Actor} - */ -export class ActorFFG extends Actor { - /** - * Augment the basic actor data with additional dynamic data. - */ - prepareData() { - super.prepareData(); - - const actorData = this.data; - const data = actorData.data; - const flags = actorData.flags; - - // Make separate methods for each Actor type (character, minion, etc.) to keep - // things organized. - if (actorData.type === "minion") this._prepareMinionData(actorData); - if (actorData.type === "character") this._prepareCharacterData(actorData); - } - - /** - * Prepare Minion type specific data - */ - _prepareMinionData(actorData) { - const data = actorData.data; - - // Set Wounds threshold to unit_wounds * quantity to account for minion group health. - data.stats.wounds.max = Math.floor(data.unit_wounds.value * data.quantity.value); - // Check we don't go below 0. - if (data.stats.wounds.max < 0) { - data.stats.wounds.max = 0; - } - - // Loop through Skills, and where groupskill = true, set the rank to 1*(quantity-1). - for (let [key, skill] of Object.entries(data.skills)) { - // Check to see if this is a group skill, otherwise do nothing. - if (skill.groupskill) { - skill.rank = Math.floor(1 * (data.quantity.value - 1)); - // Check we don't go below 0. - if (skill.rank < 0) { - skill.rank = 0; - } - } else if (!skill.groupskill) { - skill.rank = 0; - } - } - } - - /** - * Prepare Character type specific data - */ - _prepareCharacterData(actorData) { - const data = actorData.data; - const items = actorData.items; - var soak = 0; - var armoursoak = 0; - var othersoak = 0; - var encum = 0; - - // Calculate soak based on Brawn value, and any Soak modifiers in weapons, armour, gear and talents. - // Start with Brawn. Also calculate total encumbrance from items. - soak = +data.characteristics.Brawn.value; - - for (let characteristic of Object.keys(data.characteristics)) { - const strId = `SWFFG.Characteristic${this._capitalize(characteristic)}`; - const localizedField = game.i18n.localize(strId); - - data.characteristics[characteristic].label = localizedField; - } - - // Loop through all items - for (let [key, item] of Object.entries(items)) { - // For armour type, get all Soak values and add to armoursoak. - if (item.type == "armour") { - armoursoak += +item.data.soak.value; - } - // Loop through all item attributes and add any modifiers to our collection. - for (let [k, mod] of Object.entries(item.data.attributes)) { - if (mod.mod == "Soak") { - othersoak += +mod.value; - } - } - - // Calculate encumbrance. - if (item.type != "talent") { - encum += +item.data.encumbrance.value; - } - } - - // Set Encumbrance value on character. - data.stats.encumbrance.value = encum; - - // Add together all of our soak results. - soak += +armoursoak; - soak += +othersoak; - - // Finally set Soak value on character. - data.stats.soak.value = soak; - } - - /** - * Capitalize string - * @param {String} s String value to capitalize - */ - _capitalize(s) { - if (typeof s !== 'string') return '' - return s.charAt(0).toUpperCase() + s.slice(1) - } -} +/** + * Extend the base Actor entity. + * @extends {Actor} + */ +export class ActorFFG extends Actor { + /** + * Augment the basic actor data with additional dynamic data. + */ + prepareData() { + super.prepareData(); + + const actorData = this.data; + const data = actorData.data; + const flags = actorData.flags; + + // Make separate methods for each Actor type (character, minion, etc.) to keep + // things organized. + if (actorData.type === "minion") this._prepareMinionData(actorData); + if (actorData.type === "character") this._prepareCharacterData(actorData); + } + + /** + * Prepare Minion type specific data + */ + _prepareMinionData(actorData) { + const data = actorData.data; + + // Set Wounds threshold to unit_wounds * quantity to account for minion group health. + data.stats.wounds.max = Math.floor(data.unit_wounds.value * data.quantity.value); + // Check we don't go below 0. + if (data.stats.wounds.max < 0) { + data.stats.wounds.max = 0; + } + + // Loop through Skills, and where groupskill = true, set the rank to 1*(quantity-1). + for (let [key, skill] of Object.entries(data.skills)) { + // Check to see if this is a group skill, otherwise do nothing. + if (skill.groupskill) { + skill.rank = Math.floor(1 * (data.quantity.value - 1)); + // Check we don't go below 0. + if (skill.rank < 0) { + skill.rank = 0; + } + } else if (!skill.groupskill) { + skill.rank = 0; + } + } + } + + /** + * Prepare Character type specific data + */ + _prepareCharacterData(actorData) { + const data = actorData.data; + const items = actorData.items; + var soak = 0; + var armoursoak = 0; + var othersoak = 0; + var encum = 0; + + // Calculate soak based on Brawn value, and any Soak modifiers in weapons, armour, gear and talents. + // Start with Brawn. Also calculate total encumbrance from items. + soak = +data.characteristics.Brawn.value; + + for (let characteristic of Object.keys(data.characteristics)) { + const strId = `SWFFG.Characteristic${this._capitalize(characteristic)}`; + const localizedField = game.i18n.localize(strId); + + data.characteristics[characteristic].label = localizedField; + } + + // Loop through all items + for (let [key, item] of Object.entries(items)) { + // For armour type, get all Soak values and add to armoursoak. + if (item.type == "armour") { + armoursoak += +item.data.soak.value; + } + // Loop through all item attributes and add any modifiers to our collection. + for (let [k, mod] of Object.entries(item.data.attributes)) { + if (mod.mod == "Soak") { + othersoak += +mod.value; + } + } + + // Calculate encumbrance. + if (item.type != "talent") { + encum += +item.data.encumbrance.value; + } + } + + // Set Encumbrance value on character. + data.stats.encumbrance.value = encum; + + // Add together all of our soak results. + soak += +armoursoak; + soak += +othersoak; + + // Finally set Soak value on character. + data.stats.soak.value = soak; + } + + /** + * Capitalize string + * @param {String} s String value to capitalize + */ + _capitalize(s) { + if (typeof s !== 'string') return '' + return s.charAt(0).toUpperCase() + s.slice(1) + } +} diff --git a/modules/actors/actor-sheet-ffg.js b/modules/actors/actor-sheet-ffg.js index 53768a96..a40f32c5 100644 --- a/modules/actors/actor-sheet-ffg.js +++ b/modules/actors/actor-sheet-ffg.js @@ -1,330 +1,330 @@ -/** - * Extend the basic ActorSheet with some very simple modifications - * @extends {ActorSheet} - */ -export class ActorSheetFFG extends ActorSheet { - constructor(...args) { - super(...args); - /** - * Track the set of filters which are applied - * @type {Set} - */ - this._filters = { - skills: new Set(), - }; - } - - pools = new Map(); - - /** @override */ - static get defaultOptions() { - return mergeObject(super.defaultOptions, { - classes: ["starwarsffg", "sheet", "actor"], - template: "systems/starwarsffg/templates/actors/ffg-character-sheet.html", - width: 710, - height: 650, - tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "characteristics" }], - }); - } - - /** @override */ - get template() { - const path = "systems/starwarsffg/templates/actors"; - return `${path}/ffg-${this.actor.data.type}-sheet.html`; - } - - /* -------------------------------------------- */ - - /** @override */ - getData() { - const data = super.getData(); - data.dtypes = ["String", "Number", "Boolean"]; - for (let attr of Object.values(data.data.attributes)) { - attr.isCheckbox = attr.dtype === "Boolean"; - } - data.FFG = CONFIG.FFG; - - switch (this.actor.data.type) { - case "character": - this.position.width = 610; - this.position.height = 840; - break; - case "minion": - this.position.width = 700; - this.position.height = 620; - break; - case "vehicle": - this.position.width = 710; - this.position.height = 650; - default: - } - return data; - } - - /* -------------------------------------------- */ - - /** @override */ - activateListeners(html) { - super.activateListeners(html); - - // TODO: This is not needed in Foundry 0.6.0 - // Activate tabs - let tabs = html.find(".tabs"); - let initial = this._sheetTab; - new TabsV2(tabs, { - initial: initial, - callback: (clicked) => (this._sheetTab = clicked.data("tab")), - }); - - // Everything below here is only needed if the sheet is editable - if (!this.options.editable) return; - - // Update Inventory Item - By clicking entire line - html.find(".item").click((ev) => { - if (!$(ev.target).hasClass("fa-trash")) { - const li = $(ev.currentTarget); - const item = this.actor.getOwnedItem(li.data("itemId")); - if(item?.sheet) { - item.sheet.render(true); - } - } - }); - // Update Talent - By clicking entire line - html.find(".talents.item").click((ev) => { - if (!$(ev.target).hasClass("fa-trash")) { - const li = $(ev.currentTarget); - const item = this.actor.getOwnedItem(li.data("itemId")); - item.sheet.render(true); - } - }); - - // Delete Inventory Item - html.find(".item-delete").click((ev) => { - const li = $(ev.currentTarget).parents(".item"); - this.actor.deleteOwnedItem(li.data("itemId")); - li.slideUp(200, () => this.render(false)); - }); - - // Set skill filter element. - html.find(".skillfilter").each((_, elem) => { - const filters = this._filters.skills; - if (!filters.filter) { - filters.filter = "all"; - } - }); - - // Update radio button checked status for skill filter controls. - html.find(".filter-control").each((_, elem) => { - if (elem.id == this._filters.skills.filter) { - elem.checked = true; - } else { - elem.checked = false; - } - }); - - // Setup dice pool image and hide filtered skills - html.find(".skill").each((_, elem) => { - this._addSkillDicePool(elem); - const filters = this._filters.skills; - if (filters.filter != "all") { - if (elem.dataset["skilltype"] != filters.filter) { - elem.style.display = "none"; - } else { - elem.style.display = ""; - } - } - }); - - // Roll Skill - html - .find(".roll-button") - .children() - .on("click", async (event) => { - let upgradeType = null; - if (event.ctrlKey && !event.shiftKey) { - upgradeType = "ability"; - } else if (!event.ctrlKey && event.shiftKey) { - upgradeType = "difficulty"; - } - await this._rollSkill(event, upgradeType); - }); - - // Add or Remove Attribute - html.find(".attributes").on("click", ".attribute-control", this._onClickAttributeControl.bind(this)); - - // Update Filter value. - html.find(".skillfilter").on("click", ".filter-control", this._onClickFilterControl.bind(this)); - } - - /* -------------------------------------------- */ - - /** - * Listen for click events on an attribute control to modify the composition of attributes in the sheet - * @param {MouseEvent} event The originating left click event - * @private - */ - async _onClickAttributeControl(event) { - event.preventDefault(); - const a = event.currentTarget; - const action = a.dataset.action; - const attrs = this.object.data.data.attributes; - const form = this.form; - - // Add new attribute - if (action === "create") { - const nk = Object.keys(attrs).length + 1; - let newKey = document.createElement("div"); - newKey.innerHTML = ``; - form.appendChild(newKey); - await this._onSubmit(event); - } - - // Remove existing attribute - else if (action === "delete") { - const li = a.closest(".attribute"); - li.parentElement.removeChild(li); - await this._onSubmit(event); - } - } - - /** - * Listen for click events on a filter control to modify the selected filter option. - * @param {MouseEvent} event The originating left click event - * @private - */ - async _onClickFilterControl(event) { - event.preventDefault(); - const a = event.currentTarget; - const filters = this._filters.skills; - var filter = a.id; - $(a).prop("checked", true); - filters.filter = filter; - await this._onSubmit(event); - } - - /* -------------------------------------------- */ - - /** @override */ - _updateObject(event, formData) { - // Handle the free-form attributes list - const formAttrs = expandObject(formData).data.attributes || {}; - const attributes = Object.values(formAttrs).reduce((obj, v) => { - let k = v["key"].trim(); - if (/[\s\.]/.test(k)) return ui.notifications.error("Attribute keys may not contain spaces or periods"); - delete v["key"]; - obj[k] = v; - return obj; - }, {}); - - // Remove attributes which are no longer used - for (let k of Object.keys(this.object.data.data.attributes)) { - if (!attributes.hasOwnProperty(k)) attributes[`-=${k}`] = null; - } - - // Re-combine formData - formData = Object.entries(formData) - .filter((e) => !e[0].startsWith("data.attributes")) - .reduce( - (obj, e) => { - obj[e[0]] = e[1]; - return obj; - }, - { _id: this.object._id, "data.attributes": attributes } - ); - - // Update the Actor - return this.object.update(formData); - } - - async _rollSkillManual(skill, ability, difficulty) { - const dicePool = new DicePoolFFG({ - ability: ability, - difficulty: difficulty, - }); - dicePool.upgrade(skill); - await this._completeRollManual(dicePool, skillName); - } - - async _rollSkill(event, upgradeType) { - const data = this.getData(); - const row = event.target.parentElement.parentElement; - const skillName = row.parentElement.dataset["ability"]; - const skill = data.data.skills[skillName]; - const characteristic = data.data.characteristics[skill.characteristic]; - - const dicePool = new DicePoolFFG({ - ability: characteristic.value, - difficulty: 2, // Default to average difficulty - }); - dicePool.upgrade(skill.rank); - - if (upgradeType === "ability") { - dicePool.upgrade(); - } else if (upgradeType === "difficulty") { - dicePool.upgradeDifficulty(); - } - - await this._completeRoll(dicePool, `Rolling ${skillName}`, skillName); - } - - async _completeRoll(dicePool, description, skillName) { - const id = randomID(); - - const content = await renderTemplate("systems/starwarsffg/templates/roll-options.html", { - dicePool, - id, - }); - - new Dialog({ - title: description || "Finalize your roll", - content, - buttons: { - one: { - icon: '', - label: "Roll", - callback: () => { - const container = document.getElementById(id); - const finalPool = DicePoolFFG.fromContainer(container); - - ChatMessage.create({ - user: game.user._id, - speaker: this.getData(), - flavor: `Rolling ${skillName}...`, - sound: CONFIG.sounds.dice, - content: `/sw ${finalPool.renderDiceExpression()}`, - }); - }, - }, - two: { - icon: '', - label: "Cancel", - }, - }, - }).render(true); - } - - async _completeRollManual(dicePool, skillName) { - ChatMessage.create({ - user: game.user._id, - speaker: this.getData(), - flavor: `Rolling ${skillName}...`, - sound: CONFIG.sounds.dice, - content: `/sw ${dicePool.renderDiceExpression()}`, - }); - } - - _addSkillDicePool(elem) { - const data = this.getData(); - const skillName = elem.dataset["ability"]; - const skill = data.data.skills[skillName]; - const characteristic = data.data.characteristics[skill.characteristic]; - - const dicePool = new DicePoolFFG({ - ability: Math.max(characteristic.value, skill.rank), - }); - dicePool.upgrade(Math.min(characteristic.value, skill.rank)); - - const rollButton = elem.querySelector(".roll-button"); - dicePool.renderPreview(rollButton); - } -} +/** + * Extend the basic ActorSheet with some very simple modifications + * @extends {ActorSheet} + */ +export class ActorSheetFFG extends ActorSheet { + constructor(...args) { + super(...args); + /** + * Track the set of filters which are applied + * @type {Set} + */ + this._filters = { + skills: new Set(), + }; + } + + pools = new Map(); + + /** @override */ + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ["starwarsffg", "sheet", "actor"], + template: "systems/starwarsffg/templates/actors/ffg-character-sheet.html", + width: 710, + height: 650, + tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "characteristics" }], + }); + } + + /** @override */ + get template() { + const path = "systems/starwarsffg/templates/actors"; + return `${path}/ffg-${this.actor.data.type}-sheet.html`; + } + + /* -------------------------------------------- */ + + /** @override */ + getData() { + const data = super.getData(); + data.dtypes = ["String", "Number", "Boolean"]; + for (let attr of Object.values(data.data.attributes)) { + attr.isCheckbox = attr.dtype === "Boolean"; + } + data.FFG = CONFIG.FFG; + + switch (this.actor.data.type) { + case "character": + this.position.width = 610; + this.position.height = 840; + break; + case "minion": + this.position.width = 700; + this.position.height = 620; + break; + case "vehicle": + this.position.width = 710; + this.position.height = 650; + default: + } + return data; + } + + /* -------------------------------------------- */ + + /** @override */ + activateListeners(html) { + super.activateListeners(html); + + // TODO: This is not needed in Foundry 0.6.0 + // Activate tabs + let tabs = html.find(".tabs"); + let initial = this._sheetTab; + new TabsV2(tabs, { + initial: initial, + callback: (clicked) => (this._sheetTab = clicked.data("tab")), + }); + + // Everything below here is only needed if the sheet is editable + if (!this.options.editable) return; + + // Update Inventory Item - By clicking entire line + html.find(".item").click((ev) => { + if (!$(ev.target).hasClass("fa-trash")) { + const li = $(ev.currentTarget); + const item = this.actor.getOwnedItem(li.data("itemId")); + if(item?.sheet) { + item.sheet.render(true); + } + } + }); + // Update Talent - By clicking entire line + html.find(".talents.item").click((ev) => { + if (!$(ev.target).hasClass("fa-trash")) { + const li = $(ev.currentTarget); + const item = this.actor.getOwnedItem(li.data("itemId")); + item.sheet.render(true); + } + }); + + // Delete Inventory Item + html.find(".item-delete").click((ev) => { + const li = $(ev.currentTarget).parents(".item"); + this.actor.deleteOwnedItem(li.data("itemId")); + li.slideUp(200, () => this.render(false)); + }); + + // Set skill filter element. + html.find(".skillfilter").each((_, elem) => { + const filters = this._filters.skills; + if (!filters.filter) { + filters.filter = "all"; + } + }); + + // Update radio button checked status for skill filter controls. + html.find(".filter-control").each((_, elem) => { + if (elem.id == this._filters.skills.filter) { + elem.checked = true; + } else { + elem.checked = false; + } + }); + + // Setup dice pool image and hide filtered skills + html.find(".skill").each((_, elem) => { + this._addSkillDicePool(elem); + const filters = this._filters.skills; + if (filters.filter != "all") { + if (elem.dataset["skilltype"] != filters.filter) { + elem.style.display = "none"; + } else { + elem.style.display = ""; + } + } + }); + + // Roll Skill + html + .find(".roll-button") + .children() + .on("click", async (event) => { + let upgradeType = null; + if (event.ctrlKey && !event.shiftKey) { + upgradeType = "ability"; + } else if (!event.ctrlKey && event.shiftKey) { + upgradeType = "difficulty"; + } + await this._rollSkill(event, upgradeType); + }); + + // Add or Remove Attribute + html.find(".attributes").on("click", ".attribute-control", this._onClickAttributeControl.bind(this)); + + // Update Filter value. + html.find(".skillfilter").on("click", ".filter-control", this._onClickFilterControl.bind(this)); + } + + /* -------------------------------------------- */ + + /** + * Listen for click events on an attribute control to modify the composition of attributes in the sheet + * @param {MouseEvent} event The originating left click event + * @private + */ + async _onClickAttributeControl(event) { + event.preventDefault(); + const a = event.currentTarget; + const action = a.dataset.action; + const attrs = this.object.data.data.attributes; + const form = this.form; + + // Add new attribute + if (action === "create") { + const nk = Object.keys(attrs).length + 1; + let newKey = document.createElement("div"); + newKey.innerHTML = ``; + form.appendChild(newKey); + await this._onSubmit(event); + } + + // Remove existing attribute + else if (action === "delete") { + const li = a.closest(".attribute"); + li.parentElement.removeChild(li); + await this._onSubmit(event); + } + } + + /** + * Listen for click events on a filter control to modify the selected filter option. + * @param {MouseEvent} event The originating left click event + * @private + */ + async _onClickFilterControl(event) { + event.preventDefault(); + const a = event.currentTarget; + const filters = this._filters.skills; + var filter = a.id; + $(a).prop("checked", true); + filters.filter = filter; + await this._onSubmit(event); + } + + /* -------------------------------------------- */ + + /** @override */ + _updateObject(event, formData) { + // Handle the free-form attributes list + const formAttrs = expandObject(formData).data.attributes || {}; + const attributes = Object.values(formAttrs).reduce((obj, v) => { + let k = v["key"].trim(); + if (/[\s\.]/.test(k)) return ui.notifications.error("Attribute keys may not contain spaces or periods"); + delete v["key"]; + obj[k] = v; + return obj; + }, {}); + + // Remove attributes which are no longer used + for (let k of Object.keys(this.object.data.data.attributes)) { + if (!attributes.hasOwnProperty(k)) attributes[`-=${k}`] = null; + } + + // Re-combine formData + formData = Object.entries(formData) + .filter((e) => !e[0].startsWith("data.attributes")) + .reduce( + (obj, e) => { + obj[e[0]] = e[1]; + return obj; + }, + { _id: this.object._id, "data.attributes": attributes } + ); + + // Update the Actor + return this.object.update(formData); + } + + async _rollSkillManual(skill, ability, difficulty) { + const dicePool = new DicePoolFFG({ + ability: ability, + difficulty: difficulty, + }); + dicePool.upgrade(skill); + await this._completeRollManual(dicePool, skillName); + } + + async _rollSkill(event, upgradeType) { + const data = this.getData(); + const row = event.target.parentElement.parentElement; + const skillName = row.parentElement.dataset["ability"]; + const skill = data.data.skills[skillName]; + const characteristic = data.data.characteristics[skill.characteristic]; + + const dicePool = new DicePoolFFG({ + ability: characteristic.value, + difficulty: 2, // Default to average difficulty + }); + dicePool.upgrade(skill.rank); + + if (upgradeType === "ability") { + dicePool.upgrade(); + } else if (upgradeType === "difficulty") { + dicePool.upgradeDifficulty(); + } + + await this._completeRoll(dicePool, `Rolling ${skillName}`, skillName); + } + + async _completeRoll(dicePool, description, skillName) { + const id = randomID(); + + const content = await renderTemplate("systems/starwarsffg/templates/roll-options.html", { + dicePool, + id, + }); + + new Dialog({ + title: description || "Finalize your roll", + content, + buttons: { + one: { + icon: '', + label: "Roll", + callback: () => { + const container = document.getElementById(id); + const finalPool = DicePoolFFG.fromContainer(container); + + ChatMessage.create({ + user: game.user._id, + speaker: this.getData(), + flavor: `Rolling ${skillName}...`, + sound: CONFIG.sounds.dice, + content: `/sw ${finalPool.renderDiceExpression()}`, + }); + }, + }, + two: { + icon: '', + label: "Cancel", + }, + }, + }).render(true); + } + + async _completeRollManual(dicePool, skillName) { + ChatMessage.create({ + user: game.user._id, + speaker: this.getData(), + flavor: `Rolling ${skillName}...`, + sound: CONFIG.sounds.dice, + content: `/sw ${dicePool.renderDiceExpression()}`, + }); + } + + _addSkillDicePool(elem) { + const data = this.getData(); + const skillName = elem.dataset["ability"]; + const skill = data.data.skills[skillName]; + const characteristic = data.data.characteristics[skill.characteristic]; + + const dicePool = new DicePoolFFG({ + ability: Math.max(characteristic.value, skill.rank), + }); + dicePool.upgrade(Math.min(characteristic.value, skill.rank)); + + const rollButton = elem.querySelector(".roll-button"); + dicePool.renderPreview(rollButton); + } +} diff --git a/modules/combat-ffg.js b/modules/combat-ffg.js index e17e35af..385d83db 100644 --- a/modules/combat-ffg.js +++ b/modules/combat-ffg.js @@ -1,69 +1,69 @@ -/** - * Extend the base Combat entity. - * @extends {Combat} - */ -export class CombatFFG extends Combat { - - /** @override */ - _getInitiativeRoll(combatant, formula) { - const cData = combatant.actor.data.data; - const origFormula = formula; - - if (combatant.actor.data.type === "vehicle") { return new Roll("0"); } - - if (formula === "Vigilance") { - formula = _getInitiativeFormula(cData.skills.Vigilance.rank, cData.characteristics.Willpower.value, 0); - } - else if (formula === "Cool") { - formula = _getInitiativeFormula(cData.skills.Cool.rank, cData.characteristics.Presence.value, 0); - } - - const rollData = combatant.actor ? combatant.actor.getRollData() : {}; - const letters = formula.split(''); - const rolls = []; - const getSuc = new RegExp('Successes: ([0-9]+)', 'g'); - const getAdv = new RegExp('Advantages: ([0-9]+)', 'g'); - - for (const letter of letters) { - rolls.push(game.ffg.StarWars.letterToRolls(letter, 1)); - } - - let newformula = combineAll(rolls, game.ffg.StarWars.rollValuesMonoid); - - let rolling = game.specialDiceRoller.starWars.roll(newformula); - - let results = game.specialDiceRoller.starWars.formatRolls(rolling); - - let success = 0; - let advantage = 0; - - success = getSuc.exec(results); - if (success) { success = success[1]; } - advantage = getAdv.exec(results); - if (advantage) { advantage = advantage[1]; } - - let total = +success+(advantage*0.01); - - console.log(`Total is: ${total}`); - - let roll = new Roll(origFormula, rollData).roll(); - roll._result = total; - roll._total = total; - - return roll; - } -} - -function combineAll(values, monoid) { - return values - .reduce((prev, curr) => monoid.combine(prev, curr), monoid.identity); -} - -function _getInitiativeFormula(skill, ability, difficulty) { - const dicePool = new DicePoolFFG({ - ability: ability, - difficulty: difficulty - }); - dicePool.upgrade(skill); - return dicePool.renderDiceExpression(); -} +/** + * Extend the base Combat entity. + * @extends {Combat} + */ +export class CombatFFG extends Combat { + + /** @override */ + _getInitiativeRoll(combatant, formula) { + const cData = combatant.actor.data.data; + const origFormula = formula; + + if (combatant.actor.data.type === "vehicle") { return new Roll("0"); } + + if (formula === "Vigilance") { + formula = _getInitiativeFormula(cData.skills.Vigilance.rank, cData.characteristics.Willpower.value, 0); + } + else if (formula === "Cool") { + formula = _getInitiativeFormula(cData.skills.Cool.rank, cData.characteristics.Presence.value, 0); + } + + const rollData = combatant.actor ? combatant.actor.getRollData() : {}; + const letters = formula.split(''); + const rolls = []; + const getSuc = new RegExp('Successes: ([0-9]+)', 'g'); + const getAdv = new RegExp('Advantages: ([0-9]+)', 'g'); + + for (const letter of letters) { + rolls.push(game.ffg.StarWars.letterToRolls(letter, 1)); + } + + let newformula = combineAll(rolls, game.ffg.StarWars.rollValuesMonoid); + + let rolling = game.specialDiceRoller.starWars.roll(newformula); + + let results = game.specialDiceRoller.starWars.formatRolls(rolling); + + let success = 0; + let advantage = 0; + + success = getSuc.exec(results); + if (success) { success = success[1]; } + advantage = getAdv.exec(results); + if (advantage) { advantage = advantage[1]; } + + let total = +success+(advantage*0.01); + + console.log(`Total is: ${total}`); + + let roll = new Roll(origFormula, rollData).roll(); + roll._result = total; + roll._total = total; + + return roll; + } +} + +function combineAll(values, monoid) { + return values + .reduce((prev, curr) => monoid.combine(prev, curr), monoid.identity); +} + +function _getInitiativeFormula(skill, ability, difficulty) { + const dicePool = new DicePoolFFG({ + ability: ability, + difficulty: difficulty + }); + dicePool.upgrade(skill); + return dicePool.renderDiceExpression(); +} diff --git a/modules/dice-pool-ffg.js b/modules/dice-pool-ffg.js index 72590920..dad21f35 100644 --- a/modules/dice-pool-ffg.js +++ b/modules/dice-pool-ffg.js @@ -1,128 +1,128 @@ -const PROFICIENCY_ICON = "modules/special-dice-roller/public/images/sw/yellow.png"; -const ABILITY_ICON = "modules/special-dice-roller/public/images/sw/green.png"; -const CHALLENGE_ICON = "modules/special-dice-roller/public/images/sw/red.png"; -const DIFFICULTY_ICON = "modules/special-dice-roller/public/images/sw/purple.png"; -const BOOST_ICON = "modules/special-dice-roller/public/images/sw/blue.png"; -const SETBACK_ICON = "modules/special-dice-roller/public/images/sw/black.png"; -const FORCE_ICON = "modules/special-dice-roller/public/images/sw/whiteHex.png"; - -/** - * Dice pool utility specializing in the FFG special dice - */ -export class DicePoolFFG { - constructor(obj) { - if (obj === undefined) { - obj = {}; - } - if (typeof(obj) === "string") { - obj = JSON.parse(obj); - } - this.proficiency = obj.proficiency || 0; - this.ability = obj.ability || 0; - this.challenge = obj.challenge || 0; - this.difficulty = obj.difficulty || 0; - this.boost = obj.boost || 0; - this.setback = obj.setback || 0; - this.force = obj.force || 0; - } - - /** - * Upgrade the dice pool, converting any remaining ability dice into proficiency - * dice or adding an ability die if none remain. - * @param times the number of times to perform this operation, defaults to 1 - */ - upgrade(times) { - if (times === undefined) { - times = 1; - } - for (let i = 0; i < times; i++) { - if (this.ability > 0) { - this.ability--; - this.proficiency++; - } else { - this.ability++; - } - } - } - /** - * Upgrade the dice pool's difficulty, converting any remaining difficulty dice - * into challenge dice or adding an difficulty die if none remain. - * @param times the number of times to perform this operation, defaults to 1 - */ - upgradeDifficulty(times) { - if (times === undefined) { - times = 1; - } - for (let i = 0; i < times; i++) { - if (this.difficulty > 0) { - this.difficulty--; - this.challenge++; - } else { - this.difficulty++; - } - } - } - - /** - * Transform the dice pool into a rollable expression - * @returns {string} a dice expression that can be used to roll the dice pool - */ - renderDiceExpression() { - return [ - "p".repeat(this.proficiency), - "a".repeat(this.ability), - "c".repeat(this.challenge), - "d".repeat(this.difficulty), - "b".repeat(this.boost), - "s".repeat(this.setback), - "f".repeat(this.force) - ].join(""); - } - - /** - * Create a preview of the dice pool using images - * @param container {HTMLElement} where to place the preview. A container will be generated if this is undefined - * @returns {HTMLElement} - */ - renderPreview(container) { - if (container === undefined) { - container = document.createElement("div"); - container.classList.add("dice-pool"); - } - this._addIcons(container, PROFICIENCY_ICON, this.proficiency); - this._addIcons(container, ABILITY_ICON, this.ability); - this._addIcons(container, CHALLENGE_ICON, this.challenge); - this._addIcons(container, DIFFICULTY_ICON, this.difficulty); - this._addIcons(container, BOOST_ICON, this.boost); - this._addIcons(container, SETBACK_ICON, this.setback); - this._addIcons(container, FORCE_ICON, this.force); - return container; - } - - _addIcons(container, icon, times) { - for (let i = 0; i < times; i++) { - const img = document.createElement("img"); - img.src = icon; - img.width = 48; - img.height = 48; - container.appendChild(img); - } - } - - /** - * Search the passed container for inputs that contain dice pool information - * @param container the container where the inputs are located - * @returns {DicePoolFFG} - */ - static fromContainer(container) { - return new DicePoolFFG({ - proficiency: container.querySelector('[name="proficiency"]').value, - ability: container.querySelector('[name="ability"]').value, - challenge: container.querySelector('[name="challenge"]').value, - difficulty: container.querySelector('[name="difficulty"]').value, - boost: container.querySelector('[name="boost"]').value, - setback: container.querySelector('[name="setback"]').value, - force: container.querySelector('[name="force"]').value, - }) - } -} +const PROFICIENCY_ICON = "modules/special-dice-roller/public/images/sw/yellow.png"; +const ABILITY_ICON = "modules/special-dice-roller/public/images/sw/green.png"; +const CHALLENGE_ICON = "modules/special-dice-roller/public/images/sw/red.png"; +const DIFFICULTY_ICON = "modules/special-dice-roller/public/images/sw/purple.png"; +const BOOST_ICON = "modules/special-dice-roller/public/images/sw/blue.png"; +const SETBACK_ICON = "modules/special-dice-roller/public/images/sw/black.png"; +const FORCE_ICON = "modules/special-dice-roller/public/images/sw/whiteHex.png"; + +/** + * Dice pool utility specializing in the FFG special dice + */ +export class DicePoolFFG { + constructor(obj) { + if (obj === undefined) { + obj = {}; + } + if (typeof(obj) === "string") { + obj = JSON.parse(obj); + } + this.proficiency = obj.proficiency || 0; + this.ability = obj.ability || 0; + this.challenge = obj.challenge || 0; + this.difficulty = obj.difficulty || 0; + this.boost = obj.boost || 0; + this.setback = obj.setback || 0; + this.force = obj.force || 0; + } + + /** + * Upgrade the dice pool, converting any remaining ability dice into proficiency + * dice or adding an ability die if none remain. + * @param times the number of times to perform this operation, defaults to 1 + */ + upgrade(times) { + if (times === undefined) { + times = 1; + } + for (let i = 0; i < times; i++) { + if (this.ability > 0) { + this.ability--; + this.proficiency++; + } else { + this.ability++; + } + } + } + /** + * Upgrade the dice pool's difficulty, converting any remaining difficulty dice + * into challenge dice or adding an difficulty die if none remain. + * @param times the number of times to perform this operation, defaults to 1 + */ + upgradeDifficulty(times) { + if (times === undefined) { + times = 1; + } + for (let i = 0; i < times; i++) { + if (this.difficulty > 0) { + this.difficulty--; + this.challenge++; + } else { + this.difficulty++; + } + } + } + + /** + * Transform the dice pool into a rollable expression + * @returns {string} a dice expression that can be used to roll the dice pool + */ + renderDiceExpression() { + return [ + "p".repeat(this.proficiency), + "a".repeat(this.ability), + "c".repeat(this.challenge), + "d".repeat(this.difficulty), + "b".repeat(this.boost), + "s".repeat(this.setback), + "f".repeat(this.force) + ].join(""); + } + + /** + * Create a preview of the dice pool using images + * @param container {HTMLElement} where to place the preview. A container will be generated if this is undefined + * @returns {HTMLElement} + */ + renderPreview(container) { + if (container === undefined) { + container = document.createElement("div"); + container.classList.add("dice-pool"); + } + this._addIcons(container, PROFICIENCY_ICON, this.proficiency); + this._addIcons(container, ABILITY_ICON, this.ability); + this._addIcons(container, CHALLENGE_ICON, this.challenge); + this._addIcons(container, DIFFICULTY_ICON, this.difficulty); + this._addIcons(container, BOOST_ICON, this.boost); + this._addIcons(container, SETBACK_ICON, this.setback); + this._addIcons(container, FORCE_ICON, this.force); + return container; + } + + _addIcons(container, icon, times) { + for (let i = 0; i < times; i++) { + const img = document.createElement("img"); + img.src = icon; + img.width = 48; + img.height = 48; + container.appendChild(img); + } + } + + /** + * Search the passed container for inputs that contain dice pool information + * @param container the container where the inputs are located + * @returns {DicePoolFFG} + */ + static fromContainer(container) { + return new DicePoolFFG({ + proficiency: container.querySelector('[name="proficiency"]').value, + ability: container.querySelector('[name="ability"]').value, + challenge: container.querySelector('[name="challenge"]').value, + difficulty: container.querySelector('[name="difficulty"]').value, + boost: container.querySelector('[name="boost"]').value, + setback: container.querySelector('[name="setback"]').value, + force: container.querySelector('[name="force"]').value, + }) + } +} diff --git a/modules/groupmanager-ffg.js b/modules/groupmanager-ffg.js index df7bfc43..3e63e858 100644 --- a/modules/groupmanager-ffg.js +++ b/modules/groupmanager-ffg.js @@ -1,103 +1,103 @@ -export class GroupManagerLayer extends TokenLayer { - constructor() { - super(); - } - - static get layerOptions() { - return mergeObject(super.layerOptions, { - canDragCreate: false, - }); - } - /* -------------------------------------------- */ - /* Methods - /* -------------------------------------------- */ - - activate() { - super.activate(); - } - - deactivate() { - super.deactivate(); - } - - async draw() { - super.draw(); - } - - /* -------------------------------------------- */ -} - -export class GroupManager extends FormApplication { - static get defaultOptions() { - return mergeObject(super.defaultOptions, { - classes: ["starwarsffg", "form", "group-manager"], - closeOnSubmit: false, - submitOnChange: true, - submitOnClose: true, - popOut: true, - editable: game.user.isGM, - width: 300, - height: 450, - template: "systems/starwarsffg/templates/group-manager.html", - id: "group-manager", - title: "Group Manager", - }); - } - - /* -------------------------------------------- */ - - /** - * Obtain module metadata and merge it with game settings which track current module visibility - * @return {Object} The data provided to the template when rendering the form - */ - getData() { - return { g: game }; - } - - /* -------------------------------------------- */ - - /** @override */ - activateListeners(html) { - super.activateListeners(html); - - // Everything below here is only needed if the sheet is editable - if (!this.options.editable) return; - - // Flip destiny pool DARK to LIGHT - html.find(".destiny-flip-dtl").click((ev) => { - let LightPool = this.form.elements["g.ffg.DestinyPool.Light"].value; - let DarkPool = this.form.elements["g.ffg.DestinyPool.Dark"].value; - if (DarkPool > 0) { - LightPool++; - DarkPool--; - this.form.elements["g.ffg.DestinyPool.Light"].value = LightPool; - this.form.elements["g.ffg.DestinyPool.Dark"].value = DarkPool; - } - }); - - // Flip destiny pool LIGHT to DARK - html.find(".destiny-flip-ltd").click((ev) => { - let LightPool = this.form.elements["g.ffg.DestinyPool.Light"].value; - let DarkPool = this.form.elements["g.ffg.DestinyPool.Dark"].value; - if (LightPool > 0) { - LightPool--; - DarkPool++; - this.form.elements["g.ffg.DestinyPool.Light"].value = LightPool; - this.form.elements["g.ffg.DestinyPool.Dark"].value = DarkPool; - } - }); - } - - /** - * This method is called upon form submission after form data is validated - * @param event {Event} The initial triggering submission event - * @param formData {Object} The object of validated form data with which to update the object - * @private - */ - _updateObject(event, formData) { - const formDPool = expandObject(formData).g.ffg.DestinyPool || {}; - game.ffg.DestinyPool.Light = formDPool.Light; - game.ffg.DestinyPool.Dark = formDPool.Dark; - return formData; - } -} +export class GroupManagerLayer extends TokenLayer { + constructor() { + super(); + } + + static get layerOptions() { + return mergeObject(super.layerOptions, { + canDragCreate: false, + }); + } + /* -------------------------------------------- */ + /* Methods + /* -------------------------------------------- */ + + activate() { + super.activate(); + } + + deactivate() { + super.deactivate(); + } + + async draw() { + super.draw(); + } + + /* -------------------------------------------- */ +} + +export class GroupManager extends FormApplication { + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ["starwarsffg", "form", "group-manager"], + closeOnSubmit: false, + submitOnChange: true, + submitOnClose: true, + popOut: true, + editable: game.user.isGM, + width: 300, + height: 450, + template: "systems/starwarsffg/templates/group-manager.html", + id: "group-manager", + title: "Group Manager", + }); + } + + /* -------------------------------------------- */ + + /** + * Obtain module metadata and merge it with game settings which track current module visibility + * @return {Object} The data provided to the template when rendering the form + */ + getData() { + return { g: game }; + } + + /* -------------------------------------------- */ + + /** @override */ + activateListeners(html) { + super.activateListeners(html); + + // Everything below here is only needed if the sheet is editable + if (!this.options.editable) return; + + // Flip destiny pool DARK to LIGHT + html.find(".destiny-flip-dtl").click((ev) => { + let LightPool = this.form.elements["g.ffg.DestinyPool.Light"].value; + let DarkPool = this.form.elements["g.ffg.DestinyPool.Dark"].value; + if (DarkPool > 0) { + LightPool++; + DarkPool--; + this.form.elements["g.ffg.DestinyPool.Light"].value = LightPool; + this.form.elements["g.ffg.DestinyPool.Dark"].value = DarkPool; + } + }); + + // Flip destiny pool LIGHT to DARK + html.find(".destiny-flip-ltd").click((ev) => { + let LightPool = this.form.elements["g.ffg.DestinyPool.Light"].value; + let DarkPool = this.form.elements["g.ffg.DestinyPool.Dark"].value; + if (LightPool > 0) { + LightPool--; + DarkPool++; + this.form.elements["g.ffg.DestinyPool.Light"].value = LightPool; + this.form.elements["g.ffg.DestinyPool.Dark"].value = DarkPool; + } + }); + } + + /** + * This method is called upon form submission after form data is validated + * @param event {Event} The initial triggering submission event + * @param formData {Object} The object of validated form data with which to update the object + * @private + */ + _updateObject(event, formData) { + const formDPool = expandObject(formData).g.ffg.DestinyPool || {}; + game.ffg.DestinyPool.Light = formDPool.Light; + game.ffg.DestinyPool.Dark = formDPool.Dark; + return formData; + } +} diff --git a/modules/items/item-ffg.js b/modules/items/item-ffg.js index 12c50414..48f4d6f6 100644 --- a/modules/items/item-ffg.js +++ b/modules/items/item-ffg.js @@ -1,20 +1,20 @@ -/** - * Extend the basic Item with some very simple modifications. - * @extends {Item} - */ -export class ItemFFG extends Item { - /** - * Augment the basic Item data model with additional dynamic data. - */ - prepareData() { - super.prepareData(); - - // Get the Item's data - const itemData = this.data; - const actorData = this.actor ? this.actor.data : {}; - const data = itemData.data; - - itemData.safe_desc = data.description.replace(/(<([^>]+)>)/ig,""); - - } -} +/** + * Extend the basic Item with some very simple modifications. + * @extends {Item} + */ +export class ItemFFG extends Item { + /** + * Augment the basic Item data model with additional dynamic data. + */ + prepareData() { + super.prepareData(); + + // Get the Item's data + const itemData = this.data; + const actorData = this.actor ? this.actor.data : {}; + const data = itemData.data; + + itemData.safe_desc = data.description.replace(/(<([^>]+)>)/ig,""); + + } +} diff --git a/modules/items/item-sheet-ffg.js b/modules/items/item-sheet-ffg.js index 0cdda9b2..7d95390a 100644 --- a/modules/items/item-sheet-ffg.js +++ b/modules/items/item-sheet-ffg.js @@ -28,6 +28,24 @@ export class ItemSheetFFG extends ItemSheet { for (let attr of Object.values(data.data.attributes)) { attr.isCheckbox = attr.dtype === "Boolean"; } + + switch (this.object.data.type) { + case "weapon": + this.position.width = 385; + this.position.height = 650; + break; + case "armour": + case "gear": + this.position.width = 385; + this.position.height = 575; + break; + case "talent": + this.position.width = 405; + this.position.height = 475; + break; + default: + } + data.FFG = CONFIG.FFG; return data; } diff --git a/modules/swffg-config.js b/modules/swffg-config.js index 4c749112..1818285f 100644 --- a/modules/swffg-config.js +++ b/modules/swffg-config.js @@ -1,126 +1,126 @@ -export const FFG = {}; - -FFG.characteristics = { - "Brawn": "Brawn", - "Agility": "Agility", - "Intellect": "Intellect", - "Cunning": "Cunning", - "Willpower": "Willpower", - "Presence": "Presence", -}; - -FFG.character_stats = { - "wounds": "Wounds", - "strain": "Strain", - "soak": "Soak", - "defence": "Defence", - "encumbrance": "Encumbrance", - "forcePool": "Force Pool", - "credits": "Credits", -}; - -FFG.skills = { - "Brawl": "Brawl", - "Gunnery": "Gunnery", - "Lightsaber": "Lightsaber", - "Melee": "Melee", - "Ranged: Light": "Ranged: Light", - "Ranged: Heavy": "Ranged: Heavy", - "Astrogation": "Astrogation", - "Athletics ": "Athletics", - "Charm": "Charm", - "Coercion": "Coercion", - "Computers": "Computers", - "Cool": "Cool", - "Coordination": "Coordination", - "Deception": "Deception", - "Discipline": "Discipline", - "Leadership": "Leadership", - "Mechanics": "Mechanics", - "Medicine": "Medicine", - "Negotiation": "Negotiation", - "Perception": "Perception", - "Piloting: Planetary": "Piloting: Planetary", - "Piloting: Space": "Piloting: Space", - "Resilience": "Resilience", - "Skulduggery": "Skulduggery", - "Stealth": "Stealth", - "Streetwise": "Streetwise", - "Survival": "Survival", - "Vigilance": "Vigilance", - "Knowledge: Core Worlds": "Knowledge: Core Worlds", - "Knowledge: Education": "Knowledge: Education", - "Knowledge: Lore": "Knowledge: Lore", - "Knowledge: Outer Rim": "Knowledge: Outer Rim", - "Knowledge: Underworld": "Knowledge: Underworld", - "Knowledge: Warfare": "Knowledge: Warfare", - "Knowledge: Xenology": "Knowledge: Xenology", -}; - -FFG.skills.knowledgestripped = { - "Knowledge: Core Worlds": "Core Worlds", - "Knowledge: Education": "Education", - "Knowledge: Lore": "Lore", - "Knowledge: Outer Rim": "Outer Rim", - "Knowledge: Underworld": "Underworld", - "Knowledge: Warfare": "Warfare", - "Knowledge: Xenology": "Xenology", -}; - -FFG.ranges = { - "Engaged": "Engaged", - "Short": "Short", - "Medium": "Medium", - "Long": "Long", - "Extreme": "Extreme", -}; - -FFG.vehicle_ranges = { - "Close": "Close", - "Short": "Short", - "Medium": "Medium", - "Long": "Long", - "Extreme": "Extreme", -}; - -FFG.fire_arcs = { - "Forward": "Forward", - "Aft": "Aft", - "Port": "Port", - "Starboard": "Starboard", - "All": "All", -}; - -FFG.combat_skills = { - "Brawl": "Brawl", - "Gunnery": "Gunnery", - "Lightsaber": "Lightsaber", - "Melee": "Melee", - "Ranged: Light": "Ranged: Light", - "Ranged: Heavy": "Ranged: Heavy", -}; - -FFG.combat_skills.abrev = { - "Brawl": "B", - "Gunnery": "G", - "Lightsaber": "LS", - "Melee": "M", - "Ranged: Light": "RL", - "Ranged: Heavy": "RH", -}; - -FFG.activations = { - "Passive": "Passive", - "Active (Incidental)": "Active (Incidental)", - "Active (Incidental, Out of Turn)": "Active (Incidental, Out of Turn)", - "Active (Action)": "Active (Action)", - "Active (Maneuver)": "Active (Maneuver)", -}; - -FFG.mod_types = ["Characteristic", "Skill Rank", "Skill Boost", "Stat"]; - -FFG.species = {}; - -FFG.careers = {}; - -FFG.specialisations = {}; +export const FFG = {}; + +FFG.characteristics = { + "Brawn": "Brawn", + "Agility": "Agility", + "Intellect": "Intellect", + "Cunning": "Cunning", + "Willpower": "Willpower", + "Presence": "Presence", +}; + +FFG.character_stats = { + "wounds": "Wounds", + "strain": "Strain", + "soak": "Soak", + "defence": "Defence", + "encumbrance": "Encumbrance", + "forcePool": "Force Pool", + "credits": "Credits", +}; + +FFG.skills = { + "Brawl": "Brawl", + "Gunnery": "Gunnery", + "Lightsaber": "Lightsaber", + "Melee": "Melee", + "Ranged: Light": "Ranged: Light", + "Ranged: Heavy": "Ranged: Heavy", + "Astrogation": "Astrogation", + "Athletics ": "Athletics", + "Charm": "Charm", + "Coercion": "Coercion", + "Computers": "Computers", + "Cool": "Cool", + "Coordination": "Coordination", + "Deception": "Deception", + "Discipline": "Discipline", + "Leadership": "Leadership", + "Mechanics": "Mechanics", + "Medicine": "Medicine", + "Negotiation": "Negotiation", + "Perception": "Perception", + "Piloting: Planetary": "Piloting: Planetary", + "Piloting: Space": "Piloting: Space", + "Resilience": "Resilience", + "Skulduggery": "Skulduggery", + "Stealth": "Stealth", + "Streetwise": "Streetwise", + "Survival": "Survival", + "Vigilance": "Vigilance", + "Knowledge: Core Worlds": "Knowledge: Core Worlds", + "Knowledge: Education": "Knowledge: Education", + "Knowledge: Lore": "Knowledge: Lore", + "Knowledge: Outer Rim": "Knowledge: Outer Rim", + "Knowledge: Underworld": "Knowledge: Underworld", + "Knowledge: Warfare": "Knowledge: Warfare", + "Knowledge: Xenology": "Knowledge: Xenology", +}; + +FFG.skills.knowledgestripped = { + "Knowledge: Core Worlds": "Core Worlds", + "Knowledge: Education": "Education", + "Knowledge: Lore": "Lore", + "Knowledge: Outer Rim": "Outer Rim", + "Knowledge: Underworld": "Underworld", + "Knowledge: Warfare": "Warfare", + "Knowledge: Xenology": "Xenology", +}; + +FFG.ranges = { + "Engaged": "Engaged", + "Short": "Short", + "Medium": "Medium", + "Long": "Long", + "Extreme": "Extreme", +}; + +FFG.vehicle_ranges = { + "Close": "Close", + "Short": "Short", + "Medium": "Medium", + "Long": "Long", + "Extreme": "Extreme", +}; + +FFG.fire_arcs = { + "Forward": "Forward", + "Aft": "Aft", + "Port": "Port", + "Starboard": "Starboard", + "All": "All", +}; + +FFG.combat_skills = { + "Brawl": "Brawl", + "Gunnery": "Gunnery", + "Lightsaber": "Lightsaber", + "Melee": "Melee", + "Ranged: Light": "Ranged: Light", + "Ranged: Heavy": "Ranged: Heavy", +}; + +FFG.combat_skills.abrev = { + "Brawl": "B", + "Gunnery": "G", + "Lightsaber": "LS", + "Melee": "M", + "Ranged: Light": "RL", + "Ranged: Heavy": "RH", +}; + +FFG.activations = { + "Passive": "Passive", + "Active (Incidental)": "Active (Incidental)", + "Active (Incidental, Out of Turn)": "Active (Incidental, Out of Turn)", + "Active (Action)": "Active (Action)", + "Active (Maneuver)": "Active (Maneuver)", +}; + +FFG.mod_types = ["Characteristic", "Skill Rank", "Skill Boost", "Stat"]; + +FFG.species = {}; + +FFG.careers = {}; + +FFG.specialisations = {}; diff --git a/modules/swffg-main.js b/modules/swffg-main.js index 185ab450..dc0875b2 100644 --- a/modules/swffg-main.js +++ b/modules/swffg-main.js @@ -1,225 +1,225 @@ -/** - * A systems implementation of the Star Wars RPG by Fantasy Flight Games. - * Author: Esrin - * Software License: GNU GPLv3 - */ - -// Import Modules -import { FFG } from "./swffg-config.js"; -import { ActorFFG } from "./actors/actor-ffg.js"; -import { CombatFFG } from "./combat-ffg.js"; -import { ItemFFG } from "./items/item-ffg.js"; -import { ItemSheetFFG } from "./items/item-sheet-ffg.js"; -import { ActorSheetFFG } from "./actors/actor-sheet-ffg.js"; -import { DicePoolFFG } from "./dice-pool-ffg.js"; -import { GroupManagerLayer } from "./groupmanager-ffg.js"; -import { GroupManager } from "./groupmanager-ffg.js"; - -/* -------------------------------------------- */ -/* Foundry VTT Initialization */ -/* -------------------------------------------- */ - -Hooks.once("init", async function () { - console.log(`Initializing SWFFG System`); - - // Place our classes in their own namespace for later reference. - game.ffg = { - ActorFFG, - ItemFFG, - CombatFFG, - }; - - game.ffg.StarWars = game.specialDiceRoller.starWars.parsers[0]; - game.ffg.DestinyPool = { - "Light": 0, - "Dark": 0, - }; - - // Define custom Entity classes. This will override the default Actor - // to instead use our extended version. - CONFIG.Actor.entityClass = ActorFFG; - CONFIG.Item.entityClass = ItemFFG; - CONFIG.Combat.entityClass = CombatFFG; - - // A very hacky temporary workaround to override how initiative functions and provide the results of a FFG roll to the initiative tracker. - // Currently overriding the prototype due to a bug with overriding the core Combat entity which resets to default after page refresh. - /** @override */ - Combat.prototype._getInitiativeRoll = function (combatant, formula) { - const cData = combatant.actor.data.data; - const origFormula = formula; - - if (combatant.actor.data.type === "vehicle") { - return new Roll("0"); - } - - if (formula === "Vigilance") { - formula = _getInitiativeFormula(cData.skills.Vigilance.rank, cData.characteristics.Willpower.value, 0); - } else if (formula === "Cool") { - formula = _getInitiativeFormula(cData.skills.Cool.rank, cData.characteristics.Presence.value, 0); - } - - const rollData = combatant.actor ? combatant.actor.getRollData() : {}; - const letters = formula.split(""); - const rolls = []; - const getSuc = new RegExp("Successes: ([0-9]+)", "g"); - const getAdv = new RegExp("Advantages: ([0-9]+)", "g"); - - for (const letter of letters) { - rolls.push(game.ffg.StarWars.letterToRolls(letter, 1)); - } - - let newformula = combineAll(rolls, game.ffg.StarWars.rollValuesMonoid); - - let rolling = game.specialDiceRoller.starWars.roll(newformula); - - let results = game.specialDiceRoller.starWars.formatRolls(rolling); - - let success = 0; - let advantage = 0; - - success = getSuc.exec(results); - if (success) { - success = success[1]; - } - advantage = getAdv.exec(results); - if (advantage) { - advantage = advantage[1]; - } - - let total = +success + advantage * 0.01; - - console.log(`Total is: ${total}`); - - let roll = new Roll(origFormula, rollData).roll(); - roll._result = total; - roll._total = total; - - return roll; - }; - - // TURN ON OR OFF HOOK DEBUGGING - CONFIG.debug.hooks = false; - - // Give global access to FFG config. - CONFIG.FFG = FFG; - - /** - * Set an initiative formula for the system - * @type {String} - */ - // Register initiative rule - game.settings.register("starwarsffg", "initiativeRule", { - name: "Initiative Type", - hint: "Choose between Vigilance or Cool for Initiative rolls.", - scope: "world", - config: true, - default: "v", - type: String, - choices: { - v: "Use Vigilance", - c: "Use Cool", - }, - onChange: (rule) => _setffgInitiative(rule), - }); - _setffgInitiative(game.settings.get("starwarsffg", "initiativeRule")); - - function _setffgInitiative(initMethod) { - let formula; - switch (initMethod) { - case "v": - formula = "Vigilance"; - break; - - case "c": - formula = "Cool"; - break; - } - - CONFIG.Combat.initiative = { - formula: formula, - decimals: 2, - }; - } - - function combineAll(values, monoid) { - return values.reduce((prev, curr) => monoid.combine(prev, curr), monoid.identity); - } - - function _getInitiativeFormula(skill, ability, difficulty) { - const dicePool = new DicePoolFFG({ - ability: ability, - difficulty: difficulty, - }); - dicePool.upgrade(skill); - return dicePool.renderDiceExpression(); - } - - // Register sheet application classes - Actors.unregisterSheet("core", ActorSheet); - Actors.registerSheet("ffg", ActorSheetFFG, { makeDefault: true }); - Items.unregisterSheet("core", ItemSheet); - Items.registerSheet("ffg", ItemSheetFFG, { makeDefault: true }); - - // Add utilities to the global scope, this can be useful for macro makers - window.DicePoolFFG = DicePoolFFG; - - // Register Handlebars utilities - Handlebars.registerHelper("json", JSON.stringify); - - // Allows {if X = Y} type syntax in html using handlebars - Handlebars.registerHelper("iff", function (a, operator, b, opts) { - var bool = false; - switch (operator) { - case "==": - bool = a == b; - break; - case ">": - bool = a > b; - break; - case "<": - bool = a < b; - break; - case "!=": - bool = a != b; - break; - default: - throw "Unknown operator " + operator; - } - - if (bool) { - return opts.fn(this); - } else { - return opts.inverse(this); - } - }); -}); - -/* -------------------------------------------- */ -/* Set up control buttons */ -/* -------------------------------------------- */ - -Hooks.on("getSceneControlButtons", (controls) => { - if (game.user.isGM) { - controls.push({ - name: "groupmanager", - title: "Group Manager", - icon: "fas fa-users", - layer: "GroupManagerLayer", - tools: [ - { - name: "groupsheet", - title: "Open Group Sheet", - icon: "fas fa-users", - onClick: () => { - new GroupManager().render(true); - }, - button: true, - }, - ], - }); - } -}); - -Hooks.once("canvasInit", (canvas) => { - canvas.groupmanager = canvas.stage.addChildAt(new GroupManagerLayer(canvas), 8); -}); +/** + * A systems implementation of the Star Wars RPG by Fantasy Flight Games. + * Author: Esrin + * Software License: GNU GPLv3 + */ + +// Import Modules +import { FFG } from "./swffg-config.js"; +import { ActorFFG } from "./actors/actor-ffg.js"; +import { CombatFFG } from "./combat-ffg.js"; +import { ItemFFG } from "./items/item-ffg.js"; +import { ItemSheetFFG } from "./items/item-sheet-ffg.js"; +import { ActorSheetFFG } from "./actors/actor-sheet-ffg.js"; +import { DicePoolFFG } from "./dice-pool-ffg.js"; +import { GroupManagerLayer } from "./groupmanager-ffg.js"; +import { GroupManager } from "./groupmanager-ffg.js"; + +/* -------------------------------------------- */ +/* Foundry VTT Initialization */ +/* -------------------------------------------- */ + +Hooks.once("init", async function () { + console.log(`Initializing SWFFG System`); + + // Place our classes in their own namespace for later reference. + game.ffg = { + ActorFFG, + ItemFFG, + CombatFFG, + }; + + game.ffg.StarWars = game.specialDiceRoller.starWars.parsers[0]; + game.ffg.DestinyPool = { + "Light": 0, + "Dark": 0, + }; + + // Define custom Entity classes. This will override the default Actor + // to instead use our extended version. + CONFIG.Actor.entityClass = ActorFFG; + CONFIG.Item.entityClass = ItemFFG; + CONFIG.Combat.entityClass = CombatFFG; + + // A very hacky temporary workaround to override how initiative functions and provide the results of a FFG roll to the initiative tracker. + // Currently overriding the prototype due to a bug with overriding the core Combat entity which resets to default after page refresh. + /** @override */ + Combat.prototype._getInitiativeRoll = function (combatant, formula) { + const cData = combatant.actor.data.data; + const origFormula = formula; + + if (combatant.actor.data.type === "vehicle") { + return new Roll("0"); + } + + if (formula === "Vigilance") { + formula = _getInitiativeFormula(cData.skills.Vigilance.rank, cData.characteristics.Willpower.value, 0); + } else if (formula === "Cool") { + formula = _getInitiativeFormula(cData.skills.Cool.rank, cData.characteristics.Presence.value, 0); + } + + const rollData = combatant.actor ? combatant.actor.getRollData() : {}; + const letters = formula.split(""); + const rolls = []; + const getSuc = new RegExp("Successes: ([0-9]+)", "g"); + const getAdv = new RegExp("Advantages: ([0-9]+)", "g"); + + for (const letter of letters) { + rolls.push(game.ffg.StarWars.letterToRolls(letter, 1)); + } + + let newformula = combineAll(rolls, game.ffg.StarWars.rollValuesMonoid); + + let rolling = game.specialDiceRoller.starWars.roll(newformula); + + let results = game.specialDiceRoller.starWars.formatRolls(rolling); + + let success = 0; + let advantage = 0; + + success = getSuc.exec(results); + if (success) { + success = success[1]; + } + advantage = getAdv.exec(results); + if (advantage) { + advantage = advantage[1]; + } + + let total = +success + advantage * 0.01; + + console.log(`Total is: ${total}`); + + let roll = new Roll(origFormula, rollData).roll(); + roll._result = total; + roll._total = total; + + return roll; + }; + + // TURN ON OR OFF HOOK DEBUGGING + CONFIG.debug.hooks = false; + + // Give global access to FFG config. + CONFIG.FFG = FFG; + + /** + * Set an initiative formula for the system + * @type {String} + */ + // Register initiative rule + game.settings.register("starwarsffg", "initiativeRule", { + name: "Initiative Type", + hint: "Choose between Vigilance or Cool for Initiative rolls.", + scope: "world", + config: true, + default: "v", + type: String, + choices: { + v: "Use Vigilance", + c: "Use Cool", + }, + onChange: (rule) => _setffgInitiative(rule), + }); + _setffgInitiative(game.settings.get("starwarsffg", "initiativeRule")); + + function _setffgInitiative(initMethod) { + let formula; + switch (initMethod) { + case "v": + formula = "Vigilance"; + break; + + case "c": + formula = "Cool"; + break; + } + + CONFIG.Combat.initiative = { + formula: formula, + decimals: 2, + }; + } + + function combineAll(values, monoid) { + return values.reduce((prev, curr) => monoid.combine(prev, curr), monoid.identity); + } + + function _getInitiativeFormula(skill, ability, difficulty) { + const dicePool = new DicePoolFFG({ + ability: ability, + difficulty: difficulty, + }); + dicePool.upgrade(skill); + return dicePool.renderDiceExpression(); + } + + // Register sheet application classes + Actors.unregisterSheet("core", ActorSheet); + Actors.registerSheet("ffg", ActorSheetFFG, { makeDefault: true }); + Items.unregisterSheet("core", ItemSheet); + Items.registerSheet("ffg", ItemSheetFFG, { makeDefault: true }); + + // Add utilities to the global scope, this can be useful for macro makers + window.DicePoolFFG = DicePoolFFG; + + // Register Handlebars utilities + Handlebars.registerHelper("json", JSON.stringify); + + // Allows {if X = Y} type syntax in html using handlebars + Handlebars.registerHelper("iff", function (a, operator, b, opts) { + var bool = false; + switch (operator) { + case "==": + bool = a == b; + break; + case ">": + bool = a > b; + break; + case "<": + bool = a < b; + break; + case "!=": + bool = a != b; + break; + default: + throw "Unknown operator " + operator; + } + + if (bool) { + return opts.fn(this); + } else { + return opts.inverse(this); + } + }); +}); + +/* -------------------------------------------- */ +/* Set up control buttons */ +/* -------------------------------------------- */ + +Hooks.on("getSceneControlButtons", (controls) => { + if (game.user.isGM) { + controls.push({ + name: "groupmanager", + title: "Group Manager", + icon: "fas fa-users", + layer: "GroupManagerLayer", + tools: [ + { + name: "groupsheet", + title: "Open Group Sheet", + icon: "fas fa-users", + onClick: () => { + new GroupManager().render(true); + }, + button: true, + }, + ], + }); + } +}); + +Hooks.once("canvasInit", (canvas) => { + canvas.groupmanager = canvas.stage.addChildAt(new GroupManagerLayer(canvas), 8); +}); diff --git a/package.json b/package.json index 05c5049e..c878966d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "( PLEASE NOTE: This is a custom fork based on [Jaxxa's implementation](https://github.com/jaxxa/StarWarsFFG/tree/master). )", "main": "index.js", "scripts": { - "compile": "gulp css" + "compile": "gulp css", + "watch" : "gulp" }, "author": "", "license": "MIT", diff --git a/scss/components/_biography.scss b/scss/components/_biography.scss new file mode 100644 index 00000000..207bc4eb --- /dev/null +++ b/scss/components/_biography.scss @@ -0,0 +1,135 @@ +.biography { + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background-shadow { + top: 36px; + } + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(73, 12, 11); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + // width: 160px; + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + .block-value { + display: inline-block; + } + } + + .block-value { + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 110px; + } + &.double { + width: 130px; + } + + input { + width: 45px; + } + } + + .biography-values { + margin-bottom: 5px; + border: 0; + position: absolute; + bottom: 10px; + left: 0; + padding: 0; + + } + + .biography-editor { + height:475px; + } +} \ No newline at end of file diff --git a/scss/components/_characteristics.scss b/scss/components/_characteristics.scss new file mode 100644 index 00000000..d306181c --- /dev/null +++ b/scss/components/_characteristics.scss @@ -0,0 +1,69 @@ +.sheet-body { + + div.tab.characteristics { + overflow: hidden; + } + + .characteristics { + fieldset.skillfilter { + display: none; + } + + .characteristic-item { + border:0; + position: relative; + + .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: rgb(73, 12, 11); + color:white; + text-transform: uppercase; + font-size : 10px; + --notchSize: 7px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + } + + .grid { + margin-top: 0; + } + } + + .characteristic { + width: 50px; + height: 50px; + border-radius: 50%; + border: 5px double black; + margin: auto; + position: relative; + + .characteristic-value { + input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; + } + input:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + border-radius: 50%; + } + } + + + } +} \ No newline at end of file diff --git a/scss/components/_forms.scss b/scss/components/_forms.scss new file mode 100644 index 00000000..1f822f3f --- /dev/null +++ b/scss/components/_forms.scss @@ -0,0 +1,54 @@ +.item-form { + font-family: $font-primary; +} + +.block-background { + background-color: rgb(196, 219, 233); + padding: 5px; + + --notchSize: 9px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); +} + +.block-background-shadow { + position: absolute; + width: 100%; + top: 30px; + height: 30px; + background-color: rgb(125, 169, 194); + padding: 5px; + z-index: -1; + + --notchSize: 9px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); +} + +.character { + min-width: 575px; +} + +.position-relative { + position: relative; +} \ No newline at end of file diff --git a/scss/components/_header.scss b/scss/components/_header.scss new file mode 100644 index 00000000..82ed2885 --- /dev/null +++ b/scss/components/_header.scss @@ -0,0 +1,218 @@ +.header-fields { + .block-background-shadow { + top: 36px; + } + + .container.flex-group-center { + border: 0; + margin-bottom: 5px; + padding: 0 5px 5px 5px; + } + + h1 { + margin: 0; + width:100%; + } + + .header-name { + margin: 0; + position: relative; + width: 100%; + + input { + margin: 0; + width: 100%; + border: 0; + background-color: rgba(0,0,0,0); + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + + } + + .header-description-block { + margin-bottom: 5px; + margin-top: 5px; + } + + .header-description { + background-color: rgb(196, 219, 233); + --notchSize: 10px; + padding:3px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .table { + display: table; + width: 100%; + } + + .row { + display: table-row; + width:100%; + + div { + display: table-cell; + } + + .row-input { + padding: 0 5px; + } + + input { + width: 100%; + border: 0; + border-bottom: 1px solid black; + border-radius: 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .profile-block { + margin-right: 5px; + margin-left: 5px; + height: 140px; + max-width: 140px; + } + + .profile-img { + flex: 0 0 100px; + height: 124px; + width: auto; + max-width: 124px; + border: 0; + margin: auto; + } + + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(73, 12, 11); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + // width: 160px; + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + .block-value { + display: inline-block; + } + } + + .block-value { + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 65px; + } + + input { + width: 45px; + } + } +} diff --git a/scss/components/_itemarmorsheet.scss b/scss/components/_itemarmorsheet.scss new file mode 100644 index 00000000..09e5e55b --- /dev/null +++ b/scss/components/_itemarmorsheet.scss @@ -0,0 +1,238 @@ +.item-sheet-armor { + + .header-fields { + height: 340px; + } + + .charname { + width: 100%; + + input { + color: rgb(85, 49, 19); + border: 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + } + + .characteristic-item { + border:0; + position: relative; + padding:0; + margin: 0 5px; + + .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: rgb(85, 49, 19); + color:white; + text-transform: uppercase; + font-size : 10px; + --notchSize: 7px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double rgb(85, 49, 19); + margin: auto; + position: relative; + + .characteristic-value { + input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; + } + input:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + border-radius: 5px; + } + } + + + } + } + + .item-name { + margin:0; + padding-bottom:0 !important; + } + + .grid { + margin-top: 0; + } + + .block-background { + background-color: rgb(233, 192, 158); + } + + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background-shadow { + top: 36px; + } + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(85, 49, 19); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + select { + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + .block-value { + display: inline-block; + } + } + + .block-value { + + textarea { + resize:none; + font-family: 'Roboto'; + border : 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + outline: none; + } + } + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 100px; + } + &.double { + width: 235px; + } + + input { + width: 45px; + } + } + + .tabs { + height : 20px; + border: 0; + + .item { + line-height: 15px; + } + } + +} \ No newline at end of file diff --git a/scss/components/_itemgearsheet.scss b/scss/components/_itemgearsheet.scss new file mode 100644 index 00000000..61a479d9 --- /dev/null +++ b/scss/components/_itemgearsheet.scss @@ -0,0 +1,238 @@ +.item-sheet-gear { + + .header-fields { + height: 340px; + } + + .charname { + width: 100%; + + input { + color: rgb(44, 3, 68); + border: 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + } + + .characteristic-item { + border:0; + position: relative; + padding:0; + margin: 0 5px; + + .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: rgb(44, 3, 68); + color:white; + text-transform: uppercase; + font-size : 10px; + --notchSize: 7px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double rgb(44, 3, 68); + margin: auto; + position: relative; + + .characteristic-value { + input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; + } + input:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + border-radius: 5px; + } + } + + + } + } + + .item-name { + margin:0; + padding-bottom:0 !important; + } + + .grid { + margin-top: 0; + } + + .block-background { + background-color: rgb(233, 198, 253); + } + + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background-shadow { + top: 36px; + } + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(44, 3, 68); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + select { + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + .block-value { + display: inline-block; + } + } + + .block-value { + + textarea { + resize:none; + font-family: 'Roboto'; + border : 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + outline: none; + } + } + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 100px; + } + &.double { + width: 235px; + } + + input { + width: 45px; + } + } + + .tabs { + height : 20px; + border: 0; + + .item { + line-height: 15px; + } + } + +} \ No newline at end of file diff --git a/scss/components/_items.scss b/scss/components/_items.scss new file mode 100644 index 00000000..494954ec --- /dev/null +++ b/scss/components/_items.scss @@ -0,0 +1,141 @@ +.items { + table { + th { + text-align: left; + padding: 3px; + border-bottom: 1px solid rgba(0, 0, 0, .25); + background-color: rgb(73, 12, 11); + color: white; + font-size: 12px; + font-weight: normal; + } + td { + padding:3px; + } + } + + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background-shadow { + top: 36px; + } + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(73, 12, 11); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + // width: 160px; + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + .block-value { + display: inline-block; + } + } + + .block-value { + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 65px; + } + &.double { + width: 130px; + } + + input { + width: 45px; + } + } + + .item-values { + margin-bottom: 5px; + border: 0; + } +} diff --git a/scss/components/_itemweaponsheet.scss b/scss/components/_itemweaponsheet.scss new file mode 100644 index 00000000..8bb304d9 --- /dev/null +++ b/scss/components/_itemweaponsheet.scss @@ -0,0 +1,238 @@ +.item-sheet-weapon { + + .header-fields { + height: 435px; + } + + .charname { + width: 100%; + + input { + color: rgb(19, 65, 3); + border: 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + } + + .characteristic-item { + border:0; + position: relative; + padding:0; + margin: 0 5px; + + .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: rgb(19, 65, 3); + color:white; + text-transform: uppercase; + font-size : 10px; + --notchSize: 7px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double rgb(18, 71, 1); + margin: auto; + position: relative; + + .characteristic-value { + input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; + } + input:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + border-radius: 5px; + } + } + + + } + } + + .item-name { + margin:0; + padding-bottom:0 !important; + } + + .grid { + margin-top: 0; + } + + .block-background { + background-color: rgb(191,254,191); + } + + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background-shadow { + top: 36px; + } + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(19, 65, 3); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + select { + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + .block-value { + display: inline-block; + } + } + + .block-value { + + textarea { + resize:none; + font-family: 'Roboto'; + border : 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + outline: none; + } + } + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 100px; + } + &.double { + width: 235px; + } + + input { + width: 45px; + } + } + + .tabs { + height : 20px; + border: 0; + + .item { + line-height: 15px; + } + } + +} \ No newline at end of file diff --git a/scss/components/_sheet.scss b/scss/components/_sheet.scss new file mode 100644 index 00000000..577efbd7 --- /dev/null +++ b/scss/components/_sheet.scss @@ -0,0 +1,5 @@ +&.sheet { + .sheet-body { + border : 0; + } +} \ No newline at end of file diff --git a/scss/components/_skills.scss b/scss/components/_skills.scss new file mode 100644 index 00000000..78b421e4 --- /dev/null +++ b/scss/components/_skills.scss @@ -0,0 +1,59 @@ +.tableWithHeader { + + .tableWithHeader-container { + flex: 1; + margin: 2px; + position: relative; + } + + table { + th { + text-align: left; + padding: 3px; + border-bottom: 1px solid rgba(0, 0, 0, .25); + background-color: rgb(73, 12, 11); + color: white; + font-size: 12px; + font-weight: normal; + } + + td { + padding: 0 0 0 3px; + + .dice-pool { + img { + width: 1em; + height: 1em; + border: 0; + } + } + } + + .careerskill-toggle { + margin: 0; + padding: 0; + } + + .careerskill-rank { + width: 30px; + text-align: center; + } + } +} + +table { + &.items { + + .items-list { + td { + &.item-controls { + text-align: right; + width: auto; + z-index: auto; + } + } + } + + } +} + diff --git a/scss/components/_tabs.scss b/scss/components/_tabs.scss index 7598ff99..d222fc5d 100644 --- a/scss/components/_tabs.scss +++ b/scss/components/_tabs.scss @@ -17,18 +17,64 @@ // } // } +.character { + .tabs { + height: 15px; + margin-bottom: 10px; + border: 0; + .item { + line-height: 15px; + } + } +} + +.minion { + .tabs { + height: 15px; + margin-bottom: 10px; + border: 0; + .item { + line-height: 15px; + } + } +} + +.vehicle { + .tabs { + height: 15px; + margin-bottom: 10px; + border: 0; + .item { + line-height: 15px; + } + } +} + .tabs { height: 40px; - border-top: 1px solid #AAA; - border-bottom: 1px solid #AAA; + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; .item { - line-height: 40px; + line-height: 15px; font-weight: bold; + background-color: rgb(81, 98, 77); + padding: 3px; + margin: 0 5px; + --notchSize: 10px; + + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + + &:hover { + text-shadow: 0 0 8px white; + } } .item.active { text-decoration: underline; text-shadow: none; + background-color: rgb(73, 12, 11); + color: white; + font-weight: normal; } -} \ No newline at end of file +} diff --git a/scss/components/_talents.scss b/scss/components/_talents.scss new file mode 100644 index 00000000..058bdfef --- /dev/null +++ b/scss/components/_talents.scss @@ -0,0 +1,28 @@ +table { + &.talent-list { + border:0; + + th { + text-align: left; + padding: 3px; + border-bottom: 1px solid rgba(0, 0, 0, .25); + background-color: rgb(73, 12, 11); + color: white; + font-size: 12px; + font-weight: normal; + } + + td { + height: 30px; + line-height: 24px; + padding: 3px; + + .item-controls { + text-align: right; + width: auto; + z-index: auto; + } + + } + } +} \ No newline at end of file diff --git a/scss/components/_talentsheet.scss b/scss/components/_talentsheet.scss new file mode 100644 index 00000000..4c02164e --- /dev/null +++ b/scss/components/_talentsheet.scss @@ -0,0 +1,244 @@ +.item-sheet-talent { + .header-fields { + height: 260px; + } + + .charname { + width: 100%; + + input { + color: rgb(130, 21, 23); + border: 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + } + + .characteristic-item { + border:0; + position: relative; + padding:0; + margin: 0 5px; + + .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: rgb(130, 21, 23); + color:white; + text-transform: uppercase; + font-size : 10px; + --notchSize: 7px; + + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double rgb(130, 21, 23); + margin: auto; + position: relative; + + .characteristic-value { + input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; + } + input:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + border-radius: 5px; + } + } + + + } + } + + .item-name { + margin:0; + padding-bottom:0 !important; + + .charname { + input { + width: 100%; + } + } + } + + .grid { + margin-top: 0; + } + + .block-background { + background-color: rgb(242, 235, 222); + } + + .attribute { + position: relative; + padding: 0; + z-index: 1; + border:0; + + .block-background-shadow { + top: 36px; + } + + .block-background { + padding: 5px 5px; + } + + .block-title { + line-height: initial; + background-color: rgb(130, 21, 23); + color: white; + font-size: 13px; + text-transform: uppercase; + margin:auto; + + --notchSize: 8px; + clip-path: + polygon( + 0% var(--notchSize), + var(--notchSize) 0%, + calc(100% - var(--notchSize)) 0%, + 100% var(--notchSize), + 100% calc(100% - var(--notchSize)), + calc(100% - var(--notchSize)) 100%, + var(--notchSize) 100%, + 0% calc(100% - var(--notchSize)) + ); + } + + .block-attribute { + + select { + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + + .block-value { + display: inline-block; + } + } + + .block-value { + + textarea { + resize:none; + font-family: 'Roboto'; + border : 0; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + outline: none; + } + } + + &.block-single { + input { + width: 100%; + padding: 6px; + } + } + + input { + border:0; + font-size:14px; + + &:focus { + box-shadow: 0 0 5px rgb(125, 169, 194); + background-color: rgb(125, 169, 194); + } + } + } + + .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); + } + + .shadow-left { + background-color: rgb(73, 12, 11); + width: 50%; + height: 100%; + float:left; + position: relative; + padding-top: 25px; + + .shadow-text { + color: white; + text-transform: uppercase; + } + } + + .shadow-right { + background-color: rgb(125, 169, 194); + width: 50%; + height: 100%; + float:right; + position: relative; + padding-top: 25px; + + .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; + } + } + } + + .resource { + line-height: 30px; + width: 110px; + + &.split { + width: 130px; + } + &.single { + width: 65px; + } + &.double { + width: 235px; + } + + input { + width: 65px; + height: 17px; + } + } + + .tabs { + height : 20px; + border: 0; + + .item { + line-height: 15px; + } + } + +} \ No newline at end of file diff --git a/scss/global/_flex.scss b/scss/global/_flex.scss index 013c98a6..e380e089 100644 --- a/scss/global/_flex.scss +++ b/scss/global/_flex.scss @@ -1,9 +1,9 @@ -.flex-center { - align-items: center; - justify-content: center; - text-align: center; -} - -.flex-between { - justify-content: space-between; +.flex-center { + align-items: center; + justify-content: center; + text-align: center; +} + +.flex-between { + justify-content: space-between; } \ No newline at end of file diff --git a/scss/global/_grid.scss b/scss/global/_grid.scss index fb79192a..e09d14c2 100644 --- a/scss/global/_grid.scss +++ b/scss/global/_grid.scss @@ -1,79 +1,79 @@ -.grid, -.grid-2col { - display: grid; - grid-column: span 2 / span 2; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px; - margin: 10px 0; - padding: 0; -} - -.grid-3col { - grid-column: span 3 / span 3; - grid-template-columns: repeat(3, minmax(0, 1fr)); -} - -.grid-4col { - grid-column: span 4 / span 4; - grid-template-columns: repeat(4, minmax(0, 1fr)); -} - -.grid-5col { - grid-column: span 5 / span 5; - grid-template-columns: repeat(5, minmax(0, 1fr)); -} - -.grid-6col { - grid-column: span 6 / span 6; - grid-template-columns: repeat(6, minmax(0, 1fr)); -} - -.grid-7col { - grid-column: span 7 / span 7; - grid-template-columns: repeat(7, minmax(0, 1fr)); -} - -.grid-8col { - grid-column: span 8 / span 8; - grid-template-columns: repeat(8, minmax(0, 1fr)); -} - -.grid-9col { - grid-column: span 9 / span 9; - grid-template-columns: repeat(9, minmax(0, 1fr)); -} - -.grid-10col { - grid-column: span 10 / span 10; - grid-template-columns: repeat(10, minmax(0, 1fr)); -} - -.grid-11col { - grid-column: span 11 / span 11; - grid-template-columns: repeat(11, minmax(0, 1fr)); -} - -.grid-12col { - grid-column: span 12 / span 12; - grid-template-columns: repeat(12, minmax(0, 1fr)); -} - -.flex-group-center, -.flex-group-left, -.flex-group-right { - justify-content: center; - align-items: center; - text-align: center; - padding: 5px; - border: 1px solid #999; -} - -.flex-group-left { - justify-content: flex-start; - text-align: left; -} - -.flex-group-right { - justify-content: flex-end; - text-align: right; -} +.grid, +.grid-2col { + display: grid; + grid-column: span 2 / span 2; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px; + margin: 10px 0; + padding: 0; +} + +.grid-3col { + grid-column: span 3 / span 3; + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.grid-4col { + grid-column: span 4 / span 4; + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + +.grid-5col { + grid-column: span 5 / span 5; + grid-template-columns: repeat(5, minmax(0, 1fr)); +} + +.grid-6col { + grid-column: span 6 / span 6; + grid-template-columns: repeat(6, minmax(0, 1fr)); +} + +.grid-7col { + grid-column: span 7 / span 7; + grid-template-columns: repeat(7, minmax(0, 1fr)); +} + +.grid-8col { + grid-column: span 8 / span 8; + grid-template-columns: repeat(8, minmax(0, 1fr)); +} + +.grid-9col { + grid-column: span 9 / span 9; + grid-template-columns: repeat(9, minmax(0, 1fr)); +} + +.grid-10col { + grid-column: span 10 / span 10; + grid-template-columns: repeat(10, minmax(0, 1fr)); +} + +.grid-11col { + grid-column: span 11 / span 11; + grid-template-columns: repeat(11, minmax(0, 1fr)); +} + +.grid-12col { + grid-column: span 12 / span 12; + grid-template-columns: repeat(12, minmax(0, 1fr)); +} + +.flex-group-center, +.flex-group-left, +.flex-group-right { + justify-content: center; + align-items: center; + text-align: center; + padding: 5px; + border: 1px solid #999; +} + +.flex-group-left { + justify-content: flex-start; + text-align: left; +} + +.flex-group-right { + justify-content: flex-end; + text-align: right; +} diff --git a/scss/global/_window.scss b/scss/global/_window.scss index d16bacc9..981aa658 100644 --- a/scss/global/_window.scss +++ b/scss/global/_window.scss @@ -2,7 +2,7 @@ font-family: $font-primary; .window-content { - background: rgba(255, 255, 255, 0.7); + background-color: rgba(255, 255, 255, 0.7); font-size: 9pt; } } diff --git a/scss/starwarsffg.scss b/scss/starwarsffg.scss index 50031e38..5bf3e038 100644 --- a/scss/starwarsffg.scss +++ b/scss/starwarsffg.scss @@ -10,5 +10,18 @@ @import 'global/flex'; .starwarsffg { - + @import 'components/forms'; + @import 'components/sheet'; + @import 'components/resource'; + @import 'components/tabs'; + @import 'components/header'; + @import 'components/characteristics'; + @import 'components/skills'; + @import 'components/items'; + @import 'components/talents'; + @import 'components/biography'; + @import 'components/itemweaponsheet'; + @import 'components/itemarmorsheet'; + @import 'components/itemgearsheet'; + @import 'components/talentsheet'; } \ No newline at end of file diff --git a/scss/utils/_colors.scss b/scss/utils/_colors.scss index a119f260..911c3891 100644 --- a/scss/utils/_colors.scss +++ b/scss/utils/_colors.scss @@ -1,2 +1,2 @@ -$c-white: #fff; +$c-white: #fff; $c-black: #000; \ No newline at end of file diff --git a/scss/utils/_mixins.scss b/scss/utils/_mixins.scss index 69dd2ad1..030a3a7f 100644 --- a/scss/utils/_mixins.scss +++ b/scss/utils/_mixins.scss @@ -1,16 +1,16 @@ -@mixin element-invisible { - position: absolute; - - width: 1px; - height: 1px; - margin: -1px; - border: 0; - padding: 0; - - clip: rect(0 0 0 0); - overflow: hidden; -} - -@mixin hide { - display: none; +@mixin element-invisible { + position: absolute; + + width: 1px; + height: 1px; + margin: -1px; + border: 0; + padding: 0; + + clip: rect(0 0 0 0); + overflow: hidden; +} + +@mixin hide { + display: none; } \ No newline at end of file diff --git a/scss/utils/_typography.scss b/scss/utils/_typography.scss index 9737bce7..f17bfa38 100644 --- a/scss/utils/_typography.scss +++ b/scss/utils/_typography.scss @@ -1,17 +1,17 @@ -@font-face { - font-family: "Roboto"; - src: url("../fonts/Roboto-Regular.ttf") format("truetype"); -} - -@font-face { - font-family: "StarJedi"; - src: url("../fonts/StarJedi-Regular.ttf") format("truetype"); -} - -@font-face { - font-family: "Signika"; - src: url("../fonts/Signika-Regular.ttf") format("truetype"); -} - -$font-primary: "Roboto", sans-serif; -$font-secondary: "StarJedi", sans-serif; +@font-face { + font-family: "Roboto"; + src: url("../fonts/Roboto-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: "StarJedi"; + src: url("../fonts/StarJedi-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: "Signika"; + src: url("../fonts/Signika-Regular.ttf") format("truetype"); +} + +$font-primary: "Roboto", sans-serif; +$font-secondary: "StarJedi", sans-serif; diff --git a/scss/utils/_variables.scss b/scss/utils/_variables.scss index 64be658c..7cd71fe4 100644 --- a/scss/utils/_variables.scss +++ b/scss/utils/_variables.scss @@ -1,3 +1,3 @@ -$padding-sm: 5px; -$padding-md: 10px; +$padding-sm: 5px; +$padding-md: 10px; $padding-lg: 20px; \ No newline at end of file diff --git a/styles/starwarsffg.css b/styles/starwarsffg.css index cde71ede..9832d528 100644 --- a/styles/starwarsffg.css +++ b/styles/starwarsffg.css @@ -19,12 +19,11 @@ } .window-app .window-content { - background: rgba(255, 255, 255, 0.7); + background-color: rgba(255, 255, 255, 0.7); font-size: 9pt; } -.rollable:hover, -.rollable:focus { +.rollable:hover, .rollable:focus { color: #000; text-shadow: 0 0 10px red; cursor: pointer; @@ -119,3 +118,1469 @@ .flex-between { justify-content: space-between; } + +.starwarsffg .item-form { + font-family: "Roboto", sans-serif; +} + +.starwarsffg .block-background { + background-color: #c4dbe9; + padding: 5px; + --notchSize: 9px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .block-background-shadow { + position: absolute; + width: 100%; + top: 30px; + height: 30px; + background-color: #7da9c2; + padding: 5px; + z-index: -1; + --notchSize: 9px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .character { + min-width: 575px; +} + +.starwarsffg .position-relative { + position: relative; +} + +.starwarsffg.sheet .sheet-body { + border: 0; +} + +.starwarsffg .resource-label { + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .character .tabs { + height: 15px; + margin-bottom: 10px; + border: 0; +} + +.starwarsffg .character .tabs .item { + line-height: 15px; +} + +.starwarsffg .minion .tabs { + height: 15px; + margin-bottom: 10px; + border: 0; +} + +.starwarsffg .minion .tabs .item { + line-height: 15px; +} + +.starwarsffg .vehicle .tabs { + height: 15px; + margin-bottom: 10px; + border: 0; +} + +.starwarsffg .vehicle .tabs .item { + line-height: 15px; +} + +.starwarsffg .tabs { + height: 40px; + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; +} + +.starwarsffg .tabs .item { + line-height: 15px; + font-weight: bold; + background-color: #51624d; + padding: 3px; + margin: 0 5px; + --notchSize: 10px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .tabs .item:hover { + text-shadow: 0 0 8px white; +} + +.starwarsffg .tabs .item.active { + text-decoration: underline; + text-shadow: none; + background-color: #490c0b; + color: white; + font-weight: normal; +} + +.starwarsffg .header-fields .block-background-shadow { + top: 36px; +} + +.starwarsffg .header-fields .container.flex-group-center { + border: 0; + margin-bottom: 5px; + padding: 0 5px 5px 5px; +} + +.starwarsffg .header-fields h1 { + margin: 0; + width: 100%; +} + +.starwarsffg .header-fields .header-name { + margin: 0; + position: relative; + width: 100%; +} + +.starwarsffg .header-fields .header-name input { + margin: 0; + width: 100%; + border: 0; + background-color: rgba(0, 0, 0, 0); +} + +.starwarsffg .header-fields .header-name input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .header-fields .header-description-block { + margin-bottom: 5px; + margin-top: 5px; +} + +.starwarsffg .header-fields .header-description { + background-color: #c4dbe9; + --notchSize: 10px; + padding: 3px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .header-fields .table { + display: table; + width: 100%; +} + +.starwarsffg .header-fields .row { + display: table-row; + width: 100%; +} + +.starwarsffg .header-fields .row div { + display: table-cell; +} + +.starwarsffg .header-fields .row .row-input { + padding: 0 5px; +} + +.starwarsffg .header-fields .row input { + width: 100%; + border: 0; + border-bottom: 1px solid black; + border-radius: 0; +} + +.starwarsffg .header-fields .row input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .header-fields .profile-block { + margin-right: 5px; + margin-left: 5px; + height: 140px; + max-width: 140px; +} + +.starwarsffg .header-fields .profile-img { + flex: 0 0 100px; + height: 124px; + width: auto; + max-width: 124px; + border: 0; + margin: auto; +} + +.starwarsffg .header-fields .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .header-fields .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .header-fields .attribute .block-title { + line-height: initial; + background-color: #490c0b; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .header-fields .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .header-fields .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .header-fields .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .header-fields .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .header-fields .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .header-fields .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .header-fields .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .header-fields .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .header-fields .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .header-fields .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .header-fields .resource.split { + width: 130px; +} + +.starwarsffg .header-fields .resource.single { + width: 65px; +} + +.starwarsffg .header-fields .resource input { + width: 45px; +} + +.starwarsffg .sheet-body div.tab.characteristics { + overflow: hidden; +} + +.starwarsffg .sheet-body .characteristics fieldset.skillfilter { + display: none; +} + +.starwarsffg .sheet-body .characteristics .characteristic-item { + border: 0; + position: relative; +} + +.starwarsffg .sheet-body .characteristics .characteristic-item .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: #490c0b; + color: white; + text-transform: uppercase; + font-size: 10px; + --notchSize: 7px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .sheet-body .characteristics .grid { + margin-top: 0; +} + +.starwarsffg .sheet-body .characteristic { + width: 50px; + height: 50px; + border-radius: 50%; + border: 5px double black; + margin: auto; + position: relative; +} + +.starwarsffg .sheet-body .characteristic .characteristic-value input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; +} + +.starwarsffg .sheet-body .characteristic .characteristic-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + border-radius: 50%; +} + +.starwarsffg .tableWithHeader .tableWithHeader-container { + flex: 1; + margin: 2px; + position: relative; +} + +.starwarsffg .tableWithHeader table th { + text-align: left; + padding: 3px; + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + background-color: #490c0b; + color: white; + font-size: 12px; + font-weight: normal; +} + +.starwarsffg .tableWithHeader table td { + padding: 0 0 0 3px; +} + +.starwarsffg .tableWithHeader table td .dice-pool img { + width: 1em; + height: 1em; + border: 0; +} + +.starwarsffg .tableWithHeader table .careerskill-toggle { + margin: 0; + padding: 0; +} + +.starwarsffg .tableWithHeader table .careerskill-rank { + width: 30px; + text-align: center; +} + +.starwarsffg table.items .items-list td.item-controls { + text-align: right; + width: auto; + z-index: auto; +} + +.starwarsffg .items table th { + text-align: left; + padding: 3px; + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + background-color: #490c0b; + color: white; + font-size: 12px; + font-weight: normal; +} + +.starwarsffg .items table td { + padding: 3px; +} + +.starwarsffg .items .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .items .attribute .block-background-shadow { + top: 36px; +} + +.starwarsffg .items .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .items .attribute .block-title { + line-height: initial; + background-color: #490c0b; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .items .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .items .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .items .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .items .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .items .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .items .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .items .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .items .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .items .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .items .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .items .resource.split { + width: 130px; +} + +.starwarsffg .items .resource.single { + width: 65px; +} + +.starwarsffg .items .resource.double { + width: 130px; +} + +.starwarsffg .items .resource input { + width: 45px; +} + +.starwarsffg .items .item-values { + margin-bottom: 5px; + border: 0; +} + +.starwarsffg table.talent-list { + border: 0; +} + +.starwarsffg table.talent-list th { + text-align: left; + padding: 3px; + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + background-color: #490c0b; + color: white; + font-size: 12px; + font-weight: normal; +} + +.starwarsffg table.talent-list td { + height: 30px; + line-height: 24px; + padding: 3px; +} + +.starwarsffg table.talent-list td .item-controls { + text-align: right; + width: auto; + z-index: auto; +} + +.starwarsffg .biography .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .biography .attribute .block-background-shadow { + top: 36px; +} + +.starwarsffg .biography .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .biography .attribute .block-title { + line-height: initial; + background-color: #490c0b; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .biography .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .biography .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .biography .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .biography .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .biography .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .biography .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .biography .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .biography .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .biography .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .biography .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .biography .resource.split { + width: 130px; +} + +.starwarsffg .biography .resource.single { + width: 110px; +} + +.starwarsffg .biography .resource.double { + width: 130px; +} + +.starwarsffg .biography .resource input { + width: 45px; +} + +.starwarsffg .biography .biography-values { + margin-bottom: 5px; + border: 0; + position: absolute; + bottom: 10px; + left: 0; + padding: 0; +} + +.starwarsffg .biography .biography-editor { + height: 475px; +} + +.starwarsffg .item-sheet-weapon .header-fields { + height: 435px; +} + +.starwarsffg .item-sheet-weapon .charname { + width: 100%; +} + +.starwarsffg .item-sheet-weapon .charname input { + color: #134103; + border: 0; +} + +.starwarsffg .item-sheet-weapon .charname input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-weapon .characteristic-item { + border: 0; + position: relative; + padding: 0; + margin: 0 5px; +} + +.starwarsffg .item-sheet-weapon .characteristic-item .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: #134103; + color: white; + text-transform: uppercase; + font-size: 10px; + --notchSize: 7px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-weapon .characteristic-item .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double #124701; + margin: auto; + position: relative; +} + +.starwarsffg .item-sheet-weapon .characteristic-item .characteristic .characteristic-value input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; +} + +.starwarsffg .item-sheet-weapon .characteristic-item .characteristic .characteristic-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + border-radius: 5px; +} + +.starwarsffg .item-sheet-weapon .item-name { + margin: 0; + padding-bottom: 0 !important; +} + +.starwarsffg .item-sheet-weapon .grid { + margin-top: 0; +} + +.starwarsffg .item-sheet-weapon .block-background { + background-color: #bffebf; +} + +.starwarsffg .item-sheet-weapon .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .item-sheet-weapon .attribute .block-background-shadow { + top: 36px; +} + +.starwarsffg .item-sheet-weapon .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .item-sheet-weapon .attribute .block-title { + line-height: initial; + background-color: #134103; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-weapon .attribute .block-attribute select:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-weapon .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .item-sheet-weapon .attribute .block-value textarea { + resize: none; + font-family: 'Roboto'; + border: 0; +} + +.starwarsffg .item-sheet-weapon .attribute .block-value textarea:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + outline: none; +} + +.starwarsffg .item-sheet-weapon .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .item-sheet-weapon .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .item-sheet-weapon .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-weapon .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .item-sheet-weapon .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-weapon .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-weapon .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-weapon .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-weapon .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .item-sheet-weapon .resource.split { + width: 130px; +} + +.starwarsffg .item-sheet-weapon .resource.single { + width: 100px; +} + +.starwarsffg .item-sheet-weapon .resource.double { + width: 235px; +} + +.starwarsffg .item-sheet-weapon .resource input { + width: 45px; +} + +.starwarsffg .item-sheet-weapon .tabs { + height: 20px; + border: 0; +} + +.starwarsffg .item-sheet-weapon .tabs .item { + line-height: 15px; +} + +.starwarsffg .item-sheet-armor .header-fields { + height: 340px; +} + +.starwarsffg .item-sheet-armor .charname { + width: 100%; +} + +.starwarsffg .item-sheet-armor .charname input { + color: #553113; + border: 0; +} + +.starwarsffg .item-sheet-armor .charname input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-armor .characteristic-item { + border: 0; + position: relative; + padding: 0; + margin: 0 5px; +} + +.starwarsffg .item-sheet-armor .characteristic-item .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: #553113; + color: white; + text-transform: uppercase; + font-size: 10px; + --notchSize: 7px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-armor .characteristic-item .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double #553113; + margin: auto; + position: relative; +} + +.starwarsffg .item-sheet-armor .characteristic-item .characteristic .characteristic-value input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; +} + +.starwarsffg .item-sheet-armor .characteristic-item .characteristic .characteristic-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + border-radius: 5px; +} + +.starwarsffg .item-sheet-armor .item-name { + margin: 0; + padding-bottom: 0 !important; +} + +.starwarsffg .item-sheet-armor .grid { + margin-top: 0; +} + +.starwarsffg .item-sheet-armor .block-background { + background-color: #e9c09e; +} + +.starwarsffg .item-sheet-armor .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .item-sheet-armor .attribute .block-background-shadow { + top: 36px; +} + +.starwarsffg .item-sheet-armor .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .item-sheet-armor .attribute .block-title { + line-height: initial; + background-color: #553113; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-armor .attribute .block-attribute select:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-armor .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .item-sheet-armor .attribute .block-value textarea { + resize: none; + font-family: 'Roboto'; + border: 0; +} + +.starwarsffg .item-sheet-armor .attribute .block-value textarea:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + outline: none; +} + +.starwarsffg .item-sheet-armor .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .item-sheet-armor .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .item-sheet-armor .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-armor .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .item-sheet-armor .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-armor .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-armor .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-armor .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-armor .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .item-sheet-armor .resource.split { + width: 130px; +} + +.starwarsffg .item-sheet-armor .resource.single { + width: 100px; +} + +.starwarsffg .item-sheet-armor .resource.double { + width: 235px; +} + +.starwarsffg .item-sheet-armor .resource input { + width: 45px; +} + +.starwarsffg .item-sheet-armor .tabs { + height: 20px; + border: 0; +} + +.starwarsffg .item-sheet-armor .tabs .item { + line-height: 15px; +} + +.starwarsffg .item-sheet-gear .header-fields { + height: 340px; +} + +.starwarsffg .item-sheet-gear .charname { + width: 100%; +} + +.starwarsffg .item-sheet-gear .charname input { + color: #2c0344; + border: 0; +} + +.starwarsffg .item-sheet-gear .charname input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-gear .characteristic-item { + border: 0; + position: relative; + padding: 0; + margin: 0 5px; +} + +.starwarsffg .item-sheet-gear .characteristic-item .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: #2c0344; + color: white; + text-transform: uppercase; + font-size: 10px; + --notchSize: 7px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-gear .characteristic-item .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double #2c0344; + margin: auto; + position: relative; +} + +.starwarsffg .item-sheet-gear .characteristic-item .characteristic .characteristic-value input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; +} + +.starwarsffg .item-sheet-gear .characteristic-item .characteristic .characteristic-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + border-radius: 5px; +} + +.starwarsffg .item-sheet-gear .item-name { + margin: 0; + padding-bottom: 0 !important; +} + +.starwarsffg .item-sheet-gear .grid { + margin-top: 0; +} + +.starwarsffg .item-sheet-gear .block-background { + background-color: #e9c6fd; +} + +.starwarsffg .item-sheet-gear .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .item-sheet-gear .attribute .block-background-shadow { + top: 36px; +} + +.starwarsffg .item-sheet-gear .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .item-sheet-gear .attribute .block-title { + line-height: initial; + background-color: #2c0344; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-gear .attribute .block-attribute select:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-gear .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .item-sheet-gear .attribute .block-value textarea { + resize: none; + font-family: 'Roboto'; + border: 0; +} + +.starwarsffg .item-sheet-gear .attribute .block-value textarea:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + outline: none; +} + +.starwarsffg .item-sheet-gear .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .item-sheet-gear .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .item-sheet-gear .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-gear .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .item-sheet-gear .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-gear .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-gear .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-gear .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-gear .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .item-sheet-gear .resource.split { + width: 130px; +} + +.starwarsffg .item-sheet-gear .resource.single { + width: 100px; +} + +.starwarsffg .item-sheet-gear .resource.double { + width: 235px; +} + +.starwarsffg .item-sheet-gear .resource input { + width: 45px; +} + +.starwarsffg .item-sheet-gear .tabs { + height: 20px; + border: 0; +} + +.starwarsffg .item-sheet-gear .tabs .item { + line-height: 15px; +} + +.starwarsffg .item-sheet-talent .header-fields { + height: 260px; +} + +.starwarsffg .item-sheet-talent .charname { + width: 100%; +} + +.starwarsffg .item-sheet-talent .charname input { + color: #821517; + border: 0; +} + +.starwarsffg .item-sheet-talent .charname input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-talent .characteristic-item { + border: 0; + position: relative; + padding: 0; + margin: 0 5px; +} + +.starwarsffg .item-sheet-talent .characteristic-item .characteristic-label { + margin-top: 5px; + width: 100%; + text-align: center; + background-color: #821517; + color: white; + text-transform: uppercase; + font-size: 10px; + --notchSize: 7px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-talent .characteristic-item .characteristic { + width: 50px; + height: 50px; + border-radius: 10px; + border: 5px double #821517; + margin: auto; + position: relative; +} + +.starwarsffg .item-sheet-talent .characteristic-item .characteristic .characteristic-value input { + height: 40px; + border: 0; + font-size: 30px; + text-align: center; +} + +.starwarsffg .item-sheet-talent .characteristic-item .characteristic .characteristic-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + border-radius: 5px; +} + +.starwarsffg .item-sheet-talent .item-name { + margin: 0; + padding-bottom: 0 !important; +} + +.starwarsffg .item-sheet-talent .item-name .charname input { + width: 100%; +} + +.starwarsffg .item-sheet-talent .grid { + margin-top: 0; +} + +.starwarsffg .item-sheet-talent .block-background { + background-color: #f2ebde; +} + +.starwarsffg .item-sheet-talent .attribute { + position: relative; + padding: 0; + z-index: 1; + border: 0; +} + +.starwarsffg .item-sheet-talent .attribute .block-background-shadow { + top: 36px; +} + +.starwarsffg .item-sheet-talent .attribute .block-background { + padding: 5px 5px; +} + +.starwarsffg .item-sheet-talent .attribute .block-title { + line-height: initial; + background-color: #821517; + color: white; + font-size: 13px; + text-transform: uppercase; + margin: auto; + --notchSize: 8px; + -webkit-clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); + clip-path: polygon(0% var(--notchSize), var(--notchSize) 0%, calc(100% - var(--notchSize)) 0%, 100% var(--notchSize), 100% calc(100% - var(--notchSize)), calc(100% - var(--notchSize)) 100%, var(--notchSize) 100%, 0% calc(100% - var(--notchSize))); +} + +.starwarsffg .item-sheet-talent .attribute .block-attribute select:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-talent .attribute .block-attribute .block-value { + display: inline-block; +} + +.starwarsffg .item-sheet-talent .attribute .block-value textarea { + resize: none; + font-family: 'Roboto'; + border: 0; +} + +.starwarsffg .item-sheet-talent .attribute .block-value textarea:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; + outline: none; +} + +.starwarsffg .item-sheet-talent .attribute .block-value.block-single input { + width: 100%; + padding: 6px; +} + +.starwarsffg .item-sheet-talent .attribute .block-value input { + border: 0; + font-size: 14px; +} + +.starwarsffg .item-sheet-talent .attribute .block-value input:focus { + box-shadow: 0 0 5px #7da9c2; + background-color: #7da9c2; +} + +.starwarsffg .item-sheet-talent .attribute .shadow-text { + position: absolute; + top: 5px; + font-size: 9px; + left: 50%; + transform: translateX(-50%); +} + +.starwarsffg .item-sheet-talent .attribute .shadow-left { + background-color: #490c0b; + width: 50%; + height: 100%; + float: left; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-talent .attribute .shadow-left .shadow-text { + color: white; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-talent .attribute .shadow-right { + background-color: #7da9c2; + width: 50%; + height: 100%; + float: right; + position: relative; + padding-top: 25px; +} + +.starwarsffg .item-sheet-talent .attribute .shadow-right .shadow-text { + color: black; + font-weight: bold; + text-transform: uppercase; +} + +.starwarsffg .item-sheet-talent .resource { + line-height: 30px; + width: 110px; +} + +.starwarsffg .item-sheet-talent .resource.split { + width: 130px; +} + +.starwarsffg .item-sheet-talent .resource.single { + width: 65px; +} + +.starwarsffg .item-sheet-talent .resource.double { + width: 235px; +} + +.starwarsffg .item-sheet-talent .resource input { + width: 65px; + height: 17px; +} + +.starwarsffg .item-sheet-talent .tabs { + height: 20px; + border: 0; +} + +.starwarsffg .item-sheet-talent .tabs .item { + line-height: 15px; +} diff --git a/styles/swffg.css b/styles/swffg.css index 5f39e270..bb18b50e 100644 --- a/styles/swffg.css +++ b/styles/swffg.css @@ -139,7 +139,7 @@ div .container.talents { justify-content: flex-start; flex: 0 0 100px; } - +/* .starwarsffg.sheet .profile-img { flex: 0 0 100px; height: 124px; @@ -148,7 +148,7 @@ div .container.talents { margin-right: 10px; margin-left: 10px; border-radius: 15px; -} +} */ .starwarsffg.sheet .header-fields { flex: 1; @@ -234,7 +234,7 @@ div .container.talents { } .starwarsffg.sheet .sheet-body.vehicle { - height: calc(100% - 25em); + height: calc(100% - 17em); overflow: auto; } diff --git a/system.json b/system.json index f5211271..75b6ac0b 100644 --- a/system.json +++ b/system.json @@ -2,11 +2,11 @@ "name": "starwarsffg", "title": "Star Wars FFG", "description": "A system for playing Star Wars FFG games.", - "version": 0.055, + "version": 0.06, "minimumCoreVersion": "0.5.6", "compatibleCoreVersion": "0.6.1", "templateVersion": 1, - "author": "Esrin", + "author": "Esrin and Jaxxa", "esmodules": ["modules/dice-pool-ffg.js", "modules/swffg-main.js"], "styles": ["styles/swffg.css", "styles/starwarsffg.css"], "packs": [ @@ -31,8 +31,8 @@ "gridUnits": "ft", "primaryTokenAttribute": "wounds", "secondaryTokenAttribute": "strain", - "url": "https://github.com/Esrin/StarWarsFFG/tree/esrin-dev", - "manifest": "https://raw.githubusercontent.com/Esrin/StarWarsFFG/esrin-dev/system.json", - "download": "https://github.com/Esrin/StarWarsFFG/releases/download/esrin-dev_0.05/esrin-dev_0.055.zip", + "url": "https://github.com/StarWarsFoundryVTT/StarWarsFFG/tree/esrin-dev", + "manifest": "https://raw.githubusercontent.com/StarWarsFoundryVTT/StarWarsFFG/esrin-dev/system.json", + "download": "https://github.com/Esrin/StarWarsFFG/releases/download/esrin-dev_0.06/esrin-dev_0.060.zip", "license": "LICENSE.txt" } diff --git a/template.json b/template.json index dc5def41..efb7cd18 100644 --- a/template.json +++ b/template.json @@ -1,698 +1,698 @@ -{ - "Actor": { - "types": ["character", "minion", "vehicle"], - "templates": { - "biography": { - "biography": "" - }, - "species": { - "species": { - "value": "", - "type": "String" - } - }, - "career": { - "career": { - "value": "", - "type": "String" - } - }, - "specialisation": { - "specialisation": { - "value": "", - "type": "String" - } - }, - "stats": { - "stats": { - "wounds": { - "value": 0, - "min": 0, - "max": 10 - }, - "strain": { - "value": 0, - "min": 0, - "max": 10 - }, - "soak": { - "value": 2 - }, - "defence": { - "ranged": 0, - "melee": 0 - }, - "encumbrance": { - "value": 0, - "max": 0 - }, - "forcePool": { - "value": 0, - "max": 0 - }, - "credits": { - "value": 0, - "type": "Number", - "label": "Credits" - } - } - }, - "characteristics": { - "characteristics": { - "Brawn": { - "value": 2, - "label": "Brawn", - "abrev": "Br", - "max": 7 - }, - "Agility": { - "value": 2, - "label": "Agility", - "abrev": "Ag", - "max": 7 - }, - "Intellect": { - "value": 2, - "label": "Intellect", - "abrev": "Int", - "max": 7 - }, - "Cunning": { - "value": 2, - "label": "Cunning", - "abrev": "Cun", - "max": 7 - }, - "Willpower": { - "value": 2, - "label": "Willpower", - "abrev": "Will", - "max": 7 - }, - "Presence": { - "value": 2, - "label": "Presence", - "abrev": "Pr", - "max": 7 - } - } - }, - "skills": { - "skills": { - "Brawl": { - "rank": 0, - "characteristic": "Brawn", - "groupskill": false, - "careerskill": false, - "type": "Combat", - "max": 6 - }, - "Gunnery": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "Combat", - "max": 6 - }, - "Lightsaber": { - "rank": 0, - "characteristic": "Brawn", - "groupskill": false, - "careerskill": false, - "type": "Combat", - "max": 6 - }, - "Melee": { - "rank": 0, - "characteristic": "Brawn", - "groupskill": false, - "careerskill": false, - "type": "Combat", - "max": 6 - }, - "Ranged: Light": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "Combat", - "max": 6 - }, - "Ranged: Heavy": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "Combat", - "max": 6 - }, - "Astrogation": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Athletics ": { - "rank": 0, - "characteristic": "Brawn", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Charm": { - "rank": 0, - "characteristic": "Presence", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Coercion": { - "rank": 0, - "characteristic": "Willpower", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Computers": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Cool": { - "rank": 0, - "characteristic": "Presence", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Coordination": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Deception": { - "rank": 0, - "characteristic": "Cunning", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Discipline": { - "rank": 0, - "characteristic": "Willpower", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Leadership": { - "rank": 0, - "characteristic": "Presence", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Mechanics": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Medicine": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Negotiation": { - "rank": 0, - "characteristic": "Presence", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Perception": { - "rank": 0, - "characteristic": "Cunning", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Piloting: Planetary": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Piloting: Space": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Resilience": { - "rank": 0, - "characteristic": "Brawn", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Skulduggery": { - "rank": 0, - "characteristic": "Cunning", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Stealth": { - "rank": 0, - "characteristic": "Agility", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Streetwise": { - "rank": 0, - "characteristic": "Cunning", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Survival": { - "rank": 0, - "characteristic": "Cunning", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Vigilance": { - "rank": 0, - "characteristic": "Willpower", - "groupskill": false, - "careerskill": false, - "type": "General", - "max": 6 - }, - "Knowledge: Core Worlds": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - }, - "Knowledge: Education": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - }, - "Knowledge: Lore": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - }, - "Knowledge: Outer Rim": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - }, - "Knowledge: Underworld": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - }, - "Knowledge: Warfare": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - }, - "Knowledge: Xenology": { - "rank": 0, - "characteristic": "Intellect", - "groupskill": false, - "careerskill": false, - "type": "Knowledge", - "max": 6 - } - } - }, - "attributes": { - "attributes": {} - }, - "modifiers": { - "modifiers": { - "Characteristic": {}, - "Skill Rank": {}, - "Stat": {} - } - } - }, - "character": { - "templates": ["biography", "species", "career", "specialisation", "stats", "characteristics", "skills", "attributes", "modifiers"], - "encumbrance": { - "value": 0, - "type": "Number", - "label": "Encumbrance", - "abrev": "Encum" - }, - "obligation": { - "value": 0, - "type": "Number", - "label": "Obligation" - }, - "duty": { - "value": 0, - "type": "Number", - "label": "Duty" - }, - "morality": { - "value": 0, - "type": "Number", - "label": "Morality" - }, - "conflict": { - "value": 0, - "type": "Number", - "label": "Conflict" - }, - "experience": { - "total": 0, - "available": 0 - } - }, - "minion": { - "templates": ["biography", "stats", "characteristics", "skills", "attributes", "modifiers"], - "quantity": { - "value": 1, - "type": "Number", - "label": "Quantity", - "abrev": "Qty" - }, - "unit_wounds": { - "value": 0, - "type": "Number", - "label": "Unit Wounds" - } - }, - "vehicle": { - "templates": ["biography", "attributes"], - "stats": { - "silhouette": { - "value": 1, - "type": "Number", - "label": "Silhouette" - }, - "speed": { - "value": 0, - "max": 0, - "type": "Number", - "label": "Speed" - }, - "handling": { - "value": 0, - "type": "Number", - "label": "Handling" - }, - "hullTrauma": { - "value": 0, - "min": 0, - "max": 10, - "label": "Hull Trauma" - }, - "systemStrain": { - "value": 0, - "min": 0, - "max": 10, - "label": "System Strain" - }, - "shields": { - "fore": 0, - "port": 0, - "starboard": 0, - "aft": 0, - "label": "Shields" - }, - "armour": { - "value": 0, - "type": "Number", - "label": "Armour" - }, - "sensorRange": { - "value": "Short", - "type": "String" - }, - "crew": {}, - "passengerCapacity": { - "value": 0, - "type": "Number", - "label": "Passenger Capacity" - }, - "encumbrance": { - "value": 0, - "min": 0, - "max": 10 - }, - "cost": { - "value": 0, - "type": "Number", - "label": "Cost" - }, - "rarity": { - "value": 0, - "type": "Number", - "label": "Rarity" - }, - "customizationHardPoints": { - "value": 0, - "type": "Number", - "label": "Hard Points" - } - } - } - }, - "Item": { - "types": ["gear", "weapon", "armour", "talent", "shipweapon", "shipattachment"], - "templates": { - "basic": { - "description": "", - "quantity": { - "value": 1, - "type": "Number", - "label": "Quantity", - "abrev": "Qty" - }, - "encumbrance": { - "value": 0, - "type": "Number", - "label": "Encumbrance", - "abrev": "Encum" - }, - "price": { - "value": 0, - "type": "Number", - "label": "Price" - }, - "rarity": { - "value": 0, - "type": "Number", - "label": "Rarity" - }, - "attributes": {} - }, - "hardpoints": { - "hardpoints": { - "value": 0, - "type": "Number", - "label": "Hard Points", - "abrev": "HP" - } - }, - "equippable": { - "equippable": { - "value": true, - "type": "Boolean", - "equipped": false - } - } - }, - "gear": { - "templates": ["basic"] - }, - "weapon": { - "templates": ["basic", "hardpoints", "equippable"], - "skill": { - "value": "Ranged: Light", - "type": "String", - "label": "Skill" - }, - "damage": { - "value": 0, - "type": "Number", - "label": "Damage", - "abrev": "Dam" - }, - "crit": { - "value": 0, - "type": "Number", - "label": "Critical Rating", - "abrev": "Crit" - }, - "range": { - "value": "Short", - "type": "String", - "label": "Range" - }, - "special": { - "value": "", - "type": "String", - "label": "Special" - } - }, - "armour": { - "templates": ["basic", "hardpoints", "equippable"], - "defence": { - "value": 0, - "type": "Number", - "label": "Defence", - "abrev": "Def" - }, - "soak": { - "value": 0, - "type": "Number", - "label": "Soak" - } - }, - "talent": { - "templates": ["basic"], - "description": "", - "activation": { - "value": "Passive", - "type": "String", - "label": "Activation" - }, - "ranks": { - "ranked": false, - "current": 1, - "min": 0 - }, - "trees": [], - "attributes": {} - }, - "shipweapon": { - "templates": ["basic", "hardpoints", "equippable"], - "label": "Ship Weapon", - "firingarc": { - "value": "Fore", - "type": "String", - "label": "Skill" - }, - "damage": { - "value": 0, - "type": "Number", - "label": "Damage", - "abrev": "Dam" - }, - "crit": { - "value": 0, - "type": "Number", - "label": "Critical Rating", - "abrev": "Crit" - }, - "range": { - "value": "Short", - "type": "String", - "label": "Range" - }, - "special": { - "value": "", - "type": "String", - "label": "Special" - } - }, - "shipattachment": { - "templates": ["basic", "hardpoints", "equippable"], - "label": "Ship Attachment" - }, - "species": { - "description": "", - "careerskills": [], - "characteristics": { - "Brawn": { - "value": 2, - "label": "Brawn", - "abrev": "Br" - }, - "Agility": { - "value": 2, - "label": "Agility", - "abrev": "Ag" - }, - "Intellect": { - "value": 2, - "label": "Intellect", - "abrev": "Int" - }, - "Cunning": { - "value": 2, - "label": "Cunning", - "abrev": "Cun" - }, - "Willpower": { - "value": 2, - "label": "Willpower", - "abrev": "Will" - }, - "Presence": { - "value": 2, - "label": "Presence", - "abrev": "Pr" - } - } - } - } -} +{ + "Actor": { + "types": ["character", "minion", "vehicle"], + "templates": { + "biography": { + "biography": "" + }, + "species": { + "species": { + "value": "", + "type": "String" + } + }, + "career": { + "career": { + "value": "", + "type": "String" + } + }, + "specialisation": { + "specialisation": { + "value": "", + "type": "String" + } + }, + "stats": { + "stats": { + "wounds": { + "value": 0, + "min": 0, + "max": 10 + }, + "strain": { + "value": 0, + "min": 0, + "max": 10 + }, + "soak": { + "value": 2 + }, + "defence": { + "ranged": 0, + "melee": 0 + }, + "encumbrance": { + "value": 0, + "max": 0 + }, + "forcePool": { + "value": 0, + "max": 0 + }, + "credits": { + "value": 0, + "type": "Number", + "label": "Credits" + } + } + }, + "characteristics": { + "characteristics": { + "Brawn": { + "value": 2, + "label": "Brawn", + "abrev": "Br", + "max": 7 + }, + "Agility": { + "value": 2, + "label": "Agility", + "abrev": "Ag", + "max": 7 + }, + "Intellect": { + "value": 2, + "label": "Intellect", + "abrev": "Int", + "max": 7 + }, + "Cunning": { + "value": 2, + "label": "Cunning", + "abrev": "Cun", + "max": 7 + }, + "Willpower": { + "value": 2, + "label": "Willpower", + "abrev": "Will", + "max": 7 + }, + "Presence": { + "value": 2, + "label": "Presence", + "abrev": "Pr", + "max": 7 + } + } + }, + "skills": { + "skills": { + "Brawl": { + "rank": 0, + "characteristic": "Brawn", + "groupskill": false, + "careerskill": false, + "type": "Combat", + "max": 6 + }, + "Gunnery": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "Combat", + "max": 6 + }, + "Lightsaber": { + "rank": 0, + "characteristic": "Brawn", + "groupskill": false, + "careerskill": false, + "type": "Combat", + "max": 6 + }, + "Melee": { + "rank": 0, + "characteristic": "Brawn", + "groupskill": false, + "careerskill": false, + "type": "Combat", + "max": 6 + }, + "Ranged: Light": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "Combat", + "max": 6 + }, + "Ranged: Heavy": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "Combat", + "max": 6 + }, + "Astrogation": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Athletics ": { + "rank": 0, + "characteristic": "Brawn", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Charm": { + "rank": 0, + "characteristic": "Presence", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Coercion": { + "rank": 0, + "characteristic": "Willpower", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Computers": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Cool": { + "rank": 0, + "characteristic": "Presence", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Coordination": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Deception": { + "rank": 0, + "characteristic": "Cunning", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Discipline": { + "rank": 0, + "characteristic": "Willpower", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Leadership": { + "rank": 0, + "characteristic": "Presence", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Mechanics": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Medicine": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Negotiation": { + "rank": 0, + "characteristic": "Presence", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Perception": { + "rank": 0, + "characteristic": "Cunning", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Piloting: Planetary": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Piloting: Space": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Resilience": { + "rank": 0, + "characteristic": "Brawn", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Skulduggery": { + "rank": 0, + "characteristic": "Cunning", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Stealth": { + "rank": 0, + "characteristic": "Agility", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Streetwise": { + "rank": 0, + "characteristic": "Cunning", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Survival": { + "rank": 0, + "characteristic": "Cunning", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Vigilance": { + "rank": 0, + "characteristic": "Willpower", + "groupskill": false, + "careerskill": false, + "type": "General", + "max": 6 + }, + "Knowledge: Core Worlds": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + }, + "Knowledge: Education": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + }, + "Knowledge: Lore": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + }, + "Knowledge: Outer Rim": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + }, + "Knowledge: Underworld": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + }, + "Knowledge: Warfare": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + }, + "Knowledge: Xenology": { + "rank": 0, + "characteristic": "Intellect", + "groupskill": false, + "careerskill": false, + "type": "Knowledge", + "max": 6 + } + } + }, + "attributes": { + "attributes": {} + }, + "modifiers": { + "modifiers": { + "Characteristic": {}, + "Skill Rank": {}, + "Stat": {} + } + } + }, + "character": { + "templates": ["biography", "species", "career", "specialisation", "stats", "characteristics", "skills", "attributes", "modifiers"], + "encumbrance": { + "value": 0, + "type": "Number", + "label": "Encumbrance", + "abrev": "Encum" + }, + "obligation": { + "value": 0, + "type": "Number", + "label": "Obligation" + }, + "duty": { + "value": 0, + "type": "Number", + "label": "Duty" + }, + "morality": { + "value": 0, + "type": "Number", + "label": "Morality" + }, + "conflict": { + "value": 0, + "type": "Number", + "label": "Conflict" + }, + "experience": { + "total": 0, + "available": 0 + } + }, + "minion": { + "templates": ["biography", "stats", "characteristics", "skills", "attributes", "modifiers"], + "quantity": { + "value": 1, + "type": "Number", + "label": "Quantity", + "abrev": "Qty" + }, + "unit_wounds": { + "value": 0, + "type": "Number", + "label": "Unit Wounds" + } + }, + "vehicle": { + "templates": ["biography", "attributes"], + "stats": { + "silhouette": { + "value": 1, + "type": "Number", + "label": "Silhouette" + }, + "speed": { + "value": 0, + "max": 0, + "type": "Number", + "label": "Speed" + }, + "handling": { + "value": 0, + "type": "Number", + "label": "Handling" + }, + "hullTrauma": { + "value": 0, + "min": 0, + "max": 10, + "label": "Hull Trauma" + }, + "systemStrain": { + "value": 0, + "min": 0, + "max": 10, + "label": "System Strain" + }, + "shields": { + "fore": 0, + "port": 0, + "starboard": 0, + "aft": 0, + "label": "Shields" + }, + "armour": { + "value": 0, + "type": "Number", + "label": "Armour" + }, + "sensorRange": { + "value": "Short", + "type": "String" + }, + "crew": {}, + "passengerCapacity": { + "value": 0, + "type": "Number", + "label": "Passenger Capacity" + }, + "encumbrance": { + "value": 0, + "min": 0, + "max": 10 + }, + "cost": { + "value": 0, + "type": "Number", + "label": "Cost" + }, + "rarity": { + "value": 0, + "type": "Number", + "label": "Rarity" + }, + "customizationHardPoints": { + "value": 0, + "type": "Number", + "label": "Hard Points" + } + } + } + }, + "Item": { + "types": ["gear", "weapon", "armour", "talent", "shipweapon", "shipattachment"], + "templates": { + "basic": { + "description": "", + "quantity": { + "value": 1, + "type": "Number", + "label": "Quantity", + "abrev": "Qty" + }, + "encumbrance": { + "value": 0, + "type": "Number", + "label": "Encumbrance", + "abrev": "Encum" + }, + "price": { + "value": 0, + "type": "Number", + "label": "Price" + }, + "rarity": { + "value": 0, + "type": "Number", + "label": "Rarity" + }, + "attributes": {} + }, + "hardpoints": { + "hardpoints": { + "value": 0, + "type": "Number", + "label": "Hard Points", + "abrev": "HP" + } + }, + "equippable": { + "equippable": { + "value": true, + "type": "Boolean", + "equipped": false + } + } + }, + "gear": { + "templates": ["basic"] + }, + "weapon": { + "templates": ["basic", "hardpoints", "equippable"], + "skill": { + "value": "Ranged: Light", + "type": "String", + "label": "Skill" + }, + "damage": { + "value": 0, + "type": "Number", + "label": "Damage", + "abrev": "Dam" + }, + "crit": { + "value": 0, + "type": "Number", + "label": "Critical Rating", + "abrev": "Crit" + }, + "range": { + "value": "Short", + "type": "String", + "label": "Range" + }, + "special": { + "value": "", + "type": "String", + "label": "Special" + } + }, + "armour": { + "templates": ["basic", "hardpoints", "equippable"], + "defence": { + "value": 0, + "type": "Number", + "label": "Defence", + "abrev": "Def" + }, + "soak": { + "value": 0, + "type": "Number", + "label": "Soak" + } + }, + "talent": { + "templates": ["basic"], + "description": "", + "activation": { + "value": "Passive", + "type": "String", + "label": "Activation" + }, + "ranks": { + "ranked": false, + "current": 1, + "min": 0 + }, + "trees": [], + "attributes": {} + }, + "shipweapon": { + "templates": ["basic", "hardpoints", "equippable"], + "label": "Ship Weapon", + "firingarc": { + "value": "Fore", + "type": "String", + "label": "Skill" + }, + "damage": { + "value": 0, + "type": "Number", + "label": "Damage", + "abrev": "Dam" + }, + "crit": { + "value": 0, + "type": "Number", + "label": "Critical Rating", + "abrev": "Crit" + }, + "range": { + "value": "Short", + "type": "String", + "label": "Range" + }, + "special": { + "value": "", + "type": "String", + "label": "Special" + } + }, + "shipattachment": { + "templates": ["basic", "hardpoints", "equippable"], + "label": "Ship Attachment" + }, + "species": { + "description": "", + "careerskills": [], + "characteristics": { + "Brawn": { + "value": 2, + "label": "Brawn", + "abrev": "Br" + }, + "Agility": { + "value": 2, + "label": "Agility", + "abrev": "Ag" + }, + "Intellect": { + "value": 2, + "label": "Intellect", + "abrev": "Int" + }, + "Cunning": { + "value": 2, + "label": "Cunning", + "abrev": "Cun" + }, + "Willpower": { + "value": 2, + "label": "Willpower", + "abrev": "Will" + }, + "Presence": { + "value": 2, + "label": "Presence", + "abrev": "Pr" + } + } + } + } +} diff --git a/templates/actors/ffg-character-sheet.html b/templates/actors/ffg-character-sheet.html index a68205c7..09ab6b9f 100644 --- a/templates/actors/ffg-character-sheet.html +++ b/templates/actors/ffg-character-sheet.html @@ -1,89 +1,130 @@ -