forked from public/bol
Combat Tracker + power enhancements
This commit is contained in:
parent
5b91041a3f
commit
41fbc094bb
20
lang/fr.json
20
lang/fr.json
@ -459,10 +459,10 @@
|
||||
"BOL.chat.isdead": "{name} est mort !",
|
||||
"BOL.chat.epitaph": "Que son nom soit honoré sur les champs de batailles de Lémurie !",
|
||||
"BOL.chat.vitalityzero": "La Vitalité de {name} est {hp} : il va s'écrouler au sol et sombrer dans l'inconscience !",
|
||||
"BOL.chat.vitalityheroism": "Vous pouvez dépenser 1 Point d'Héroisme pour reprendre vos esprits pendant 1 round.",
|
||||
"BOL.chat.vitalityheroism": "Vous pouvez dépenser 1 Point d'Héroisme/Vilainie pour reprendre vos esprits pendant 1 round.",
|
||||
"BOL.chat.vitalityheroismhint": "Dans ce cas votre vitalité remonte à son maximum divisé par 2 (arrondi au supérieur).",
|
||||
"BOL.chat.vitalitydying": "La Vitalité de {name} est de {hp} ! Il est mourant ...",
|
||||
"BOL.chat.vitalitydyingheroism": "Vous pouvez cependant dépenser 1 Point d'Héroisme pour Défier la Mort (cf. page 58).",
|
||||
"BOL.chat.vitalitydyingheroism": "Vous pouvez cependant dépenser 1 Point d'Héroisme/Vilainie pour Défier la Mort (cf. page 58).",
|
||||
"BOL.chat.alchemytitle": "Préparation Alchimique : {name}",
|
||||
"BOL.chat.alchemypoints": "Points de Création Investis : {pcCostCurrent}",
|
||||
"BOL.chat.alchemysuccess": "La préparation alchimique a été réalisée avec succès !<br>Créez l'item ou l'effet correspondant dans votre Inventaire.<br>L'avancement dans la préparation a été remis à 0.",
|
||||
@ -475,19 +475,19 @@
|
||||
"BOL.chat.applydamagetotarget": "Appliquer les dommages à la cible",
|
||||
"BOL.chat.fightoption": "Option de combat",
|
||||
"BOL.chat.reroll": "Relancer (1 P. Heroisme)",
|
||||
"BOL.chat.toheroic": "Transformer en succés Héroïque (1 P. Héroisme)",
|
||||
"BOL.chat.tolegend": "Transformer en succes Légendaire (1 P. Heroisme)",
|
||||
"BOL.chat.toheroic": "Transformer en succés Héroïque (1 P. Héroisme/Vilainie)",
|
||||
"BOL.chat.tolegend": "Transformer en succes Légendaire (1 P. Heroisme/Vilainie)",
|
||||
"BOL.chat.hurttitle": "{name} va encaisser {damageTotal} dégats !",
|
||||
"BOL.chat.armordefault": "C'est une attaque au défaut de l'armure : vous devez encaisser SANS la protection de l'armure !",
|
||||
"BOL.chat.witharmor": "Encaisser avec la protection de l'armure",
|
||||
"BOL.chat.withoutarmor": "Encaisser sans la protection de l'armure",
|
||||
"BOL.chat.shakeoff": "Juste une égratignure (1 Point d'Héroisme)",
|
||||
"BOL.chat.splinteredshield": "Parade in Extremis avec {name} (1 Point d'Héroisme)",
|
||||
"BOL.chat.shakeoff": "Juste une égratignure (1 Point d'Héroisme/Vilainie)",
|
||||
"BOL.chat.splinteredshield": "Parade in Extremis avec {name} (1 Point d'Héroisme/Vilainie)",
|
||||
"BOL.chat.damagesummary": "Dégats subis par {name}",
|
||||
"BOL.chat.protectvalue": "Protection de l'armure",
|
||||
"BOL.chat.noprotectvalue": "Aucune protection d'armure !",
|
||||
"BOL.chat.heroreducedamage": "Un point d'héroisme dépensé, pour une réduction des dommages supplémentaire de {total}.",
|
||||
"BOL.chat.herosplintered": "Aucun dommage encaissé, grâce à la parade in-extremis avec {weaponHero.name}. L'arme a été détruite pendant cette parade ! Un point d'héroisme a également été dépensé.",
|
||||
"BOL.chat.heroreducedamage": "Un point d'héroisme/vilainie dépensé, pour une réduction des dommages supplémentaire de {total}.",
|
||||
"BOL.chat.herosplintered": "Aucun dommage encaissé, grâce à la parade in-extremis avec {weaponHero.name}. L'arme a été détruite pendant cette parade ! Un point d'héroisme/vilainie a également été dépensé.",
|
||||
"BOL.chat.finaldamage": "Encaissement final : {finalDamage} dégats !",
|
||||
"BOL.chat.spell": "Sort",
|
||||
"BOL.chat.spellcost": "Cout en Points de Pouvoir",
|
||||
@ -525,13 +525,13 @@
|
||||
"BOL.chat.usedhoroscope": "Horoscope utilisé",
|
||||
"BOL.chat.horoscopedeleted": "Le(s) Horoscopes utilisé(s) a/ont été supprimé(s) automatiquement.",
|
||||
"BOL.chat.criticaloptions": "Succès critique !! Vous pouvez faire (1 option au choix) :",
|
||||
"BOL.chat.criticalcarnage": "Faire un Carnage : vous avez une attaque gratuite supplémentaire. Cette seconde attaque ne peut bénéficier d'un Point d'Héroisme.",
|
||||
"BOL.chat.criticalcarnage": "Faire un Carnage : vous avez une attaque gratuite supplémentaire. Cette seconde attaque ne peut bénéficier d'un Point d'Héroisme/vilainie.",
|
||||
"BOL.chat.criticalplus6": "Coup Dévastateur : +6 aux dommages (cf bouton ci-dessous).",
|
||||
"BOL.chat.criticalprecise": "Coup Précis : Vous frappez pour diminuer les capacités de votre adversaire. Décrivez ce que vous faites, et si le MJ l'accepte, votre opposant subira un Dé de Malus pour les actions concernées.",
|
||||
"BOL.chat.criticalunarm": "Désarmement : Si votre adversaire a une arme en main, vous le désarmez.",
|
||||
"BOL.chat.criticalrabble": "Massacrer la piétaille : Si vous combattez de la Piétaille, les résultats des dommages indiquent le nombre d'adversaires mis hors de combat.",
|
||||
"BOL.chat.criticalpush": "Renversement : Si la taille le permet, vous poussez votre adversaire au sol, il souffrira d'1 Dé de Malus pour toutes ses actions au round suivant.",
|
||||
"BOL.chat.criticalup": "Transformer en Légendaire : En dépensant 1 point d'Héroisme, vous pouvez transformer ce Succès Héroïque en Légendaire, qui vous permet de prendre 2 options dans la liste ci-dessus (cf. bouton pour un +12 aux dommages par exemple).",
|
||||
"BOL.chat.criticalup": "Transformer en Légendaire : En dépensant 1 point d'Héroisme/Vilainie, vous pouvez transformer ce Succès Héroïque en Légendaire, qui vous permet de prendre 2 options dans la liste ci-dessus (cf. bouton pour un +12 aux dommages par exemple).",
|
||||
"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",
|
||||
|
||||
|
@ -85,11 +85,13 @@ export class BoLActor extends Actor {
|
||||
if (this.type == 'character') {
|
||||
let newVitality = 10 + this.system.attributes.vigor.value + this.system.resources.hp.bonus
|
||||
if (this.system.resources.hp.max != newVitality) {
|
||||
this.update({ 'system.resources.hp.max': newVitality })
|
||||
let actor = this
|
||||
setTimeout( function() { actor.update({ 'system.resources.hp.max': newVitality }) }, 800 )
|
||||
}
|
||||
let newPower = 10 + this.system.attributes.mind.value + this.system.resources.power.bonus
|
||||
if (this.system.resources.power.max != newPower) {
|
||||
this.update({ 'system.resources.power.max': newPower })
|
||||
let actor = this
|
||||
setTimeout( function() { actor.update({ 'system.resources.power.max': newPower }) }, 800 )
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,8 +102,10 @@ export class BoLActor extends Actor {
|
||||
|
||||
} else {
|
||||
super.prepareDerivedData()
|
||||
if (this.id) {
|
||||
this.updateResourcesData()
|
||||
this.manageHealthState();
|
||||
this.manageHealthState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,11 +113,29 @@ export class BoLActor extends Actor {
|
||||
get details() {
|
||||
return this.system.details
|
||||
}
|
||||
addEffectModifiers( myList, dataPath) {
|
||||
for (let attr of myList) {
|
||||
attr.numModifier = 0
|
||||
attr.diceModifier = ""
|
||||
let effects = this.items.filter( i => i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier == dataPath+attr.key)
|
||||
for (let effect of effects) {
|
||||
if ( Number(effect.system.properties.modifier)) {
|
||||
attr.numModifier += Number(effect.system.properties.modifier)
|
||||
} else {
|
||||
attr.diceModifier += "+"+effect.system.properties.modifier
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
get attributes() {
|
||||
return Object.values(this.system.attributes)
|
||||
let attrList = duplicate(Object.values(this.system.attributes))
|
||||
this.addEffectModifiers(attrList, "system.attributes.")
|
||||
return attrList
|
||||
}
|
||||
get aptitudes() {
|
||||
return Object.values(this.system.aptitudes)
|
||||
let aptList = Object.values(this.system.aptitudes)
|
||||
this.addEffectModifiers(aptList, "system.aptitudes.")
|
||||
return aptList
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -241,19 +263,18 @@ export class BoLActor extends Actor {
|
||||
/*-------------------------------------------- */
|
||||
get armorMalusValue() { // used for Fight Options
|
||||
for (let armor of this.armors) {
|
||||
if (armor.system.properties.armorQuality.includes("light")) {
|
||||
if (armor.system.properties.armorQuality?.includes("light")) {
|
||||
return 1
|
||||
}
|
||||
if (armor.system.properties.armorQuality.includes("medium")) {
|
||||
if (armor.system.properties.armorQuality?.includes("medium")) {
|
||||
return 2
|
||||
}
|
||||
if (armor.system.properties.armorQuality.includes("heavy")) {
|
||||
if (armor.system.properties.armorQuality?.includes("heavy")) {
|
||||
return 3
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
get resources() {
|
||||
return Object.values(this.system.resources)
|
||||
}
|
||||
@ -812,6 +833,33 @@ export class BoLActor extends Actor {
|
||||
}
|
||||
return game.bol.config.creatureSize["medium"].order // Medium size per default
|
||||
}
|
||||
/*-------------------------------------------- */
|
||||
checkNumeric(myObject) {
|
||||
if ( myObject) {
|
||||
for (let key in myObject) {
|
||||
if ( myObject[key].value === null ) {
|
||||
myObject[key].value = 0
|
||||
}
|
||||
if ( myObject[key].value === NaN ) {
|
||||
myObject[key].value = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
_preUpdate(data, options, userId) {
|
||||
if (data.system?.attributes) {
|
||||
this.checkNumeric(data.system.attributes)
|
||||
}
|
||||
if (data.system?.aptitudes) {
|
||||
this.checkNumeric(data.system.aptitudes)
|
||||
}
|
||||
if (data.system?.resources) {
|
||||
this.checkNumeric(data.system.resources)
|
||||
}
|
||||
super._preUpdate(data, options, userId)
|
||||
}
|
||||
|
||||
/*-------------------------------------------- */
|
||||
getInitiativeRank(rollData = undefined, isCombat = false, combatData) {
|
||||
@ -821,11 +869,12 @@ export class BoLActor extends Actor {
|
||||
let fvttInit = 4 // Pietaille par defaut
|
||||
if (this.type == 'character') {
|
||||
fvttInit = 5
|
||||
if (!rollData) {
|
||||
fvttInit = -1
|
||||
if (!rollData) {
|
||||
if (isCombat) {
|
||||
ui.notifications.info(game.i18n.localize("BOL.ui.warninitiative"))
|
||||
BoLRoll.aptitudeCheck(this, "init", undefined, combatData)
|
||||
if (game.user.isGM ) {
|
||||
game.socket.emit("system.bol", { name: "msg_request_init_roll", data: { actorId: this.id, combatData : combatData } })
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (rollData.isLegendary) {
|
||||
|
@ -284,7 +284,7 @@ export class BoLRoll {
|
||||
for (let effect of this.rollData.bolApplicableEffects) {
|
||||
if (effect.system.properties.modifier == "1B") {
|
||||
this.rollData.bmDice++;
|
||||
} else if (effect.system.properties.modifier == "1B") {
|
||||
} else if (effect.system.properties.modifier == "2B") {
|
||||
this.rollData.bmDice += 2;
|
||||
} else if (effect.system.properties.modifier == "1M") {
|
||||
this.rollData.bmDice--;
|
||||
|
@ -25,7 +25,7 @@ export class BoLCombatManager extends Combat {
|
||||
// calculate initiative
|
||||
for (let cId = 0; cId < ids.length; cId++) {
|
||||
const combatant = this.combatants.get(ids[cId])
|
||||
let fvttInit = combatant.actor.getInitiativeRank(false, true, {combatId: this.id, combatantId: combatant.id } )
|
||||
let fvttInit = combatant.actor.getInitiativeRank(false, true, { combatId: this.id, combatantId: combatant.id })
|
||||
fvttInit += (cId / 100)
|
||||
await this.updateEmbeddedDocuments("Combatant", [{ _id: ids[cId], initiative: fvttInit }]);
|
||||
}
|
||||
@ -34,9 +34,18 @@ export class BoLCombatManager extends Combat {
|
||||
/************************************************************************************/
|
||||
nextRound() {
|
||||
let combatants = this.combatants.contents
|
||||
let autoRemoveDead = game.settings.get("bol", "auto-remove-dead") // Optionnal auto-removal of dead char.
|
||||
for (let c of combatants) {
|
||||
let actor = game.actors.get( c.actorId )
|
||||
actor.clearRoundModifiers()
|
||||
//let actor = game.actors.get(c.actorId)
|
||||
c.actor.clearRoundModifiers()
|
||||
let toRemove = []
|
||||
if (autoRemoveDead && c.actor.type == "encounter" && (c.actor.system.chartype == "tough" || c.actor.system.chartype == "creature" || c.actor.system.chartype == "base") && c.actor.system.resources.hp.value <= 0) {
|
||||
toRemove.push( c.id || c._id)
|
||||
}
|
||||
//console.log("REM", autoRemoveDead, toRemove, c.actor)
|
||||
if (toRemove.length>0) {
|
||||
this.deleteEmbeddedDocuments('Combatant', toRemove)
|
||||
}
|
||||
}
|
||||
super.nextRound()
|
||||
}
|
||||
@ -45,7 +54,7 @@ export class BoLCombatManager extends Combat {
|
||||
startCombat() {
|
||||
let combatants = this.combatants.contents
|
||||
for (let c of combatants) {
|
||||
let actor = game.actors.get( c.actorId )
|
||||
let actor = game.actors.get(c.actorId)
|
||||
actor.storeVitaliteCombat()
|
||||
}
|
||||
return super.startCombat()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { BoLDefaultRoll } from "../controllers/bol-rolls.js";
|
||||
import { BoLRoll, BoLDefaultRoll } from "../controllers/bol-rolls.js";
|
||||
|
||||
// Spell circle to min PP cost
|
||||
const __circle2minpp = { 0: 0, 1: 2, 2: 6, 3: 11 }
|
||||
@ -26,6 +26,14 @@ export class BoLUtility {
|
||||
type: Boolean,
|
||||
onChange: lang => window.location.reload()
|
||||
})
|
||||
game.settings.register("bol", "auto-remove-dead", {
|
||||
name: "Enlever les PNJs morts automatiquement",
|
||||
hint: "Supprime les PNJ (piétaille, créatures, coriaces) automatiquement du combat lorsqu'ils sont à 0 Vitalité ou moins",
|
||||
scope: "world",
|
||||
config: true,
|
||||
default: false,
|
||||
type: Boolean
|
||||
})
|
||||
game.settings.register("bol", "dice-formula", {
|
||||
name: "Formule de dés",
|
||||
hint: "Sélectionne la formule de dés (par défaut 2d6)",
|
||||
@ -305,6 +313,14 @@ export class BoLUtility {
|
||||
let message = game.messages.get(messageId)
|
||||
return message.getFlag("world", "bol-roll-data")
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static requestInitRoll(actorId, combatData ) {
|
||||
let actor = game.actors.get( actorId )
|
||||
if (actor && actor.isOwner) {
|
||||
ui.notifications.info(game.i18n.localize("BOL.ui.warninitiative"))
|
||||
BoLRoll.aptitudeCheck(actor, "init", undefined, combatData)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static cleanupButtons(id) {
|
||||
@ -574,6 +590,9 @@ export class BoLUtility {
|
||||
if (sockmsg.name == "msg_cleanup_buttons") {
|
||||
$(`#${sockmsg.data.id}`).hide() // Hide the options roll buttons
|
||||
}
|
||||
if (sockmsg.name == "msg_request_init_roll") {
|
||||
this.requestInitRoll( sockmsg.data.actorId, sockmsg.data.combatData)
|
||||
}
|
||||
if (sockmsg.name == "msg_damage_handling") {
|
||||
BoLUtility.processDamageHandling(sockmsg.data.attackId, sockmsg.data.defenseMode, sockmsg.data.weaponId, sockmsg.data.msgId)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
],
|
||||
"url": "https://www.uberwald.me/gitea/public/bol",
|
||||
"license": "LICENSE.txt",
|
||||
"version": "10.5.13",
|
||||
"version": "10.5.14",
|
||||
"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.13.zip",
|
||||
"download": "https://www.uberwald.me/gitea/public/bol/archive/bol-v10.5.14.zip",
|
||||
"background": "systems/bol/ui/page_accueil.webp",
|
||||
"gridDistance": 1.5,
|
||||
"gridUnits": "m",
|
||||
|
@ -1,8 +1,18 @@
|
||||
<div class="attributes flexrow">
|
||||
{{#each attributes as |attribute id|}}
|
||||
<div class="attribute stat flex1 flex-group-center {{key}}">
|
||||
<label class="stat-label"><a class="rollable" data-roll-type="attribute" data-roll="2d6+@attributes.{{key}}.value" data-adv="0" data-key="{{key}}">{{localize label}}</a></label><br/>
|
||||
<input class="stat-value rounded" type="text" name="system.attributes.{{key}}.value" value="{{numberFormat value decimals=0 sign=true}}" data-dtype="Number"/><br/>
|
||||
<label class="stat-label"><a class="rollable" data-roll-type="attribute" data-roll="2d6+@attributes.{{key}}.value" data-adv="0" data-key="{{key}}">{{localize label}}</a></label>
|
||||
{{#if attribute.numModifier}}
|
||||
<label class="stat-value rounded">{{attribute.numModifier}}</label>
|
||||
{{/if}}
|
||||
{{#if (count attribute.diceModifier)}}
|
||||
<label class="stat-value rounded">{{attribute.diceModifier}}</label>
|
||||
{{/if}}
|
||||
<br/>
|
||||
|
||||
<input class="stat-value rounded" type="text" name="system.attributes.{{key}}.value" value="{{numberFormat value decimals=0 sign=true}}" data-dtype="Number"/>
|
||||
<br/>
|
||||
|
||||
<span class="stat-roll rollable" title="2d6" data-roll-type="attribute" data-roll="2d6+@attributes.{{key}}.value" data-adv="0" data-key="{{key}}">
|
||||
<i class="darkgreen fas fa-dice"></i>
|
||||
</span>
|
||||
@ -24,8 +34,17 @@
|
||||
<div class="aptitudes flexrow">
|
||||
{{#each aptitudes as |aptitude id|}}
|
||||
<div class="aptitude stat flex1 flex-group-center">
|
||||
<label class="stat-label"><a class="rollable" data-roll-type="aptitude" data-roll="2d6+@aptitudes.{{key}}.value" data-adv="0" data-key="{{key}}">{{localize label}}</a></label><br/>
|
||||
<label class="stat-label"><a class="rollable" data-roll-type="aptitude" data-roll="2d6+@aptitudes.{{key}}.value" data-adv="0" data-key="{{key}}">{{localize label}}</a></label>
|
||||
{{#if aptitude.numModifier}}
|
||||
<label class="stat-value rounded">{{aptitude.numModifier}}</label>
|
||||
{{/if}}
|
||||
{{#if (count aptitude.diceModifier)}}
|
||||
<label class="stat-value rounded">{{aptitude.diceModifier}}</label>
|
||||
{{/if}}
|
||||
<br/>
|
||||
|
||||
<input class="stat-value rounded-border" type="text" name="system.aptitudes.{{key}}.value" value="{{numberFormat value decimals=0 sign=true}}" data-dtype="Number"/><br/>
|
||||
|
||||
<span class="stat-roll rollable" title="2d6" data-roll-type="aptitude" data-roll="2d6+@aptitudes.{{key}}.value" data-adv="0" data-key="{{key}}">
|
||||
<i class="darkgreen fas fa-dice"></i>
|
||||
</span>
|
||||
|
Loading…
Reference in New Issue
Block a user