Combat Tracker + power enhancements

This commit is contained in:
2023-04-06 20:15:04 +02:00
parent 5b91041a3f
commit 41fbc094bb
7 changed files with 132 additions and 36 deletions

View File

@ -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()
this.updateResourcesData()
this.manageHealthState();
if (this.id) {
this.updateResourcesData()
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) {

View File

@ -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--;

View File

@ -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,12 +54,12 @@ 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()
}
/************************************************************************************/
_onDelete() {
let combatants = this.combatants.contents
@ -63,4 +72,4 @@ export class BoLCombatManager extends Combat {
}
}

View File

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