diff --git a/css/bol.css b/css/bol.css index 7b4a3b4..9e7f637 100644 --- a/css/bol.css +++ b/css/bol.css @@ -514,15 +514,6 @@ min-width: 460px; min-height: 400px; } -.bol.sheet.item .window-content { - background-color: white; - background-image: url("/systems/bol/ui/logo.webp"); - background-repeat: no-repeat; - background-size: 190px 115px; - height: 100%; - padding: 5px; - overflow-y: hidden; -} .bol.sheet.item .window-content form { height: 100%; } diff --git a/lang/fr.json b/lang/fr.json index 1e4b5ee..cf1933b 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1,5 +1,5 @@ { - "BOL.attributes.vigor": "Force", + "BOL.attributes.vigor": "Vigueur", "BOL.attributes.agility": "Agilité", "BOL.attributes.mind": "Esprit", "BOL.attributes.appeal": "Aura", @@ -50,5 +50,41 @@ "rank": "Niveau", "attribut": "Attribut", "subtype": "Type", - "Language": "Langue" + "Language": "Langue", + "Level": "Niveau", + "Roll": "Lancer", + + "Melee": "Mêlée", + "Ranged": "Tir", + "Quantity": "Quantité", + "Weight":"Poids", + "Damage": "Dommages", + "Two Hands": "A Deux Mains", + "Thrown": "Peut-être lancé", + "Range": "Portée (m.)", + "Reload": "A Recharger", + "Reload Duration": "Durée de rechargement (rounds)" , + "Can be hidden": "Peut être cachée", + "Ignore Shield": "Ignore les boucliers", + "Improvised": "Improvisée", + "Properties": "Propriétés", + "Protection Roll": "Jet de Protection", + "Protection Fixed": "Protection statique (si pas de jet)", + "None": "Aucun", + "Social Malus": "Malus Social", + "Agility Malus":"Malus d'Agilité", + "Initiative Malus": "Malus d'Initiative", + "Power Cost": "Cout en Points de Pouvoir", + "Equipped": "Equipé", + "Attack with": "Attaque avec", + "Range Modifier": "Modificateur de portée", + "Point Blank": "Bout portant", + "Short": "Courte", + "Medium": "Moyenne", + "Long": "Long", + "Very Long": "Très longue", + "Extreme": "Extrême", + "Maximum": "Maximale", + "Defender": "Défenseur", + "Defense score": "Score de défense" } \ No newline at end of file diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index b332134..00e46b7 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -26,7 +26,9 @@ export class BoLActorSheet extends ActorSheet { actor.data.attributes = Object.values(actor.data.data.attributes); actor.data.aptitudes = Object.values(actor.data.data.aptitudes); actor.data.resources = Object.values(actor.data.data.resources); - actor.data.equipment = actor.data.items.filter(i => i.type === "item"); + actor.data.equipment = actor.data.items.filter(i => i.type === "item" || i.type == 'weapon' || i.type == 'armor'); + actor.data.weapons = duplicate(actor.data.items.filter(i => i.type == 'weapon' )); + actor.data.armors = duplicate(actor.data.items.filter(i => i.type == 'armor' )); actor.data.features = { "origin" : actor.data.items.find(i => i.type === "feature" && i.data.subtype === "origin"), "race" : actor.data.items.find(i => i.type === "feature" && i.data.subtype === "race"), @@ -34,10 +36,7 @@ export class BoLActorSheet extends ActorSheet { "boons" : actor.data.items.filter(i => i.type === "feature" && i.data.subtype === "boon"), "flaws" : actor.data.items.filter(i => i.type === "feature" && i.data.subtype === "flaw") }; - // data.attributes = ["String", "Number", "Boolean"]; - // for (let attr of Object.values(data.data.attributes)) { - // attr.isCheckbox = attr.dtype === "Boolean"; - // } + return actor; } @@ -58,12 +57,18 @@ export class BoLActorSheet extends ActorSheet { console.log(item); item.sheet.render(true); }); - + html.find('.roll-attribute').click(ev => { + this.actor.rollAttributeAptitude( $(ev.currentTarget).data("attr-key") ); + }); html.find('.roll-career').click(ev => { const li = $(ev.currentTarget).parents(".item"); this.actor.rollCareer( li.data("itemId") ); }); - + html.find('.roll-weapon').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + this.actor.rollWeapon( li.data("itemId") ); + }); + // Delete Inventory Item html.find('.item-delete').click(ev => { const li = $(ev.currentTarget).parents(".item"); diff --git a/module/actor/actor.js b/module/actor/actor.js index aed2d54..0032cf6 100644 --- a/module/actor/actor.js +++ b/module/actor/actor.js @@ -6,6 +6,7 @@ import { BoLUtility } from "../system/bol-utility.js"; * @extends {Actor} */ export class BoLActor extends Actor { + /** @override */ prepareData() { super.prepareData(); @@ -19,22 +20,23 @@ export class BoLActor extends Actor { // Make separate methods for each Actor type (character, npc, etc.) to keep // things organized. - // if (actorData.type === 'character') this._prepareCharacterData(actorData); + if (actorData.type === 'character') { + this._prepareCharacterData(actorData); + } } // /** // * Prepare Character type specific data // */ - // _prepareCharacterData(actorData) { - // const data = actorData.data; - // - // // Make modifications to data here. For example: - //// // Loop through ability scores, and add their modifiers to our sheet output. - // for (let [key, ability] of Object.entries(data.abilities)) { - // // Calculate the modifier using d20 rules. - // ability.mod = Math.floor((ability.value - 10) / 2); - // } - // } + /* -------------------------------------------- */ + _prepareCharacterData(actorData) { + let newVitality = 10 + this.data.data.attributes.vigor.value; + if ( newVitality != this.data.data.resources.hp.max) { + this.data.data.resources.hp.max = newVitality; + this.update( { 'data.resources.hp.max': newVitality}); + } + } + /* -------------------------------------------- */ getBoons() { return this.data.items.filter(i => i.type === "feature" && i.data.subtype === "boon"); @@ -52,6 +54,35 @@ export class BoLActor extends Actor { this.currentRollData = rollData; } + /* -------------------------------------------- */ + async rollAttributeAptitude( attrKey ) { + let attr = this.data.data.attributes[attrKey]; + if ( !attr) { + attr = this.data.data.aptitudes[attrKey]; + } + if (attr) { + let rollData = { + mode : "attribute", + actorId: this.id, + actorImg: this.img, + attribute: duplicate(attr), + boons : this.getBoons(), + flaws : this.getFlaws(), + d6Bonus: 0, + d6Malus: 0, + rollMode: game.settings.get("core", "rollMode"), + title: game.i18n.localize(attr.label), + optionsBonusMalus: BoLUtility.buildListOptions(-8, +2), + bonusMalus: 0 + } + let rollDialog = await BoLRollDialog.create( this, rollData); + rollDialog.render( true ); + } else { + ui.notifications.warn("Unable to find attribute " + attrKey ); + } + } + + /* -------------------------------------------- */ async rollCareer( careerId ) { let career = BoLUtility.data(this.data.items.find( item => item.type == 'feature' && item.id == careerId)); if (career) { @@ -77,4 +108,49 @@ export class BoLActor extends Actor { ui.notifications.warn("Unable to find career for actor " + this.name + " - Career ID " + careerId); } } + + /* -------------------------------------------- */ + async rollWeapon( weaponId ) { + let weapon = BoLUtility.data(this.data.items.find( item => item.type == 'weapon' && item.id == weaponId)); + if (weapon) { + let target = BoLUtility.getTarget(); + if ( !target) { + ui.notifications.warn("You must have a target to attack with a Weapon"); + return; + } + let objectDefender = BoLUtility.data(game.actors.get(target.data.actorId)); + objectDefender = mergeObject(objectDefender, target.data.actorData); + let rollData = { + mode : "weapon", + actorId: this.id, + actorImg: this.img, + weapon : weapon, + target: target, + defender: objectDefender, + boons : this.getBoons(), + flaws : this.getFlaws(), + rollAttribute: 'agility', + attributes: duplicate(this.data.data.attributes), // For damage bonus + d6Bonus: 0, + d6Malus: 0, + rollMode: game.settings.get("core", "rollMode"), + title: weapon.name, + rangeModifier: 0, + optionsBonusMalus: BoLUtility.buildListOptions(-8, +2), + bonusMalus: 0 + } + if ( weapon.data.type == 'melee') { + rollData.aptitude = duplicate(this.data.data.aptitudes.melee); + } else { + rollData.aptitude = duplicate(this.data.data.aptitudes.ranged); + } + console.log("WEAPON ! ", rollData); + let rollDialog = await BoLRollDialog.create( this, rollData); + rollDialog.render( true ); + } else { + ui.notifications.warn("Unable to find weapon for actor " + this.name + " - Weapon ID " + weaponId); + } + } + + } \ No newline at end of file diff --git a/module/item/item-sheet.js b/module/item/item-sheet.js index 4d1fae1..34abaed 100644 --- a/module/item/item-sheet.js +++ b/module/item/item-sheet.js @@ -20,11 +20,11 @@ export class BoLItemSheet extends ItemSheet { get template() { const path = "systems/bol/templates/item"; // Return a single sheet for all item types. - return `${path}/item-sheet.hbs`; + //return `${path}/item-sheet.hbs`; // Alternatively, you could use the following return statement to do a // unique item sheet by type, like `weapon-sheet.html`. - // return `${path}/${this.item.data.type}-sheet.html`; + return `${path}/item-${this.item.data.type}-sheet.hbs`; } /* -------------------------------------------- */ diff --git a/module/system/bol-utility.js b/module/system/bol-utility.js index 22ba4f7..5c4a449 100644 --- a/module/system/bol-utility.js +++ b/module/system/bol-utility.js @@ -117,6 +117,15 @@ export class BoLUtility { this.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions); } + /* -------------------------------------------- */ + static getTarget() { + if (game.user.targets && game.user.targets.size == 1) { + for (let target of game.user.targets) { + return target; + } + } + return undefined; + } /* -------------------------------------------- */ static async rollBoL( rollData ) { @@ -136,9 +145,19 @@ export class BoLUtility { nbDice += d6BM; // Final modifier - let modifier = Number(rollData.attributes[rollData.rollAttribute].value) + Number(rollData.career.data.rank) + Number(rollData.bonusMalus); + let modifier = Number(rollData.bonusMalus); + if ( rollData.mode == 'career') { + modifier += Number(rollData.attributes[rollData.rollAttribute].value) + Number(rollData.career.data.rank); + } else if ( rollData.mode == 'attribute' ) { + modifier += rollData.attribute.value; + } else if ( rollData.mode == 'weapon') { + modifier += Number(rollData.attributes[rollData.rollAttribute].value) + Number(rollData.aptitude.value) + Number(rollData.rangeModifier); + modifier -= rollData.defender.aptitudes.def.value; + } + let formula = nbDice+"d6"+mode+"+"+modifier; - console.log("Goigin to roll ", formula, rollData.attributes, rollData.rollAttribute); + + console.log("Going to roll ", formula, rollData.attributes, rollData.rollAttribute); let myRoll = new Roll(formula).roll( { async: false}); await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode") ); rollData.roll = myRoll; @@ -152,7 +171,6 @@ export class BoLUtility { this.createChatWithRollMode( rollData.alias, { content: await renderTemplate(`systems/bol/templates/roll/chat-generic-result.hbs`, rollData) }); - // TODO } /* -------------------------------------------- */ diff --git a/module/system/roll-dialog.js b/module/system/roll-dialog.js index 699fdf4..7000c95 100644 --- a/module/system/roll-dialog.js +++ b/module/system/roll-dialog.js @@ -18,12 +18,12 @@ export class BoLRollDialog extends Dialog { buttons: { roll: { icon: '', - label: "Roll !", + label: game.i18n.localize("Roll"), callback: () => { this.roll() } }, cancel: { icon: '', - label: "Cancel", + label: game.i18n.localize("Cancel"), callback: () => { this.close() } } }, default: "roll", diff --git a/styles/bol.less b/styles/bol.less index b345e55..c81ac21 100644 --- a/styles/bol.less +++ b/styles/bol.less @@ -338,13 +338,6 @@ } &.item { .window-content { - background-color: white; - background-image: url("/systems/bol/ui/logo.webp"); - background-repeat: no-repeat; - background-size: @logo-width @logo-height; - height: 100%; - padding: 5px; - overflow-y: hidden; form { height: 100%; diff --git a/system.json b/system.json index fd00eb8..af07d0c 100644 --- a/system.json +++ b/system.json @@ -2,10 +2,10 @@ "name": "bol", "title": "Barbarians of Lemuria", "description": "The Barbarians of Lemuria system for FoundryVTT!", - "version": "0.8.8.3", + "version": "0.8.8.7", "minimumCoreVersion": "0.8.6", - "compatibleCoreVersion": "0.8.8", - "templateVersion": 4, + "compatibleCoreVersion": "0.8.9", + "templateVersion": 8, "author": "Zigmund", "esmodules": ["module/bol.js"], "styles": ["css/bol.css"], diff --git a/template.json b/template.json index 8461d05..1860daf 100644 --- a/template.json +++ b/template.json @@ -128,7 +128,7 @@ } }, "Item": { - "types": ["item", "feature"], + "types": ["item", "feature", "weapon", "armor"], "templates": { "base": { "subtype" : "default", @@ -168,6 +168,33 @@ "quantity": 1, "weight": 0 }, + "weapon": { + "type": "", + "quantity": 1, + "weight": 0, + "damage": "", + "range": "", + "thrown": false, + "twohands": false, + "reload": false, + "reloadduration": 0, + "canbehidden": false, + "ignoreshield": false, + "improvised": false, + "equipped": false, + "description": "" + }, + "armor": { + "type": "", + "protectionroll": "", + "protectionfixed": 0, + "socialmalus": false, + "agilitymalus": 0, + "initmalus": 0, + "powercost": 0, + "equipped": false, + "description": "" + }, "feature": { "rank": 0, "templates": ["base"] diff --git a/templates/actor/actor-sheet.hbs b/templates/actor/actor-sheet.hbs index 318332b..0e624f3 100644 --- a/templates/actor/actor-sheet.hbs +++ b/templates/actor/actor-sheet.hbs @@ -25,7 +25,7 @@ {{!-- Sheet Tab Navigation --}} @@ -35,7 +35,7 @@