diff --git a/lang/en.json b/lang/en.json index 1c15c6e..2de175f 100644 --- a/lang/en.json +++ b/lang/en.json @@ -102,7 +102,12 @@ "BOL.ui.shieldMalus": "Malus de Bouclier", "BOL.ui.defenseScore": "Score de Defense", "BOL.ui.defender": "Défenseur", - + "BOL.ui.difficulty": "Difficulty", + "BOL.ui.spellProperties": "Spell Properties", + "BOL.ui.duration": "Duration", + "BOL.ui.spellkeep": "Maintain", + "BOL.ui.concentrate": "Concentrate", + "BOL.featureCategory.origins": "Origines", "BOL.featureCategory.races": "Races", "BOL.featureCategory.careers": "Carrières", @@ -198,6 +203,7 @@ "BOL.itemProperty.slot" : "Emplacement utilisé", "BOL.itemProperty.reload": "Rechargement (Actions)", "BOL.itemProperty.weaponSize" : "Classe d'arme", + "BOL.itemProperty.difficulty": "Difficulty", "BOL.itemStat.quantity": "Quantité", "BOL.itemStat.weight": "Poids", diff --git a/lang/fr.json b/lang/fr.json index e7656e3..670e5bd 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -53,8 +53,8 @@ "BOL.ui.delete": "Supprimer", "BOL.ui.roll" : "Utiliser", "BOL.ui.equipment" : "Équipement", - "BOL.ui.equipmentProperties" : "Propiétés d'équipement", - "BOL.ui.weaponProperties" : "Propiétés offensives", + "BOL.ui.equipmentProperties" : "Propriétés d'équipement", + "BOL.ui.weaponProperties" : "Propriétés offensives", "BOL.ui.protectionProperties" : "Protection", "BOL.ui.magicalProperties" : "Propriétés magiques", "BOL.ui.capacityProperties" : "Propriétés de capacité", @@ -103,6 +103,11 @@ "BOL.ui.shieldMalus": "Malus de Bouclier", "BOL.ui.defenseScore": "Score de Defense", "BOL.ui.defender": "Défenseur", + "BOL.ui.difficulty": "Difficulté", + "BOL.ui.spellProperties": "Propriétés du Sort", + "BOL.ui.duration": "Durée", + "BOL.ui.spellkeep": "Prolongation", + "BOL.ui.concentrate": "Concentration", "BOL.featureCategory.origins": "Origines", "BOL.featureCategory.races": "Races", @@ -199,6 +204,7 @@ "BOL.itemProperty.slot" : "Emplacement utilisé", "BOL.itemProperty.reload": "Rechargement (Actions)", "BOL.itemProperty.weaponSize" : "Classe d'arme", + "BOL.itemProperty.difficulty": "Difficulté", "BOL.itemStat.quantity": "Quantité", "BOL.itemStat.weight": "Poids", diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index d4e98e4..18070af 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -115,7 +115,7 @@ export class BoLActorSheet extends ActorSheet { formData.details = this.actor.details; formData.attributes = this.actor.attributes; formData.aptitudes = this.actor.aptitudes; - formData.resources = this.actor.resources; + formData.resources = this.actor.getResourcesFromType(); formData.equipment = this.actor.equipment; formData.weapons = this.actor.weapons; formData.protections = this.actor.protections; diff --git a/module/actor/actor.js b/module/actor/actor.js index 1eeda1d..e02dcb8 100644 --- a/module/actor/actor.js +++ b/module/actor/actor.js @@ -12,7 +12,12 @@ export class BoLActor extends Actor { // const flags = actorData.flags; // Make separate methods for each Actor type (character, npc, etc.) to keep things organized. if (actorData.type === 'character') { - //this._prepareCharacterData(actorData); + actorData.type = 'player'; + actorData.villainy = false; + } + if (actorData.type === 'encounter') { + actorData.type = 'tough'; + actorData.villainy = true; } super.prepareData(); } @@ -24,13 +29,15 @@ export class BoLActor extends Actor { /* -------------------------------------------- */ updateResourcesData( ) { - let newVitality = 10 + this.data.data.attributes.vigor.value + this.data.data.resources.hp.bonus - if ( this.data.data.resources.hp.max != newVitality) { - this.update( {'data.resources.hp.max': newVitality} ); - } - let newPower = 10 + this.data.data.attributes.mind.value + this.data.data.resources.power.bonus - if ( this.data.data.resources.power.max != newPower) { - this.update( {'data.resources.power.max': newPower} ); + if ( this.type == 'character') { + let newVitality = 10 + this.data.data.attributes.vigor.value + this.data.data.resources.hp.bonus + if ( this.data.data.resources.hp.max != newVitality) { + this.update( {'data.resources.hp.max': newVitality} ); + } + let newPower = 10 + this.data.data.attributes.mind.value + this.data.data.resources.power.bonus + if ( this.data.data.resources.power.max != newPower) { + this.update( {'data.resources.power.max': newPower} ); + } } } @@ -126,6 +133,35 @@ export class BoLActor extends Actor { get misc() { return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && (i.data.subtype === "other" ||i.data.subtype === "container" ||i.data.subtype === "scroll" || i.data.subtype === "jewel")); } + + heroReroll( ) { + if (this.type == 'character') { + return this.data.data.resources.hero.value > 0; + } else { + if (this.data.data.type == 'adversary') { + return this.data.data.resources.hero.value > 0; + } + } + return false + } + + getResourcesFromType() { + let resources = {}; + if (this.type == 'encounter') { + resources['hp'] = this.data.data.resources.hp; + if (this.data.data.type != 'base') { + resources['faith'] = this.data.data.resources.faith + resources['power'] = this.data.data.resources.power + } + if (this.data.data.type == 'adversary') { + resources['hero'] = duplicate(this.data.data.resources.hero) + resources['hero'].label = "BOL.resources.villainy" + } + } else { + resources = this.data.data.resources; + } + return resources + } buildFeatures(){ return { diff --git a/module/controllers/bol-rolls.js b/module/controllers/bol-rolls.js index e758854..91ee36f 100644 --- a/module/controllers/bol-rolls.js +++ b/module/controllers/bol-rolls.js @@ -89,7 +89,7 @@ export class BoLRoll { const adv = html.find('#adv').val(); const mod = html.find('#mod').val(); let careers = html.find('#career').val(); - const career = (careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i))); + const career = (!careers || careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i))); const isMalus = adv < 0; const dicePool = (isMalus) ? 2 - parseInt(adv) : 2 + parseInt(adv); const attrValue = eval(`actor.data.data.attributes.${attr}.value`); @@ -118,7 +118,9 @@ export class BoLRoll { careers: attackDef.attackerData.features.careers, boons: attackDef.attackerData.features.boons, flaws: attackDef.attackerData.features.flaws, + defence: 0 }; + if (attackDef.defender) { dialogData.defence = attackDef.defender.defenseValue, dialogData.shieldBlock = 'none' @@ -156,7 +158,7 @@ export class BoLRoll { } let careers = html.find('#career').val(); - const career = (careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i))); + const career = (!careers || careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i))); const isMalus = adv < 0; const dicePool = (isMalus) ? 2 - parseInt(adv) : 2 + parseInt(adv); const attrValue = eval(`attackDef.attacker.data.data.attributes.${attr}.value`); @@ -204,7 +206,7 @@ export class BoLRoll { const adv = html.find('#adv').val(); const mod = html.find('#mod').val(); let careers = html.find('#career').val(); - const career = (careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i))); + const career = (!careers || careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i))); const isMalus = adv < 0; const dicePool = (isMalus) ? 2 - parseInt(adv) : 2 + parseInt(adv); const aptValue = eval(`actor.data.data.aptitudes.${apt}.value`); @@ -259,6 +261,7 @@ export class BoLDefaultRoll { const tplData = { actor: actor, label: this._label, + reroll: actor.heroReroll(), isSuccess: this._isSuccess, isFailure: !this._isSuccess, isCritical: this._isCritical, @@ -280,9 +283,10 @@ export class BoLAttackRoll { } async roll() { + console.log("Attack def",this.attackDef.formula ) const r = new Roll(this.attackDef.formula); await r.roll({ "async": false }); - //await BoLUtility.showDiceSoNice(r); + await BoLUtility.showDiceSoNice(r); const activeDice = r.terms[0].results.filter(r => r.active); const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b); this._isSuccess = (r.total >= 9); @@ -294,16 +298,39 @@ export class BoLAttackRoll { flavor: msgFlavor, speaker: ChatMessage.getSpeaker({ actor: this.attackDef.attacker }), flags: { msgType: "default" } - }); + }).then( this.processResult() ); }); + } + async processDefense() { + if (this._isCritical) { + ChatMessage.create({ + alias: this.attackDef.attacker.name, + whisper: BoLUtility.getWhisperRecipientsAndGMs(this.attackDef.attacker.name), + content: await renderTemplate('systems/bol/templates/chat/rolls/attack-heroic-card.hbs', { + attackId: attackDef.id, + attacker: attackDef.attacker, + defender: attackDef.defender, + defenderWeapons: defenderWeapons, + damageTotal: attackDef.damageRoll.total + }) + }) + } else { + BoLUtility.sendAttackSuccess( this.attackDef); + } + } + + async processResult( ) { if (this._isSuccess) { let attrDamage = this.attackDef.weapon.data.data.properties.damageAttribute; - let weaponFormula = BoLUtility.getDamageFormula(this.attackDef.weapon.data.data.properties.damage) + let weaponFormula = BoLUtility.getDamageFormula(this.attackDef.weapon.data.data.properties.damage, + this.attackDef.weapon.data.data.properties.damageModifiers, + this.attackDef.weapon.data.data.properties.damageMultiplier) let damageFormula = weaponFormula + "+" + this.attackDef.attacker.data.data.attributes[attrDamage].value; + console.log("Formula", damageFormula) this.damageRoll = new Roll(damageFormula); await this.damageRoll.roll({ "async": false }); - //await BoLUtility.showDiceSoNice(this.damageRoll); + await BoLUtility.showDiceSoNice(this.damageRoll); // Update attackDef object this.attackDef.damageFormula = damageFormula; this.attackDef.damageRoll = this.damageRoll; @@ -314,23 +341,8 @@ export class BoLAttackRoll { flavor: msgFlavor, speaker: ChatMessage.getSpeaker({ actor: this.attackDef.attacker }), flags: { msgType: "default" } - }); + }).then( this.processDefense() ); }); - if (this._isCritical) { - ChatMessage.create({ - alias: this.attackDef.attacker.name, - whisper: BoLUtility.getWhisperRecipientsAndGMs(this.attackDef.attacker.name), - content: await renderTemplate('systems/bol/templates/chat/rolls/attack-heroic-card.hbs', { - attackId: attackDef.id, - attacker: attackDef.attacker, - defender: attackDef.defender, - defenderWeapons: defenderWeapons, - damageTotal: attackDef.damageRoll.total - }) - }) - } else { - BoLUtility.sendAttackSuccess( this.attackDef); - } } } @@ -351,6 +363,7 @@ export class BoLAttackRoll { const tplData = { actor: actor, label: this._label, + reroll: actor.heroReroll(), isSuccess: this._isSuccess, isFailure: !this._isSuccess, isCritical: this._isCritical, diff --git a/module/system/bol-utility.js b/module/system/bol-utility.js index 0a1a82e..6ff321a 100644 --- a/module/system/bol-utility.js +++ b/module/system/bol-utility.js @@ -111,6 +111,7 @@ export class BoLUtility { static async chatListeners(html) { // Damage handling html.on("click", '.damage-increase', event => { + event.preventDefault(); let attackId = event.currentTarget.attributes['data-attack-id'].value; let damageMode = event.currentTarget.attributes['data-damage-mode'].value; if ( game.user.isGM) { @@ -120,11 +121,17 @@ export class BoLUtility { } }); + html.on("click", '.hero-reroll', event => { + event.preventDefault(); + ui.notifications.warn("Not implemented up to now"); + } ); + html.on("click", '.damage-handling', event => { + event.preventDefault(); let attackId = event.currentTarget.attributes['data-attack-id'].value; let defenseMode = event.currentTarget.attributes['data-defense-mode'].value; let weaponId = (event.currentTarget.attributes['data-weapon-id']) ? event.currentTarget.attributes['data-weapon-id'].value : -1 - //console.log("DEFENSE1", event.currentTarget, attackId, defenseMode, weaponId); + console.log("DEFENSE1", event.currentTarget, attackId, defenseMode, weaponId); if ( game.user.isGM) { BoLUtility.processDamageHandling(event, attackId, defenseMode, weaponId) } else { @@ -165,10 +172,14 @@ export class BoLUtility { } BoLUtility.removeChatMessageId(BoLUtility.findChatMessageId(event.currentTarget)); + //console.log("Damage Handling", event, attackId, defenseMode, weaponId) // Only GM process this let attackDef = this.attackStore[attackId]; if (attackDef) { + if (attackDef.defenseDone) return; // ?? Why ??? + attackDef.defenseDone = true attackDef.defenseMode = defenseMode; + if (defenseMode == 'damage-with-armor') { let armorFormula = attackDef.defender.getArmorFormula(); attackDef.rollArmor = new Roll(armorFormula) @@ -249,7 +260,6 @@ export class BoLUtility { } /* -------------------------------------------- */ - static removeChatMessageId(messageId) { if (messageId){ game.messages.get(messageId)?.delete(); @@ -371,8 +381,9 @@ export class BoLUtility { } /* -------------------------------------------- */ - static getDamageFormula(damageString) { + static getDamageFormula(damageString, modifier=0, multiplier = 1) { if (damageString[0] == 'd') { damageString = "1" + damageString } // Help parsing + if (modifier == null) modifier = 0; var myReg = new RegExp('(\\d+)[dD]([\\d]+)([MB]*)?([\\+\\d]*)?', 'g'); let res = myReg.exec(damageString); let nbDice = parseInt(res[1]); @@ -390,7 +401,7 @@ export class BoLUtility { modIndex = 4; } } - let formula = nbDice + "d" + res[2] + postForm + ((res[modIndex]) ? res[modIndex] : ""); + let formula = "(" + nbDice + "d" + res[2] + postForm + "+" + modifier +") *" + multiplier; return formula; } /* -------------------------------------------- */ diff --git a/module/system/config.js b/module/system/config.js index 92dd123..3b8fa90 100644 --- a/module/system/config.js +++ b/module/system/config.js @@ -17,6 +17,13 @@ BOL.damageValues = { "d6BB" : "d6B + dé bonus", } +BOL.damageMultiplier = { + "1": "x1", + "2": "x2", + "3": "x3", + "4": "x4", +} + BOL.equipmentSlots = { "none" : "BOL.equipmentSlots.none", "head" : "BOL.equipmentSlots.head", @@ -189,7 +196,8 @@ BOL.itemProperties2 = { "throwing" : "BOL.itemProperty.throwing", "activable" : "BOL.itemProperty.activable", "powder" : "BOL.itemProperty.powder", - "damage" : "BOL.itemProperty.damage" + "damage" : "BOL.itemProperty.damage", + "difficulty": "BOL.itemProperty.difficulty" } BOL.itemStats = { diff --git a/module/system/helpers.js b/module/system/helpers.js index d0a4ea9..c7dadb5 100644 --- a/module/system/helpers.js +++ b/module/system/helpers.js @@ -4,6 +4,10 @@ export const registerHandlebarsHelpers = function () { return val == null; }); + Handlebars.registerHelper('exists', function (val) { + return val != null && val != undefined; + }); + Handlebars.registerHelper('isEmpty', function (list) { if (list) return list.length == 0; else return 0; diff --git a/module/system/templates.js b/module/system/templates.js index aabc003..42fe80e 100644 --- a/module/system/templates.js +++ b/module/system/templates.js @@ -23,6 +23,7 @@ export const preloadHandlebarsTemplates = async function () { "systems/bol/templates/item/parts/properties/item/vehicle-properties.hbs", "systems/bol/templates/item/parts/properties/item/protection-properties.hbs", "systems/bol/templates/item/parts/properties/item/weapon-properties.hbs", + "systems/bol/templates/item/parts/properties/item/spell-properties.hbs", "systems/bol/templates/item/parts/properties/item/magical-properties.hbs", "systems/bol/templates/item/parts/properties/feature/career-properties.hbs", "systems/bol/templates/item/parts/properties/feature/boon-properties.hbs", diff --git a/system.json b/system.json index 6e551a4..ebedc65 100644 --- a/system.json +++ b/system.json @@ -7,8 +7,8 @@ "url": "https://github.com/ZigmundKreud/bol", "license": "LICENSE.txt", "flags": {}, - "version": "0.8.9.2", - "templateVersion": 10, + "version": "0.8.9.6", + "templateVersion": 14, "minimumCoreVersion": "0.8.6", "compatibleCoreVersion": "9", "scripts": [], diff --git a/template.json b/template.json index 699a1c7..16645eb 100644 --- a/template.json +++ b/template.json @@ -109,6 +109,7 @@ "key": "power", "label": "BOL.resources.power", "value": 0, + "bonus": 0, "max": 0 } } @@ -116,7 +117,7 @@ }, "character": { "templates": [ "base" ], - "type": "npc", + "type": "player", "villainy": false, "xp": { "key": "xp", @@ -134,6 +135,7 @@ "encounter": { "templates": [ "base" ], "type": "tough", + "villainy": false, "size": "", "environment": "" } diff --git a/templates/actor/parts/actor-header.hbs b/templates/actor/parts/actor-header.hbs index 4a867b8..49b9937 100644 --- a/templates/actor/parts/actor-header.hbs +++ b/templates/actor/parts/actor-header.hbs @@ -5,6 +5,8 @@
+ + {{#if (eq data.type "player")}}

@@ -15,7 +17,19 @@

-
+ {{else}} +
+
+ +
+ {{/if}} + diff --git a/templates/actor/parts/tabs/actor-actions.hbs b/templates/actor/parts/tabs/actor-actions.hbs index ec968ba..e6c0974 100644 --- a/templates/actor/parts/tabs/actor-actions.hbs +++ b/templates/actor/parts/tabs/actor-actions.hbs @@ -1,10 +1,3 @@ -
    -
  1. -
    {{localize "BOL.ui.maneuvers"}}
    -
  2. -
  3. Attaque à mains nues

  4. -
- {{#each combat as |combatType id|}}
  1. diff --git a/templates/actor/parts/tabs/actor-stats.hbs b/templates/actor/parts/tabs/actor-stats.hbs index 4218ecb..ba97b77 100644 --- a/templates/actor/parts/tabs/actor-stats.hbs +++ b/templates/actor/parts/tabs/actor-stats.hbs @@ -23,10 +23,15 @@
    - {{#each data.resources as |resource id|}} + {{#each resources as |resource id|}}

    + {{#if (eq @root.data.type 'player')}} + {{#if (exists bonus)}} + + {{/if}} + {{/if}}
    {{/each}} diff --git a/templates/chat/rolls/default-roll-card.hbs b/templates/chat/rolls/default-roll-card.hbs index 4d8e0d2..2cee17f 100644 --- a/templates/chat/rolls/default-roll-card.hbs +++ b/templates/chat/rolls/default-roll-card.hbs @@ -13,7 +13,10 @@

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

    {{/if}} {{/if}} -

    {{description}} +

    {{description}}

    +{{#if reroll}} +Relancer! +{{/if}} {{!#if hasDescription}} diff --git a/templates/item/item-sheet.hbs b/templates/item/item-sheet.hbs index 35bff17..122fc41 100644 --- a/templates/item/item-sheet.hbs +++ b/templates/item/item-sheet.hbs @@ -23,10 +23,10 @@ {{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
    - {{#if (equals item.type "item")}} + {{#if (eq item.type "item")}} {{> "systems/bol/templates/item/parts/properties/item-properties.hbs"}} {{/if}} - {{#if (equals item.type "feature")}} + {{#if (eq item.type "feature")}} {{> "systems/bol/templates/item/parts/properties/feature-properties.hbs"}} {{/if}}
    diff --git a/templates/item/parts/properties/item-properties.hbs b/templates/item/parts/properties/item-properties.hbs index 57260e1..fd69f4c 100644 --- a/templates/item/parts/properties/item-properties.hbs +++ b/templates/item/parts/properties/item-properties.hbs @@ -11,12 +11,15 @@ -{{#if (equals data.category "equipment")}} +{{#if (eq data.category "equipment")}} {{> "systems/bol/templates/item/parts/properties/item/equipment-properties.hbs"}} {{/if}} -{{#if (equals data.category "capacity")}} +{{#if (eq data.category "capacity")}} {{> "systems/bol/templates/item/parts/properties/item/capacity-properties.hbs"}} {{/if}} -{{#if (equals data.category "vehicle")}} +{{#if (eq data.category "vehicle")}} {{> "systems/bol/templates/item/parts/properties/item/vehicle-properties.hbs"}} {{/if}} +{{#if (eq data.category "spell")}} + {{> "systems/bol/templates/item/parts/properties/item/spell-properties.hbs"}} +{{/if}} diff --git a/templates/item/parts/properties/item/spell-properties.hbs b/templates/item/parts/properties/item/spell-properties.hbs new file mode 100644 index 0000000..eb1d471 --- /dev/null +++ b/templates/item/parts/properties/item/spell-properties.hbs @@ -0,0 +1,27 @@ +

    {{localize "BOL.ui.spellProperties"}}

    +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + +
    +
    + +
    +
    diff --git a/templates/item/parts/properties/item/weapon-properties.hbs b/templates/item/parts/properties/item/weapon-properties.hbs index 3c91ed8..c48f5a7 100644 --- a/templates/item/parts/properties/item/weapon-properties.hbs +++ b/templates/item/parts/properties/item/weapon-properties.hbs @@ -115,6 +115,18 @@ +
    + +
    + +
    +