From 02b3dd5e0f8123aa44ef47ba09fb9d8768845da9 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Thu, 10 Mar 2022 21:05:53 +0100 Subject: [PATCH] Add fight options --- css/bol.css | 11 ++ lang/en.json | 21 ++- lang/fr.json | 23 ++- module/actor/actor-sheet.js | 32 ++-- module/actor/actor.js | 121 +++++++++++-- module/controllers/bol-rolls.js | 165 ++++++++++++------ module/system/bol-combat.js | 13 +- module/system/bol-utility.js | 90 +++------- module/system/config.js | 13 +- module/system/templates.js | 4 +- packs/fightoptions.db | 7 + system.json | 13 +- templates/actor/actor-sheet.hbs | 6 +- templates/actor/parts/tabs/actor-actions.hbs | 10 ++ templates/chat/chat-activate-fight-option.hbs | 14 ++ templates/chat/chat-generic-result.hbs | 41 ----- templates/chat/chat-vitality-zero.hbs | 6 +- templates/chat/rolls/damage-roll-card.hbs | 1 + templates/chat/rolls/default-roll-card.hbs | 40 +++-- templates/chat/rolls/defense-request-card.hbs | 4 + templates/dialogs/fightoptions-roll-part.hbs | 10 ++ templates/dialogs/weapon-roll-dialog.hbs | 4 +- .../parts/properties/feature-properties.hbs | 6 +- .../feature/fightoption-properties.hbs | 19 ++ 24 files changed, 447 insertions(+), 227 deletions(-) create mode 100644 packs/fightoptions.db create mode 100644 templates/chat/chat-activate-fight-option.hbs delete mode 100644 templates/chat/chat-generic-result.hbs create mode 100644 templates/dialogs/fightoptions-roll-part.hbs create mode 100644 templates/item/parts/properties/feature/fightoption-properties.hbs diff --git a/css/bol.css b/css/bol.css index 1306fc2..f2be19b 100644 --- a/css/bol.css +++ b/css/bol.css @@ -617,6 +617,14 @@ a:hover { color: darkred; font-weight: bold; } +h2.good { + color: darkgreen; + font-weight: bold; +} +h2.bad { + color: darkred; + font-weight: bold; +} .message-header h2.roll { color: darkslategrey; font-weight: bold; @@ -935,3 +943,6 @@ body.system-bol img#logo { width: 64px; height: 64px; } +.dialog-button { + max-height: 2rem; +} \ No newline at end of file diff --git a/lang/en.json b/lang/en.json index fc15c9d..dd94b73 100644 --- a/lang/en.json +++ b/lang/en.json @@ -140,6 +140,14 @@ "BOL.ui.rangeModifiers": "Range modifier", "BOL.ui.money": "Bougette", "BOL.ui.moneyTitle": "Gold & Treasure", + "BOL.ui.fightOption": "Fight Options", + "BOL.ui.none": "None", + "BOL.ui.fightOptionType": "Fight Options types", + "BOL.ui.activated": "Activated", + "BOL.ui.deactivated": "Deactivated", + "BOL.ui.status": "Status", + "BOL.ui.toactivated": "Active (>Désactiver)", + "BOL.ui.todeactivated": "Inactive (>Activer)", "BOL.featureCategory.origins": "Origines", "BOL.featureCategory.races": "Races", @@ -147,6 +155,7 @@ "BOL.featureCategory.boons": "Avantages", "BOL.featureCategory.flaws": "Désavantages", "BOL.featureCategory.languages": "Langages", + "BOL.featureCategory.fightoptions": "Fight Options", "BOL.featureSubtypes.origin": "Origine", "BOL.featureSubtypes.race": "Race", @@ -155,13 +164,22 @@ "BOL.featureSubtypes.flaw": "Désavantage", "BOL.featureSubtypes.language": "Langage", "BOL.featureSubtypes.gods": "Faith & Gods", - + "BOL.featureSubtypes.fightOption": "Combat Option", + "BOL.bougette.nomoney": "Nothing", "BOL.bougette.tolive": "To live", "BOL.bougette.easylife": "Easy Life", "BOL.bougette.luxury" : "Luxury life", "BOL.bougette.rich": "Rich!", + "BOL.fightOptionTypes.armor": "Attaque au défaut d'armure", + "BOL.fightOptionTypes.intrepid": "Attaque intrépide", + "BOL.fightOptionTypes.twoweaponsdef": "Combat à 2 armes (Défense)", + "BOL.fightOptionTypes.twoweaponsatt": "Combat à 2 armes (Attaque)", + "BOL.fightOptionTypes.fulldefense": "Défense totale", + "BOL.fightOptionTypes.defense": "Posture défensive", + "BOL.fightOptionTypes.attack": "Posture offensive", + "BOL.itemCategory.object": "Objet", "BOL.itemCategory.equipment": "Équipement", "BOL.itemCategory.consumable": "Consommable", @@ -175,6 +193,7 @@ "BOL.combatCategory.shields": "Boucliers", "BOL.combatCategory.melee": "Armes de contact", "BOL.combatCategory.ranged": "Armes à distance", + "BOL.combatCategory.fightOptions": "Fight options", "BOL.equipmentCategory.weapon": "Arme", "BOL.equipmentCategory.armor": "Armure", diff --git a/lang/fr.json b/lang/fr.json index 8e9ee15..ee4e34b 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -142,6 +142,14 @@ "BOL.ui.rangeModifiers": "Mod. de Portée", "BOL.ui.money": "Bougette", "BOL.ui.moneyTitle": "Or et Piecettes", + "BOL.ui.fightOption": "Options de Combat", + "BOL.ui.none": "Aucune", + "BOL.ui.fightOptionType": "Types d'options de Combat", + "BOL.ui.activated": "Active", + "BOL.ui.deactivated": "Inactive", + "BOL.ui.toactivated": "Active (>Désactiver)", + "BOL.ui.todeactivated": "Inactive (>Activer)", + "BOL.ui.status": "Statut", "BOL.featureCategory.origins": "Origines", "BOL.featureCategory.races": "Races", @@ -149,7 +157,8 @@ "BOL.featureCategory.boons": "Avantages", "BOL.featureCategory.flaws": "Désavantages", "BOL.featureCategory.languages": "Langues", - + "BOL.featureCategory.fightoptions": "Options de Combat", + "BOL.bougette.nomoney": "A sec", "BOL.bougette.tolive": "De quoi vivre", "BOL.bougette.easylife": "A l'aise", @@ -163,6 +172,15 @@ "BOL.featureSubtypes.flaw": "Désavantage", "BOL.featureSubtypes.language": "Langue", "BOL.featureSubtypes.gods": "Dieux & Foi", + "BOL.featureSubtypes.fightOption": "Option de Combat", + + "BOL.fightOptionTypes.armor": "Attaque au défaut d'armure", + "BOL.fightOptionTypes.intrepid": "Attaque intrépide", + "BOL.fightOptionTypes.twoweaponsdef": "Combat à 2 armes (Défense)", + "BOL.fightOptionTypes.twoweaponsatt": "Combat à 2 armes (Attaque)", + "BOL.fightOptionTypes.fulldefense": "Défense totale", + "BOL.fightOptionTypes.defense": "Posture défensive", + "BOL.fightOptionTypes.attack": "Posture offensive", "BOL.itemCategory.object": "Objet", "BOL.itemCategory.equipment": "Équipement", @@ -177,7 +195,8 @@ "BOL.combatCategory.shields": "Boucliers", "BOL.combatCategory.melee": "Armes de contact", "BOL.combatCategory.ranged": "Armes à distance", - + "BOL.combatCategory.fightOptions": "Options de combat", + "BOL.equipmentCategory.weapon": "Arme", "BOL.equipmentCategory.armor": "Armure", "BOL.equipmentCategory.protection": "Protection", diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index 33dd183..e9d3597 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -42,7 +42,12 @@ export class BoLActorSheet extends ActorSheet { html.find('.create_item').click(ev => { this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvel Equipement", type: "item" }], { renderSheet: true }); }); - + + html.find(".toggle-fight-option").click((ev) => { + const li = $(ev.currentTarget).parents(".item") + this.actor.toggleFightOption( li.data("itemId") ) + }) + html.find(".inc-dec-btns-alchemy").click((ev) => { const li = $(ev.currentTarget).parents(".item"); this.actor.spendAlchemyPoint( li.data("itemId"), 1) @@ -97,17 +102,6 @@ export class BoLActorSheet extends ActorSheet { // Rollable abilities. html.find('.rollable').click(this._onRoll.bind(this)); - // 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") ); - // }); } /* -------------------------------------------- */ @@ -131,11 +125,11 @@ export class BoLActorSheet extends ActorSheet { formData.alchemy = this.actor.alchemy formData.containers = this.actor.containers formData.treasure = this.actor.treasure - formData.treasure = this.actor.treasure - formData.treasure = this.actor.alchemyrecipe - formData.vehicles = this.actor.vehicles; - formData.ammos = this.actor.ammos; - formData.misc = this.actor.misc; + formData.alchemyrecipe = this.actor.alchemyrecipe + formData.vehicles = this.actor.vehicles + formData.fightoptions = this.actor.fightoptions + formData.ammos = this.actor.ammos + formData.misc = this.actor.misc formData.combat = this.actor.buildCombat() formData.features = this.actor.buildFeatures() formData.isGM = game.user.isGM @@ -148,9 +142,9 @@ export class BoLActorSheet extends ActorSheet { formData.isAlchemist = this.actor.isAlchemist() formData.isPriest = this.actor.isPriest() - formData.isGM= game.user.isGM + formData.isGM = game.user.isGM - console.log("ACTORDATA", formData); + console.log("ACTORDATA", formData) return formData; } /* -------------------------------------------- */ diff --git a/module/actor/actor.js b/module/actor/actor.js index 663835f..8f7b4b0 100644 --- a/module/actor/actor.js +++ b/module/actor/actor.js @@ -22,11 +22,6 @@ export class BoLActor extends Actor { super.prepareData(); } - /* -------------------------------------------- */ - //_onUpdate(changed, options, user) { - // - //} - /* -------------------------------------------- */ updateResourcesData( ) { if ( this.type == 'character') { @@ -50,22 +45,92 @@ export class BoLActor extends Actor { /* -------------------------------------------- */ get itemData(){ - return Array.from(this.data.items.values()).map(i => i.data); + return Array.from(this.data.items.values()).map(i => i.data) } get details() { - return this.data.data.details; + return this.data.data.details } get attributes() { - return Object.values(this.data.data.attributes); + return Object.values(this.data.data.attributes) } get aptitudes() { - return Object.values(this.data.data.aptitudes); + return Object.values(this.data.data.aptitudes) } + /* -------------------------------------------- */ get defenseValue() { - return this.data.data.aptitudes.def.value; + let defMod = 0 + let fo = this.getActiveFightOption() + if (fo && fo.data.properties.fightoptiontype == "intrepid" ) { + defMod += -2 + } + if (fo && fo.data.properties.fightoptiontype == "fulldefense" ) { + defMod += 2 + } + if (fo && fo.data.properties.fightoptiontype == "twoweaponsdef" && !fo.data.properties.used) { + defMod += 1 + this.updateEmbeddedDocuments("Item", [ {_id: fo._id, 'data.properties.used': true}] ) + } + if (fo && fo.data.properties.fightoptiontype == "defense" ) { + defMod += 1 + } + if (fo && fo.data.properties.fightoptiontype == "attack" ) { + defMod += -1 + } + return this.data.data.aptitudes.def.value + defMod } + + /* -------------------------------------------- */ + getActiveFightOption( ) { + let it = this.itemData.find(i => i.type === "feature" && i.data.subtype === "fightoption" && i.data.properties.activated) + if (it) { + return duplicate(it) + } + return undefined + } + + /* -------------------------------------------- */ + async toggleFightOption( itemId) { + let fightOption = this.data.items.get(itemId) + let state + let updates = [] + + if ( fightOption) { + fightOption = duplicate(fightOption) + if (fightOption.data.properties.activated) { + state = false + } else { + state = true + } + updates.push( {_id: fightOption._id, 'data.properties.activated': state} ) // Update the selected one + await this.updateEmbeddedDocuments("Item", updates) // Apply all changes + // Then notify + ChatMessage.create({ + alias: this.name, + whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name), + content: await renderTemplate('systems/bol/templates/chat/chat-activate-fight-option.hbs', { name: this.name, img: fightOption.img, foName: fightOption.name, state: state} ) + }) + + } + } + + /* -------------------------------------------- */ + get armorMalusValue() { // used for Fight Options + for(let armor of this.armors) { + if (armor.data.properties.armorQuality.includes("light")) { + return 1 + } + if (armor.data.properties.armorQuality.includes("medium")) { + return 2 + } + if (armor.data.properties.armorQuality.includes("heavy")) { + return 3 + } + } + return 0 + } + get resources() { - return Object.values(this.data.data.resources); + return Object.values(this.data.data.resources) } get boons() { return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "boon"); @@ -83,13 +148,16 @@ export class BoLActor extends Actor { return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "race"); } get languages() { - return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "language"); + return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "language") + } + get fightoptions() { + return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "fightoption") } get features() { - return this.itemData.filter(i => i.type === "feature"); + return this.itemData.filter(i => i.type === "feature") } get equipment() { - return this.itemData.filter(i => i.type === "item"); + return this.itemData.filter(i => i.type === "item") } get armors() { return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "armor"); @@ -100,7 +168,7 @@ export class BoLActor extends Actor { get shields() { return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "shield"); } - + get weapons() { return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "weapon"); } @@ -267,9 +335,15 @@ export class BoLActor extends Actor { "label": "BOL.featureCategory.languages", "ranked": false, "items": this.languages + }, + "fightoptions": { + "label": "BOL.featureCategory.fightoptions", + "ranked": false, + "items": this.fightoptions } - }; + } } + buildCombat(){ return { "melee" : { @@ -278,6 +352,7 @@ export class BoLActor extends Actor { "protection" : false, "blocking" : false, "ranged" : false, + "options": false, "items" : this.melee }, "ranged" : { @@ -286,6 +361,7 @@ export class BoLActor extends Actor { "protection" : false, "blocking" : false, "ranged" : true, + "options": false, "items" : this.ranged }, "protections" : { @@ -294,6 +370,7 @@ export class BoLActor extends Actor { "protection" : true, "blocking" : false, "ranged" : false, + "options": false, "items" : this.protections }, "shields" : { @@ -302,9 +379,19 @@ export class BoLActor extends Actor { "protection" : false, "blocking" : true, "ranged" : false, + "options": false, "items" : this.shields + }, + "fightoptions" : { + "label" : "BOL.combatCategory.fightOptions", + "weapon" : false, + "protection" : false, + "blocking" : false, + "ranged" : false, + "options": true, + "items" : this.fightoptions } - }; + } } /*-------------------------------------------- */ diff --git a/module/controllers/bol-rolls.js b/module/controllers/bol-rolls.js index ea14062..c631b13 100644 --- a/module/controllers/bol-rolls.js +++ b/module/controllers/bol-rolls.js @@ -3,39 +3,47 @@ import { BoLUtility } from "../system/bol-utility.js"; const __adv2dice = { ["1B"]: 3, ["2B"]: 4, ["2"]: 2, ["1M"]: 3, ["2M"]: 4 } const _apt2attr = { init: "mind", melee: "agility", ranged: "agility", def: "vigor" } +/* -------------------------------------------- */ export class BoLRoll { + + /* -------------------------------------------- */ static options() { return { classes: ["bol", "dialog"], width: 480, height: 540 }; } + /* -------------------------------------------- */ static convertToAdv(adv) { if (adv == 0) return "2" return Math.abs(adv) + (adv < 0) ? 'M' : 'B'; } + /* -------------------------------------------- */ static getDefaultAttribute(key) { return _apt2attr[key] } + /* -------------------------------------------- */ static attributeCheck(actor, actorData, dataset, event) { - const key = dataset.key; - const adv = dataset.adv; - let attribute = eval(`actor.data.data.attributes.${key}`); - let label = (attribute.label) ? game.i18n.localize(attribute.label) : null; - let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label); - return this.displayRollDialog( - { - mode: "attribute", - actor: actor, - actorData: actorData, - attribute: attribute, - attrValue: attribute.value, - aptValue: 0, - label: label, - careerBonus: 0, - description: description, - adv: this.convertToAdv(adv), - mod: 0 - }); + const key = dataset.key + const adv = dataset.adv + + let attribute = eval(`actor.data.data.attributes.${key}`) + let label = (attribute.label) ? game.i18n.localize(attribute.label) : null + let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) + + let rollData = { + mode: "attribute", + actor: actor, + actorData: actorData, + attribute: attribute, + attrValue: attribute.value, + aptValue: 0, + label: label, + careerBonus: 0, + description: description, + adv: this.convertToAdv(adv), + mod: 0 + } + return this.displayRollDialog( rollData ) } /* -------------------------------------------- */ @@ -69,24 +77,31 @@ export class BoLRoll { /* -------------------------------------------- */ static weaponCheck(actor, actorData, dataset, event) { let target = BoLUtility.getTarget() - const li = $(event.currentTarget).parents(".item"); - const weapon = actor.items.get(li.data("item-id")); + const li = $(event.currentTarget).parents(".item") + const weapon = actor.items.get(li.data("item-id")) if (!weapon) { - ui.notifications.warn("Unable to find weapon !"); + ui.notifications.warn("Unable to find weapon !") return; } let weaponData = weapon.data.data let attribute = eval(`actor.data.data.attributes.${weaponData.properties.attackAttribute}`) let aptitude = eval(`actor.data.data.aptitudes.${weaponData.properties.attackAptitude}`) - console.debug("WEAPON!", weaponData) - let attackDef = { + // Manage specific case + let fightOption= actor.getActiveFightOption() + if ( fightOption && fightOption.data.fightoptiontype == "fulldefense") { + ui.notifications.warn(`{{actor.name}} est en Défense Totale ! Il ne peut pas attaquer ce round.`) + return + } + // Build the roll structure + let rolldata = { mode: "weapon", actor: actor, actorData: actorData, weapon: weapon, isRanged: weaponData.properties.ranged || weaponData.properties.throwing, target: target, + fightOption: fightOption, careerBonus: 0, defender: (target) ? game.actors.get(target.data.actorId) : undefined, attribute: attribute, @@ -98,7 +113,7 @@ export class BoLRoll { label: (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName'), description: actor.name + " - " + game.i18n.localize('BOL.ui.weaponAttack'), } - return this.displayRollDialog(attackDef); + return this.displayRollDialog(rolldata) } /* -------------------------------------------- */ @@ -179,7 +194,36 @@ export class BoLRoll { } $('#roll-modifier').val( this.rollData.attrValue + "+" + this.rollData.aptValue + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" + - this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "+" + this.rollData.shieldMalus ) + this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "-" + this.rollData.modArmorMalus + "-" + + this.rollData.shieldMalus + "+" + this.rollData.attackModifier ) + } + + /* -------------------------------------------- */ + static preProcessFightOption( rollData) { + rollData.damagesIgnoresArmor = false // Always reset flags + rollData.modArmorMalus = 0 + rollData.attackModifier = 0 + + let fgItem = rollData.fightOption + if (fgItem ) { + console.log(fgItem) + if (fgItem.data.properties.fightoptiontype == "armordefault") { + rollData.modArmorMalus = rollData.armorMalus // Activate the armor malus + rollData.damagesIgnoresArmor = true + } + if (fgItem.data.properties.fightoptiontype == "intrepid") { + rollData.attackModifier += 2 + } + if (fgItem.data.properties.fightoptiontype == "defense") { + rollData.attackModifier += -1 + } + if (fgItem.data.properties.fightoptiontype == "attack") { + rollData.attackModifier += 1 + } + if (fgItem.data.properties.fightoptiontype == "twoweaponsdef" || fgItem.data.properties.fightoptiontype == "twoweaponsatt") { + rollData.attackModifier += -1 + } + } } /* -------------------------------------------- */ @@ -250,15 +294,37 @@ export class BoLRoll { }) } + /* -------------------------------------------- */ + static preProcessWeapon( rollData) { + if (rollData.mode == "weapon") { + rollData.weaponModifier = rollData.weapon.data.data.properties.attackModifiers ?? 0; + rollData.attackBonusDice = rollData.weapon.data.data.properties.attackBonusDice + if (rollData.defender) { // If target is selected + rollData.defence = rollData.defender.defenseValue + rollData.armorMalus = rollData.defender.armorMalusValue + rollData.shieldBlock = 'none' + let shields = rollData.defender.shields + for (let shield of shields) { + rollData.shieldBlock = (shield.data.properties.blocking.blockingAll) ? 'blockall' : 'blockone'; + rollData.shieldAttackMalus = (shield.data.properties.blocking.malus) ? shield.data.properties.blocking.malus : 1; + rollData.applyShieldMalus = false + } + } + } + } + /* ROLL DIALOGS */ /* -------------------------------------------- */ static async displayRollDialog(rollData, onEnter = "submit") { + // initialize default flags/values const rollOptionTpl = `systems/bol/templates/dialogs/${rollData.mode}-roll-dialog.hbs` rollData.careers = rollData.actorData.features.careers rollData.boons = rollData.actor.bonusBoons rollData.flaws = rollData.actor.malusFlaws rollData.defence = 0 + rollData.attackModifier = 0 // Used for fight options + rollData.modArmorMalus = 0 // Used for fight options rollData.bDice = 0 rollData.mDice = 0 rollData.nbBoons = 0 @@ -273,31 +339,17 @@ export class BoLRoll { rollData.modRanged = rollData.modRanged ?? 0 rollData.mod = rollData.mod ?? 0 rollData.id = randomID(16) - - // Weapon mode specific management rollData.weaponModifier = 0 rollData.attackBonusDice = false - - // Saves + rollData.armorMalus = 0 + // Specific stuff + this.preProcessWeapon(rollData) + this.preProcessFightOption(rollData) + // Save this.rollData = rollData console.log("ROLLDATA", rollData) - if (rollData.mode == "weapon") { - rollData.weaponModifier = rollData.weapon.data.data.properties.attackModifiers ?? 0; - rollData.attackBonusDice = rollData.weapon.data.data.properties.attackBonusDice - if (rollData.defender) { // If target is selected - rollData.defence = rollData.defender.defenseValue - rollData.shieldBlock = 'none' - let shields = rollData.defender.shields - //console.log("Shields", shields) - for (let shield of shields) { - rollData.shieldBlock = (shield.data.properties.blocking.blockingAll) ? 'blockall' : 'blockone'; - rollData.shieldAttackMalus = (shield.data.properties.blocking.malus) ? shield.data.properties.blocking.malus : 1; - rollData.applyShieldMalus = false - } - } - } - + // Then display+process the dialog const rollOptionContent = await renderTemplate(rollOptionTpl, rollData); let d = new Dialog({ title: rollData.label, @@ -325,7 +377,7 @@ export class BoLRoll { const isMalus = rollData.mDice > 0 rollData.nbDice += (rollData.attackBonusDice) ? 1 : 0 - const modifiers = rollData.attrValue + rollData.aptValue + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence + rollData.shieldMalus + const modifiers = rollData.attrValue + rollData.aptValue + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier const formula = (isMalus) ? rollData.nbDice + "d6kl2 + " + modifiers : rollData.nbDice + "d6kh2 + " + modifiers rollData.formula = formula rollData.modifiers = modifiers @@ -365,15 +417,16 @@ export class BoLDefaultRoll { async roll() { - const r = new Roll(this.rollData.formula); - await r.roll({ "async": false }); - const activeDice = r.terms[0].results.filter(r => r.active); - const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b); + const r = new Roll(this.rollData.formula) + // console.log("Roll formula", this.rollData.formula) + await r.roll({ "async": false }) + const activeDice = r.terms[0].results.filter(r => r.active) + const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b) this.rollData.roll = r - this.rollData.isSuccess = (r.total >= 9); + this.rollData.isSuccess = (r.total >= 9) this.rollData.isCritical = (diceTotal === 12) this.rollData.isRealCritical = (diceTotal === 12) - this.rollData.isFumble = (diceTotal === 2); + this.rollData.isFumble = (diceTotal === 2) this.rollData.isFailure = !this.rollData.isSuccess if (this.rollData.reroll == undefined) { this.rollData.reroll = this.rollData.actor.heroReroll() @@ -456,10 +509,10 @@ export class BoLDefaultRoll { bonusDmg = 12 } let attrDamageValue = this.getDamageAttributeValue(this.rollData.weapon.data.data.properties.damageAttribute) - let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.data.data) + let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.data.data, this.rollData.fightOption ) let damageFormula = weaponFormula + "+" + bonusDmg + "+" + attrDamageValue - console.log("DAMAGE !!!", damageFormula, attrDamageValue) + console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData) //console.log("Formula", weaponFormula, damageFormula, this.rollData.weapon.data.data.properties.damage) this.rollData.damageFormula = damageFormula @@ -474,7 +527,7 @@ export class BoLDefaultRoll { _buildDamageChatMessage(rollData) { const rollMessageTpl = 'systems/bol/templates/chat/rolls/damage-roll-card.hbs'; - return renderTemplate(rollMessageTpl, rollData); + return renderTemplate(rollMessageTpl, rollData) } _buildChatMessage(rollData) { diff --git a/module/system/bol-combat.js b/module/system/bol-combat.js index d8bf799..2d7600e 100644 --- a/module/system/bol-combat.js +++ b/module/system/bol-combat.js @@ -48,7 +48,18 @@ export class BoLCombatManager extends Combat { fvttInit += (cId / 100) await this.updateEmbeddedDocuments("Combatant", [{ _id: ids[cId], initiative: fvttInit }]); } - console.log("TODO : Compute init for actor"); } + + /************************************************************************************/ + nextRound() { + let combatants = this.combatants.contents + for (let c of combatants) { + let actor = game.actors.get( c.data.actorId ) + //actor.clearRoundModifiers() + } + super.nextRound() + } + + } diff --git a/module/system/bol-utility.js b/module/system/bol-utility.js index 788fdad..0b7a5e9 100644 --- a/module/system/bol-utility.js +++ b/module/system/bol-utility.js @@ -139,7 +139,7 @@ export class BoLUtility { chatGM.whisper = this.getUsers(user => user.isGM); chatGM.content = "Blind message of " + game.user.name + "
" + chatOptions.content; console.log("blindMessageToGM", chatGM); - game.socket.emit("system.fvtt-fragged-kingdom", { msg: "msg_gm_chat_message", data: chatGM }); + game.socket.emit("system.bol", { msg: "msg_gm_chat_message", data: chatGM }); } /* -------------------------------------------- */ @@ -335,53 +335,6 @@ export class BoLUtility { return undefined; } - /* -------------------------------------------- */ - static async rollBoL(rollData) { - - // Dice bonus/malus selection - let nbDice = 2; - let d6BM = 0; - let mode = ""; - if (rollData.d6Malus > rollData.d6Bonus) { - d6BM = rollData.d6Malus - rollData.d6Bonus; - mode = "kl2"; - } - if (rollData.d6Bonus > rollData.d6Malus) { - d6BM = rollData.d6Bonus - rollData.d6Malus; - mode = "kh2"; - } - nbDice += d6BM; - - // Final modifier - 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.data.aptitudes.def.value; - } - - let formula = nbDice + "d6" + mode + "+" + modifier; - - 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; - rollData.formula = formula; - rollData.modifier = modifier; - rollData.nbDice = nbDice; - rollData.finalScore = myRoll.total; - - let actor = game.actors.get(rollData.actorId); - actor.saveRollData(rollData); - - this.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/bol/templates/chat/chat-generic-result.hbs`, rollData) - }); - } - /* -------------------------------------------- */ static async processAttackSuccess(attackDef) { if (!game.user.isGM) { // Only GM process this @@ -399,9 +352,10 @@ export class BoLUtility { attacker: attackDef.attacker, defender: attackDef.defender, defenderWeapons: defenderWeapons, - damageTotal: attackDef.damageRoll.total + damageTotal: attackDef.damageRoll.total, + damagesIgnoresArmor: attackDef.damagesIgnoresArmor, }) - }); + }) } /* -------------------------------------------- */ @@ -423,7 +377,8 @@ export class BoLUtility { } /* -------------------------------------------- */ - static getDamageFormula(weaponData) { + static getDamageFormula(weaponData, fightOption) { + let upgradeDamage = (fightOption && fightOption.data.properties.fightoptiontype == "twoweaponsatt") let damageString = weaponData.properties.damage let modifier = weaponData.properties.damageModifiers ?? 0 let multiplier = weaponData.properties.damageMultiplier ?? 1 @@ -435,26 +390,33 @@ export class BoLUtility { let formula = damageString if (damageString.includes("d") || damageString.includes("D")) { - var myReg = new RegExp('(\\d+)[dD]([\\d]+)([MB]*)?([\\+\\d]*)?', 'g'); - let res = myReg.exec(damageString); - let nbDice = parseInt(res[1]); - let postForm = 'kh' + nbDice; - let modIndex = 3; + var myReg = new RegExp('(\\d+)[dD]([\\d]+)([MB]*)?([\\+\\d]*)?', 'g') + let res = myReg.exec(damageString) + let nbDice = parseInt(res[1]) + let postForm = 'kh' + nbDice + let modIndex = 3 + // Upgrade damage if needed + if ( upgradeDamage && ( !res[3] || res[3]=="") ) { + res[3] = "B" // Upgrade to bonus + } if (res[3]) { + if ( upgradeDamage && res[3] == 'M') { + res[3] = "" // Disable lamlus for upgradeDamage + } if (res[3] == 'M') { - postForm = 'kl' + nbDice; - nbDice++; - modIndex = 4; + postForm = 'kl' + nbDice + nbDice++ + modIndex = 4 } if (res[3] == 'B') { - postForm = 'kh' + nbDice; - nbDice++; - modIndex = 4; + postForm = 'kh' + nbDice + nbDice++ + modIndex = 4 } } - formula = "(" + nbDice + "d" + res[2] + reroll + postForm + "+" + modifier + ") *" + multiplier; + formula = "(" + nbDice + "d" + res[2] + reroll + postForm + "+" + modifier + ") *" + multiplier } - return formula; + return formula } /* -------------------------------------------- */ diff --git a/module/system/config.js b/module/system/config.js index 663590a..cbb6dc5 100644 --- a/module/system/config.js +++ b/module/system/config.js @@ -254,7 +254,18 @@ BOL.featureSubtypes = { "boon" : "BOL.featureSubtypes.boon", "flaw" : "BOL.featureSubtypes.flaw", "language" : "BOL.featureSubtypes.language", - "godsfaith" : "BOL.featureSubtypes.gods" + "godsfaith" : "BOL.featureSubtypes.gods", + "fightoption" : "BOL.featureSubtypes.fightOption" +} + +BOL.fightOptionTypes = { + "armordefault": "BOL.fightOptionTypes.armor", + "intrepid": "BOL.fightOptionTypes.intrepid", + "twoweaponsdef": "BOL.fightOptionTypes.twoweaponsdef", + "twoweaponsatt": "BOL.fightOptionTypes.twoweaponsatt", + "fulldefense": "BOL.fightOptionTypes.fulldefense", + "defense": "BOL.fightOptionTypes.defense", + "attack": "BOL.fightOptionTypes.attack", } BOL.itemIcons = { diff --git a/module/system/templates.js b/module/system/templates.js index 10ad3df..f3619a7 100644 --- a/module/system/templates.js +++ b/module/system/templates.js @@ -33,6 +33,7 @@ export const preloadHandlebarsTemplates = async function () { "systems/bol/templates/item/parts/properties/feature/flaw-properties.hbs", "systems/bol/templates/item/parts/properties/feature/origin-properties.hbs", "systems/bol/templates/item/parts/properties/feature/race-properties.hbs", + "systems/bol/templates/item/parts/properties/feature/fightoption-properties.hbs", // DIALOGS "systems/bol/templates/chat/rolls/attack-damage-card.hbs", @@ -47,7 +48,8 @@ export const preloadHandlebarsTemplates = async function () { "systems/bol/templates/dialogs/career-roll-part.hbs", "systems/bol/templates/dialogs/boons-roll-part.hbs", "systems/bol/templates/dialogs/flaws-roll-part.hbs", - "systems/bol/templates/dialogs/total-roll-part.hbs", + "systems/bol/templates/dialogs/total-roll-part.hbs", + "systems/bol/templates/dialogs/fightoptions-roll-part.hbs", ]; // Load the template parts diff --git a/packs/fightoptions.db b/packs/fightoptions.db new file mode 100644 index 0000000..ec8a92b --- /dev/null +++ b/packs/fightoptions.db @@ -0,0 +1,7 @@ +{"_id":"4VsEmcj4YpdAaaZY","name":"Attaque au Défaut d'armure","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous visez une zone du corps non protégée ou un point faible de l’armure de votre adversaire.

\n

Appliquez la valeur de protection fixe de l’armure comme malus à votre jet d’attaque (-1 pour une armure légère, -2 pour une armure moyenne et -3 pour une armure lourde). Si votre attaque passe malgré ce malus, les dégâts de votre coup ignorent la protection de l’armure.

\n

Si le MJ l’accepte, cette option de combat pourra également permettre de trouver le défaut de l’armure naturelle d’une créature.

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"armordefault","activated":false},"rank":0,"fightoptiontype":"armordefault"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.3nzfQvMvkK4ujRqI"}}} +{"name":"Posture Défensive","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous choisissez d’adopter une attitude prudente, en restant toujours prêt à parer ou à esquiver l’attaque de votre adversaire. Combattre en posture défensive vous confère un bonus de +1 en défense, mais vous subissez un malus de -1 à votre jet d’attaque.

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"defense","activated":false},"rank":0,"fightoptiontype":"defense"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.CS1fCtHTxp5v1krr"}},"_id":"FQPqaB86ZkRzsKwG"} +{"name":"Défense Totale","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous consacrez votre round à esquiver, parer et vous protéger des coups. Vous n’ effectuez pas d’attaque durant le round, mais bénéficiez d’un bonus de +2 en défense, qui s’ajoute éventuellement à celui que pourrait vous apporter un bouclier ou une arme secondaire de parade.

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"fulldefense","activated":false},"rank":0,"fightoptiontype":"fulldefense"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.t8v7isBpnFzAbmUI"}},"_id":"JRboSn5RuGILpH0B"} +{"name":"Combat à Deux Armes (Défensif)","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous ne pouvez utiliser que des armes légères ou moyennes.

