Compare commits

..

5 Commits

Author SHA1 Message Date
5b91041a3f Fix options de combat 2023-04-04 13:41:22 +02:00
e7f3851daa Fix dice default 2023-03-29 23:04:02 +02:00
75d562f922 Nouvelle option d'ignorer les dommages 2023-03-25 08:42:14 +01:00
ba7e25e8c7 Fix and +/- 2023-03-18 13:51:46 +01:00
83d3f17dd0 Messages de recuperation 2023-03-18 10:24:30 +01:00
15 changed files with 278 additions and 190 deletions

View File

@ -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.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.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.soeasy": "Inmanquable (+4)",
"BOL.dialog.veryeasy": "Trés Facile (+2)", "BOL.dialog.veryeasy": "Trés Facile (+2)",
"BOL.dialog.easy": "Facile (+1)", "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.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.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.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"
} }

View File

@ -60,6 +60,12 @@ export class BoLActorSheet extends ActorSheet {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.spendAlchemyPoint(li.data("itemId"), 1) 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 // Incr./Decr. career ranks
html.find(".inc-dec-btns").click((ev) => { html.find(".inc-dec-btns").click((ev) => {

View File

@ -22,6 +22,17 @@ export class BoLActor extends Actor {
super.prepareData() super.prepareData()
} }
/* -------------------------------------------- */
isHeroAdversary() {
if (this.type === 'character') {
return true
}
if (this.type === 'encounter' && this.chartype == "adversary") {
return true
}
return false
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getCharType() { getCharType() {
if (this.type === 'character') { if (this.type === 'character') {
@ -32,11 +43,11 @@ export class BoLActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
getVillainy() { getVillainy() {
if (this.type === 'character') { if (this.type === 'encounter' && this.chartype == "adversary") {
return false
}
return true return true
} }
return false
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getBougette() { getBougette() {
@ -459,9 +470,11 @@ export class BoLActor extends Actor {
//Spent points //Spent points
this.spentAstrologyPoints(rollData.astrologyPointsCost) this.spentAstrologyPoints(rollData.astrologyPointsCost)
if (rollData.horoscopeType == "minor") { if (rollData.horoscopeType == "minor") {
let horoscope = { name: "SITUATION A SPECIFIER", type :"feature", let horoscope = {
name: "SITUATION A SPECIFIER", type: "feature",
img: "icons/magic/perception/eye-ringed-glow-angry-large-red.webp", img: "icons/magic/perception/eye-ringed-glow-angry-large-red.webp",
system :{subtype: "horoscope", properties: { system: {
subtype: "horoscope", properties: {
ishoroscopemajor: false, ishoroscopemajor: false,
horoscopeanswer: (rollData.isSuccess) ? "favorable" : "unfavorable", horoscopeanswer: (rollData.isSuccess) ? "favorable" : "unfavorable",
rank: rollData.careerBonus rank: rollData.careerBonus
@ -732,7 +745,7 @@ export class BoLActor extends Actor {
ChatMessage.create({ ChatMessage.create({
alias: this.name, alias: this.name,
whisper: BoLUtility.getWhisperRecipientsAndGMs(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 { } else {
if (prone) { if (prone) {
@ -751,6 +764,42 @@ export class BoLActor extends Actor {
await this.setFlag("world", "last-initiative", rollData) 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() { clearInitiative() {
this.unsetFlag("world", "last-initiative") this.unsetFlag("world", "last-initiative")
@ -823,6 +872,11 @@ export class BoLActor extends Actor {
await this.update({ 'system.resources.hero.value': newHeroP }); 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) { async sufferDamage(damage) {
let newHP = this.system.resources.hp.value - damage let newHP = this.system.resources.hp.value - damage

View File

@ -523,6 +523,7 @@ export class BoLRoll {
rollData.nbBoons = 0 rollData.nbBoons = 0
rollData.nbFlaws = 0 rollData.nbFlaws = 0
rollData.nbDice = 0 rollData.nbDice = 0
rollData.isHeroAdversary = actor.isHeroAdversary()
if (rollData.shieldBlock == 'blockall') { if (rollData.shieldBlock == 'blockall') {
rollData.shieldMalus = rollData.shieldAttackMalus; rollData.shieldMalus = rollData.shieldAttackMalus;
} else { } else {
@ -677,10 +678,10 @@ export class BoLDefaultRoll {
async sendChatMessage() { async sendChatMessage() {
let actor = BoLUtility.getActorFromRollData(this.rollData) let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildChatMessage(this.rollData).then(async msgFlavor => { this._buildChatMessage(this.rollData).then(async msgFlavor => {
//console.log("MSG", msgFlavor )
let msg = await this.rollData.roll.toMessage({ let msg = await this.rollData.roll.toMessage({
user: game.user.id, user: game.user.id,
rollMode: game.settings.get("core", "rollMode"), rollMode: game.settings.get("core", "rollMode"),
//whisper: BoLUtility.getWhisperRecipientsAndGMs(this.rollData.actor.name),
flavor: msgFlavor, flavor: msgFlavor,
speaker: ChatMessage.getSpeaker({ actor: actor }), speaker: ChatMessage.getSpeaker({ actor: actor }),
}) })
@ -766,13 +767,13 @@ export class BoLDefaultRoll {
let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.system, this.rollData.fightOption) let weaponFormula = BoLUtility.getDamageFormula(this.rollData.weapon.system, this.rollData.fightOption)
let damageFormula = weaponFormula + "+" + bonusDmg + "+" + attrDamageValue let damageFormula = weaponFormula + "+" + bonusDmg + "+" + attrDamageValue
console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData)
//console.log("Formula", weaponFormula, damageFormula, this.rollData.weapon.data.data.properties.damage) //console.log("Formula", weaponFormula, damageFormula, this.rollData.weapon.data.data.properties.damage)
this.rollData.damageFormula = damageFormula this.rollData.damageFormula = damageFormula
this.rollData.damageRoll = new Roll(damageFormula) this.rollData.damageRoll = new Roll(damageFormula)
await this.rollData.damageRoll.roll({ "async": false }) await this.rollData.damageRoll.roll({ "async": false })
this.rollData.damageTotal = this.rollData.damageRoll.total this.rollData.damageTotal = this.rollData.damageRoll.total
console.log("DAMAGE !!!", damageFormula, attrDamageValue, this.rollData)
} }
BoLUtility.cleanupButtons(this.rollData.optionsId) BoLUtility.cleanupButtons(this.rollData.optionsId)
this.sendDamageMessage() this.sendDamageMessage()

View File

@ -41,12 +41,23 @@ export class BoLCombatManager extends Combat {
super.nextRound() 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() { _onDelete() {
let combatants = this.combatants.contents let combatants = this.combatants.contents
for (let c of combatants) { for (let c of combatants) {
let actor = game.actors.get(c.actorId) let actor = game.actors.get(c.actorId)
actor.clearInitiative() actor.clearInitiative()
actor.displayRecuperation()
} }
super._onDelete() super._onDelete()
} }

View File

@ -8,8 +8,6 @@ export class BoLUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static init() { static init() {
this.attackStore = {}
game.settings.register("bol", "rollArmor", { game.settings.register("bol", "rollArmor", {
name: "Effectuer des jets pour les armures", name: "Effectuer des jets pour les armures",
hint: "Effectue un jet de dés pour les armures (valeur fixe si désactivé)", 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)", hint: "Sélectionne la formule de dés (par défaut 2d6)",
scope: "world", scope: "world",
config: true, config: true,
default: "2d6", default: "6",
type: String, type: String,
choices: { "6": "2d6", "8":"2d8", "10":"2d10", "12":"2d12", "20":"2d20"}, choices: { "6": "2d6", "8":"2d8", "10":"2d10", "12":"2d12", "20":"2d20"},
onChange: value => { onChange: value => {
@ -151,7 +149,7 @@ export class BoLUtility {
df = "6" df = "6"
} }
return { return {
diceFormula: this.diceFormula, diceFormula: df,
successValue : this.successValue, successValue : this.successValue,
criticalSuccessValue: this.criticalSuccessValue, criticalSuccessValue: this.criticalSuccessValue,
criticalFailureValue: this.criticalFailureValue criticalFailureValue: this.criticalFailureValue
@ -193,29 +191,6 @@ export class BoLUtility {
CONFIG.statusEffects = duplicate(game.bol.config.statusEffects) 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) { static createDirectOptionList(min, max) {
let options = {}; let options = {};
@ -260,7 +235,7 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getUsers(filter) { 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) { static getWhisperRecipients(rollMode, name) {
@ -298,13 +273,13 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static sendAttackSuccess(attackDef) { static sendAttackSuccess(rollData) {
if (attackDef.targetId) { if (rollData.targetId) {
// Broadcast to GM or process it directly in case of GM defense // Broadcast to GM or process it directly in case of GM defense
if (!game.user.isGM) { 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 { } 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 } }) 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) { if (!game.user.isGM) {
return return
} }
let message = game.messages.get(msgId)
let rollData = message.getFlag("world", "bol-roll-data")
BoLUtility.removeChatMessageId(msgId) BoLUtility.removeChatMessageId(msgId)
console.log("Damage Handling", attackId, defenseMode, weaponId) console.log("Damage Handling", attackId, defenseMode, weaponId)
// Only GM process this // Only GM process this
let attackDef = this.attackStore[attackId] if (rollData && rollData.defenderId) {
if (attackDef && attackDef.defenderId) { if (rollData.defenseDone || defenseMode == 'damage-not-applied') {
if (attackDef.defenseDone) {
return return
} // ?? Why ??? } // ?? Why ???
attackDef.defenseDone = true rollData.defenseDone = true
attackDef.defenseMode = defenseMode rollData.defenseMode = defenseMode
let token = game.scenes.current.tokens.get(attackDef.targetId) let token = game.scenes.current.tokens.get(rollData.targetId)
let defender = token.actor let defender = token.actor
if (defenseMode == 'damage-with-armor') { if (defenseMode == 'damage-with-armor') {
let armorFormula = defender.getArmorFormula() let armorFormula = defender.getArmorFormula()
attackDef.rollArmor = new Roll(armorFormula) rollData.rollArmor = new Roll(armorFormula)
attackDef.rollArmor.roll({ async: false }) rollData.rollArmor.roll({ async: false })
attackDef.armorProtect = (attackDef.rollArmor.total < 0) ? 0 : attackDef.rollArmor.total rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
attackDef.finalDamage = attackDef.damageTotal - attackDef.armorProtect rollData.finalDamage = rollData.damageTotal - rollData.armorProtect
attackDef.finalDamage = (attackDef.finalDamage < 0) ? 0 : attackDef.finalDamage rollData.finalDamage = (rollData.finalDamage < 0) ? 0 : rollData.finalDamage
defender.sufferDamage(attackDef.finalDamage) defender.sufferDamage(rollData.finalDamage)
console.log("Armor roll -> result ", attackDef) console.log("Armor roll -> result ", rollData)
} }
if (defenseMode == 'damage-without-armor') { if (defenseMode == 'damage-without-armor') {
attackDef.finalDamage = attackDef.damageTotal rollData.finalDamage = atrollDatatackDef.damageTotal
defender.sufferDamage(attackDef.finalDamage) defender.sufferDamage(rollData.finalDamage)
} }
if (defenseMode == 'hero-reduce-damage') { if (defenseMode == 'hero-reduce-damage') {
let armorFormula = defender.getArmorFormula() let armorFormula = defender.getArmorFormula()
attackDef.rollArmor = new Roll(armorFormula) rollData.rollArmor = new Roll(armorFormula)
attackDef.rollArmor.roll({ async: false }) rollData.rollArmor.roll({ async: false })
attackDef.armorProtect = (attackDef.rollArmor.total < 0) ? 0 : attackDef.rollArmor.total rollData.armorProtect = (rollData.rollArmor.total < 0) ? 0 : rollData.rollArmor.total
attackDef.rollHero = new Roll("1d6") rollData.rollHero = new Roll("1d6")
attackDef.rollHero.roll({ async: false }) rollData.rollHero.roll({ async: false })
attackDef.finalDamage = attackDef.damageTotal - attackDef.rollHero.total - attackDef.armorProtect rollData.finalDamage = rollData.damageTotal - rollData.rollHero.total - rollData.armorProtect
attackDef.finalDamage = (attackDef.finalDamage < 0) ? 0 : attackDef.finalDamage rollData.finalDamage = (rollData.finalDamage < 0) ? 0 : rollData.finalDamage
defender.sufferDamage(attackDef.finalDamage) defender.sufferDamage(rollData.finalDamage)
defender.subHeroPoints(1) defender.subHeroPoints(1)
} }
if (defenseMode == 'hero-in-extremis') { if (defenseMode == 'hero-in-extremis') {
attackDef.finalDamage = 0; rollData.finalDamage = 0;
attackDef.weaponHero = defender.weapons.find(item => item._id == weaponId); rollData.weaponHero = defender.weapons.find(item => item._id == weaponId);
defender.deleteEmbeddedDocuments("Item", [weaponId]); defender.deleteEmbeddedDocuments("Item", [weaponId]);
} }
@ -456,16 +446,16 @@ export class BoLUtility {
} }
} }
let damageResults = { let damageResults = {
attackId: attackDef.id, attackId: rollData.id,
attacker: attackDef.attacker, attacker: rollData.attacker,
rollArmor: attackDef.rollArmor, rollArmor: rollData.rollArmor,
rollHero: attackDef.rollHero, rollHero: rollData.rollHero,
weaponHero: attackDef.weaponHero, weaponHero: rollData.weaponHero,
armorProtect: attackDef.armorProtect, armorProtect: rollData.armorProtect,
name: defender.name, name: defender.name,
defender: defender, defender: defender,
defenseMode: attackDef.defenseMode, defenseMode: rollData.defenseMode,
finalDamage: attackDef.finalDamage finalDamage: rollData.finalDamage
} }
ChatMessage.create({ ChatMessage.create({
alias: defender.name, alias: defender.name,
@ -509,7 +499,7 @@ export class BoLUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isRangedWeapon(weapon) { 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) { static async processAttackSuccess(rollData) {
console.log("Attack success processing", attackDef) console.log("Attack success processing", rollData)
if (!game.user.isGM || !attackDef.defenderId) { // Only GM process this if (!game.user.isGM || !rollData.defenderId) { // Only GM process this
return return
} }
// Build and send the defense message to the relevant people (ie GM + defender) // Build and send the defense message to the relevant people (ie GM + defender)
let defender = game.actors.get(attackDef.defenderId) let defender = game.actors.get(rollData.defenderId)
console.log("DEF WEP", attackDef, defender)
let defenderWeapons = defender.weapons || [] let defenderWeapons = defender.weapons || []
this.attackStore[attackDef.id] = attackDef // Store ! let msg = await ChatMessage.create({
ChatMessage.create({
alias: defender.name, alias: defender.name,
whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name), whisper: BoLUtility.getWhisperRecipientsAndGMs(defender.name),
content: await renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', { content: await renderTemplate('systems/bol/templates/chat/rolls/defense-request-card.hbs', {
attackId: attackDef.id, attackId: rollData.id,
attacker: attackDef.attacker, attacker: rollData.attacker,
defender: defender, defender: defender,
defenderWeapons: defenderWeapons, defenderWeapons: defenderWeapons,
damageTotal: attackDef.damageRoll.total, damageTotal: rollData.damageTotal,
damagesIgnoresArmor: attackDef.damagesIgnoresArmor, 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) { static computeSpellCost(spell, nbOptCond = 0) {
let pp = spell.data.properties.ppcost let pp = spell.system.properties.ppcost
let minpp = __circle2minpp[spell.data.properties.circle] let minpp = __circle2minpp[spell.system.properties.circle]
pp = (pp - nbOptCond < minpp) ? minpp : pp - nbOptCond pp = (pp - nbOptCond < minpp) ? minpp : pp - nbOptCond
return pp return pp
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getDamageFormula(weaponData, fightOption) { 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 damageString = weaponData.properties.damage
let modifier = weaponData.properties.damageModifiers ?? 0 let modifier = weaponData.properties.damageModifiers ?? 0
let multiplier = weaponData.properties.damageMultiplier ?? 1 let multiplier = weaponData.properties.damageMultiplier ?? 1

View File

@ -118,7 +118,7 @@ export const registerHandlebarsHelpers = function () {
}) })
Handlebars.registerHelper('includesKey', function (items, type, key) { Handlebars.registerHelper('includesKey', function (items, type, key) {
// console.log(items); // 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) { Handlebars.registerHelper('includes', function (array, val) {
return array.includes(val); return array.includes(val);

View File

@ -49,7 +49,7 @@ export default function registerHooks() {
let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
name: actor.data.name, name: actor.name,
type: "script", type: "script",
img: "icons/svg/dice-target.svg", img: "icons/svg/dice-target.svg",
command: command command: command
@ -65,9 +65,9 @@ export default function registerHooks() {
let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
name: journal.data.name, name: journal.name,
type: "script", type: "script",
img: (journal.data.img) ? journal.data.img : "icons/svg/book.svg", img: (journal.img) ? journal.img : "icons/svg/book.svg",
command: command command: command
}, {displaySheet: false}) }, {displaySheet: false})
game.user.assignHotbarMacro(macro, slot); game.user.assignHotbarMacro(macro, slot);

View File

@ -37,13 +37,13 @@ export class Macros {
}; };
if(rollType === "attribute") { 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 rollLabel = (attribute.label) ? game.i18n.localize(attribute.label) : null;
let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) ; let description = actor.name + " - " + game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label) ;
BoLRoll.attributeRollDialog(actor, actorData, attribute, rollLabel, description, adv, mod); BoLRoll.attributeRollDialog(actor, actorData, attribute, rollLabel, description, adv, mod);
} }
else if(rollType === "aptitude") { 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 rollLabel = (aptitude.label) ? game.i18n.localize(aptitude.label) : null;
let description = actor.name + " - " + game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label) ; let description = actor.name + " - " + game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label) ;
BoLRoll.aptitudeRollDialog(actor, actorData, aptitude, rollLabel, description, adv, mod); BoLRoll.aptitudeRollDialog(actor, actorData, aptitude, rollLabel, description, adv, mod);

View File

@ -14,7 +14,7 @@
], ],
"url": "https://www.uberwald.me/gitea/public/bol", "url": "https://www.uberwald.me/gitea/public/bol",
"license": "LICENSE.txt", "license": "LICENSE.txt",
"version": "10.5.8", "version": "10.5.13",
"compatibility": { "compatibility": {
"minimum": "10", "minimum": "10",
"verified": "10" "verified": "10"
@ -202,7 +202,7 @@
], ],
"socket": true, "socket": true,
"manifest": "https://www.uberwald.me/gitea/public/bol/raw/v10/system.json", "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", "background": "systems/bol/ui/page_accueil.webp",
"gridDistance": 1.5, "gridDistance": 1.5,
"gridUnits": "m", "gridUnits": "m",

View File

@ -50,6 +50,10 @@
<div class="resource stat flex1 flex-group-center"> <div class="resource stat flex1 flex-group-center">
<label class="stat-label">{{localize label}}</label><br/> <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"/> <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>&nbsp;
<a class="inc-dec-btns-resource" data-target="{{key}}" data-incr="1"><i class="fas fa-plus-square"></i></a>&nbsp;
{{#if (eq @root.charType 'player')}} {{#if (eq @root.charType 'player')}}
{{#if (exists bonus)}} {{#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> <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>

View 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>

View File

@ -5,6 +5,7 @@
<div class="flexrow"> <div class="flexrow">
{{#if isHeroAdversary}}
{{#if (eq hp 0)}} {{#if (eq hp 0)}}
{{localize "BOL.chat.vitalityzero" name=name hp=hp}} {{localize "BOL.chat.vitalityzero" name=name hp=hp}}
<br>{{localize "BOL.chat.vitalityheroism"}} <br>{{localize "BOL.chat.vitalityheroism"}}
@ -18,6 +19,10 @@
<br><strong>{{localize "BOL.chat.isdead" name=name}}</strong> <br><strong>{{localize "BOL.chat.isdead" name=name}}</strong>
<br>{{localize "BOL.chat.epitaph"}} <br>{{localize "BOL.chat.epitaph"}}
{{/if}} {{/if}}
{{else}}
<br><strong>{{localize "BOL.chat.isdead" name=name}}</strong>
<br>{{localize "BOL.chat.epitaph"}}
{{/if}}
</div> </div>

View File

@ -1,20 +1,20 @@
<div> <div>
{{#if isSuccess}} {{#if isSuccess}}
{{#if isLegendary}} {{#if isLegendary}}
<h2 class="success critical"><i class="fas fa-check-double"></i>&nbsp;{{localize "BOL.ui.criticallegend"}}... <h2 class="success critical"><i class="fas fa-check-double"></i> {{localize "BOL.ui.criticallegend"}}...
{{else}} {{else}}
{{#if isCritical}} {{#if isCritical}}
<h2 class="success critical"><i class="fas fa-check-double"></i>&nbsp;{{localize "BOL.ui.critical"}}... <h2 class="success critical"><i class="fas fa-check-double"></i> {{localize "BOL.ui.critical"}}...
{{else}} {{else}}
<h2 class="success"><i class="fas fa-check"></i>&nbsp;{{localize "BOL.ui.success"}}... <h2 class="success"><i class="fas fa-check"></i> {{localize "BOL.ui.success"}}...
{{/if}} {{/if}}
{{/if}} {{/if}}
{{/if}} {{/if}}
{{#if isFailure}} {{#if isFailure}}
{{#if isFumble}} {{#if isFumble}}
<h2 class="failure fumble"><i class="fas fa-skull-crossbones"></i>&nbsp;{{localize "BOL.ui.fumble"}}... <h2 class="failure fumble"><i class="fas fa-skull-crossbones"></i> {{localize "BOL.ui.fumble"}}...
{{else}} {{else}}
<h2 class="failure"><i class="fas fa-times"></i>&nbsp;{{localize "BOL.ui.failure"}}... <h2 class="failure"><i class="fas fa-times"></i> {{localize "BOL.ui.failure"}}...
{{/if}} {{/if}}
{{/if}} {{/if}}
<img class="chat-icon" src="{{img}}" alt="{{actor.name}}"/> <img class="chat-icon" src="{{img}}" alt="{{actor.name}}"/>
@ -52,9 +52,6 @@
{{/if}} {{/if}}
<div id="{{optionsId}}"> <div id="{{optionsId}}">
{{#if isCritical}} {{#if isCritical}}
<div> <div>
{{localize "BOL.chat.criticalinfo"}} {{localize "BOL.chat.criticalinfo"}}
@ -83,14 +80,14 @@
{{/if}} {{/if}}
{{#if reroll}} {{#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}}
{{#if (and isSuccess (not isCritical))}} {{#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}}
{{#if isRealCritical}} {{#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}} {{/if}}
<br> <br>

View File

@ -6,13 +6,17 @@
{{/if}} {{/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-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}} {{#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> <button class="damage-handling" data-defense-mode="hero-reduce-damage" data-attack-id="{{attackId}}">{{localize "BOL.chat.shakeoff"}}</button>
{{#each defenderWeapons as |weapon idx|}} {{#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> <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}} {{/each}}
{{/if}} {{/if}}
{{/if}}
<button class="damage-handling" data-defense-mode="damage-not-applied" data-attack-id="{{attackId}}">{{localize "BOL.chat.nodamage"}}</button>