Add fight options
This commit is contained in:
@ -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;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ export class BoLUtility {
|
||||
chatGM.whisper = this.getUsers(user => user.isGM);
|
||||
chatGM.content = "Blind message of " + game.user.name + "<br>" + 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
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user