\n

Vous attaquez avec une arme et parez avec l’autre. Vous considérez l’arme de parade comme l’équivalent d’un petit bouclier (+1 en défense contre une attaque), mais vous subissez un malus de -1 sur votre jet d’attaque avec votre autre arme.

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"twoweaponsdef","activated":false},"rank":0,"fightoptiontype":"twoweapons"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.lyMbLMPnFk0oXaSr"}},"_id":"JtU8EmKuda0M4Onv"} +{"_id":"a3Ev9xm8aM9kAmi3","name":"Attaque Intrépide","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous attaquez avec la plus extrême témérité.

\n

Vous ne bénéficiez pas de l’éventuel bonus d’un bouclier ou d’une arme secondaire de parade et subissez un malus de -2 à la défense. En revanche, vous bénéficiez d’un bonus de +2 au jet d’attaque.

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"intrepid","activated":false},"rank":0,"fightoptiontype":"intrepid"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.589BS9KBGnUazrFA"}}} +{"name":"Posture Offensive","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous vous concentrez sur l’attaque, au détriment de votre défense. Cette option vous confère un bonus de +1 au jet d’attaque, mais vous subissez un malus de -1 en défense.

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"attack","activated":false},"rank":0,"fightoptiontype":"attack"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.BF7F5WvL1pbWVHNq"}},"_id":"hgUHJP6JFxbeiRQL"} +{"name":"Combat à Deux Armes (Offensif)","type":"feature","img":"icons/skills/melee/weapons-crossed-poleaxes-white.webp","data":{"category":null,"subtype":"fightoption","description":"

