Compare commits
5 Commits
bol-v10.5.
...
bol-v10.5.
Author | SHA1 | Date | |
---|---|---|---|
5b91041a3f | |||
e7f3851daa | |||
75d562f922 | |||
ba7e25e8c7 | |||
83d3f17dd0 |
@ -535,6 +535,10 @@
|
||||
"BOL.chat.criticalinfo": "C'est un succès Héroïque ou Légendaire ! Choisissez vos options et effets !",
|
||||
"BOL.chat.criticalbuttonjournal": "Succès Héroïque/Légendaire",
|
||||
|
||||
"BOL.chat.losshp": "{name}} a perdu {lossHP} points de Vitalité. Si il se repose quelques minutes, il peut récupérer {recupHP} points de Vitalité.",
|
||||
"BOL.chat.applyrecup": "Récupérer pendant quelques minutes (+{recupHP} Vitalité)",
|
||||
"BOL.chat.inforecup": "{name} vient de récupérer {recupHP} points de Vitalité après quelques minutes de repos.",
|
||||
|
||||
"BOL.dialog.soeasy": "Inmanquable (+4)",
|
||||
"BOL.dialog.veryeasy": "Trés Facile (+2)",
|
||||
"BOL.dialog.easy": "Facile (+1)",
|
||||
@ -573,6 +577,6 @@
|
||||
"BOL.chat.welcome3": "Les cartes intégrées au système le sont grace à l'aimable autorisation de leur auteur Guillaume Tavernier et des éditions Ludospherik. Merci à eux !.",
|
||||
"BOL.chat.welcome4": "Tout le support et le suivi de ce système est disponible via le <a href='https://discord.gg/pPSDNJk'>Discord Foundry FR</a>.",
|
||||
"BOL.chat.welcome5": "Consulter l'aide en ligne pour plus d'informations : @UUID[Compendium.bol.aides-de-jeu.97rugQOtiwt8zPfQ]{Aide du Jeu}.",
|
||||
"BOL.chat.welcome6": "Bon jeu en Lemurie !"
|
||||
|
||||
"BOL.chat.welcome6": "Bon jeu en Lemurie !",
|
||||
"BOL.chat.nodamage": "Ne pas appliquer les dommages"
|
||||
}
|
@ -60,6 +60,12 @@ export class BoLActorSheet extends ActorSheet {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.actor.spendAlchemyPoint(li.data("itemId"), 1)
|
||||
})
|
||||
html.find(".inc-dec-btns-resource").click((ev) => {
|
||||
const dataset = ev.currentTarget.dataset;
|
||||
const target = dataset.target
|
||||
const incr = parseInt(dataset.incr)
|
||||
this.actor.incDecResources(target, incr)
|
||||
})
|
||||
|
||||
// Incr./Decr. career ranks
|
||||
html.find(".inc-dec-btns").click((ev) => {
|
||||
|
@ -22,6 +22,17 @@ export class BoLActor extends Actor {
|
||||
super.prepareData()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isHeroAdversary() {
|
||||
if (this.type === 'character') {
|
||||
return true
|
||||
}
|
||||
if (this.type === 'encounter' && this.chartype == "adversary") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCharType() {
|
||||
if (this.type === 'character') {
|
||||
@ -32,17 +43,17 @@ export class BoLActor extends Actor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getVillainy() {
|
||||
if (this.type === 'character') {
|
||||
return false
|
||||
if (this.type === 'encounter' && this.chartype == "adversary") {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getBougette() {
|
||||
if ( this.type == "character") {
|
||||
if (this.type == "character") {
|
||||
let b = duplicate(this.system.bougette)
|
||||
b.label = game.i18n.localize( game.bol.config.bougetteState[String(this.system.bougette.value)] )
|
||||
b.label = game.i18n.localize(game.bol.config.bougetteState[String(this.system.bougette.value)])
|
||||
b.diceImg = "icons/dice/" + game.bol.config.bougetteDice[String(this.system.bougette.value)] + "black.svg"
|
||||
return b
|
||||
}
|
||||
@ -51,9 +62,9 @@ export class BoLActor extends Actor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollBougette() {
|
||||
if ( this.type == "character") {
|
||||
if (this.type == "character") {
|
||||
let attribute = duplicate(this.system.attributes.vigor)
|
||||
let rollData = BoLRoll.getCommonRollData(this, "bougette", attribute, undefined )
|
||||
let rollData = BoLRoll.getCommonRollData(this, "bougette", attribute, undefined)
|
||||
rollData.formula = game.bol.config.bougetteDice[String(this.system.bougette.value)]
|
||||
let r = new BoLDefaultRoll(rollData)
|
||||
r.roll()
|
||||
@ -62,10 +73,10 @@ export class BoLActor extends Actor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
decBougette() {
|
||||
if ( this.type == "character") {
|
||||
let bougette = duplicate(this.system.bougette)
|
||||
bougette.value = Math.max( Number(bougette.value) - 1, 0)
|
||||
this.update( { 'system.bougette': bougette } )
|
||||
if (this.type == "character") {
|
||||
let bougette = duplicate(this.system.bougette)
|
||||
bougette.value = Math.max(Number(bougette.value) - 1, 0)
|
||||
this.update({ 'system.bougette': bougette })
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +148,7 @@ export class BoLActor extends Actor {
|
||||
}
|
||||
// Apply defense effects
|
||||
for (let i of this.items) {
|
||||
if (i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier.includes("aptitudes.def") ) {
|
||||
if (i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier.includes("aptitudes.def")) {
|
||||
defMod += Number(i.system.properties.modifier)
|
||||
}
|
||||
}
|
||||
@ -389,7 +400,7 @@ export class BoLActor extends Actor {
|
||||
}
|
||||
// Apply vigor effects
|
||||
for (let i of this.items) {
|
||||
if (i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier.includes("vigor") ) {
|
||||
if (i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier.includes("vigor")) {
|
||||
attrDamageValue += Number(i.system.properties.modifier)
|
||||
}
|
||||
}
|
||||
@ -437,20 +448,20 @@ export class BoLActor extends Actor {
|
||||
spentAstrologyPoints(points) {
|
||||
let astrology = duplicate(this.system.resources.astrologypoints)
|
||||
astrology.value -= points
|
||||
astrology.value = Math.max(astrology.value,0)
|
||||
this.update( { 'system.resources.astrologypoints': astrology} )
|
||||
astrology.value = Math.max(astrology.value, 0)
|
||||
this.update({ 'system.resources.astrologypoints': astrology })
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
getHoroscopesBonus() {
|
||||
let astro = this.items.filter(it => it.type == "feature" && it.system.subtype == "horoscope" && !it.system.properties.ishoroscopemajor
|
||||
&& it.system.properties.horoscopeanswer == "favorable")
|
||||
&& it.system.properties.horoscopeanswer == "favorable")
|
||||
return astro
|
||||
}
|
||||
/*-------------------------------------------- */
|
||||
getHoroscopesMalus() {
|
||||
let astro = this.items.filter(it => it.type == "feature" && it.system.subtype == "horoscope" && !it.system.properties.ishoroscopemajor
|
||||
&& it.system.properties.horoscopeanswer == "unfavorable")
|
||||
&& it.system.properties.horoscopeanswer == "unfavorable")
|
||||
return astro
|
||||
}
|
||||
|
||||
@ -458,26 +469,28 @@ export class BoLActor extends Actor {
|
||||
manageHoroscope(rollData) {
|
||||
//Spent points
|
||||
this.spentAstrologyPoints(rollData.astrologyPointsCost)
|
||||
if ( rollData.horoscopeType == "minor") {
|
||||
let horoscope = { name: "SITUATION A SPECIFIER", type :"feature",
|
||||
if (rollData.horoscopeType == "minor") {
|
||||
let horoscope = {
|
||||
name: "SITUATION A SPECIFIER", type: "feature",
|
||||
img: "icons/magic/perception/eye-ringed-glow-angry-large-red.webp",
|
||||
system :{subtype: "horoscope", properties: {
|
||||
ishoroscopemajor: false,
|
||||
horoscopeanswer: (rollData.isSuccess) ? "favorable": "unfavorable",
|
||||
rank: rollData.careerBonus
|
||||
}
|
||||
system: {
|
||||
subtype: "horoscope", properties: {
|
||||
ishoroscopemajor: false,
|
||||
horoscopeanswer: (rollData.isSuccess) ? "favorable" : "unfavorable",
|
||||
rank: rollData.careerBonus
|
||||
}
|
||||
}
|
||||
}
|
||||
this.createEmbeddedDocuments('Item', [horoscope])
|
||||
}
|
||||
if ( rollData.horoscopeType == "major" ) {
|
||||
if ( rollData.isSuccess) {
|
||||
if (rollData.horoscopeType == "major") {
|
||||
if (rollData.isSuccess) {
|
||||
this.subHeroPoints(1)
|
||||
} else {
|
||||
this.addHeroPoints(1)
|
||||
}
|
||||
}
|
||||
if ( rollData.horoscopeType == "majorgroup" ) {
|
||||
if (rollData.horoscopeType == "majorgroup") {
|
||||
let rID = randomID(16)
|
||||
let horoscopes = duplicate(game.settings.get("bol", "horoscope-group"))
|
||||
horoscopes[rID] = {
|
||||
@ -485,7 +498,7 @@ export class BoLActor extends Actor {
|
||||
name: game.i18n.localize("BOL.ui.groupHoroscope") + this.name,
|
||||
maxDice: rollData.careerBonus,
|
||||
availableDice: rollData.careerBonus,
|
||||
type: (rollData.isSuccess) ? "bonus": "malus"
|
||||
type: (rollData.isSuccess) ? "bonus" : "malus"
|
||||
}
|
||||
game.settings.set("bol", "horoscope-group", horoscopes)
|
||||
}
|
||||
@ -497,10 +510,10 @@ export class BoLActor extends Actor {
|
||||
return this.system.resources.astrologypoints.value
|
||||
}
|
||||
/*-------------------------------------------- */
|
||||
removeHoroscopeMinor( rollData) {
|
||||
removeHoroscopeMinor(rollData) {
|
||||
let toDel = []
|
||||
for(let horo of rollData.selectedHoroscope) {
|
||||
toDel.push( horo._id )
|
||||
for (let horo of rollData.selectedHoroscope) {
|
||||
toDel.push(horo._id)
|
||||
}
|
||||
if (toDel.length > 0) {
|
||||
this.deleteEmbeddedDocuments('Item', toDel)
|
||||
@ -519,7 +532,7 @@ export class BoLActor extends Actor {
|
||||
newPC = alchemy.system.properties.pccurrent + pcCost
|
||||
await this.updateEmbeddedDocuments('Item', [{ _id: alchemy.id, 'system.properties.pccurrent': newPC }])
|
||||
} else {
|
||||
ui.notifications.warn( game.i18n.localize("BOL.ui.nomorealchemypoints") )
|
||||
ui.notifications.warn(game.i18n.localize("BOL.ui.nomorealchemypoints"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -716,30 +729,30 @@ export class BoLActor extends Actor {
|
||||
let lastHP = await this.getFlag("world", hpID)
|
||||
if (lastHP != this.system.resources.hp.value && game.user.isGM) { // Only GM sends this
|
||||
await this.setFlag("world", hpID, this.system.resources.hp.value)
|
||||
let prone = this.effects.find( ef => ef.label == "EFFECT.StatusProne")
|
||||
let dead = this.effects.find( ef => ef.label == "EFFECT.StatusDead")
|
||||
let prone = this.effects.find(ef => ef.label == "EFFECT.StatusProne")
|
||||
let dead = this.effects.find(ef => ef.label == "EFFECT.StatusDead")
|
||||
if (this.system.resources.hp.value <= 0) {
|
||||
if ( !prone) {
|
||||
if (!prone) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [
|
||||
{label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg', flags: { core: { statusId: 'prone' } } }
|
||||
{ label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg', flags: { core: { statusId: 'prone' } } }
|
||||
])
|
||||
}
|
||||
if ( this.system.resources.hp.value < -5 && !dead) {
|
||||
if (this.system.resources.hp.value < -5 && !dead) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [
|
||||
{label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg', flags: { core: { statusId: 'dead' } } }
|
||||
{ label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg', flags: { core: { statusId: 'dead' } } }
|
||||
])
|
||||
}
|
||||
ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-vitality-zero.hbs', { name: this.name, img: this.img, hp: this.system.resources.hp.value })
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-vitality-zero.hbs', { name: this.name, img: this.img, hp: this.system.resources.hp.value, isHeroAdversary: this.isHeroAdversary() })
|
||||
})
|
||||
} else {
|
||||
if ( prone ) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [ prone.id ] )
|
||||
if (prone) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [prone.id])
|
||||
}
|
||||
if ( dead ) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [ dead.id ] )
|
||||
if (dead) {
|
||||
await this.deleteEmbeddedDocuments("ActiveEffect", [dead.id])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -751,9 +764,45 @@ export class BoLActor extends Actor {
|
||||
await this.setFlag("world", "last-initiative", rollData)
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
storeVitaliteCombat() {
|
||||
this.setFlag("world", "vitalite-before-combat", duplicate(this.system.resources.hp))
|
||||
}
|
||||
/*-------------------------------------------- */
|
||||
async displayRecuperation() {
|
||||
let previousHP = this.getFlag("world", "vitalite-before-combat")
|
||||
let lossHP = previousHP.value - this.system.resources.hp.value
|
||||
//console.log(">>>>> RECUP INFO", previousHP, this.system.resources.hp.value)
|
||||
if (previousHP && lossHP > 0 && this.system.resources.hp.value > 0) {
|
||||
let msg = await ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/chat-recup-information.hbs', {
|
||||
name: this.name,
|
||||
actorId: this.id,
|
||||
lossHP: lossHP,
|
||||
recupHP: Math.ceil(lossHP / 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
this.unsetFlag("world", "vitalite-before-combat")
|
||||
}
|
||||
/*-------------------------------------------- */
|
||||
async applyRecuperation(recupHP) {
|
||||
let hp = duplicate(this.system.resources.hp)
|
||||
hp.value += recupHP
|
||||
hp.value = Math.min(hp.value, hp.max)
|
||||
this.update({ 'system.resources.hp': hp })
|
||||
let msg = await ChatMessage.create({
|
||||
alias: this.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: game.i18n.format( "BOL.chat.inforecup", {name: this.name, recupHP: recupHP} )
|
||||
})
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
clearInitiative() {
|
||||
this.unsetFlag("world", "last-initiative" )
|
||||
this.unsetFlag("world", "last-initiative")
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
@ -770,40 +819,40 @@ export class BoLActor extends Actor {
|
||||
rollData = this.getFlag("world", "last-initiative")
|
||||
}
|
||||
let fvttInit = 4 // Pietaille par defaut
|
||||
if (this.type == 'character' ) {
|
||||
if (this.type == 'character') {
|
||||
fvttInit = 5
|
||||
if (!rollData) {
|
||||
fvttInit = -1
|
||||
if ( isCombat ) {
|
||||
if (isCombat) {
|
||||
ui.notifications.info(game.i18n.localize("BOL.ui.warninitiative"))
|
||||
BoLRoll.aptitudeCheck(this, "init", undefined, combatData )
|
||||
BoLRoll.aptitudeCheck(this, "init", undefined, combatData)
|
||||
}
|
||||
} else {
|
||||
if (rollData.isLegendary) {
|
||||
fvttInit = 10
|
||||
} else if (rollData.isCritical) {
|
||||
fvttInit = 9
|
||||
} else if (rollData.isSuccess ) {
|
||||
} else if (rollData.isSuccess) {
|
||||
fvttInit = 8
|
||||
} else if (rollData.isFumble) {
|
||||
fvttInit = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( this.getCharType() == 'adversary') {
|
||||
if (this.getCharType() == 'adversary') {
|
||||
fvttInit = 7
|
||||
}
|
||||
if ( this.getCharType() == 'tough') {
|
||||
if (this.getCharType() == 'tough') {
|
||||
fvttInit = 6
|
||||
}
|
||||
if ( this.getCharType() == 'creature') {
|
||||
if (this.getCharType() == 'creature') {
|
||||
let mySize = this.getSize()
|
||||
let sizeSmall = game.bol.config.creatureSize["small"].order
|
||||
let sizeMedium = game.bol.config.creatureSize["medium"].order
|
||||
if ( mySize >= sizeSmall && mySize <= sizeMedium) {
|
||||
if (mySize >= sizeSmall && mySize <= sizeMedium) {
|
||||
fvttInit = 6
|
||||
}
|
||||
if ( mySize > sizeMedium) {
|
||||
if (mySize > sizeMedium) {
|
||||
fvttInit = 7
|
||||
}
|
||||
}
|
||||
@ -823,6 +872,11 @@ export class BoLActor extends Actor {
|
||||
await this.update({ 'system.resources.hero.value': newHeroP });
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
incDecResources(target, value) {
|
||||
let newValue = this.system.resources[target].value + value
|
||||
this.update({ [`system.resources.${target}.value`]: newValue })
|
||||
}
|
||||
/*-------------------------------------------- */
|
||||
async sufferDamage(damage) {
|
||||
let newHP = this.system.resources.hp.value - damage
|
||||
@ -839,13 +893,13 @@ export class BoLActor extends Actor {
|
||||
} else if (protect.system.subtype == 'armor') {
|
||||
if (BoLUtility.getRollArmor()) {
|
||||
if (!protect.system.properties.soak.formula || protect.system.properties.soak.formula == "") {
|
||||
ui.notifications.warn( game.i18n.localize("BOL.ui.armornoformula", protect.name) )
|
||||
ui.notifications.warn(game.i18n.localize("BOL.ui.armornoformula", protect.name))
|
||||
} else {
|
||||
formula += "+" + " max(" + protect.system.properties.soak.formula + ",0)"
|
||||
}
|
||||
} else {
|
||||
if (protect.system.properties.soak.value == undefined) {
|
||||
ui.notifications.warn( game.i18n.localize("BOL.ui.armornoformula", protect.name) )
|
||||
ui.notifications.warn(game.i18n.localize("BOL.ui.armornoformula", protect.name))
|
||||
} else {
|
||||
formula += "+ " + protect.system.properties.soak.value
|
||||
}
|
||||
|
@ -523,6 +523,7 @@ export class BoLRoll {
|
||||
rollData.nbBoons = 0
|
||||
rollData.nbFlaws = 0
|
||||
rollData.nbDice = 0
|
||||
rollData.isHeroAdversary = actor.isHeroAdversary()
|
||||
if (rollData.shieldBlock == 'blockall') {
|
||||
rollData.shieldMalus = rollData.shieldAttackMalus;
|
||||
} else {
|
||||
@ -677,10 +678,10 @@ export class BoLDefaultRoll {
|
||||
async sendChatMessage() {
|
||||
let actor = BoLUtility.getActorFromRollData(this.rollData)
|
||||
this._buildChatMessage(this.rollData).then(async msgFlavor => {
|
||||
//console.log("MSG", msgFlavor )
|
||||
let msg = await this.rollData.roll.toMessage({
|
||||
user: game.user.id,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
//whisper: BoLUtility.getWhisperRecipientsAndGMs(this.rollData.actor.name),
|
||||
flavor: msgFlavor,
|
||||
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
||||
})
|
||||
@ -766,13 +767,13 @@ export class BoLDefaultRoll {
|
||||
let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.system, this.rollData.fightOption)
|
||||
|
||||
let damageFormula = weaponFormula + "+" + bonusDmg + "+" + attrDamageValue
|
||||
console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData)
|
||||
|
||||
//console.log("Formula", weaponFormula, damageFormula, this.rollData.weapon.data.data.properties.damage)
|
||||
this.rollData.damageFormula = damageFormula
|
||||
this.rollData.damageRoll = new Roll(damageFormula)
|
||||
await this.rollData.damageRoll.roll({ "async": false })
|
||||
this.rollData.damageTotal = this.rollData.damageRoll.total
|
||||
console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData)
|
||||
}
|
||||
BoLUtility.cleanupButtons(this.rollData.optionsId)
|
||||
this.sendDamageMessage()
|
||||
|
@ -41,12 +41,23 @@ export class BoLCombatManager extends Combat {
|
||||
super.nextRound()
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
startCombat() {
|
||||
let combatants = this.combatants.contents
|
||||
for (let c of combatants) {
|
||||
let actor = game.actors.get( c.actorId )
|
||||
actor.storeVitaliteCombat()
|
||||
}
|
||||
return super.startCombat()
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
_onDelete() {
|
||||
let combatants = this.combatants.contents
|
||||
for (let c of combatants) {
|
||||
let actor = game.actors.get(c.actorId)
|
||||
actor.clearInitiative()
|
||||
actor.displayRecuperation()
|
||||
}
|
||||
super._onDelete()
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ export class BoLUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static init() {
|
||||
this.attackStore = {}
|
||||
|
||||
game.settings.register("bol", "rollArmor", {
|
||||
name: "Effectuer des jets pour les armures",
|
||||
hint: "Effectue un jet de dés pour les armures (valeur fixe si désactivé)",
|
||||
@ -33,7 +31,7 @@ export class BoLUtility {
|
||||
hint: "Sélectionne la formule de dés (par défaut 2d6)",
|
||||
scope: "world",
|
||||
config: true,
|
||||
default: "2d6",
|
||||
default: "6",
|
||||
type: String,
|
||||
choices: { "6": "2d6", "8":"2d8", "10":"2d10", "12":"2d12", "20":"2d20"},
|
||||
onChange: value => {
|
||||
@ -151,7 +149,7 @@ export class BoLUtility {
|
||||
df = "6"
|
||||
}
|
||||
return {
|
||||
diceFormula: this.diceFormula,
|
||||
diceFormula: df,
|
||||
successValue : this.successValue,
|
||||
criticalSuccessValue: this.criticalSuccessValue,
|
||||
criticalFailureValue: this.criticalFailureValue
|
||||
@ -193,29 +191,6 @@ export class BoLUtility {
|
||||
CONFIG.statusEffects = duplicate(game.bol.config.statusEffects)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static templateData(it) {
|
||||
return BoLUtility.data(it)?.data ?? {}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static data(it) {
|
||||
if (it instanceof Actor || it instanceof Item || it instanceof Combatant) {
|
||||
return it.data;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static storeRoll(roll) {
|
||||
this.rollTab[roll.id] = roll
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getRoll(rollId) {
|
||||
return this.rollTab[roll.id]
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static createDirectOptionList(min, max) {
|
||||
let options = {};
|
||||
@ -260,7 +235,7 @@ export class BoLUtility {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getUsers(filter) {
|
||||
return game.users.filter(filter).map(user => user.data._id);
|
||||
return game.users.filter(filter).map(user => user.id);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getWhisperRecipients(rollMode, name) {
|
||||
@ -298,13 +273,13 @@ export class BoLUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static sendAttackSuccess(attackDef) {
|
||||
if (attackDef.targetId) {
|
||||
static sendAttackSuccess(rollData) {
|
||||
if (rollData.targetId) {
|
||||
// Broadcast to GM or process it directly in case of GM defense
|
||||
if (!game.user.isGM) {
|
||||
game.socket.emit("system.bol", { name: "msg_attack_success", data: duplicate(attackDef) })
|
||||
game.socket.emit("system.bol", { name: "msg_attack_success", data: duplicate(rollData) })
|
||||
} else {
|
||||
BoLUtility.processAttackSuccess(attackDef)
|
||||
BoLUtility.processAttackSuccess(rollData)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -397,6 +372,19 @@ export class BoLUtility {
|
||||
game.socket.emit("system.bol", { name: "msg_damage_handling", data: { msgId: msgId, attackId: attackId, defenseMode: defenseMode, weaponId: weaponId } })
|
||||
}
|
||||
})
|
||||
|
||||
html.on("click", '.recup-vitalite', event => {
|
||||
event.preventDefault()
|
||||
let actorId = event.currentTarget.attributes['data-actor-id'].value
|
||||
let recupHP = event.currentTarget.attributes['data-recup-hp'].value
|
||||
let actor = game.actors.get(actorId)
|
||||
|
||||
let messageId = BoLUtility.findChatMessageId(event.currentTarget)
|
||||
BoLUtility.removeChatMessageId(messageId)
|
||||
|
||||
actor.applyRecuperation(recupHP)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -404,48 +392,50 @@ export class BoLUtility {
|
||||
if (!game.user.isGM) {
|
||||
return
|
||||
}
|
||||
let message = game.messages.get(msgId)
|
||||
let rollData = message.getFlag("world", "bol-roll-data")
|
||||
BoLUtility.removeChatMessageId(msgId)
|
||||
|
||||
console.log("Damage Handling", attackId, defenseMode, weaponId)
|
||||
// Only GM process this
|
||||
let attackDef = this.attackStore[attackId]
|
||||
if (attackDef && attackDef.defenderId) {
|
||||
if (attackDef.defenseDone) {
|
||||
if (rollData && rollData.defenderId) {
|
||||
if (rollData.defenseDone || defenseMode == 'damage-not-applied') {
|
||||
return
|
||||
} // ?? Why ???
|
||||
attackDef.defenseDone = true
|
||||
attackDef.defenseMode = defenseMode
|
||||
let token = game.scenes.current.tokens.get(attackDef.targetId)
|
||||
rollData.defenseDone = true
|
||||
rollData.defenseMode = defenseMode
|
||||
let token = game.scenes.current.tokens.get(rollData.targetId)
|
||||
let defender = token.actor
|
||||
|
||||
if (defenseMode == 'damage-with-armor') {
|
||||
let armorFormula = defender.getArmorFormula()
|
||||
attackDef.rollArmor = new Roll(armorFormula)
|
||||
attackDef.rollArmor.roll({ async: false })
|
||||
attackDef.armorProtect = (attackDef.rollArmor.total < 0) ? 0 : attackDef.rollArmor.total
|
||||
attackDef.finalDamage = attackDef.damageTotal - attackDef.armorProtect
|
||||
attackDef.finalDamage = (attackDef.finalDamage < 0) ? 0 : attackDef.finalDamage
|
||||
defender.sufferDamage(attackDef.finalDamage)
|
||||
console.log("Armor roll -> result ", attackDef)
|
||||
rollData.rollArmor = new Roll(armorFormula)
|
||||
rollData.rollArmor.roll({ async: false })
|
||||
rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
|
||||
rollData.finalDamage = rollData.damageTotal - rollData.armorProtect
|
||||
rollData.finalDamage = (rollData.finalDamage < 0) ? 0 : rollData.finalDamage
|
||||
defender.sufferDamage(rollData.finalDamage)
|
||||
console.log("Armor roll -> result ", rollData)
|
||||
}
|
||||
if (defenseMode == 'damage-without-armor') {
|
||||
attackDef.finalDamage = attackDef.damageTotal
|
||||
defender.sufferDamage(attackDef.finalDamage)
|
||||
rollData.finalDamage = atrollDatatackDef.damageTotal
|
||||
defender.sufferDamage(rollData.finalDamage)
|
||||
}
|
||||
if (defenseMode == 'hero-reduce-damage') {
|
||||
let armorFormula = defender.getArmorFormula()
|
||||
attackDef.rollArmor = new Roll(armorFormula)
|
||||
attackDef.rollArmor.roll({ async: false })
|
||||
attackDef.armorProtect = (attackDef.rollArmor.total < 0) ? 0 : attackDef.rollArmor.total
|
||||
attackDef.rollHero = new Roll("1d6")
|
||||
attackDef.rollHero.roll({ async: false })
|
||||
attackDef.finalDamage = attackDef.damageTotal - attackDef.rollHero.total - attackDef.armorProtect
|
||||
attackDef.finalDamage = (attackDef.finalDamage < 0) ? 0 : attackDef.finalDamage
|
||||
defender.sufferDamage(attackDef.finalDamage)
|
||||
rollData.rollArmor = new Roll(armorFormula)
|
||||
rollData.rollArmor.roll({ async: false })
|
||||
rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
|
||||
rollData.rollHero = new Roll("1d6")
|
||||
rollData.rollHero.roll({ async: false })
|
||||
rollData.finalDamage = rollData.damageTotal - rollData.rollHero.total - rollData.armorProtect
|
||||
rollData.finalDamage = (rollData.finalDamage < 0) ? 0 : rollData.finalDamage
|
||||
defender.sufferDamage(rollData.finalDamage)
|
||||
defender.subHeroPoints(1)
|
||||
}
|
||||
if (defenseMode == 'hero-in-extremis') {
|
||||
attackDef.finalDamage = 0;
|
||||
attackDef.weaponHero = defender.weapons.find(item => item._id == weaponId);
|
||||
rollData.finalDamage = 0;
|
||||
rollData.weaponHero = defender.weapons.find(item => item._id == weaponId);
|
||||
defender.deleteEmbeddedDocuments("Item", [weaponId]);
|
||||
}
|
||||
|
||||
@ -456,16 +446,16 @@ export class BoLUtility {
|
||||
}
|
||||
}
|
||||
let damageResults = {
|
||||
attackId: attackDef.id,
|
||||
attacker: attackDef.attacker,
|
||||
rollArmor: attackDef.rollArmor,
|
||||
rollHero: attackDef.rollHero,
|
||||
weaponHero: attackDef.weaponHero,
|
||||
armorProtect: attackDef.armorProtect,
|
||||
attackId: rollData.id,
|
||||
attacker: rollData.attacker,
|
||||
rollArmor: rollData.rollArmor,
|
||||
rollHero: rollData.rollHero,
|
||||
weaponHero: rollData.weaponHero,
|
||||
armorProtect: rollData.armorProtect,
|
||||
name: defender.name,
|
||||
defender: defender,
|
||||
defenseMode: attackDef.defenseMode,
|
||||
finalDamage: attackDef.finalDamage
|
||||
defenseMode: rollData.defenseMode,
|
||||
finalDamage: rollData.finalDamage
|
||||
}
|
||||
ChatMessage.create({
|
||||
alias: defender.name,
|
||||
@ -509,7 +499,7 @@ export class BoLUtility {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isRangedWeapon(weapon) {
|
||||
return weapon.data.type == 'ranged' || weapon.data.thrown;
|
||||
return weapon.system.type == 'ranged' || weapon.system.thrown;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -552,28 +542,28 @@ export class BoLUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async processAttackSuccess(attackDef) {
|
||||
console.log("Attack success processing", attackDef)
|
||||
if (!game.user.isGM || !attackDef.defenderId) { // Only GM process this
|
||||
static async processAttackSuccess(rollData) {
|
||||
console.log("Attack success processing", rollData)
|
||||
if (!game.user.isGM || !rollData.defenderId) { // Only GM process this
|
||||
return
|
||||
}
|
||||
// Build and send the defense message to the relevant people (ie GM + defender)
|
||||
let defender = game.actors.get(attackDef.defenderId)
|
||||
console.log("DEF WEP", attackDef, defender)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let defenderWeapons = defender.weapons || []
|
||||
this.attackStore[attackDef.id] = attackDef // Store !
|
||||
ChatMessage.create({
|
||||
let msg = await ChatMessage.create({
|
||||
alias: defender.name,
|
||||
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
|
||||
content: await renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
|
||||
attackId: attackDef.id,
|
||||
attacker: attackDef.attacker,
|
||||
attackId: rollData.id,
|
||||
attacker: rollData.attacker,
|
||||
defender: defender,
|
||||
defenderWeapons: defenderWeapons,
|
||||
damageTotal: attackDef.damageRoll.total,
|
||||
damagesIgnoresArmor: attackDef.damagesIgnoresArmor,
|
||||
damageTotal: rollData.damageTotal,
|
||||
damagesIgnoresArmor: rollData.damagesIgnoresArmor,
|
||||
})
|
||||
})
|
||||
msg.setFlag("world", "bol-roll-data", rollData)
|
||||
console.log("DEF WEP", rollData, defender)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -591,15 +581,15 @@ export class BoLUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeSpellCost(spell, nbOptCond = 0) {
|
||||
let pp = spell.data.properties.ppcost
|
||||
let minpp = __circle2minpp[spell.data.properties.circle]
|
||||
let pp = spell.system.properties.ppcost
|
||||
let minpp = __circle2minpp[spell.system.properties.circle]
|
||||
pp = (pp - nbOptCond < minpp) ? minpp : pp - nbOptCond
|
||||
return pp
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getDamageFormula(weaponData, fightOption) {
|
||||
let upgradeDamage = (fightOption && fightOption.data.properties.fightoptiontype == "twoweaponsatt")
|
||||
let upgradeDamage = (fightOption && fightOption.system.properties.fightoptiontype == "twoweaponsatt")
|
||||
let damageString = weaponData.properties.damage
|
||||
let modifier = weaponData.properties.damageModifiers ?? 0
|
||||
let multiplier = weaponData.properties.damageMultiplier ?? 1
|
||||
|
@ -118,7 +118,7 @@ export const registerHandlebarsHelpers = function () {
|
||||
})
|
||||
Handlebars.registerHelper('includesKey', function (items, type, key) {
|
||||
// console.log(items);
|
||||
return items.filter(i => i.type === type).map(i => i.data.key).includes(key);
|
||||
return items.filter(i => i.type === type).map(i => i.system.key).includes(key);
|
||||
})
|
||||
Handlebars.registerHelper('includes', function (array, val) {
|
||||
return array.includes(val);
|
||||
|
@ -49,7 +49,7 @@ export default function registerHooks() {
|
||||
let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
name: actor.data.name,
|
||||
name: actor.name,
|
||||
type: "script",
|
||||
img: "icons/svg/dice-target.svg",
|
||||
command: command
|
||||
@ -65,9 +65,9 @@ export default function registerHooks() {
|
||||
let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
name: journal.data.name,
|
||||
name: journal.name,
|
||||
type: "script",
|
||||
img: (journal.data.img) ? journal.data.img : "icons/svg/book.svg",
|
||||
img: (journal.img) ? journal.img : "icons/svg/book.svg",
|
||||
command: command
|
||||
}, {displaySheet: false})
|
||||
game.user.assignHotbarMacro(macro, slot);
|
||||
|
@ -37,13 +37,13 @@ export class Macros {
|
||||
};
|
||||
|
||||
if(rollType === "attribute") {
|
||||
let attribute = eval(`actor.data.data.attributes.${key}`);
|
||||
let attribute = eval(`actor.system.attributes.${key}`);
|
||||
let rollLabel = (attribute.label) ? game.i18n.localize(attribute.label) : null;
|
||||
let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) ;
|
||||
BoLRoll.attributeRollDialog(actor, actorData, attribute, rollLabel, description, adv, mod);
|
||||
}
|
||||
else if(rollType === "aptitude") {
|
||||
let aptitude = eval(`actor.data.data.aptitudes.${key}`);
|
||||
let aptitude = eval(`actor.system.aptitudes.${key}`);
|
||||
let rollLabel = (aptitude.label) ? game.i18n.localize(aptitude.label) : null;
|
||||
let description = actor.name + " - " + game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label) ;
|
||||
BoLRoll.aptitudeRollDialog(actor, actorData, aptitude, rollLabel, description, adv, mod);
|
||||
|
@ -14,7 +14,7 @@
|
||||
],
|
||||
"url": "https://www.uberwald.me/gitea/public/bol",
|
||||
"license": "LICENSE.txt",
|
||||
"version": "10.5.8",
|
||||
"version": "10.5.13",
|
||||
"compatibility": {
|
||||
"minimum": "10",
|
||||
"verified": "10"
|
||||
@ -202,7 +202,7 @@
|
||||
],
|
||||
"socket": true,
|
||||
"manifest": "https://www.uberwald.me/gitea/public/bol/raw/v10/system.json",
|
||||
"download": "https://www.uberwald.me/gitea/public/bol/archive/bol-v10.5.8.zip",
|
||||
"download": "https://www.uberwald.me/gitea/public/bol/archive/bol-v10.5.13.zip",
|
||||
"background": "systems/bol/ui/page_accueil.webp",
|
||||
"gridDistance": 1.5,
|
||||
"gridUnits": "m",
|
||||
|
@ -50,6 +50,10 @@
|
||||
<div class="resource stat flex1 flex-group-center">
|
||||
<label class="stat-label">{{localize label}}</label><br/>
|
||||
<input class="stat-value resources-value" type="text" name="system.resources.{{key}}.value" value="{{numberFormat value decimals=0 sign=false}}" data-dtype="Number"/>
|
||||
|
||||
<a class="inc-dec-btns-resource" data-target="{{key}}" data-incr="-1"><i class="fas fa-minus-square"></i></a>
|
||||
<a class="inc-dec-btns-resource" data-target="{{key}}" data-incr="1"><i class="fas fa-plus-square"></i></a>
|
||||
|
||||
{{#if (eq @root.charType 'player')}}
|
||||
{{#if (exists bonus)}}
|
||||
<span class="flexrow"><label class="stat-max bonus-text">Bonus</label><input class="resource-bonus resources-value" type="text" name="system.resources.{{key}}.bonus" value="{{numberFormat bonus decimals=0 sign=false}}" data-dtype="Number"/></span>
|
||||
|
12
templates/chat/chat-recup-information.hbs
Normal file
12
templates/chat/chat-recup-information.hbs
Normal file
@ -0,0 +1,12 @@
|
||||
<div>
|
||||
<img class="chat-icon" src="{{img}}" alt="{{name}}"/>
|
||||
<h2 class="bad"><strong>{{name}}</strong></h2>
|
||||
</div>
|
||||
|
||||
<div class="flexrow">
|
||||
|
||||
{{localize "BOL.chat.losshp" lossHP=lossHP recupHP=recupHP}}
|
||||
<button class="recup-vitalite" data-actor-id="{{actorId}}" data-recup-hp="{{recupHP}}">{{localize "BOL.chat.applyrecup" recupHP=recupHP}}</button>
|
||||
|
||||
</div>
|
||||
|
@ -5,18 +5,23 @@
|
||||
|
||||
<div class="flexrow">
|
||||
|
||||
{{#if (eq hp 0)}}
|
||||
{{localize "BOL.chat.vitalityzero" name=name hp=hp}}
|
||||
<br>{{localize "BOL.chat.vitalityheroism"}}
|
||||
<br>{{localize "BOL.chat.vitalityheroismhint"}}
|
||||
{{else}}
|
||||
{{localize "BOL.chat.vitalitydying" name=name hp=hp}}
|
||||
<br>{{localize "BOL.chat.vitalitydyingheroism"}}
|
||||
{{/if}}
|
||||
{{#if isHeroAdversary}}
|
||||
{{#if (eq hp 0)}}
|
||||
{{localize "BOL.chat.vitalityzero" name=name hp=hp}}
|
||||
<br>{{localize "BOL.chat.vitalityheroism"}}
|
||||
<br>{{localize "BOL.chat.vitalityheroismhint"}}
|
||||
{{else}}
|
||||
{{localize "BOL.chat.vitalitydying" name=name hp=hp}}
|
||||
<br>{{localize "BOL.chat.vitalitydyingheroism"}}
|
||||
{{/if}}
|
||||
|
||||
{{#if (lt hp -5)}}
|
||||
<br><strong>{{localize "BOL.chat.isdead" name=name}}</strong>
|
||||
<br>{{localize "BOL.chat.epitaph"}}
|
||||
{{#if (lt hp -5)}}
|
||||
<br><strong>{{localize "BOL.chat.isdead" name=name}}</strong>
|
||||
<br>{{localize "BOL.chat.epitaph"}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<br><strong>{{localize "BOL.chat.isdead" name=name}}</strong>
|
||||
<br>{{localize "BOL.chat.epitaph"}}
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
|
@ -1,20 +1,20 @@
|
||||
<div>
|
||||
{{#if isSuccess}}
|
||||
{{#if isLegendary}}
|
||||
<h2 class="success critical"><i class="fas fa-check-double"></i> {{localize "BOL.ui.criticallegend"}}...
|
||||
<h2 class="success critical"><i class="fas fa-check-double"></i> {{localize "BOL.ui.criticallegend"}}...
|
||||
{{else}}
|
||||
{{#if isCritical}}
|
||||
<h2 class="success critical"><i class="fas fa-check-double"></i> {{localize "BOL.ui.critical"}}...
|
||||
<h2 class="success critical"><i class="fas fa-check-double"></i> {{localize "BOL.ui.critical"}}...
|
||||
{{else}}
|
||||
<h2 class="success"><i class="fas fa-check"></i> {{localize "BOL.ui.success"}}...
|
||||
<h2 class="success"><i class="fas fa-check"></i> {{localize "BOL.ui.success"}}...
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if isFailure}}
|
||||
{{#if isFumble}}
|
||||
<h2 class="failure fumble"><i class="fas fa-skull-crossbones"></i> {{localize "BOL.ui.fumble"}}...
|
||||
<h2 class="failure fumble"><i class="fas fa-skull-crossbones"></i> {{localize "BOL.ui.fumble"}}...
|
||||
{{else}}
|
||||
<h2 class="failure"><i class="fas fa-times"></i> {{localize "BOL.ui.failure"}}...
|
||||
<h2 class="failure"><i class="fas fa-times"></i> {{localize "BOL.ui.failure"}}...
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<img class="chat-icon" src="{{img}}" alt="{{actor.name}}"/>
|
||||
@ -52,9 +52,6 @@
|
||||
{{/if}}
|
||||
|
||||
<div id="{{optionsId}}">
|
||||
|
||||
|
||||
|
||||
{{#if isCritical}}
|
||||
<div>
|
||||
{{localize "BOL.chat.criticalinfo"}}
|
||||
@ -83,14 +80,14 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if reroll}}
|
||||
<button class="chat-button button hero-reroll bol-margin-tb-2" data-roll-id=="{{rollId}}" data-actor-id="{{actor.id}}">{{localize "BOL.chat.reroll"}}</button>
|
||||
<button class="chat-button button hero-reroll bol-margin-tb-2" data-actor-id="{{actorId}}">{{localize "BOL.chat.reroll"}}</button>
|
||||
{{/if}}
|
||||
{{#if (and isSuccess (not isCritical))}}
|
||||
<button class="chat-button button transform-heroic-roll bol-margin-tb-2" data-roll-id=="{{rollId}}" data-actor-id="{{actor.id}}">{{localize "BOL.chat.toheroic"}}</button>
|
||||
<button class="chat-button button transform-heroic-roll bol-margin-tb-2" data-actor-id="{{actorId}}">{{localize "BOL.chat.toheroic"}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if isRealCritical}}
|
||||
<button class="chat-button button transform-legendary-roll bol-margin-tb-2" data-roll-id=="{{rollId}}" data-actor-id="{{actor.id}}">{{localize "BOL.chat.tolegend"}}</button>
|
||||
<button class="chat-button button transform-legendary-roll bol-margin-tb-2" data-actor-id="{{actorId}}">{{localize "BOL.chat.tolegend"}}</button>
|
||||
{{/if}}
|
||||
|
||||
<br>
|
||||
|
@ -6,13 +6,17 @@
|
||||
{{/if}}
|
||||
|
||||
<button class="damage-handling" data-defense-mode="damage-with-armor" data-attack-id="{{attackId}}">{{localize "BOL.chat.witharmor"}}</button>
|
||||
<button class="damage-handling" data-defense-mode="damage-without-armor" data-attack-id="{{attackId}}">{{localize "BOL.chat.withoutarmor"}}</button>
|
||||
<button class="damage-handling" data-defense-mode="damage-without-armor" data-attack--id="{{attackId}}">{{localize "BOL.chat.withoutarmor"}}</button>
|
||||
|
||||
{{#if defender.system.resources.hero.value}}
|
||||
<button class="damage-handling" data-defense-mode="hero-reduce-damage" data-attack-id="{{attackId}}">{{localize "BOL.chat.shakeoff"}}</button>
|
||||
|
||||
{{#each defenderWeapons as |weapon idx|}}
|
||||
<button class="damage-handling" data-defense-mode="hero-in-extremis" data-attack-id="{{@root.attackId}}" data-weapon-id="{{weapon._id}}">{{localize "BOL.chat.splinteredshield" name=weapon.name}}</button>
|
||||
{{/each}}
|
||||
{{#if isHeroAdversary}}
|
||||
{{#if (gt defender.system.resources.hero.value 0)}}
|
||||
<button class="damage-handling" data-defense-mode="hero-reduce-damage" data-attack-id="{{attackId}}">{{localize "BOL.chat.shakeoff"}}</button>
|
||||
|
||||
{{#each defenderWeapons as |weapon idx|}}
|
||||
<button class="damage-handling" data-defense-mode="hero-in-extremis" data-attack-id="{{@root.attackId}}" data-weapon-id="{{weapon._id}}">{{localize "BOL.chat.splinteredshield" name=weapon.name}}</button>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<button class="damage-handling" data-defense-mode="damage-not-applied" data-attack-id="{{attackId}}">{{localize "BOL.chat.nodamage"}}</button>
|
||||
|
||||
|
Reference in New Issue
Block a user