Add HUD actions

This commit is contained in:
2022-03-21 23:21:05 +01:00
parent fff6b2a733
commit a5ba6d5215
9 changed files with 357 additions and 196 deletions

View File

@ -6,7 +6,7 @@ import { BoLUtility } from "../system/bol-utility.js";
* @extends {Actor}
*/
export class BoLActor extends Actor {
/** @override */
prepareData() {
const actorData = this.data;
@ -23,15 +23,15 @@ export class BoLActor extends Actor {
}
/* -------------------------------------------- */
updateResourcesData( ) {
if ( this.type == 'character') {
updateResourcesData() {
if (this.type == 'character') {
let newVitality = 10 + this.data.data.attributes.vigor.value + this.data.data.resources.hp.bonus
if ( this.data.data.resources.hp.max != newVitality) {
this.update( {'data.resources.hp.max': newVitality} );
if (this.data.data.resources.hp.max != newVitality) {
this.update({ 'data.resources.hp.max': newVitality });
}
let newPower = 10 + this.data.data.attributes.mind.value + this.data.data.resources.power.bonus
if ( this.data.data.resources.power.max != newPower) {
this.update( {'data.resources.power.max': newPower} );
if (this.data.data.resources.power.max != newPower) {
this.update({ 'data.resources.power.max': newPower });
}
}
}
@ -44,7 +44,7 @@ export class BoLActor extends Actor {
}
/* -------------------------------------------- */
get itemData(){
get itemData() {
return Array.from(this.data.items.values()).map(i => i.data)
}
get details() {
@ -58,11 +58,11 @@ export class BoLActor extends Actor {
}
/* -------------------------------------------- */
clearRoundModifiers( ) { // Process data/items that are finished at end of a round
clearRoundModifiers() { // Process data/items that are finished at end of a round
let foList = this.fightoptions
for(let fo of foList) {
for (let fo of foList) {
if (fo.data.properties.used) {
this.updateEmbeddedDocuments("Item", [ {_id: fo._id, 'data.properties.used': false}] )
this.updateEmbeddedDocuments("Item", [{ _id: fo._id, 'data.properties.used': false }])
}
}
}
@ -71,27 +71,27 @@ export class BoLActor extends Actor {
get defenseValue() {
let defMod = 0
let fo = this.getActiveFightOption()
if (fo && fo.data.properties.fightoptiontype == "intrepid" ) {
if (fo && fo.data.properties.fightoptiontype == "intrepid") {
defMod += -2
}
if (fo && fo.data.properties.fightoptiontype == "fulldefense" ) {
if (fo && fo.data.properties.fightoptiontype == "fulldefense") {
defMod += 2
}
if (fo && fo.data.properties.fightoptiontype == "twoweaponsdef" && !fo.data.properties.used) {
defMod += 1
this.updateEmbeddedDocuments("Item", [ {_id: fo._id, 'data.properties.used': true}] )
this.updateEmbeddedDocuments("Item", [{ _id: fo._id, 'data.properties.used': true }])
}
if (fo && fo.data.properties.fightoptiontype == "defense" ) {
if (fo && fo.data.properties.fightoptiontype == "defense") {
defMod += 1
}
if (fo && fo.data.properties.fightoptiontype == "attack" ) {
if (fo && fo.data.properties.fightoptiontype == "attack") {
defMod += -1
}
return this.data.data.aptitudes.def.value + defMod
}
/* -------------------------------------------- */
getActiveFightOption( ) {
getActiveFightOption() {
let it = this.itemData.find(i => i.type === "feature" && i.data.subtype === "fightoption" && i.data.properties.activated)
if (it) {
return duplicate(it)
@ -100,15 +100,15 @@ export class BoLActor extends Actor {
}
/* -------------------------------------------- */
incAttributeXP( key) {
incAttributeXP(key) {
let attr = duplicate(this.data.data.attributes[key])
if (attr) {
let nextXP = (attr.value == -1) ? 2 : attr.value + (attr.value+1)
let nextXP = (attr.value == -1) ? 2 : attr.value + (attr.value + 1)
let xp = duplicate(this.data.data.xp)
if ( xp.total - xp.spent >= nextXP) {
if (xp.total - xp.spent >= nextXP) {
attr.value += 1
xp.spent += nextXP
this.update( { [`data.attributes.${key}`]: attr, [`data.xp`]: xp } )
this.update({ [`data.attributes.${key}`]: attr, [`data.xp`]: xp })
} else {
ui.notifications.warn("Pas assez de points d'expérience !")
}
@ -116,31 +116,31 @@ export class BoLActor extends Actor {
}
/* -------------------------------------------- */
incAptitudeXP( key) {
incAptitudeXP(key) {
let apt = duplicate(this.data.data.aptitudes[key])
if (apt) {
let nextXP = (apt.value == -1) ? 1 : apt.value + 2
let xp = duplicate(this.data.data.xp)
if ( xp.total - xp.spent >= nextXP) {
if (xp.total - xp.spent >= nextXP) {
apt.value += 1
xp.spent += nextXP
this.update( { [`data.aptitudes.${key}`]: apt, [`data.xp`]: xp } )
this.update({ [`data.aptitudes.${key}`]: apt, [`data.xp`]: xp })
} else {
ui.notifications.warn("Pas assez de points d'expérience !")
}
}
}
/* -------------------------------------------- */
incCareerXP( itemId) {
let career = this.data.items.get( itemId )
incCareerXP(itemId) {
let career = this.data.items.get(itemId)
if (career) {
career = duplicate(career)
let nextXP = career.data.rank + 1
let xp = duplicate(this.data.data.xp)
if ( xp.total - xp.spent >= nextXP) {
if (xp.total - xp.spent >= nextXP) {
xp.spent += nextXP
this.update( { [`data.xp`]: xp } )
this.updateEmbeddedDocuments( 'Item', [ { _id: career._id, 'data.rank': career.data.rank + 1 } ])
this.update({ [`data.xp`]: xp })
this.updateEmbeddedDocuments('Item', [{ _id: career._id, 'data.rank': career.data.rank + 1 }])
} else {
ui.notifications.warn("Pas assez de points d'expérience !")
}
@ -148,25 +148,25 @@ export class BoLActor extends Actor {
}
/* -------------------------------------------- */
async toggleFightOption( itemId) {
async toggleFightOption(itemId) {
let fightOption = this.data.items.get(itemId)
let state
let updates = []
if ( fightOption) {
if (fightOption) {
fightOption = duplicate(fightOption)
if (fightOption.data.properties.activated) {
state = false
} else {
state = true
}
updates.push( {_id: fightOption._id, 'data.properties.activated': state} ) // Update the selected one
updates.push({ _id: fightOption._id, 'data.properties.activated': state }) // Update the selected one
await this.updateEmbeddedDocuments("Item", updates) // Apply all changes
// Then notify
ChatMessage.create({
alias: this.name,
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
content: await renderTemplate('systems/bol/templates/chat/chat-activate-fight-option.hbs', { name: this.name, img: fightOption.img, foName: fightOption.name, state: state} )
content: await renderTemplate('systems/bol/templates/chat/chat-activate-fight-option.hbs', { name: this.name, img: fightOption.img, foName: fightOption.name, state: state })
})
}
@ -174,14 +174,14 @@ export class BoLActor extends Actor {
/* -------------------------------------------- */
get armorMalusValue() { // used for Fight Options
for(let armor of this.armors) {
if (armor.data.properties.armorQuality.includes("light")) {
for (let armor of this.armors) {
if (armor.data.properties.armorQuality.includes("light")) {
return 1
}
if (armor.data.properties.armorQuality.includes("medium")) {
if (armor.data.properties.armorQuality.includes("medium")) {
return 2
}
if (armor.data.properties.armorQuality.includes("heavy")) {
if (armor.data.properties.armorQuality.includes("heavy")) {
return 3
}
}
@ -219,7 +219,7 @@ export class BoLActor extends Actor {
return this.itemData.filter(i => i.type === "item")
}
get armors() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "armor");
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "armor");
}
get helms() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "helm");
@ -227,7 +227,7 @@ export class BoLActor extends Actor {
get shields() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "shield");
}
get weapons() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && i.data.subtype === "weapon");
}
@ -235,10 +235,10 @@ export class BoLActor extends Actor {
return this.armors.concat(this.helms).concat(this.shields)
}
get spells() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "spell");
return this.itemData.filter(i => i.type === "item" && i.data.category === "spell");
}
get alchemy() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "alchemy");
return this.itemData.filter(i => i.type === "item" && i.data.category === "alchemy");
}
get melee() {
return this.weapons.filter(i => i.data.properties.melee === true);
@ -264,9 +264,9 @@ export class BoLActor extends Actor {
}
get misc() {
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && (i.data.subtype === "other" ||i.data.subtype === "container" ||i.data.subtype === "scroll" || i.data.subtype === "jewel"));
return this.itemData.filter(i => i.type === "item" && i.data.category === "equipment" && (i.data.subtype === "other" || i.data.subtype === "container" || i.data.subtype === "scroll" || i.data.subtype === "jewel"));
}
get bonusBoons() {
return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "boon" && i.data.properties.isbonusdice);
}
@ -274,67 +274,67 @@ export class BoLActor extends Actor {
return this.itemData.filter(i => i.type === "feature" && i.data.subtype === "flaw" && i.data.properties.ismalusdice);
}
isSorcerer( ) {
if ( this.careers.find( item => item.data.properties.sorcerer == true) )
isSorcerer() {
if (this.careers.find(item => item.data.properties.sorcerer == true))
return true
return false
}
isAlchemist( ) {
if ( this.careers.find( item => item.data.properties.alchemist == true) )
isAlchemist() {
if (this.careers.find(item => item.data.properties.alchemist == true))
return true
return false
}
isPriest( ) {
if ( this.careers.find( item => item.data.properties.priest == true) )
isPriest() {
if (this.careers.find(item => item.data.properties.priest == true))
return true
return false
}
spendPowerPoint( ppCost ) {
spendPowerPoint(ppCost) {
let newPP = this.data.data.resources.power.value - ppCost
newPP = (newPP<0) ? 0 : newPP
this.update( {'data.resources.power.value': newPP})
newPP = (newPP < 0) ? 0 : newPP
this.update({ 'data.resources.power.value': newPP })
}
resetAlchemyStatus( alchemyId ) {
let alchemy = this.data.items.get( alchemyId)
resetAlchemyStatus(alchemyId) {
let alchemy = this.data.items.get(alchemyId)
if (alchemy) {
this.updateEmbeddedDocuments('Item', [{_id: alchemy.id, 'data.properties.pccurrent': 0}] )
this.updateEmbeddedDocuments('Item', [{ _id: alchemy.id, 'data.properties.pccurrent': 0 }])
}
}
async spendAlchemyPoint( alchemyId, pcCost) {
let alchemy = this.data.items.get( alchemyId)
async spendAlchemyPoint(alchemyId, pcCost) {
let alchemy = this.data.items.get(alchemyId)
if (alchemy) {
pcCost = Number(pcCost)?? 0
if ( this.data.data.resources.alchemypoints.value >= pcCost) {
pcCost = Number(pcCost) ?? 0
if (this.data.data.resources.alchemypoints.value >= pcCost) {
let newPC = this.data.data.resources.alchemypoints.value - pcCost
newPC = (newPC<0) ? 0 : newPC
this.update( {'data.resources.alchemypoints.value': newPC} )
newPC = (newPC < 0) ? 0 : newPC
this.update({ 'data.resources.alchemypoints.value': newPC })
newPC = alchemy.data.data.properties.pccurrent + pcCost
await this.updateEmbeddedDocuments('Item', [{_id: alchemy.id, 'data.properties.pccurrent': newPC}] )
await this.updateEmbeddedDocuments('Item', [{ _id: alchemy.id, 'data.properties.pccurrent': newPC }])
} else {
ui.notifications.warn("Plus assez de Points de Création !")
}
}
}
}
getAlchemistBonus() {
let sorcerer = this.careers.find( item => item.data.properties.alchemist == true)
let sorcerer = this.careers.find(item => item.data.properties.alchemist == true)
if (sorcerer) {
return sorcerer.data.rank
}
return 0;
}
getSorcererBonus() {
let sorcerer = this.careers.find( item => item.data.properties.sorcerer == true)
let sorcerer = this.careers.find(item => item.data.properties.sorcerer == true)
if (sorcerer) {
return sorcerer.data.rank
}
return 0;
}
heroReroll( ) {
heroReroll() {
if (this.type == 'character') {
return this.data.data.resources.hero.value > 0;
} else {
@ -363,7 +363,7 @@ export class BoLActor extends Actor {
return resources
}
buildFeatures(){
buildFeatures() {
return {
"careers": {
"label": "BOL.featureCategory.careers",
@ -402,68 +402,89 @@ export class BoLActor extends Actor {
}
}
}
buildCombat(){
buildCombat() {
return {
"melee" : {
"label" : "BOL.combatCategory.melee",
"weapon" : true,
"protection" : false,
"blocking" : false,
"ranged" : false,
"melee": {
"label": "BOL.combatCategory.melee",
"weapon": true,
"protection": false,
"blocking": false,
"ranged": false,
"options": false,
"items" : this.melee
"items": this.melee
},
"ranged" : {
"label" : "BOL.combatCategory.ranged",
"weapon" : true,
"protection" : false,
"blocking" : false,
"ranged" : true,
"ranged": {
"label": "BOL.combatCategory.ranged",
"weapon": true,
"protection": false,
"blocking": false,
"ranged": true,
"options": false,
"items" : this.ranged
"items": this.ranged
},
"protections" : {
"label" : "BOL.combatCategory.protections",
"weapon" : false,
"protection" : true,
"blocking" : false,
"ranged" : false,
"protections": {
"label": "BOL.combatCategory.protections",
"weapon": false,
"protection": true,
"blocking": false,
"ranged": false,
"options": false,
"items" : this.protections
"items": this.protections
},
"shields" : {
"label" : "BOL.combatCategory.shields",
"weapon" : false,
"protection" : false,
"blocking" : true,
"ranged" : false,
"shields": {
"label": "BOL.combatCategory.shields",
"weapon": false,
"protection": false,
"blocking": true,
"ranged": false,
"options": false,
"items" : this.shields
"items": this.shields
},
"fightoptions" : {
"label" : "BOL.combatCategory.fightOptions",
"weapon" : false,
"protection" : false,
"blocking" : false,
"ranged" : false,
"fightoptions": {
"label": "BOL.combatCategory.fightOptions",
"weapon": false,
"protection": false,
"blocking": false,
"ranged": false,
"options": true,
"items" : this.fightoptions
"items": this.fightoptions
}
}
}
/*-------------------------------------------- */
buildRollList() {
let rolls = []
for ( let key in this.data.data.attributes) {
let attr = this.data.data.attributes[key]
rolls.push( { key: key, value: attr.value, name: attr.label, type: "attribute"})
}
for ( let key in this.data.data.aptitudes) {
if ( key != "def") {
let apt = this.data.data.aptitudes[key]
rolls.push( { key: key, value: apt.value, name: apt.label, type: "aptitude"})
}
}
return rolls
}
/*-------------------------------------------- */
buildListeActions() {
return this.melee.concat(this.ranged)
}
/*-------------------------------------------- */
async manageHealthState() {
let hpID = "lastHP"+this.id
let lastHP = await this.getFlag("world", hpID )
if ( lastHP != this.data.data.resources.hp.value ) {
let hpID = "lastHP" + this.id
let lastHP = await this.getFlag("world", hpID)
if (lastHP != this.data.data.resources.hp.value) {
await this.setFlag("world", hpID, this.data.data.resources.hp.value)
if (this.data.data.resources.hp.value <= 0 ) {
if (this.data.data.resources.hp.value <= 0) {
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.data.data.resources.hp.value} )
content: await renderTemplate('systems/bol/templates/chat/chat-vitality-zero.hbs', { name: this.name, img: this.img, hp: this.data.data.resources.hp.value })
})
}
}
@ -471,7 +492,7 @@ export class BoLActor extends Actor {
/*-------------------------------------------- */
registerInit(initScore, isCritical, isFumble) {
this.update( { 'data.combat.lastinit': initScore, 'data.combat.iscritical': isCritical, 'data.combat.isfumble': isFumble} )
this.update({ 'data.combat.lastinit': initScore, 'data.combat.iscritical': isCritical, 'data.combat.isfumble': isFumble })
}
/*-------------------------------------------- */
@ -480,60 +501,60 @@ export class BoLActor extends Actor {
}
/*-------------------------------------------- */
async subHeroPoints( nb) {
async subHeroPoints(nb) {
let newHeroP = this.data.data.resources.hero.value - nb;
newHeroP = (newHeroP < 0 ) ? 0 : newHeroP;
await this.update( { 'data.resources.hero.value': newHeroP} );
newHeroP = (newHeroP < 0) ? 0 : newHeroP;
await this.update({ 'data.resources.hero.value': newHeroP });
}
/*-------------------------------------------- */
async sufferDamage( damage) {
async sufferDamage(damage) {
let newHP = this.data.data.resources.hp.value - damage;
await this.update( { 'data.resources.hp.value': newHP} );
await this.update({ 'data.resources.hp.value': newHP });
}
/* -------------------------------------------- */
getArmorFormula( ) {
let protectWorn = this.protections.filter( item => item.data.worn)
getArmorFormula() {
let protectWorn = this.protections.filter(item => item.data.worn)
let formula = ""
for (let protect of protectWorn) {
if ( protect.data.subtype == 'helm') {
formula += "+1"
} else if ( protect.data.subtype == 'armor') {
if ( BoLUtility.getRollArmor() ) {
if ( !protect.data.properties.soak.formula || protect.data.properties.soak.formula=="") {
ui.notifications.warn(`L'armure ${protect.name} n'a pas de formule pour la protection !`)
} else {
if (protect.data.subtype == 'helm') {
formula += "+1"
} else if (protect.data.subtype == 'armor') {
if (BoLUtility.getRollArmor()) {
if (!protect.data.properties.soak.formula || protect.data.properties.soak.formula == "") {
ui.notifications.warn(`L'armure ${protect.name} n'a pas de formule pour la protection !`)
} else {
formula += "+" + protect.data.properties.soak.formula
}
} else {
if ( protect.data.properties.soak.value == undefined ) {
ui.notifications.warn(`L'armure ${protect.name} n'a pas de valeur fixe pour la protection !`)
} else {
formula += "+ " + protect.data.properties.soak.value
} else {
if (protect.data.properties.soak.value == undefined) {
ui.notifications.warn(`L'armure ${protect.name} n'a pas de valeur fixe pour la protection !`)
} else {
formula += "+ " + protect.data.properties.soak.value
}
}
}
}
console.log("Protect Formula", formula)
return (formula == "") ? "0" :formula;
return (formula == "") ? "0" : formula;
}
/* -------------------------------------------- */
rollProtection( itemId) {
let armor = this.data.items.get( itemId )
if ( armor ) {
let armorFormula = armor.data.data.properties.soak.formula;
rollProtection(itemId) {
let armor = this.data.items.get(itemId)
if (armor) {
let armorFormula = armor.data.data.properties.soak.formula;
let rollArmor = new Roll(armorFormula)
rollArmor.roll( {async: false} ).toMessage();
rollArmor.roll({ async: false }).toMessage();
}
}
/* -------------------------------------------- */
rollWeaponDamage( itemId) {
let weapon = this.data.items.get(itemId )
if ( weapon ) {
let r = new BoLDefaultRoll( { id: randomID(16), isSuccess: true, mode: "weapon", weapon: weapon, actor: this} )
rollWeaponDamage(itemId) {
let weapon = this.data.items.get(itemId)
if (weapon) {
let r = new BoLDefaultRoll({ id: randomID(16), isSuccess: true, mode: "weapon", weapon: weapon, actor: this })
r.setSuccess(true)
r.rollDamage()
}
@ -542,7 +563,7 @@ export class BoLActor extends Actor {
/* -------------------------------------------- */
toggleEquipItem(item) {
const equipable = item.data.data.properties.equipable;
if(equipable){
if (equipable) {
let itemData = duplicate(item.data);
itemData.data.worn = !itemData.data.worn;
return item.update(itemData);