Vous ne pouvez utiliser que des armes légères ou moyennes.

\n

Vous attaquez avec vos deux armes. Vous n’effectuez qu’un seul jet d’attaque avec un malus de -1, mais vous infligez des dégâts comme si vous maniez une arme moyenne (si vous utilisez deux armes légères) ou une arme lourde (si vous utilisez une arme moyenne et une arme légère, ou deux armes moyennes).

","properties":{"ismalusdice":false,"isbonusdice":false,"fightoptiontype":"twoweaponsatt","activated":false},"rank":0,"fightoptiontype":"twoweapons"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"kQghu0tL1dft5xLu":3},"flags":{"core":{"sourceId":"Item.lyMbLMPnFk0oXaSr"}},"_id":"wM4ZIVSSKApgzEmN"} diff --git a/system.json b/system.json index c3d5a22..d6765ca 100644 --- a/system.json +++ b/system.json @@ -7,8 +7,8 @@ "url": "https://github.com/ZigmundKreud/bol", "license": "LICENSE.txt", "flags": {}, - "version": "1.1.0", - "templateVersion": 21, + "version": "1.2.0", + "templateVersion": 22, "minimumCoreVersion": "0.8.6", "compatibleCoreVersion": "9", "scripts": [], @@ -135,6 +135,15 @@ "system": "bol", "entity": "Item", "private": false + }, + { + "label": "Options de Combat", + "type": "Item", + "name": "fightoptions", + "path": "packs/fightoptions.db", + "system": "bol", + "entity": "Item", + "private": false } ], "system": [], diff --git a/templates/actor/actor-sheet.hbs b/templates/actor/actor-sheet.hbs index ccd3564..1378ccc 100644 --- a/templates/actor/actor-sheet.hbs +++ b/templates/actor/actor-sheet.hbs @@ -26,13 +26,17 @@ {{!-- Sheet Body --}}
{{> - "systems/bol/templates/actor/parts/tabs/actor-stats.hbs"}}
+ "systems/bol/templates/actor/parts/tabs/actor-stats.hbs"}} + +
{{> "systems/bol/templates/actor/parts/tabs/actor-actions.hbs"}}
+
{{> "systems/bol/templates/actor/parts/tabs/actor-combat.hbs"}}
+
{{> "systems/bol/templates/actor/parts/tabs/actor-features.hbs"}}
diff --git a/templates/actor/parts/tabs/actor-actions.hbs b/templates/actor/parts/tabs/actor-actions.hbs index f46a60b..53e21e3 100644 --- a/templates/actor/parts/tabs/actor-actions.hbs +++ b/templates/actor/parts/tabs/actor-actions.hbs @@ -6,6 +6,7 @@ {{#if blocking}}
{{localize "BOL.ui.blocking"}}
{{/if}} {{#if weapon}}
{{localize "BOL.ui.damages"}}
{{/if}} {{#if ranged}}
{{localize "BOL.ui.range"}}
{{else}}
{{/if}} + {{#if options}}
{{localize "BOL.ui.status"}}
{{else}}
{{/if}} {{#each combatType.items as |item id|}}
  • @@ -15,6 +16,15 @@ {{#if ../blocking}}
    {{item.data.properties.blocking.malus}}
    {{/if}} {{#if ../weapon}}{{/if}} {{#if ../ranged}}
    {{item.data.properties.range}}
    {{else}}
    {{/if}} + {{#if ../options}}
    + {{#if item.data.properties.activated}} + {{localize "BOL.ui.toactivated"}} + {{else}} + {{localize "BOL.ui.todeactivated"}} + {{/if}} +
    {{else}} +
    + {{/if}}
  • {{/each}} diff --git a/templates/chat/chat-activate-fight-option.hbs b/templates/chat/chat-activate-fight-option.hbs new file mode 100644 index 0000000..8df2d51 --- /dev/null +++ b/templates/chat/chat-activate-fight-option.hbs @@ -0,0 +1,14 @@ +
    + {{name}} +

    {{name}}

    +
    + +
    + {{#if state}} + {{name}} active son option de combat {{foName}} pour ce round ! + {{else}} + {{name}} désactive son option de combat {{foName}} pour ce round ! + {{/if}} + +
    + diff --git a/templates/chat/chat-generic-result.hbs b/templates/chat/chat-generic-result.hbs deleted file mode 100644 index 3fae038..0000000 --- a/templates/chat/chat-generic-result.hbs +++ /dev/null @@ -1,41 +0,0 @@ -
    - {{alias}} -

    {{alias}}

    -
    -
    -

    - {{#if (eq mode "attribute")}} - {{localize attribute.label}} - {{else}} - {{#if (eq mode "career")}} - {{localize "Career"}} : {{career.name}} - {{else}} - {{#if (eq mode "weapon")}} - {{localize "Attack with"}} {{weapon.name}} - {{/if}} - {{/if}} - {{/if}} -

    -
    -
    -
    -
    {{formula}}
    -
    {{modifier}}
    - -

    {{finalScore}}

    -
    -
    \ No newline at end of file diff --git a/templates/chat/chat-vitality-zero.hbs b/templates/chat/chat-vitality-zero.hbs index d38db51..0ea5d05 100644 --- a/templates/chat/chat-vitality-zero.hbs +++ b/templates/chat/chat-vitality-zero.hbs @@ -1,5 +1,7 @@ -{{name}} -

    {{name}}

    +
    + {{name}} +

    {{name}}

    +
    diff --git a/templates/chat/rolls/damage-roll-card.hbs b/templates/chat/rolls/damage-roll-card.hbs index 4675127..7294674 100644 --- a/templates/chat/rolls/damage-roll-card.hbs +++ b/templates/chat/rolls/damage-roll-card.hbs @@ -5,4 +5,5 @@
    +
    {{/if}} diff --git a/templates/chat/rolls/default-roll-card.hbs b/templates/chat/rolls/default-roll-card.hbs index 2c7f447..0b3a296 100644 --- a/templates/chat/rolls/default-roll-card.hbs +++ b/templates/chat/rolls/default-roll-card.hbs @@ -1,21 +1,30 @@ -{{actor.name}} -{{#if isSuccess}} - {{#if isCritical}} -

     {{localize "BOL.ui.critical"}}...

    - {{else}} -

     {{localize "BOL.ui.success"}}...

    - {{/if}} -{{/if}} -{{#if isFailure}} - {{#if isFumble}} -

     {{localize "BOL.ui.fumble"}}...

    - {{else}} -

     {{localize "BOL.ui.failure"}}...

    - {{/if}} -{{/if}} +
    + {{#if isSuccess}} + {{#if isCritical}} +

     {{localize "BOL.ui.critical"}}... + {{else}} +

     {{localize "BOL.ui.success"}}... + {{/if}} + {{/if}} + {{#if isFailure}} + {{#if isFumble}} +

     {{localize "BOL.ui.fumble"}}... + {{else}} +

     {{localize "BOL.ui.failure"}}... + {{/if}} + {{/if}} + {{actor.name}} +

    +

    {{description}}

    +{{#if fightOption}} +
    + Option de combat : {{fightOption.name}} +
    +{{/if}} +
    {{#if (and isSuccess weapon)}} {{> "systems/bol/templates/chat/rolls/attack-damage-card.hbs"}} @@ -33,4 +42,5 @@ {{#if isRealCritical}} {{/if}} +
    \ No newline at end of file diff --git a/templates/chat/rolls/defense-request-card.hbs b/templates/chat/rolls/defense-request-card.hbs index 01b42c3..a333d19 100644 --- a/templates/chat/rolls/defense-request-card.hbs +++ b/templates/chat/rolls/defense-request-card.hbs @@ -1,6 +1,10 @@ {{defender.name}} Va encaisser {{damageTotal}} dégats ! +{{#if damagesIgnoresArmor}} +
    C'est une attaque au défaut de l'armure : vous devez encaisser SANS la protection de l'armure ! +{{/if}} + diff --git a/templates/dialogs/fightoptions-roll-part.hbs b/templates/dialogs/fightoptions-roll-part.hbs new file mode 100644 index 0000000..bda2690 --- /dev/null +++ b/templates/dialogs/fightoptions-roll-part.hbs @@ -0,0 +1,10 @@ + {{#if fightOption}} +
    +
    + +
    +
    + {{fightOption.name}} +
    +
    + {{/if}} diff --git a/templates/dialogs/weapon-roll-dialog.hbs b/templates/dialogs/weapon-roll-dialog.hbs index 3da3628..e7ef2a7 100644 --- a/templates/dialogs/weapon-roll-dialog.hbs +++ b/templates/dialogs/weapon-roll-dialog.hbs @@ -45,10 +45,12 @@ {{> "systems/bol/templates/dialogs/flaws-roll-part.hbs"}} + {{> "systems/bol/templates/dialogs/fightoptions-roll-part.hbs"}} + {{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}} {{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}} {{> "systems/bol/templates/dialogs/total-roll-part.hbs"}} - \ No newline at end of file + diff --git a/templates/item/parts/properties/feature-properties.hbs b/templates/item/parts/properties/feature-properties.hbs index b2d7f97..ae9e3a2 100644 --- a/templates/item/parts/properties/feature-properties.hbs +++ b/templates/item/parts/properties/feature-properties.hbs @@ -12,9 +12,9 @@ {{#if (equals data.subtype "career")}} {{> "systems/bol/templates/item/parts/properties/feature/career-properties.hbs"}} {{/if}} -{{!#if (equals data.subtype "origin")}} - {{!> "systems/bol/templates/item/parts/properties/feature/origin-properties.hbs"}} -{{!/if}} +{{#if (equals data.subtype "fightoption")}} + {{> "systems/bol/templates/item/parts/properties/feature/fightoption-properties.hbs"}} +{{/if}} {{!#if (equals data.subtype "race")}} {{!> "systems/bol/templates/item/parts/properties/feature/race-properties.hbs"}} {{!/if}} diff --git a/templates/item/parts/properties/feature/fightoption-properties.hbs b/templates/item/parts/properties/feature/fightoption-properties.hbs new file mode 100644 index 0000000..dd3e0db --- /dev/null +++ b/templates/item/parts/properties/feature/fightoption-properties.hbs @@ -0,0 +1,19 @@ +

    {{localize "BOL.ui.fightOption"}}

    + +
    + +
    + +
    +
    +
    + + +
    +