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")}}