diff --git a/modules/pegasus-actor.js b/modules/pegasus-actor.js index 318f6f4..952d09f 100644 --- a/modules/pegasus-actor.js +++ b/modules/pegasus-actor.js @@ -124,9 +124,9 @@ export class PegasusActor extends Actor { this.updateSize() } if (this.type == 'vehicle') { - this.computeVehicleStats(); + this.computeVehicleStats() } - super.prepareDerivedData(); + super.prepareDerivedData() } /* -------------------------------------------- */ @@ -263,2259 +263,2279 @@ export class PegasusActor extends Actor { effect.system.stataffected = "mr" effect.system.bonusdice = true await this.createEmbeddedDocuments('Item', [effect]) - ChatMessage.create({ content: `Tactician Bonus Dice has been added to ${this.name} (${level})`, - whisper: ChatMessage.getWhisperRecipients('GM') } ) + ChatMessage.create({ + content: `Tactician Bonus Dice has been added to ${this.name} (${level})`, + whisper: ChatMessage.getWhisperRecipients('GM') + }) } async removeTacticianEffect() { - let effect = this.items.find(item => item.name.toLowerCase().includes("tactician bonus dice")) - if (effect) { - await this.deleteEmbeddedDocuments('Item', [effect.id]) - ChatMessage.create({ content: `Tactician Bonus Dice has been removed to ${this.name}`,whisper: ChatMessage.getWhisperRecipients('GM') } ) - } -} - -/* -------------------------------------------- */ -isEnhancer() { - let role = this.items.find(item => item.type == 'role') - return role && role.system.perksrole == "enhancer" -} -hasEnhancerBonus() { - let effect = this.items.find(item => item.name.toLowerCase().includes("enhancer bonus dice")) - return effect -} - async addEnhancerEffect(name, level) { - let effect = duplicate(__bonusEffect) - effect.name = `${name} Enhancer Bonus Dice ALL` - effect.system.effectlevel = level - effect.system.stataffected = "all" - effect.system.bonusdice = true - await this.createEmbeddedDocuments('Item', [effect]) - ChatMessage.create({ content: `Enhancer Bonus Dice has been added to ${this.name} (${level})`,whisper: ChatMessage.getWhisperRecipients('GM') }) -} - async removeEnhancerEffect() { - let effect = this.items.find(item => item.name.toLowerCase().includes("enhancer bonus dice")) - if (effect) { - await this.deleteEmbeddedDocuments('Item', [effect.id]) - ChatMessage.create({ content: `Enhancer Bonus Dice has been removed to ${this.name}`,whisper: ChatMessage.getWhisperRecipients('GM') }) - } -} - -/* -------------------------------------------- */ -isAgitator() { - let role = this.items.find(item => item.type == 'role') - return role && role.system.perksrole == "agitator" -} -hasAgitatorHindrance() { - let effect = this.items.find(item => item.name.toLowerCase().includes("hindered by agitator")) - return effect -} - async addAgitatorHindrance(name, level) { - let effect = duplicate(__bonusEffect) - effect.name = `Hindered by Agitator ${name}` - effect.system.effectlevel = level - effect.system.stataffected = "all" - effect.system.genre = "negative" - effect.system.hindrance = true - await this.createEmbeddedDocuments('Item', [effect]) - ChatMessage.create({ content: `Agitator Hindrance has been added to ${this.name} (${level})`,whisper: ChatMessage.getWhisperRecipients('GM') }) -} - async removeAgitatorHindrance() { - let effect = this.items.find(item => item.name.toLowerCase().includes("hindered by agitator")) - if (effect) { - await this.deleteEmbeddedDocuments('Item', [effect.id]) - ChatMessage.create({ content: `Agitator Hindrance has been removed to ${this.name}` ,whisper: ChatMessage.getWhisperRecipients('GM')}) - } -} - -/* -------------------------------------------- */ -checkAndPrepareEquipment(item) { - if (item.system.resistance) { - item.system.resistanceDice = PegasusUtility.getDiceFromLevel(item.system.resistance) - } - if (item.system.idr) { - item.system.idrDice = PegasusUtility.getDiceFromLevel(item.system.idr) - } - if (item.system.damage) { - item.system.damageDice = PegasusUtility.getDiceFromLevel(item.system.damage) - } - if (item.system.level) { - item.system.levelDice = PegasusUtility.getDiceFromLevel(item.system.level) - } -} - -/* -------------------------------------------- */ -checkAndPrepareEquipments(listItem) { - for (let item of listItem) { - this.checkAndPrepareEquipment(item) - } - return listItem -} - -/* -------------------------------------------- */ -getWeapons() { - let comp = duplicate(this.items.filter(item => item.type == 'weapon') || []); - return comp; -} -/* -------------------------------------------- */ -getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = duplicate(item) - if (item.type == 'specialisation') { - item.system.dice = PegasusUtility.getDiceFromLevel(item.system.level); + let effect = this.items.find(item => item.name.toLowerCase().includes("tactician bonus dice")) + if (effect) { + await this.deleteEmbeddedDocuments('Item', [effect.id]) + ChatMessage.create({ content: `Tactician Bonus Dice has been removed to ${this.name}`, whisper: ChatMessage.getWhisperRecipients('GM') }) } } - return item; -} -/* -------------------------------------------- */ -getSpecs() { - let comp = duplicate(this.items.filter(item => item.type == 'specialisation') || []); - for (let c of comp) { - c.system.dice = PegasusUtility.getDiceFromLevel(c.system.level); + /* -------------------------------------------- */ + isEnhancer() { + let role = this.items.find(item => item.type == 'role') + return role && role.system.perksrole == "enhancer" + } + hasEnhancerBonus() { + let effect = this.items.find(item => item.name.toLowerCase().includes("enhancer bonus dice")) + return effect + } + async addEnhancerEffect(name, level) { + let effect = duplicate(__bonusEffect) + effect.name = `${name} Enhancer Bonus Dice ALL` + effect.system.effectlevel = level + effect.system.stataffected = "all" + effect.system.bonusdice = true + await this.createEmbeddedDocuments('Item', [effect]) + ChatMessage.create({ content: `Enhancer Bonus Dice has been added to ${this.name} (${level})`, whisper: ChatMessage.getWhisperRecipients('GM') }) + } + async removeEnhancerEffect() { + let effect = this.items.find(item => item.name.toLowerCase().includes("enhancer bonus dice")) + if (effect) { + await this.deleteEmbeddedDocuments('Item', [effect.id]) + ChatMessage.create({ content: `Enhancer Bonus Dice has been removed to ${this.name}`, whisper: ChatMessage.getWhisperRecipients('GM') }) + } + } + + /* -------------------------------------------- */ + isAgitator() { + let role = this.items.find(item => item.type == 'role') + return role && role.system.perksrole == "agitator" + } + hasAgitatorHindrance() { + let effect = this.items.find(item => item.name.toLowerCase().includes("hindered by agitator")) + return effect + } + async addAgitatorHindrance(name, level) { + let effect = duplicate(__bonusEffect) + effect.name = `Hindered by Agitator ${name}` + effect.system.effectlevel = level + effect.system.stataffected = "all" + effect.system.genre = "negative" + effect.system.hindrance = true + await this.createEmbeddedDocuments('Item', [effect]) + ChatMessage.create({ content: `Agitator Hindrance has been added to ${this.name} (${level})`, whisper: ChatMessage.getWhisperRecipients('GM') }) + } + async removeAgitatorHindrance() { + let effect = this.items.find(item => item.name.toLowerCase().includes("hindered by agitator")) + if (effect) { + await this.deleteEmbeddedDocuments('Item', [effect.id]) + ChatMessage.create({ content: `Agitator Hindrance has been removed to ${this.name}`, whisper: ChatMessage.getWhisperRecipients('GM') }) + } + } + + /* -------------------------------------------- */ + checkAndPrepareEquipment(item) { + if (item.system.resistance) { + item.system.resistanceDice = PegasusUtility.getDiceFromLevel(item.system.resistance) + } + if (item.system.idr) { + item.system.idrDice = PegasusUtility.getDiceFromLevel(item.system.idr) + } + if (item.system.damage) { + item.system.damageDice = PegasusUtility.getDiceFromLevel(item.system.damage) + } + if (item.system.level) { + item.system.levelDice = PegasusUtility.getDiceFromLevel(item.system.level) + } + } + + /* -------------------------------------------- */ + checkAndPrepareEquipments(listItem) { + for (let item of listItem) { + this.checkAndPrepareEquipment(item) + } + return listItem + } + + /* -------------------------------------------- */ + getWeapons() { + let comp = duplicate(this.items.filter(item => item.type == 'weapon') || []); + return comp; + } + /* -------------------------------------------- */ + getItemById(id) { + let item = this.items.find(item => item.id == id); + if (item) { + item = duplicate(item) + if (item.type == 'specialisation') { + item.system.dice = PegasusUtility.getDiceFromLevel(item.system.level); + } + } + return item; + } + + /* -------------------------------------------- */ + getSpecs() { + let comp = duplicate(this.items.filter(item => item.type == 'specialisation') || []); + for (let c of comp) { + c.system.dice = PegasusUtility.getDiceFromLevel(c.system.level); + } + return comp; } - return comp; -} /* -------------------------------------------- */ async manageWorstFear(flag) { - if (flag) { - let effect = await PegasusUtility.getEffectFromCompendium("Worst Fear") - effect.system.worstfear = true - this.createEmbeddedDocuments('Item', [effect]) - } else { - let effect = this.items.find(item => item.type == "effect" && item.system.worstfear) - if (effect) { - this.deleteEmbeddedDocuments('Item', [effect.id]) + if (flag) { + let effect = await PegasusUtility.getEffectFromCompendium("Worst Fear") + effect.system.worstfear = true + this.createEmbeddedDocuments('Item', [effect]) + } else { + let effect = this.items.find(item => item.type == "effect" && item.system.worstfear) + if (effect) { + this.deleteEmbeddedDocuments('Item', [effect.id]) + } } } -} /* -------------------------------------------- */ async manageDesires(flag) { - if (flag) { - let effect = await PegasusUtility.getEffectFromCompendium("Desire") - //console.log("EFFECT", effect) - effect.system.desires = true - this.createEmbeddedDocuments('Item', [effect]) - } else { - let effect = this.items.find(item => item.type == "effect" && item.system.desires) - if (effect) { - this.deleteEmbeddedDocuments('Item', [effect.id]) + if (flag) { + let effect = await PegasusUtility.getEffectFromCompendium("Desire") + //console.log("EFFECT", effect) + effect.system.desires = true + this.createEmbeddedDocuments('Item', [effect]) + } else { + let effect = this.items.find(item => item.type == "effect" && item.system.desires) + if (effect) { + this.deleteEmbeddedDocuments('Item', [effect.id]) + } } } -} -/* -------------------------------------------- */ -getRelevantSpec(statKey) { - let comp = duplicate(this.items.filter(item => item.type == 'specialisation' && item.system.statistic == statKey) || []); - for (let c of comp) { - c.system.dice = PegasusUtility.getDiceFromLevel(c.system.level); + /* -------------------------------------------- */ + getRelevantSpec(statKey) { + let comp = duplicate(this.items.filter(item => item.type == 'specialisation' && item.system.statistic == statKey) || []); + for (let c of comp) { + c.system.dice = PegasusUtility.getDiceFromLevel(c.system.level); + } + return comp; } - return comp; -} /* -------------------------------------------- */ async activatePerk(perkId) { - let item = this.items.find(item => item.id == perkId); - if (item && item.system) { - let update = { _id: item.id, "data.active": !item.system.active }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity + let item = this.items.find(item => item.id == perkId); + if (item && item.system) { + let update = { _id: item.id, "data.active": !item.system.active }; + await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity + } } -} /* -------------------------------------------- */ async activateViceOrVirtue(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let nrg = duplicate(this.system.nrg) - if (!item.system.activated) { // Current value + let item = this.items.find(item => item.id == itemId) + if (item && item.system) { + let nrg = duplicate(this.system.nrg) + if (!item.system.activated) { // Current value - let effects = [] - for (let effect of item.system.effectsgained) { - effect.system.powerId = itemId // Link to the perk, in order to dynamically remove them - effects.push(effect) - } - if (effects.length) { - await this.createEmbeddedDocuments('Item', effects) - } - } else { - let toRem = [] - for (let item of this.items) { - if (item.type == 'effect' && item.system.powerId == itemId) { - toRem.push(item.id) + let effects = [] + for (let effect of item.system.effectsgained) { + effect.system.powerId = itemId // Link to the perk, in order to dynamically remove them + effects.push(effect) + } + if (effects.length) { + await this.createEmbeddedDocuments('Item', effects) + } + } else { + let toRem = [] + for (let item of this.items) { + if (item.type == 'effect' && item.system.powerId == itemId) { + toRem.push(item.id) + } + } + if (toRem.length) { + await this.deleteEmbeddedDocuments('Item', toRem) } } - if (toRem.length) { - await this.deleteEmbeddedDocuments('Item', toRem) + let update = { _id: item.id, "data.activated": !item.system.activated } + await this.updateEmbeddedDocuments('Item', [update]) // Updates one EmbeddedEntity + } + } + + /* -------------------------------------------- */ + updatePPP() { + let ppp = 0 + for (let power of this.items) { + if (power.type == "power") { + ppp += Number(power.system.powerlevelcost) } } - let update = { _id: item.id, "data.activated": !item.system.activated } - await this.updateEmbeddedDocuments('Item', [update]) // Updates one EmbeddedEntity - } -} - -/* -------------------------------------------- */ -updatePPP() { - let ppp = 0 - for (let power of this.items) { - if (power.type == "power") { - ppp += Number(power.system.powerlevelcost) + if (ppp != this.system.ppp.spentPPP) { + this.update({ 'system.ppp.spentPPP': ppp }) } } - if (ppp != this.system.ppp.spentPPP) { - this.update({ 'system.ppp.spentPPP': ppp }) - } -} -/* -------------------------------------------- */ -updateSize() { - let sizeBonus = 0 - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.effectlevel > 0 && effect.system.affectsize) { - sizeBonus += effect.system.effectlevel + /* -------------------------------------------- */ + updateSize() { + let sizeBonus = 0 + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.effectlevel > 0 && effect.system.affectsize) { + sizeBonus += effect.system.effectlevel + } + } + if (sizeBonus != this.system.biodata.sizebonus) { + this.update({ 'system.biodata.sizebonus': sizeBonus }) } } - if (sizeBonus != this.system.biodata.sizebonus) { - this.update({ 'system.biodata.sizebonus': sizeBonus }) - } -} /* -------------------------------------------- */ async activatePower(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { + let item = this.items.find(item => item.id == itemId) + if (item && item.system) { - let nrg = duplicate(this.system.nrg) - if (!item.system.activated) { // Current value + let nrg = duplicate(this.system.nrg) + if (!item.system.activated) { // Current value - if (item.system.costspent > nrg.value || item.system.costspent > nrg.max) { - return ui.notifications.warn("Not enough NRG to activate the Power " + item.name) - } + if (item.system.costspent > nrg.value || item.system.costspent > nrg.max) { + return ui.notifications.warn("Not enough NRG to activate the Power " + item.name) + } - nrg.activated += item.system.costspent - nrg.value -= item.system.costspent - nrg.max -= item.system.costspent - await this.update({ 'system.nrg': nrg }) + nrg.activated += item.system.costspent + nrg.value -= item.system.costspent + nrg.max -= item.system.costspent + await this.update({ 'system.nrg': nrg }) - let effects = [] - for (let effect of item.system.effectsgained) { - effect.system.powerId = itemId // Link to the perk, in order to dynamically remove them - effects.push(effect) - } - if (effects.length) { - await this.createEmbeddedDocuments('Item', effects) - } - if (item.system.activatedtext.length > 0) { - ChatMessage.create({ content: `Power ${item.name} activated : ${item.system.activatedtext}` }) - } - } else { - nrg.activated -= item.system.costspent - nrg.max += item.system.costspent - await this.update({ 'system.nrg': nrg }) + let effects = [] + for (let effect of item.system.effectsgained) { + effect.system.powerId = itemId // Link to the perk, in order to dynamically remove them + effects.push(effect) + } + if (effects.length) { + await this.createEmbeddedDocuments('Item', effects) + } + if (item.system.activatedtext.length > 0) { + ChatMessage.create({ content: `Power ${item.name} activated : ${item.system.activatedtext}` }) + } + } else { + nrg.activated -= item.system.costspent + nrg.max += item.system.costspent + await this.update({ 'system.nrg': nrg }) - let toRem = [] - for (let item of this.items) { - if (item.type == 'effect' && item.system.powerId == itemId) { - toRem.push(item.id) + let toRem = [] + for (let item of this.items) { + if (item.type == 'effect' && item.system.powerId == itemId) { + toRem.push(item.id) + } + } + if (toRem.length) { + await this.deleteEmbeddedDocuments('Item', toRem) + } + if (item.system.deactivatedtext.length > 0) { + ChatMessage.create({ content: `Power ${item.name} deactivated : ${item.system.deactivatedtext}` }) } } - if (toRem.length) { - await this.deleteEmbeddedDocuments('Item', toRem) - } - if (item.system.deactivatedtext.length > 0) { - ChatMessage.create({ content: `Power ${item.name} deactivated : ${item.system.deactivatedtext}` }) - } + let update = { _id: item.id, "data.activated": !item.system.activated } + await this.updateEmbeddedDocuments('Item', [update]) // Updates one EmbeddedEntity } - let update = { _id: item.id, "data.activated": !item.system.activated } - await this.updateEmbeddedDocuments('Item', [update]) // Updates one EmbeddedEntity } -} /* -------------------------------------------- */ async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId); - if (item && item.system) { - let update = { _id: item.id, "data.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } -} - -/* -------------------------------------------- */ -compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; -} - -/* ------------------------------------------- */ -getEquipments() { - return this.items.filter(item => item.type == 'shield' || item.type == 'armor' || item.type == "weapon" || item.type == "equipment"); -} -/* ------------------------------------------- */ -getEquipmentsOnly() { - return duplicate(this.items.filter(item => item.type == "equipment") || []) -} - -/* ------------------------------------------- */ -computeThreatLevel() { - let tl = 0 - for (let key of statThreatLevel) { // Init with concerned stats - tl += PegasusUtility.getDiceValue(this.system.statistics[key].value) - } - let powers = duplicate(this.getPowers() || []) - if (powers.length > 0) { // Then add some mental ones of powers - tl += PegasusUtility.getDiceValue(this.system.statistics.foc.value) - tl += PegasusUtility.getDiceValue(this.system.statistics.mnd.value) - } - tl += PegasusUtility.getDiceValue(this.system.mr.value) - let specThreat = this.items.filter(it => it.type == "specialisation" && it.system.isthreatlevel) || [] - for (let spec of specThreat) { - tl += PegasusUtility.getDiceValue(spec.system.level) - } - tl += this.system.nrg.absolutemax + this.system.secondary.health.max + this.system.secondary.delirium.max - tl += this.getPerks().length * 5 - - let weapons = this.getWeapons() - for (let weapon of weapons) { - tl += PegasusUtility.getDiceValue(weapon.system.damage) - } - let armors = this.getArmors() - for (let armor of armors) { - tl += PegasusUtility.getDiceValue(armor.system.resistance) - } - let shields = duplicate(this.getShields()) - for (let shield of shields) { - tl += PegasusUtility.getDiceValue(shield.system.level) - } - let abilities = duplicate(this.getAbilities()) - for (let ability of abilities) { - tl += ability.system.threatlevel - } - let equipments = this.getEquipmentsOnly() - for (let equip of equipments) { - tl += equip.system.threatlevel - } - if (tl != this.system.biodata.threatlevel) { - this.update({ 'system.biodata.threatlevel': tl }) - } -} - - /* ------------------------------------------- */ - async buildContainerTree() { - let equipments = duplicate(this.items.filter(item => item.type == "equipment") || []) - for (let equip1 of equipments) { - if (equip1.system.iscontainer) { - equip1.system.contents = [] - equip1.system.contentsEnc = 0 - for (let equip2 of equipments) { - if (equip1._id != equip2._id && equip2.system.containerid == equip1._id) { - equip1.system.contents.push(equip2) - let q = equip2.system.quantity ?? 1 - equip1.system.contentsEnc += q * equip2.system.weight - } - } + let item = this.items.find(item => item.id == itemId); + if (item && item.system) { + let update = { _id: item.id, "data.equipped": !item.system.equipped }; + await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity } } - // Compute whole enc - let enc = 0 - for (let item of equipments) { - item.system.idrDice = PegasusUtility.getDiceFromLevel(Number(item.system.idr)) - if (item.system.equipped) { - if (item.system.iscontainer) { - enc += item.system.contentsEnc - } else if (item.system.containerid == "") { + /* -------------------------------------------- */ + compareName(a, b) { + if (a.name < b.name) { + return -1; + } + if (a.name > b.name) { + return 1; + } + return 0; + } + + /* ------------------------------------------- */ + getEquipments() { + return this.items.filter(item => item.type == 'shield' || item.type == 'armor' || item.type == "weapon" || item.type == "equipment"); + } + /* ------------------------------------------- */ + getEquipmentsOnly() { + return duplicate(this.items.filter(item => item.type == "equipment") || []) + } + + /* ------------------------------------------- */ + computeThreatLevel() { + let tl = 0 + for (let key of statThreatLevel) { // Init with concerned stats + tl += PegasusUtility.getDiceValue(this.system.statistics[key].value) + } + let powers = duplicate(this.getPowers() || []) + if (powers.length > 0) { // Then add some mental ones of powers + tl += PegasusUtility.getDiceValue(this.system.statistics.foc.value) + tl += PegasusUtility.getDiceValue(this.system.statistics.mnd.value) + } + tl += PegasusUtility.getDiceValue(this.system.mr.value) + let specThreat = this.items.filter(it => it.type == "specialisation" && it.system.isthreatlevel) || [] + for (let spec of specThreat) { + tl += PegasusUtility.getDiceValue(spec.system.level) + } + tl += this.system.nrg.absolutemax + this.system.secondary.health.max + this.system.secondary.delirium.max + tl += this.getPerks().length * 5 + + let weapons = this.getWeapons() + for (let weapon of weapons) { + tl += PegasusUtility.getDiceValue(weapon.system.damage) + } + let armors = this.getArmors() + for (let armor of armors) { + tl += PegasusUtility.getDiceValue(armor.system.resistance) + } + let shields = duplicate(this.getShields()) + for (let shield of shields) { + tl += PegasusUtility.getDiceValue(shield.system.level) + } + let abilities = duplicate(this.getAbilities()) + for (let ability of abilities) { + tl += ability.system.threatlevel + } + let equipments = this.getEquipmentsOnly() + for (let equip of equipments) { + tl += equip.system.threatlevel + } + if (tl != this.system.biodata.threatlevel) { + this.update({ 'system.biodata.threatlevel': tl }) + } + } + + /* ------------------------------------------- */ + async buildContainerTree() { + let equipments = duplicate(this.items.filter(item => item.type == "equipment") || []) + for (let equip1 of equipments) { + if (equip1.system.iscontainer) { + equip1.system.contents = [] + equip1.system.contentsEnc = 0 + for (let equip2 of equipments) { + if (equip1._id != equip2._id && equip2.system.containerid == equip1._id) { + equip1.system.contents.push(equip2) + let q = equip2.system.quantity ?? 1 + equip1.system.contentsEnc += q * equip2.system.weight + } + } + } + } + + // Compute whole enc + let enc = 0 + for (let item of equipments) { + item.system.idrDice = PegasusUtility.getDiceFromLevel(Number(item.system.idr)) + if (item.system.equipped) { + if (item.system.iscontainer) { + enc += item.system.contentsEnc + } else if (item.system.containerid == "") { + let q = item.system.quantity ?? 1 + enc += q * item.system.weight + } + } + } + for (let item of this.items) { // Process items/shields/armors + if ((item.type == "weapon" || item.type == "shield" || item.type == "armor") && item.system.equipped) { let q = item.system.quantity ?? 1 enc += q * item.system.weight } } - } - for (let item of this.items) { // Process items/shields/armors - if ((item.type == "weapon" || item.type == "shield" || item.type == "armor") && item.system.equipped) { - let q = item.system.quantity ?? 1 - enc += q * item.system.weight + + // Store local values + this.encCurrent = enc + this.containersTree = equipments.filter(item => item.system.containerid == "") // Returns the root of equipements without container + + // Manages slow effect + let overCapacity = Math.floor(this.encCurrent / this.getEncumbranceCapacity()) + this.encHindrance = Math.floor(this.encCurrent / this.getEncumbranceCapacity()) + + //console.log("Capacity", overCapacity, this.encCurrent / this.getEncumbranceCapacity() ) + let effect = this.items.find(item => item.type == "effect" && item.system.slow) + if (overCapacity >= 4) { + if (!effect) { + effect = await PegasusUtility.getEffectFromCompendium("Slowed") + effect.system.slow = true + this.createEmbeddedDocuments('Item', [effect]) + } + } else { + if (effect) { + this.deleteEmbeddedDocuments('Item', [effect.id]) + } } } - // Store local values - this.encCurrent = enc - this.containersTree = equipments.filter(item => item.system.containerid == "") // Returns the root of equipements without container - - // Manages slow effect - let overCapacity = Math.floor(this.encCurrent / this.getEncumbranceCapacity()) - this.encHindrance = Math.floor(this.encCurrent / this.getEncumbranceCapacity()) - - //console.log("Capacity", overCapacity, this.encCurrent / this.getEncumbranceCapacity() ) - let effect = this.items.find(item => item.type == "effect" && item.system.slow) - if (overCapacity >= 4) { - if (!effect) { - effect = await PegasusUtility.getEffectFromCompendium("Slowed") - effect.system.slow = true - this.createEmbeddedDocuments('Item', [effect]) + /* -------------------------------------------- */ + modifyStun(incDec) { + let combat = duplicate(this.system.combat) + combat.stunlevel += incDec + if (combat.stunlevel >= 0) { + this.update({ 'system.combat': combat }) + let chatData = { + user: game.user.id, + rollMode: game.settings.get("core", "rollMode"), + whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')) + } + if (incDec > 0) { + chatData.content = `
${this.name} suffered a Stun level.${this.name} recovered a Stun level. 0) { + ChatMessage.create({ content: `${this.name} Stun threshold has been exceeded.` }) + } + if (incDec > 0 && stunAbove > 0) { + let delirium = duplicate(this.system.secondary.delirium) + delirium.value -= incDec + this.update({ 'system.secondary.delirium': delirium }) } } -} -/* -------------------------------------------- */ -modifyStun(incDec) { - let combat = duplicate(this.system.combat) - combat.stunlevel += incDec - if (combat.stunlevel >= 0) { - this.update({ 'system.combat': combat }) + /* -------------------------------------------- */ + modifyMomentum(incDec) { + let momentum = duplicate(this.system.momentum) + momentum.value += incDec + this.update({ 'system.momentum': momentum }) let chatData = { user: game.user.id, rollMode: game.settings.get("core", "rollMode"), whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')) } if (incDec > 0) { - chatData.content = `
${this.name} suffered a Stun level.${this.name} has gained a Momentum${this.name} recovered a Stun level.${this.name} has used a Momentum= 0) { + PegasusUtility.showMomentumDialog(this.id) + } } - let stunAbove = combat.stunlevel - combat.stunthreshold - if (stunAbove > 0) { - ChatMessage.create({ content: `${this.name} Stun threshold has been exceeded.` }) - } - if (incDec > 0 && stunAbove > 0) { - let delirium = duplicate(this.system.secondary.delirium) - delirium.value -= incDec - this.update({ 'system.secondary.delirium': delirium }) - } -} -/* -------------------------------------------- */ -modifyMomentum(incDec) { - let momentum = duplicate(this.system.momentum) - momentum.value += incDec - this.update({ 'system.momentum': momentum }) - let chatData = { - user: game.user.id, - rollMode: game.settings.get("core", "rollMode"), - whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')) + /* -------------------------------------------- */ + getActiveEffects(matching = it => true) { + let array = Array.from(this.getEmbeddedCollection("ActiveEffect").values()); + return Array.from(this.getEmbeddedCollection("ActiveEffect").values()).filter(it => matching(it)); } - if (incDec > 0) { - chatData.content = `
${this.name} has gained a Momentum${this.name} has used a Momentum it.system.label == label); } - ChatMessage.create(chatData) - if (incDec < 0 && momentum.value >= 0) { - PegasusUtility.showMomentumDialog(this.id) + /* -------------------------------------------- */ + getEffectById(id) { + return this.getActiveEffects().find(it => it.id == id); } -} -/* -------------------------------------------- */ -getActiveEffects(matching = it => true) { - let array = Array.from(this.getEmbeddedCollection("ActiveEffect").values()); - return Array.from(this.getEmbeddedCollection("ActiveEffect").values()).filter(it => matching(it)); -} -/* -------------------------------------------- */ -getEffectByLabel(label) { - return this.getActiveEffects().find(it => it.system.label == label); -} -/* -------------------------------------------- */ -getEffectById(id) { - return this.getActiveEffects().find(it => it.id == id); -} - -/* -------------------------------------------- */ -getAttribute(attrKey) { - return this.system.attributes[attrKey]; -} + /* -------------------------------------------- */ + getAttribute(attrKey) { + return this.system.attributes[attrKey]; + } /* -------------------------------------------- */ async addObjectToContainer(itemId, containerId) { - let container = this.items.find(item => item.id == containerId && item.system.iscontainer) - let object = this.items.find(item => item.id == itemId) - if (container) { - if (object.system.iscontainer) { - ui.notifications.warn("Only 1 level of container allowed") - return + let container = this.items.find(item => item.id == containerId && item.system.iscontainer) + let object = this.items.find(item => item.id == itemId) + if (container) { + if (object.system.iscontainer) { + ui.notifications.warn("Only 1 level of container allowed") + return + } + let alreadyInside = this.items.filter(item => item.system.containerid && item.system.containerid == containerId); + if (alreadyInside.length >= container.system.containercapacity) { + ui.notifications.warn("Container is already full !") + return + } else { + await this.updateEmbeddedDocuments("Item", [{ _id: object.id, 'system.containerid': containerId }]) + } + } else if (object && object.system.containerid) { // remove from container + console.log("Removeing: ", object) + await this.updateEmbeddedDocuments("Item", [{ _id: object.id, 'system.containerid': "" }]); } - let alreadyInside = this.items.filter(item => item.system.containerid && item.system.containerid == containerId); - if (alreadyInside.length >= container.system.containercapacity) { - ui.notifications.warn("Container is already full !") - return - } else { - await this.updateEmbeddedDocuments("Item", [{ _id: object.id, 'system.containerid': containerId }]) - } - } else if (object && object.system.containerid) { // remove from container - console.log("Removeing: ", object) - await this.updateEmbeddedDocuments("Item", [{ _id: object.id, 'system.containerid': "" }]); } -} -/* -------------------------------------------- */ -checkVirtue(virtue) { - let vices = this.getVices() - for (let vice of vices) { - let nonVirtues = vice.system.unavailablevirtue - for (let blockedVirtue of nonVirtues) { - if (blockedVirtue.name.toLowerCase() == virtue.name.toLowerCase()) { - return false + /* -------------------------------------------- */ + checkVirtue(virtue) { + let vices = this.getVices() + for (let vice of vices) { + let nonVirtues = vice.system.unavailablevirtue + for (let blockedVirtue of nonVirtues) { + if (blockedVirtue.name.toLowerCase() == virtue.name.toLowerCase()) { + return false + } } } + return true } - return true -} -/* -------------------------------------------- */ -checkVice(vice) { - let virtues = this.getVirtues() - for (let virtue of virtues) { - let nonVices = virtue.system.unavailablevice - for (let blockedVice of nonVices) { - if (blockedVice.name.toLowerCase() == vice.name.toLowerCase()) { - return false + /* -------------------------------------------- */ + checkVice(vice) { + let virtues = this.getVirtues() + for (let virtue of virtues) { + let nonVices = virtue.system.unavailablevice + for (let blockedVice of nonVices) { + if (blockedVice.name.toLowerCase() == vice.name.toLowerCase()) { + return false + } } } + return true } - return true -} /* -------------------------------------------- */ async preprocessItem(event, item, onDrop = false) { - console.log("Pre-process", item) - if (item.type != "effect" && __isVehicle[item.type]) { - ui.notifications.warn("You can't drop Vehicles item over a character sheet.") - return - } + console.log("Pre-process", item) + if (item.type != "effect" && __isVehicle[item.type]) { + ui.notifications.warn("You can't drop Vehicles item over a character sheet.") + return + } - // Pre-filter effects - if (item.type == 'effect') { - if (this.checkMentalDisruption() && item.system.type == "mental" && item.system.genre == "positive") { - ChatMessage.create({ content: "Effects of this type cannot be applied while Disruption is applied, Use a Soft Action to remove Disruption" }) - return + // Pre-filter effects + if (item.type == 'effect') { + if (this.checkMentalDisruption() && item.system.type == "mental" && item.system.genre == "positive") { + ChatMessage.create({ content: "Effects of this type cannot be applied while Disruption is applied, Use a Soft Action to remove Disruption" }) + return + } + if (this.checkPhysicalDisruption() && item.system.type == "physical" && item.system.genre == "positive") { + ChatMessage.create({ content: "Effects of this type cannot be applied while Disruption is applied, Use a Soft Action to remove Disruption" }) + return + } + if (this.checkMentalImmunity() && item.system.type == "mental" && item.system.genre == "negative") { + ChatMessage.create({ content: "Effects of this type cannot be applied while Immunity is applied" }) + return + } + if (this.checkPhysicalImmunity() && item.system.type == "physical" && item.system.genre == "negative") { + ChatMessage.create({ content: "Effects of this type cannot be applied while Immunity is applied" }) + return + } } - if (this.checkPhysicalDisruption() && item.system.type == "physical" && item.system.genre == "positive") { - ChatMessage.create({ content: "Effects of this type cannot be applied while Disruption is applied, Use a Soft Action to remove Disruption" }) - return - } - if (this.checkMentalImmunity() && item.system.type == "mental" && item.system.genre == "negative") { - ChatMessage.create({ content: "Effects of this type cannot be applied while Immunity is applied" }) - return - } - if (this.checkPhysicalImmunity() && item.system.type == "physical" && item.system.genre == "negative") { - ChatMessage.create({ content: "Effects of this type cannot be applied while Immunity is applied" }) - return - } - } - if (item.type == 'race') { - this.applyRace(item) - } else if (item.type == 'role') { - this.applyRole(item) - } else if (item.type == 'ability') { - this.applyAbility(item, [], true) - if (!onDrop) { - await this.createEmbeddedDocuments('Item', [item]) + if (item.type == 'race') { + this.applyRace(item) + } else if (item.type == 'role') { + this.applyRole(item) + } else if (item.type == 'ability') { + this.applyAbility(item, [], true) + if (!onDrop) { + await this.createEmbeddedDocuments('Item', [item]) + } + } else { + if (!onDrop) { + await this.createEmbeddedDocuments('Item', [item]) + } } - } else { - if (!onDrop) { - await this.createEmbeddedDocuments('Item', [item]) + // Check virtue/vice validity + if (item.type == "virtue") { + if (!this.checkVirtue(item)) { + ui.notifications.info("Virtue is not allowed due to Vice.") + return false + } } - } - // Check virtue/vice validity - if (item.type == "virtue") { - if (!this.checkVirtue(item)) { - ui.notifications.info("Virtue is not allowed due to Vice.") - return false + if (item.type == "vice") { + if (!this.checkVice(item)) { + ui.notifications.info("Vice is not allowed due to Virtue.") + return false + } } - } - if (item.type == "vice") { - if (!this.checkVice(item)) { - ui.notifications.info("Vice is not allowed due to Virtue.") - return false + if (item.type == "power" && item.system.purchasedtext.length > 0) { + ChatMessage.create({ content: `Power ${item.name} puchased : ${item.system.purchasedtext}` }) } + let dropID = $(event.target).parents(".item").attr("data-item-id") // Only relevant if container drop + let objectID = item.id || item._id + this.addObjectToContainer(objectID, dropID) + return true } - if (item.type == "power" && item.system.purchasedtext.length > 0) { - ChatMessage.create({ content: `Power ${item.name} puchased : ${item.system.purchasedtext}` }) - } - let dropID = $(event.target).parents(".item").attr("data-item-id") // Only relevant if container drop - let objectID = item.id || item._id - this.addObjectToContainer(objectID, dropID) - return true -} /* -------------------------------------------- */ async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item && item.system) { - let update = { _id: item.id, "data.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } -} -/* -------------------------------------------- */ -getInitiativeScore(combatId, combatantId) { - if (this.type == 'character') { - this.rollMR(true, combatId, combatantId) - } - if (this.type == 'vehicle') { - this.rollMR(true, combatId, combatantId) - } - console.log("Init required !!!!") - return -1; -} - -/* -------------------------------------------- */ -getSubActors() { - let subActors = []; - if (this.system.subactors) { - for (let id of this.system.subactors) { - subActors.push(duplicate(game.actors.get(id))) + let item = this.items.find(item => item.id == equipmentId); + if (item && item.system) { + let update = { _id: item.id, "data.equipped": !item.system.equipped }; + await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity } } - return subActors; -} + /* -------------------------------------------- */ + getInitiativeScore(combatId, combatantId) { + if (this.type == 'character') { + this.rollMR(true, combatId, combatantId) + } + if (this.type == 'vehicle') { + this.rollMR(true, combatId, combatantId) + } + console.log("Init required !!!!") + return -1; + } + + /* -------------------------------------------- */ + getSubActors() { + let subActors = []; + if (this.system.subactors) { + for (let id of this.system.subactors) { + subActors.push(duplicate(game.actors.get(id))) + } + } + return subActors; + } /* -------------------------------------------- */ async addSubActor(subActorId) { - let subActors = duplicate(this.system.subactors || []); - subActors.push(subActorId); - await this.update({ 'system.subactors': subActors }); -} + let subActors = duplicate(this.system.subactors || []); + subActors.push(subActorId); + await this.update({ 'system.subactors': subActors }); + } /* -------------------------------------------- */ async delSubActor(subActorId) { - let newArray = []; - for (let id of this.system.subactors) { - if (id != subActorId) { - newArray.push(id); - } - } - await this.update({ 'system.subactors': newArray }); -} - -/* -------------------------------------------- */ -syncRoll(rollData) { - let linkedRollId = PegasusUtility.getDefenseState(this.id); - if (linkedRollId) { - rollData.linkedRollId = linkedRollId; - } - this.lastRollId = rollData.rollId; - PegasusUtility.saveRollData(rollData); -} - -/* -------------------------------------------- */ -getStat(statKey) { - let stat - if (this.type == "character" && statKey == 'mr') { - stat = duplicate(this.system.mr); - } else { - stat = duplicate(this.system.statistics[statKey]); - } - stat.dice = PegasusUtility.getDiceFromLevel(stat.value || stat.level); - return stat; -} - -/* -------------------------------------------- */ -getOneSpec(specId) { - let spec = this.items.find(item => item.type == 'specialisation' && item.id == specId) - if (spec) { - spec = duplicate(spec); - spec.system.dice = PegasusUtility.getDiceFromLevel(spec.system.level); - } - return spec; -} - -/* -------------------------------------------- */ -specPowerActivate(specId) { - let spec = this.getOneSpec(specId) - if (spec) { - let powers = [] - for (let power of spec.system.powers) { - if (power.data) { - power.system = power.data + let newArray = []; + for (let id of this.system.subactors) { + if (id != subActorId) { + newArray.push(id); } - power.system.specId = specId - powers.push(power) } - if (powers.length > 0) { - this.createEmbeddedDocuments('Item', powers) - } - this.updateEmbeddedDocuments('Item', [{ _id: specId, 'system.powersactivated': true }]) + await this.update({ 'system.subactors': newArray }); } -} -/* -------------------------------------------- */ -specPowerDeactivate(specId) { - let toRem = [] - for (let power of this.items) { - if (power.type == "power" && power.system.specId && power.system.specId == specId) { - toRem.push(power.id) + /* -------------------------------------------- */ + syncRoll(rollData) { + let linkedRollId = PegasusUtility.getDefenseState(this.id); + if (linkedRollId) { + rollData.linkedRollId = linkedRollId; } + this.lastRollId = rollData.rollId; + PegasusUtility.saveRollData(rollData); } - if (toRem.length > 0) { - this.deleteEmbeddedDocuments('Item', toRem) - } - this.updateEmbeddedDocuments('Item', [{ _id: specId, 'system.powersactivated': false }]) -} -/* -------------------------------------------- */ -equipActivate(itemId) { - let item = this.items.get(itemId) - if (item) { - let effects = [] - for (let effect of item.system.effects) { - effect.system.itemId = itemId // Keep link - effects.push(effect) + /* -------------------------------------------- */ + getStat(statKey) { + let stat + if (this.type == "character" && statKey == 'mr') { + stat = duplicate(this.system.mr); + } else { + stat = duplicate(this.system.statistics[statKey]); } - if (effects.length > 0) { - this.createEmbeddedDocuments('Item', effects) - } - this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.activated': true }]) + stat.dice = PegasusUtility.getDiceFromLevel(stat.value || stat.level); + return stat; } -} -/* -------------------------------------------- */ -equipDeactivate(itemId) { - let toRem = [] - for (let item of this.items) { - if (item.system.itemId && item.system.itemId == itemId) { - toRem.push(item.id) + /* -------------------------------------------- */ + getOneSpec(specId) { + let spec = this.items.find(item => item.type == 'specialisation' && item.id == specId) + if (spec) { + spec = duplicate(spec); + spec.system.dice = PegasusUtility.getDiceFromLevel(spec.system.level); + } + return spec; + } + + /* -------------------------------------------- */ + specPowerActivate(specId) { + let spec = this.getOneSpec(specId) + if (spec) { + let powers = [] + for (let power of spec.system.powers) { + if (power.data) { + power.system = power.data + } + power.system.specId = specId + powers.push(power) + } + if (powers.length > 0) { + this.createEmbeddedDocuments('Item', powers) + } + this.updateEmbeddedDocuments('Item', [{ _id: specId, 'system.powersactivated': true }]) } } - if (toRem.length > 0) { - this.deleteEmbeddedDocuments('Item', toRem) + + /* -------------------------------------------- */ + specPowerDeactivate(specId) { + let toRem = [] + for (let power of this.items) { + if (power.type == "power" && power.system.specId && power.system.specId == specId) { + toRem.push(power.id) + } + } + if (toRem.length > 0) { + this.deleteEmbeddedDocuments('Item', toRem) + } + this.updateEmbeddedDocuments('Item', [{ _id: specId, 'system.powersactivated': false }]) + } + + /* -------------------------------------------- */ + equipActivate(itemId) { + let item = this.items.get(itemId) + if (item) { + let effects = [] + for (let effect of item.system.effects) { + effect.system.itemId = itemId // Keep link + effects.push(effect) + } + if (effects.length > 0) { + this.createEmbeddedDocuments('Item', effects) + } + this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.activated': true }]) + } + } + + /* -------------------------------------------- */ + equipDeactivate(itemId) { + let toRem = [] + for (let item of this.items) { + if (item.system.itemId && item.system.itemId == itemId) { + toRem.push(item.id) + } + } + if (toRem.length > 0) { + this.deleteEmbeddedDocuments('Item', toRem) + } + this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.activated': false }]) } - this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.activated': false }]) -} /* -------------------------------------------- */ async perkEffectUsed(itemId) { - let effect = this.items.get(itemId) - if (effect) { - PegasusUtility.createChatWithRollMode(effect.name, { - content: await renderTemplate(`systems/fvtt-pegasus-rpg/templates/chat-effect-used.html`, effect.data) - }); + let effect = this.items.get(itemId) + if (effect) { + PegasusUtility.createChatWithRollMode(effect.name, { + content: await renderTemplate(`systems/fvtt-pegasus-rpg/templates/chat-effect-used.html`, effect.data) + }); - this.deleteEmbeddedDocuments('Item', [effect.id]) + this.deleteEmbeddedDocuments('Item', [effect.id]) + } } -} -/* -------------------------------------------- */ -disableWeaverPerk(perk) { - if (perk.system.isweaver) { - for (let spec of this.items) { - if (spec.type == 'specialisation' && spec.system.ispowergroup) { - this.specPowerDeactivate(spec.id) + /* -------------------------------------------- */ + disableWeaverPerk(perk) { + if (perk.system.isweaver) { + for (let spec of this.items) { + if (spec.type == 'specialisation' && spec.system.ispowergroup) { + this.specPowerDeactivate(spec.id) + } } } } -} -/* -------------------------------------------- */ -enableWeaverPerk(perk) { - if (perk.system.isweaver) { - for (let spec of this.items) { - if (spec.type == 'specialisation' && spec.system.ispowergroup) { - this.specPowerActivate(spec.id) + /* -------------------------------------------- */ + enableWeaverPerk(perk) { + if (perk.system.isweaver) { + for (let spec of this.items) { + if (spec.type == 'specialisation' && spec.system.ispowergroup) { + this.specPowerActivate(spec.id) + } } } } -} /* -------------------------------------------- */ async cleanPerkEffects(itemId) { - let effects = [] - for (let item of this.items) { - if (item.type == "effect" && item.system.perkId == itemId) { - effects.push(item.id) + let effects = [] + for (let item of this.items) { + if (item.type == "effect" && item.system.perkId == itemId) { + effects.push(item.id) + } + } + if (effects.length > 0) { + console.log("DELET!!!!", effects, this) + await this.deleteEmbeddedDocuments('Item', effects) } } - if (effects.length > 0) { - console.log("DELET!!!!", effects, this) - await this.deleteEmbeddedDocuments('Item', effects) - } -} /* -------------------------------------------- */ async updatePerkUsed(itemId, index, checked) { - let item = this.items.get(itemId) - if (item && index) { - let key = "data.used" + index - await this.updateEmbeddedDocuments('Item', [{ _id: itemId, [`${key}`]: checked }]) - item = this.items.get(itemId) // Refresh - if (item.system.nbuse == "next1action" && item.system.used1) { - this.cleanPerkEffects(itemId) - } - if (item.system.nbuse == "next2action" && item.system.used1 && item.system.used2) { - this.cleanPerkEffects(itemId) - } - if (item.system.nbuse == "next3action" && item.system.used1 && item.system.used2 && item.system.used3) { - this.cleanPerkEffects(itemId) + let item = this.items.get(itemId) + if (item && index) { + let key = "data.used" + index + await this.updateEmbeddedDocuments('Item', [{ _id: itemId, [`${key}`]: checked }]) + item = this.items.get(itemId) // Refresh + if (item.system.nbuse == "next1action" && item.system.used1) { + this.cleanPerkEffects(itemId) + } + if (item.system.nbuse == "next2action" && item.system.used1 && item.system.used2) { + this.cleanPerkEffects(itemId) + } + if (item.system.nbuse == "next3action" && item.system.used1 && item.system.used2 && item.system.used3) { + this.cleanPerkEffects(itemId) + } } } -} /* -------------------------------------------- */ async updatePowerSpentCost(itemId, value) { - let item = this.items.get(itemId) - if (item && value) { - value = Number(value) || 0 - await this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.costspent': value }]) + let item = this.items.get(itemId) + if (item && value) { + value = Number(value) || 0 + await this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.costspent': value }]) + } } -} /* -------------------------------------------- */ async cleanupPerksIfTrauma() { - if (this.getTraumaState() == "severetrauma") { - for (let perk of this.items) { - if (perk.type == "perk") { - this.cleanPerkEffects(perk.id) - this.updateEmbeddedDocuments('Item', [{ _id: perk.id, 'system.status': "ready", 'system.used1': false, 'system.used2': false, 'system.used3': false }]) - ChatMessage.create({ content: `Perk ${perk.name} has been deactivated due to Severe Trauma state !` }) + if (this.getTraumaState() == "severetrauma") { + for (let perk of this.items) { + if (perk.type == "perk") { + this.cleanPerkEffects(perk.id) + this.updateEmbeddedDocuments('Item', [{ _id: perk.id, 'system.status': "ready", 'system.used1': false, 'system.used2': false, 'system.used3': false }]) + ChatMessage.create({ content: `Perk ${perk.name} has been deactivated due to Severe Trauma state !` }) + } } } } -} -/* -------------------------------------------- */ -incDecNRG(value) { - if (this.type == "character") { - let nrg = duplicate(this.system.nrg) - nrg.value += value - if (nrg.value >= 0 && nrg.value <= nrg.max) { - this.update({ 'system.nrg': nrg }) - } - } else { - let pc = duplicate(this.system.statistics.pc) - pc.curnrg += value - if (pc.curnrg >= 0 && pc.curnrg <= pc.maxnrg) { - this.update({ 'system.statistics.pc': pc }) + /* -------------------------------------------- */ + incDecNRG(value) { + if (this.type == "character") { + let nrg = duplicate(this.system.nrg) + nrg.value += value + if (nrg.value >= 0 && nrg.value <= nrg.max) { + this.update({ 'system.nrg': nrg }) + } + } else { + let pc = duplicate(this.system.statistics.pc) + pc.curnrg += value + if (pc.curnrg >= 0 && pc.curnrg <= pc.maxnrg) { + this.update({ 'system.statistics.pc': pc }) + } } } -} /* -------------------------------------------- */ async updatePerkStatus(itemId, status) { - let item = this.items.get(itemId) - if (item) { + let item = this.items.get(itemId) + if (item) { - if (item.system.status == status) return;// Ensure we are really changing the status - if (this.checkNoPerksAllowed()) { - await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.status': "ready" }]) - ChatMessage.create({ content: "No perks activation allowed due to effect !" }) - return - } + if (item.system.status == status) return;// Ensure we are really changing the status + if (this.checkNoPerksAllowed()) { + await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.status': "ready" }]) + ChatMessage.create({ content: "No perks activation allowed due to effect !" }) + return + } - // Severe Trauma management - if (this.getTraumaState() == "severetrauma") { - if (!this.severeTraumaMessage) { - let chatData = { - user: game.user.id, - rollMode: game.settings.get("core", "rollMode"), - whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')) + // Severe Trauma management + if (this.getTraumaState() == "severetrauma") { + if (!this.severeTraumaMessage) { + let chatData = { + user: game.user.id, + rollMode: game.settings.get("core", "rollMode"), + whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')) + } + chatData.content = `
${this.name} is suffering from Severe Trauma and cannot use Perks at this time.${this.name} is suffering from Severe Trauma and cannot use Perks at this time.= item.system.features.nrgcost.value) && (this.system.nrg.max >= item.system.features.nrgcost.value)) { + let updateOK = true + if (status == "ready") { + await this.cleanPerkEffects(itemId) + await this.updateEmbeddedDocuments('Item', [{ _id: itemId, 'system.used1': false, 'system.used2': false, 'system.used3': false }]) + if (item.system.features.nrgcost.flag) { let nrg = duplicate(this.system.nrg) - nrg.activated += item.system.features.nrgcost.value - nrg.value -= item.system.features.nrgcost.value - nrg.max -= item.system.features.nrgcost.value + nrg.activated -= item.system.features.nrgcost.value + nrg.max += item.system.features.nrgcost.value await this.update({ 'system.nrg': nrg }) - } else { - updateOK = false - ui.notifications.warn("Not enough NRG to activate the Perk " + item.name) } + if (item.system.features.bonushealth.flag) { + let health = duplicate(this.system.secondary.health) + health.value -= Number(item.system.features.bonushealth.value) || 0 + health.max -= Number(item.system.features.bonushealth.value) || 0 + await this.update({ 'system.secondary.health': health }) + } + if (item.system.features.bonusdelirium.flag) { + let delirium = duplicate(this.system.secondary.delirium) + delirium.value -= Number(item.system.features.bonusdelirium.value) || 0 + delirium.max -= Number(item.system.features.bonusdelirium.value) || 0 + await this.update({ 'system.secondary.delirium': delirium }) + } + if (item.system.features.bonusnrg.flag) { + let nrg = duplicate(this.system.nrg) + nrg.value -= Number(item.system.features.bonusnrg.value) || 0 + nrg.max -= Number(item.system.features.bonusnrg.value) || 0 + await this.update({ 'system.nrg': nrg }) + } + this.disableWeaverPerk(item) + PegasusUtility.createChatWithRollMode(item.name, { + content: await renderTemplate(`systems/fvtt-pegasus-rpg/templates/chat-perk-ready.html`, { name: this.name, perk: duplicate(item) }) + }) } - if (item.system.features.bonushealth.flag) { - let health = duplicate(this.system.secondary.health) - health.value += Number(item.system.features.bonushealth.value) || 0 - health.max += Number(item.system.features.bonushealth.value) || 0 - await this.update({ 'system.secondary.health': health }) + if (status == "activated") { + // Add effects linked to the perk + let effects = [] + for (let effect of item.system.effectsgained) { + if (effect.data) { + effect.system = effect.data + } + effect.system.perkId = itemId // Link to the perk, in order to dynamically remove them + effect.system.isUsed = false // Flag to indicate removal when used in a roll window + effects.push(effect) + } + if (effects.length) { + await this.createEmbeddedDocuments('Item', effects) + } + // Manage additional flags + if (item.system.features.nrgcost.flag) { + if ((this.system.nrg.value >= item.system.features.nrgcost.value) && (this.system.nrg.max >= item.system.features.nrgcost.value)) { + let nrg = duplicate(this.system.nrg) + nrg.activated += item.system.features.nrgcost.value + nrg.value -= item.system.features.nrgcost.value + nrg.max -= item.system.features.nrgcost.value + await this.update({ 'system.nrg': nrg }) + } else { + updateOK = false + ui.notifications.warn("Not enough NRG to activate the Perk " + item.name) + } + } + if (item.system.features.bonushealth.flag) { + let health = duplicate(this.system.secondary.health) + health.value += Number(item.system.features.bonushealth.value) || 0 + health.max += Number(item.system.features.bonushealth.value) || 0 + await this.update({ 'system.secondary.health': health }) + } + if (item.system.features.bonusdelirium.flag) { + let delirium = duplicate(this.system.secondary.delirium) + delirium.value += Number(item.system.features.bonusdelirium.value) || 0 + delirium.max += Number(item.system.features.bonusdelirium.value) || 0 + await this.update({ 'system.secondary.delirium': delirium }) + } + if (item.system.features.bonusnrg.flag) { + let nrg = duplicate(this.system.nrg) + nrg.value += Number(item.system.features.bonusnrg.value) || 0 + nrg.max += Number(item.system.features.bonusnrg.value) || 0 + await this.update({ 'system.nrg': nrg }) + } + PegasusUtility.createChatWithRollMode(item.name, { + content: await renderTemplate(`systems/fvtt-pegasus-rpg/templates/chat-perk-activated.html`, { name: this.name, perk: duplicate(item) }) + }) + this.enableWeaverPerk(item) } - if (item.system.features.bonusdelirium.flag) { - let delirium = duplicate(this.system.secondary.delirium) - delirium.value += Number(item.system.features.bonusdelirium.value) || 0 - delirium.max += Number(item.system.features.bonusdelirium.value) || 0 - await this.update({ 'system.secondary.delirium': delirium }) + if (updateOK) { + await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.status': status }]) } - if (item.system.features.bonusnrg.flag) { - let nrg = duplicate(this.system.nrg) - nrg.value += Number(item.system.features.bonusnrg.value) || 0 - nrg.max += Number(item.system.features.bonusnrg.value) || 0 - await this.update({ 'system.nrg': nrg }) - } - PegasusUtility.createChatWithRollMode(item.name, { - content: await renderTemplate(`systems/fvtt-pegasus-rpg/templates/chat-perk-activated.html`, { name: this.name, perk: duplicate(item) }) - }) - this.enableWeaverPerk(item) - } - if (updateOK) { - await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.status': status }]) } } -} /* -------------------------------------------- */ async deleteAllItemsByType(itemType) { - let items = this.items.filter(item => item.type == itemType); - await this.deleteEmbeddedDocuments('Item', items); -} + let items = this.items.filter(item => item.type == itemType); + await this.deleteEmbeddedDocuments('Item', items); + } /* -------------------------------------------- */ async addItemWithoutDuplicate(newItem) { - let item = this.items.find(item => item.type == newItem.type && item.name.toLowerCase() == newItem.name.toLowerCase()) - if (!item) { - await this.createEmbeddedDocuments('Item', [newItem]); + let item = this.items.find(item => item.type == newItem.type && item.name.toLowerCase() == newItem.name.toLowerCase()) + if (!item) { + await this.createEmbeddedDocuments('Item', [newItem]); + } } -} -/* -------------------------------------------- */ -getTraumaState() { - this.traumaState = "none" - if (this.type == "character") { - let negDelirium = -Math.floor((this.system.secondary.delirium.max + 1) / 2) + /* -------------------------------------------- */ + getTraumaState() { + this.traumaState = "none" if (this.type == "character") { - if (this.system.secondary.delirium.value <= 0 && this.system.secondary.delirium.value >= negDelirium) { - this.traumaState = "trauma" + let negDelirium = -Math.floor((this.system.secondary.delirium.max + 1) / 2) + if (this.type == "character") { + if (this.system.secondary.delirium.value <= 0 && this.system.secondary.delirium.value >= negDelirium) { + this.traumaState = "trauma" + } + if (this.system.secondary.delirium.value < negDelirium) { + this.traumaState = "severetrauma" + } } - if (this.system.secondary.delirium.value < negDelirium) { - this.traumaState = "severetrauma" + } + return this.traumaState + } + + /* -------------------------------------------- */ + getLevelRemaining() { + return this.system.biodata?.currentlevelremaining || 0 + } + /* -------------------------------------------- */ + modifyHeroLevelRemaining(incDec) { + let biodata = duplicate(this.system.biodata) + biodata.currentlevelremaining = Math.max(biodata.currentlevelremaining + incDec, 0) + this.update({ "system.biodata": biodata }) + ChatMessage.create({ content: `${this.name} has used a Hero Level to reroll !` }) + return biodata.currentlevelremaining + } + + /* -------------------------------------------- */ + checkIgnoreHealth() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.ignorehealthpenalty) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkMentalDisruption() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.mentaldisruption) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkPhysicalDisruption() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.physicaldisruption) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkMentalImmunity() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.mentalimmunity) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkPhysicalImmunity() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.physicalimmunity) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkNoBonusDice() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.nobonusdice) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkNoPerksAllowed() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.noperksallowed) { + return true + } + } + return false + } + /* -------------------------------------------- */ + checkIfPossible() { + for (let effect of this.items) { + if (effect.type == "effect" && effect.system.isthispossible.length > 0) { + ChatMessage.create({ content: effect.system.isthispossible }) } } } - return this.traumaState -} - -/* -------------------------------------------- */ -getLevelRemaining() { - return this.system.biodata?.currentlevelremaining || 0 -} -/* -------------------------------------------- */ -modifyHeroLevelRemaining(incDec) { - let biodata = duplicate(this.system.biodata) - biodata.currentlevelremaining = Math.max(biodata.currentlevelremaining + incDec, 0) - this.update({ "system.biodata": biodata }) - ChatMessage.create({ content: `${this.name} has used a Hero Level to reroll !` }) - return biodata.currentlevelremaining -} - -/* -------------------------------------------- */ -checkIgnoreHealth() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.ignorehealthpenalty) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkMentalDisruption() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.mentaldisruption) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkPhysicalDisruption() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.physicaldisruption) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkMentalImmunity() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.mentalimmunity) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkPhysicalImmunity() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.physicalimmunity) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkNoBonusDice() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.nobonusdice) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkNoPerksAllowed() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.noperksallowed) { - return true - } - } - return false -} -/* -------------------------------------------- */ -checkIfPossible() { - for (let effect of this.items) { - if (effect.type == "effect" && effect.system.isthispossible.length > 0) { - ChatMessage.create({ content: effect.system.isthispossible }) - } - } -} /* -------------------------------------------- */ async computeNRGHealth() { - if (this.isOwner || game.user.isGM) { - let updates = {} - let phyDiceValue = PegasusUtility.getDiceValue(this.system.statistics.phy.value) + this.system.secondary.health.bonus + this.system.statistics.phy.mod; - if (phyDiceValue != this.system.secondary.health.max) { - updates['system.secondary.health.max'] = phyDiceValue - } - if (this.computeValue) { - updates['system.secondary.health.value'] = phyDiceValue - } - let mndDiceValue = PegasusUtility.getDiceValue(this.system.statistics.mnd.value) + this.system.secondary.delirium.bonus + this.system.statistics.mnd.mod; - if (mndDiceValue != this.system.secondary.delirium.max) { - updates['system.secondary.delirium.max'] = mndDiceValue - } - if (this.computeValue) { - updates['system.secondary.delirium.value'] = mndDiceValue - } - let stlDiceValue = PegasusUtility.getDiceValue(this.system.statistics.stl.value) + this.system.secondary.stealthhealth.bonus + this.system.statistics.stl.mod; - if (stlDiceValue != this.system.secondary.stealthhealth.max) { - updates['system.secondary.stealthhealth.max'] = stlDiceValue - } - if (this.computeValue) { - updates['system.secondary.stealthhealth.value'] = stlDiceValue - } - - let socDiceValue = PegasusUtility.getDiceValue(this.system.statistics.soc.value) + this.system.secondary.socialhealth.bonus + this.system.statistics.soc.mod; - if (socDiceValue != this.system.secondary.socialhealth.max) { - updates['system.secondary.socialhealth.max'] = socDiceValue - } - if (this.computeValue) { - updates['system.secondary.socialhealth.value'] = socDiceValue - } - - let nrgValue = PegasusUtility.getDiceValue(this.system.statistics.foc.value) + this.system.nrg.mod + this.system.statistics.foc.mod - if (nrgValue != this.system.nrg.absolutemax) { - updates['system.nrg.absolutemax'] = nrgValue - } - if (this.computeValue) { - updates['system.nrg.max'] = nrgValue - updates['system.nrg.value'] = nrgValue - } - - let stunth = PegasusUtility.getDiceValue(this.system.statistics.phy.value) + PegasusUtility.getDiceValue(this.system.statistics.mnd.value) + PegasusUtility.getDiceValue(this.system.statistics.foc.value) - + this.system.statistics.mnd.mod + this.system.statistics.phy.mod + this.system.statistics.foc.mod - if (stunth != this.system.combat.stunthreshold) { - updates['system.combat.stunthreshold'] = stunth - } - - let momentum = this.system.statistics.foc.value + this.system.statistics.foc.mod - if (momentum != this.system.momentum.max) { - updates['system.momentum.value'] = 0 - updates['system.momentum.max'] = momentum - } - - let mrLevel = (this.system.statistics.agi.value + this.system.statistics.str.value) - this.system.statistics.phy.value - mrLevel = (mrLevel < 1) ? 1 : mrLevel; - if (mrLevel != this.system.mr.value) { - updates['system.mr.value'] = mrLevel - } - - let moralitythreshold = - (Number(PegasusUtility.getDiceValue(this.system.statistics.foc.value)) + Number(this.system.statistics.foc.mod)) - if (moralitythreshold != this.system.biodata.moralitythreshold) { - updates['system.biodata.moralitythreshold'] = moralitythreshold - } - if (!this.isToken) { - if (this.warnMorality != this.system.biodata.morality && this.system.biodata.morality < 0) { - console.log("CHAR", this) - ChatMessage.create({ content: "WARNING: Your character is dangerously close to becoming corrupted and defeated. Start on a path of redemption!" }) + if (this.isOwner || game.user.isGM) { + let updates = {} + let phyDiceValue = PegasusUtility.getDiceValue(this.system.statistics.phy.value) + this.system.secondary.health.bonus + this.system.statistics.phy.mod; + if (phyDiceValue != this.system.secondary.health.max) { + updates['system.secondary.health.max'] = phyDiceValue } - if (this.warnMorality != this.system.biodata.morality) { - this.warnMorality = this.system.biodata.morality + if (this.computeValue) { + updates['system.secondary.health.value'] = phyDiceValue + } + let mndDiceValue = PegasusUtility.getDiceValue(this.system.statistics.mnd.value) + this.system.secondary.delirium.bonus + this.system.statistics.mnd.mod; + if (mndDiceValue != this.system.secondary.delirium.max) { + updates['system.secondary.delirium.max'] = mndDiceValue + } + if (this.computeValue) { + updates['system.secondary.delirium.value'] = mndDiceValue + } + let stlDiceValue = PegasusUtility.getDiceValue(this.system.statistics.stl.value) + this.system.secondary.stealthhealth.bonus + this.system.statistics.stl.mod; + if (stlDiceValue != this.system.secondary.stealthhealth.max) { + updates['system.secondary.stealthhealth.max'] = stlDiceValue + } + if (this.computeValue) { + updates['system.secondary.stealthhealth.value'] = stlDiceValue } - } - let race = this.getRace() - if (race && race.name && (race.name != this.system.biodata.racename)) { - updates['system.biodata.racename'] = race.name - } - let role = this.getRole() - if (role && role.name && (role.name != this.system.biodata.rolename)) { - updates['system.biodata.rolename'] = role.name - } - if (Object.entries(updates).length > 0) { - await this.update(updates) - } - this.computeThreatLevel() - } + let socDiceValue = PegasusUtility.getDiceValue(this.system.statistics.soc.value) + this.system.secondary.socialhealth.bonus + this.system.statistics.soc.mod; + if (socDiceValue != this.system.secondary.socialhealth.max) { + updates['system.secondary.socialhealth.max'] = socDiceValue + } + if (this.computeValue) { + updates['system.secondary.socialhealth.value'] = socDiceValue + } - if (this.isOwner || game.user.isGM) { - // Update current hindrance level - let hindrance = this.system.combat.hindrancedice - if (!this.checkIgnoreHealth()) { - if (this.system.secondary.health.value < 0) { - if (this.system.secondary.health.value < -Math.floor((this.system.secondary.health.max + 1) / 2)) { // Severe wounded - hindrance += 3 - } else { - hindrance += 1 + let nrgValue = PegasusUtility.getDiceValue(this.system.statistics.foc.value) + this.system.nrg.mod + this.system.statistics.foc.mod + if (nrgValue != this.system.nrg.absolutemax) { + updates['system.nrg.absolutemax'] = nrgValue + } + if (this.computeValue) { + updates['system.nrg.max'] = nrgValue + updates['system.nrg.value'] = nrgValue + } + + let stunth = PegasusUtility.getDiceValue(this.system.statistics.phy.value) + PegasusUtility.getDiceValue(this.system.statistics.mnd.value) + PegasusUtility.getDiceValue(this.system.statistics.foc.value) + + this.system.statistics.mnd.mod + this.system.statistics.phy.mod + this.system.statistics.foc.mod + if (stunth != this.system.combat.stunthreshold) { + updates['system.combat.stunthreshold'] = stunth + } + + let momentum = this.system.statistics.foc.value + this.system.statistics.foc.mod + if (momentum != this.system.momentum.max) { + updates['system.momentum.value'] = 0 + updates['system.momentum.max'] = momentum + } + + let mrLevel = (this.system.statistics.agi.value + this.system.statistics.str.value) - this.system.statistics.phy.value + mrLevel = (mrLevel < 1) ? 1 : mrLevel; + if (mrLevel != this.system.mr.value) { + updates['system.mr.value'] = mrLevel + } + + let moralitythreshold = - (Number(PegasusUtility.getDiceValue(this.system.statistics.foc.value)) + Number(this.system.statistics.foc.mod)) + if (moralitythreshold != this.system.biodata.moralitythreshold) { + updates['system.biodata.moralitythreshold'] = moralitythreshold + } + if (!this.isToken) { + if (this.warnMorality != this.system.biodata.morality && this.system.biodata.morality < 0) { + console.log("CHAR", this) + ChatMessage.create({ content: "WARNING: Your character is dangerously close to becoming corrupted and defeated. Start on a path of redemption!" }) + } + if (this.warnMorality != this.system.biodata.morality) { + this.warnMorality = this.system.biodata.morality } } - } - this.system.combat.hindrancedice = hindrance - this.getTraumaState() - this.cleanupPerksIfTrauma() - this.parseStatEffects() - this.parseStatusEffects() - } -} -/* -------------------------------------------- */ -parseStatEffects() { - if ( this.system.biodata.noautobonus) { // If we are in "no-bonus mode - return + let race = this.getRace() + if (race && race.name && (race.name != this.system.biodata.racename)) { + updates['system.biodata.racename'] = race.name + } + let role = this.getRole() + if (role && role.name && (role.name != this.system.biodata.rolename)) { + updates['system.biodata.rolename'] = role.name + } + if (Object.entries(updates).length > 0) { + await this.update(updates) + } + this.computeThreatLevel() + } + + if (this.isOwner || game.user.isGM) { + // Update current hindrance level + let hindrance = this.system.combat.hindrancedice + if (!this.checkIgnoreHealth()) { + if (this.system.secondary.health.value < 0) { + if (this.system.secondary.health.value < -Math.floor((this.system.secondary.health.max + 1) / 2)) { // Severe wounded + hindrance += 3 + } else { + hindrance += 1 + } + } + } + this.system.combat.hindrancedice = hindrance + this.getTraumaState() + this.cleanupPerksIfTrauma() + this.parseStatEffects() + this.parseStatusEffects() + } } - let effects = this.items.filter(effect => effect.type == "effect" && effect.system.genre == "positive" && effect.system.statdice) - for (let statKey in this.system.statistics) { - let stat = duplicate(this.system.statistics[statKey]) + + /* -------------------------------------------- */ + parseStatEffects() { + if (this.system.biodata.noautobonus) { // If we are in "no-bonus mode + return + } + let effects = this.items.filter(effect => effect.type == "effect" && effect.system.genre == "positive" && effect.system.statdice) + for (let statKey in this.system.statistics) { + let stat = duplicate(this.system.statistics[statKey]) + let bonus = 0 + for (let effect of effects) { + if (effect.system.stataffected == statKey) { + bonus += Number(effect.system.effectlevel) + } + } + if (bonus != stat.bonuseffect) { + stat.bonuseffect = bonus + this.update({ [`system.statistics.${statKey}`]: stat }) + } + } + } + + /* -------------------------------------------- */ + parseStatusEffects() { + if (this.system.biodata.noautobonus) { // If we are in "no-bonus mode + return + } + let effects = this.items.filter(effect => effect.type == "effect" && effect.system.affectstatus && (Number(effect.system.effectlevel) > 0)) + for (let statusKey in this.system.secondary) { + let status = duplicate(this.system.secondary[statusKey]) + let bonus = 0 + for (let effect of effects) { + if (effect.system.affectedstatus && effect.system.affectedstatus == statusKey) { + bonus += Number(effect.system.effectlevel) + } + } + if (bonus != status.bonus) { + status.bonus = bonus + this.update({ [`system.secondary.${statusKey}`]: status }) + } + } + + let nrg = duplicate(this.system.nrg) let bonus = 0 for (let effect of effects) { - if (effect.system.stataffected == statKey) { + if (effect.system.affectedstatus && effect.system.affectedstatus == "nrg") { bonus += Number(effect.system.effectlevel) } } - if (bonus != stat.bonuseffect) { - stat.bonuseffect = bonus - this.update({ [`system.statistics.${statKey}`]: stat }) + if (bonus != nrg.mod) { + nrg.mod = bonus + this.update({ [`system.nrg`]: nrg }) } - } -} -/* -------------------------------------------- */ -parseStatusEffects() { - if ( this.system.biodata.noautobonus) { // If we are in "no-bonus mode - return } - let effects = this.items.filter(effect => effect.type == "effect" && effect.system.affectstatus && (Number(effect.system.effectlevel) > 0)) - for (let statusKey in this.system.secondary) { - let status = duplicate(this.system.secondary[statusKey]) - let bonus = 0 - for (let effect of effects) { - if (effect.system.affectedstatus && effect.system.affectedstatus == statusKey) { - bonus += Number(effect.system.effectlevel) - } - } - if (bonus != status.bonus) { - status.bonus = bonus - this.update({ [`system.secondary.${statusKey}`]: status }) - } - } - - let nrg = duplicate(this.system.nrg) - let bonus = 0 - for (let effect of effects) { - if (effect.system.affectedstatus && effect.system.affectedstatus == "nrg") { - bonus += Number(effect.system.effectlevel) - } - } - if (bonus != nrg.mod) { - nrg.mod = bonus - this.update({ [`system.nrg`]: nrg }) - } - -} /* -------------------------------------------- */ async modStat(key, inc = 1) { - let stat = duplicate(this.system.statistics[key]) - stat.mod += parseInt(inc) - await this.update({ [`data.statistics.${key}`]: stat }) -} + let stat = duplicate(this.system.statistics[key]) + stat.mod += parseInt(inc) + await this.update({ [`data.statistics.${key}`]: stat }) + } /* -------------------------------------------- */ async valueStat(key, inc = 1) { - key = key.toLowerCase() - let stat = duplicate(this.system.statistics[key]) - stat.value += parseInt(inc) - await this.update({ [`data.statistics.${key}`]: stat }) -} + key = key.toLowerCase() + let stat = duplicate(this.system.statistics[key]) + stat.value += parseInt(inc) + await this.update({ [`data.statistics.${key}`]: stat }) + } /* -------------------------------------------- */ async addIncSpec(spec, inc = 1) { - console.log("Using spec : ", spec, inc) - let specExist = this.items.find(item => item.type == 'specialisation' && item.name.toLowerCase() == spec.name.toLowerCase()) - if (specExist) { - specExist = duplicate(specExist) - specExist.system.level += inc; - let update = { _id: specExist._id, "data.level": specExist.system.level }; - await this.updateEmbeddedDocuments('Item', [update]); - } else { - spec.system.level += inc; - await this.createEmbeddedDocuments('Item', [spec]); + console.log("Using spec : ", spec, inc) + let specExist = this.items.find(item => item.type == 'specialisation' && item.name.toLowerCase() == spec.name.toLowerCase()) + if (specExist) { + specExist = duplicate(specExist) + specExist.system.level += inc; + let update = { _id: specExist._id, "data.level": specExist.system.level }; + await this.updateEmbeddedDocuments('Item', [update]); + } else { + spec.system.level += inc; + await this.createEmbeddedDocuments('Item', [spec]); + } } -} /* -------------------------------------------- */ async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantity + incDec - if (newQ >= 0) { - const updated = await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantity': newQ }]) // pdates one EmbeddedEntity + let objetQ = this.items.get(objetId) + if (objetQ) { + let newQ = objetQ.system.quantity + incDec + if (newQ >= 0) { + const updated = await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantity': newQ }]) // pdates one EmbeddedEntity + } } } -} /* -------------------------------------------- */ async incDecAmmo(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.ammocurrent + incDec; - if (newQ >= 0 && newQ <= objetQ.system.ammomax) { - const updated = await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.ammocurrent': newQ }]); // pdates one EmbeddedEntity + let objetQ = this.items.get(objetId) + if (objetQ) { + let newQ = objetQ.system.ammocurrent + incDec; + if (newQ >= 0 && newQ <= objetQ.system.ammomax) { + const updated = await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.ammocurrent': newQ }]); // pdates one EmbeddedEntity + } } } -} /* -------------------------------------------- */ async applyAbility(ability, updates = [], directUpdate = false) { - // manage stat bonus - if (ability.system.affectedstat != "notapplicable") { - let stat = duplicate(this.system.statistics[ability.system.affectedstat]) - stat.mod += Number(ability.system.statmodifier) - updates[`system.statistics.${ability.system.affectedstat}`] = stat - } - // manage status bonus - if (ability.system.statusaffected != "notapplicable") { - if (ability.system.statusaffected == 'nrg') { - let nrg = duplicate(this.system.nrg) - nrg.mod += Number(ability.system.statusmodifier) - updates[`system.nrg`] = nrg + // manage stat bonus + if (ability.system.affectedstat != "notapplicable") { + let stat = duplicate(this.system.statistics[ability.system.affectedstat]) + stat.mod += Number(ability.system.statmodifier) + updates[`system.statistics.${ability.system.affectedstat}`] = stat } - if (ability.system.statusaffected == 'health') { - let health = duplicate(this.system.secondary.health) - health.bonus += Number(ability.system.statusmodifier) - updates[`system.secondary.health`] = health + // manage status bonus + if (ability.system.statusaffected != "notapplicable") { + if (ability.system.statusaffected == 'nrg') { + let nrg = duplicate(this.system.nrg) + nrg.mod += Number(ability.system.statusmodifier) + updates[`system.nrg`] = nrg + } + if (ability.system.statusaffected == 'health') { + let health = duplicate(this.system.secondary.health) + health.bonus += Number(ability.system.statusmodifier) + updates[`system.secondary.health`] = health + } + if (ability.system.statusaffected == 'delirium') { + let delirium = duplicate(this.system.secondary.delirium) + delirium.bonus += Number(ability.system.statusmodifier) + updates[`system.secondary.delirium`] = delirium + } } - if (ability.system.statusaffected == 'delirium') { - let delirium = duplicate(this.system.secondary.delirium) - delirium.bonus += Number(ability.system.statusmodifier) - updates[`system.secondary.delirium`] = delirium + if (directUpdate) { + await this.update(updates) } - } - if (directUpdate) { - await this.update(updates) - } - let newItems = [] - if (ability.system.effectsgained) { - for (let effect of ability.system.effectsgained) { - if (!effect.system) effect.system = effect.data - newItems.push(effect); + let newItems = [] + if (ability.system.effectsgained) { + for (let effect of ability.system.effectsgained) { + if (!effect.system) effect.system = effect.data + newItems.push(effect); + } } - } - if (ability.system.powersgained) { - for (let power of ability.system.powersgained) { - if (!power.system) power.system = power.data - newItems.push(power); + if (ability.system.powersgained) { + for (let power of ability.system.powersgained) { + if (!power.system) power.system = power.data + newItems.push(power); + } } - } - if (ability.system.specialisations) { - for (let spec of ability.system.specialisations) { - if (!spec.system) spec.system = spec.data - newItems.push(spec); + if (ability.system.specialisations) { + for (let spec of ability.system.specialisations) { + if (!spec.system) spec.system = spec.data + newItems.push(spec); + } } - } - if (ability.system.attackgained) { - for (let weapon of ability.system.attackgained) { - if (!weapon.system) weapon.system = weapon.data - newItems.push(weapon); + if (ability.system.attackgained) { + for (let weapon of ability.system.attackgained) { + if (!weapon.system) weapon.system = weapon.data + newItems.push(weapon); + } } - } - if (ability.system.armorgained) { - for (let armor of ability.system.armorgained) { - if (!armor.system) armor.system = armor.data - newItems.push(armor); + if (ability.system.armorgained) { + for (let armor of ability.system.armorgained) { + if (!armor.system) armor.system = armor.data + newItems.push(armor); + } } + console.log("Ability : adding", newItems) + await this.createEmbeddedDocuments('Item', newItems) } - console.log("Ability : adding", newItems) - await this.createEmbeddedDocuments('Item', newItems) -} /* -------------------------------------------- */ async applyRace(race) { - let updates = { 'system.biodata.racename': race.name } - let newItems = [] - await this.deleteAllItemsByType('race') - newItems.push(race); + let updates = { 'system.biodata.racename': race.name } + let newItems = [] + await this.deleteAllItemsByType('race') + newItems.push(race); - console.log("DROPPED RACE", race) - for (let ability of race.system.abilities) { - if (!ability.system) ability.system = ability.data - newItems.push(ability) - this.applyAbility(ability, updates) - } - if (race.system.perksgained) { - for (let power of race.system.perks) { - if (!power.system) power.system = power.data - newItems.push(power); + console.log("DROPPED RACE", race) + for (let ability of race.system.abilities) { + if (!ability.system) ability.system = ability.data + newItems.push(ability) + this.applyAbility(ability, updates) } + if (race.system.perksgained) { + for (let power of race.system.perks) { + if (!power.system) power.system = power.data + newItems.push(power); + } + } + + await this.update(updates) + await this.createEmbeddedDocuments('Item', newItems) + console.log("Updates", updates, newItems) + console.log("Updated actor", this) } - await this.update(updates) - await this.createEmbeddedDocuments('Item', newItems) - console.log("Updates", updates, newItems) - console.log("Updated actor", this) -} - -/* -------------------------------------------- */ -getIncreaseStatValue(updates, statKey) { - let stat = duplicate(this.system.statistics[statKey]) - stat.value += 1; - updates[`data.statistics.${statKey}`] = stat -} + /* -------------------------------------------- */ + getIncreaseStatValue(updates, statKey) { + let stat = duplicate(this.system.statistics[statKey]) + stat.value += 1; + updates[`data.statistics.${statKey}`] = stat + } /* -------------------------------------------- */ async applyRole(role) { - console.log("ROLE", role) + console.log("ROLE", role) - let updates = { 'system.biodata.rolename': role.name } - let newItems = [] - await this.deleteAllItemsByType('role') - newItems.push(role) + let updates = { 'system.biodata.rolename': role.name } + let newItems = [] + await this.deleteAllItemsByType('role') + newItems.push(role) - this.getIncreaseStatValue(updates, role.system.statincrease1) - this.getIncreaseStatValue(updates, role.system.statincrease2) + this.getIncreaseStatValue(updates, role.system.statincrease1) + this.getIncreaseStatValue(updates, role.system.statincrease2) - if (role.system.specialability.length > 0) { - //console.log("Adding ability", role.system.specialability) - newItems = newItems.concat(duplicate(role.system.specialability)) // Add new ability - this.applyAbility(role.system.specialability[0], newItems) - } - await this.update(updates) - await this.createEmbeddedDocuments('Item', newItems) - -} - - -/* -------------------------------------------- */ -addHindrancesList(effectsList) { - if (this.type == "character") { - if (this.system.combat.stunlevel > 0) { - effectsList.push({ label: "Stun Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 2 }) - } - if (this.system.combat.hindrancedice > 0) { - effectsList.push({ label: "Wounds Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: this.system.combat.hindrancedice }) - } - let overCapacity = Math.floor(this.encCurrent / this.getEncumbranceCapacity()) - if (overCapacity > 0) { - effectsList.push({ label: "Encumbrance Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: overCapacity }) - } - if (this.system.biodata.morality <= 0) { - effectsList.push({ label: "Morality Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 3 }) - } - let effects = this.items.filter(item => item.type == 'effect') - for (let effect of effects) { - effect = duplicate(effect) - if (effect.system.hindrance) { - effectsList.push({ label: effect.name, type: "effect", foreign: true, actorId: this.id, applied: false, effect: effect, value: effect.system.effectlevel }) - } - } - } - if (this.type == "vehicle") { - if (this.system.stun.value > 0) { - effectsList.push({ label: "Stun Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 2 }) - } - if (this.isVehicleCrawling()) { - effectsList.push({ label: "Crawling Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 3 }) - } - if (this.isVehicleSlow()) { - effectsList.push({ label: "Slow Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 1 }) - } - if (this.isVehicleAverage()) { - effectsList.push({ label: "Average Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 1 }) - } - if (this.isVehicleFast()) { - effectsList.push({ label: "Fast Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 3 }) - } - if (this.isVehicleExFast()) { - effectsList.push({ label: "Ext. Fast Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 5 }) - } - } -} - -/* -------------------------------------------- */ -/* ROLL SECTION -/* -------------------------------------------- */ -pushEffect(rollData, effect) { - if (this.getTraumaState() == "none" && !this.checkNoBonusDice()) { - rollData.effectsList.push({ label: effect.name, type: "effect", applied: false, effect: effect, value: effect.system.effectlevel }) - } else { - if (!effect.system.bonusdice) { // Do not push bonus dice effect when TraumaState is activated - rollData.effectsList.push({ label: effect.name, type: "effect", applied: false, effect: effect, value: effect.system.effectlevel }) - } - } -} - -/* -------------------------------------------- */ -addEffects(rollData, isInit = false, isPower = false, isPowerDmg = false) { - let effects = this.items.filter(item => item.type == 'effect') - for (let effect of effects) { - effect = duplicate(effect) - if (!effect.system.hindrance && !effect.system.statdice - && (effect.system.stataffected != "notapplicable" || effect.system.specaffected.length > 0) - && effect.system.stataffected != "special" - && effect.system.stataffected != "powerroll" - && effect.system.stataffected != "powerdmgroll") { - if (effect.system.effectstatlevel) { - effect.system.effectlevel = this.system.statistics[effect.system.effectstat].value - } - this.pushEffect(rollData, effect) - } - if (isPower && effect.system.stataffected == "powerroll") { - this.pushEffect(rollData, effect) - } - if (isPowerDmg && effect.system.stataffected == "powerdmgroll") { - this.pushEffect(rollData, effect) + if (role.system.specialability.length > 0) { + //console.log("Adding ability", role.system.specialability) + newItems = newItems.concat(duplicate(role.system.specialability)) // Add new ability + this.applyAbility(role.system.specialability[0], newItems) } + await this.update(updates) + await this.createEmbeddedDocuments('Item', newItems) } -} -/* -------------------------------------------- */ -addArmorsShields(rollData, statKey = "none", useShield = false, subKey = undefined) { - if (statKey == 'phy' && subKey == "dmg-res") { - let armors = this.getArmors() - for (let armor of armors) { - rollData.armorsList.push({ label: `Armor ${armor.name}`, type: "armor", applied: false, value: armor.system.resistance }) - } - } - if (useShield) { - let shields = this.items.filter(item => item.type == "shield" && item.system.equipped) - for (let sh of shields) { - rollData.armorsList.push({ label: `Shield ${sh.name}`, type: "shield", applied: false, value: sh.system.level }) - } - } -} -addWeapons(rollData, statKey) { - let weapons = this.getWeapons() - for (let weapon of weapons) { - if (weapon.system.equipped && weapon.system.statistic == statKey) { - rollData.weaponsList.push({ label: `Attack ${weapon.name}`, type: "attack", applied: false, weapon: weapon, value: 0, damageDice: PegasusUtility.getDiceFromLevel(0) }) - } - if (weapon.system.equipped && weapon.system.canbethrown && statKey == "agi") { - rollData.weaponsList.push({ label: `Attack ${weapon.name}`, type: "attack", applied: false, weapon: weapon, value: 0, damageDice: PegasusUtility.getDiceFromLevel(0) }) - } - if (weapon.system.equipped && weapon.system.enhanced && weapon.system.enhancedstat == statKey) { - rollData.weaponsList.push({ label: `Enhanced Attack ${weapon.name}`, type: "enhanced", applied: false, weapon: weapon, value: weapon.system.enhancedlevel, damageDice: PegasusUtility.getDiceFromLevel(weapon.system.enhancedlevel) }) - } - if (weapon.system.equipped && weapon.system.damagestatistic == statKey) { - rollData.weaponsList.push({ label: `Damage ${weapon.name}`, type: "damage", applied: false, weapon: weapon, value: weapon.system.damage, damageDice: PegasusUtility.getDiceFromLevel(weapon.system.damage) }) - } - } -} -addEquipments(rollData, statKey) { - let equipments = this.getEquipmentsOnly() - for (let equip of equipments) { - if (equip.system.equipped && equip.system.stataffected == statKey) { - rollData.equipmentsList.push({ label: `Item ${equip.name}`, type: "item", applied: false, equip: equip, value: equip.system.level }) - } - } -} -addVehicleWeapons(rollData, vehicle) { - if (vehicle) { - let modules = vehicle.items.filter(vehicle => vehicle.type == "vehicleweaponmodule") - if (modules && modules.length > 0) { - for (let module of modules) { - rollData.vehicleWeapons.push({ label: `Weapon ${module.name}`, type: "item", applied: false, weapon: module, value: module.system.damagedicevalue }) - } - } - } -} -/* -------------------------------------------- */ -getCommonRollData(statKey = undefined, useShield = false, isInit = false, isPower = false, subKey = "", vehicle = undefined) { - let rollData = PegasusUtility.getBasicRollData(isInit) - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.img = this.img - rollData.traumaState = this.getTraumaState() - rollData.levelRemaining = this.getLevelRemaining() - rollData.activePerks = duplicate(this.getActivePerks()) - rollData.diceList = PegasusUtility.getDiceList() - rollData.noBonusDice = this.checkNoBonusDice() - rollData.dicePool = [] - rollData.subKey = subKey - - if (subKey == "melee-dmg" || subKey == "ranged-dmg" || subKey == "power-dmg") { - rollData.isDamage = true - } - - if (statKey) { - rollData.statKey = statKey - rollData.stat = this.getStat(statKey) - if (rollData.stat.value != undefined) { - rollData.stat.level = rollData.stat.value // Normalize - } - rollData.statDicesLevel = rollData.stat.level + rollData.stat.bonuseffect - rollData.statMod = rollData.stat.mod - if (vehicle) { - rollData.vehicle = duplicate(vehicle) - if (subKey == "melee-dmg") { - if (vehicle.isVehicleFullStop()) { - ui.notifications.warn("MR not added to Melee Damage due to Full Stop.") - } else { - rollData.statVehicle = vehicle.system.statistics.mr - rollData.vehicleKey = "mr" - } - this.addVehicleWeapons(rollData, vehicle) - } - if (subKey == "ranged-atk") { - rollData.statVehicle = vehicle.system.statistics.fc - rollData.vehicleKey = "fc" - } - if (subKey == "ranged-dmg") { - this.addVehicleWeapons(rollData, vehicle) - } - if (subKey == "defence") { - if (vehicle.isVehicleFullStop()) { - ui.notifications.warn("MAN not added to Defense due to Full Stop.") - } else { - rollData.statVehicle = vehicle.system.statistics.man - rollData.vehicleKey = "man" - } - vehicle.addVehicleShields(rollData) - } - vehicle.addEffects(rollData, false, false, false) - //this.addVehiculeHindrances(rollData.effectsList, vehicle) - //this.addVehicleBonus(rollData, vehicle) - } - - rollData.specList = this.getRelevantSpec(statKey) - rollData.selectedSpec = "0" - if (statKey.toLowerCase() == "mr") { - rollData.img = "systems/fvtt-pegasus-rpg/images/icons/MR.webp" - } else { - let abbrev = rollData.stat.abbrev.toUpperCase() - rollData.img = `systems/fvtt-pegasus-rpg/images/icons/${abbrev}.webp` - } - rollData.dicePool = rollData.dicePool.concat(PegasusUtility.buildDicePool("stat", rollData.statDicesLevel, rollData.stat.mod)) - if (rollData.statVehicle) { - rollData.dicePool = rollData.dicePool.concat(PegasusUtility.buildDicePool("statvehicle", rollData.statVehicle.currentlevel, 0)) - } - } - - if (statKey == "mr") { + /* -------------------------------------------- */ + addHindrancesList(effectsList) { if (this.type == "character") { - rollData.mrVehicle = PegasusUtility.checkIsVehicleCrew(this.id) - if (rollData.mrVehicle) { - rollData.effectsList.push({ - label: `Vehicle ${rollData.mrVehicle.name} MR Bonus`, - type: "effect", applied: false, isdynamic: true, value: rollData.mrVehicle.system.statistics.mr.currentlevel - }) + if (this.system.combat.stunlevel > 0) { + effectsList.push({ label: "Stun Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 2 }) + } + if (this.system.combat.hindrancedice > 0) { + effectsList.push({ label: "Wounds Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: this.system.combat.hindrancedice }) + } + let overCapacity = Math.floor(this.encCurrent / this.getEncumbranceCapacity()) + if (overCapacity > 0) { + effectsList.push({ label: "Encumbrance Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: overCapacity }) + } + if (this.system.biodata.morality <= 0) { + effectsList.push({ label: "Morality Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 3 }) + } + let effects = this.items.filter(item => item.type == 'effect') + for (let effect of effects) { + effect = duplicate(effect) + if (effect.system.hindrance) { + effectsList.push({ label: effect.name, type: "effect", foreign: true, actorId: this.id, applied: false, effect: effect, value: effect.system.effectlevel }) + } } } if (this.type == "vehicle") { - for (let member of this.system.crew) { - let actor = game.actors.get(member.id) - let specList = actor.getRelevantSpec("mr") - rollData.effectsList.push({ - label: `Crew ${actor.name} MR Bonus`, - type: "effect", applied: false, isdynamic: true, value: actor.system.mr.value + actor.system.mr.bonuseffect, specList: specList - }) + if (this.system.stun.value > 0) { + effectsList.push({ label: "Stun Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 2 }) + } + if (this.isVehicleCrawling()) { + effectsList.push({ label: "Crawling Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 3 }) + } + if (this.isVehicleSlow()) { + effectsList.push({ label: "Slow Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 1 }) + } + if (this.isVehicleAverage()) { + effectsList.push({ label: "Average Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 1 }) + } + if (this.isVehicleFast()) { + effectsList.push({ label: "Fast Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 3 }) + } + if (this.isVehicleExFast()) { + effectsList.push({ label: "Ext. Fast Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 5 }) } } } - this.processSizeBonus(rollData) - this.addEffects(rollData, isInit, isPower, subKey == "power-dmg") - this.addArmorsShields(rollData, statKey, useShield, subKey) - this.addWeapons(rollData, statKey, useShield) - this.addEquipments(rollData, statKey) - console.log("ROLLDATA", rollData) - - return rollData -} - -/* -------------------------------------------- */ -processSizeBonus(rollData) { - if (rollData.defenderTokenId) { - let diffSize = rollData.defenderSize - this.system.biodata.sizenum + this.system.biodata.sizebonus - //console.log("Diffsize", diffSize) - if (rollData.subKey == "melee-atk" || rollData.subKey == "ranged-atk") { - if (diffSize > 0) { - rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: diffSize }) - } - } - if (rollData.subKey == "dmg-res") { - if (diffSize < 0) { - rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: Math.abs(diffSize) }) - } - } - if (rollData.subKey == "defence") { - if (diffSize > 0) { - rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: Math.abs(diffSize) }) - } - } - if (rollData.subKey == "melee-dmg" || rollData.subKey == "ranged-dmg" || rollData.subKey == "power-dmg") { - if (diffSize < 0) { - rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: Math.abs(diffSize) }) + /* -------------------------------------------- */ + /* ROLL SECTION + /* -------------------------------------------- */ + pushEffect(rollData, effect) { + if (this.getTraumaState() == "none" && !this.checkNoBonusDice()) { + rollData.effectsList.push({ label: effect.name, type: "effect", applied: false, effect: effect, value: effect.system.effectlevel }) + } else { + if (!effect.system.bonusdice) { // Do not push bonus dice effect when TraumaState is activated + rollData.effectsList.push({ label: effect.name, type: "effect", applied: false, effect: effect, value: effect.system.effectlevel }) } } } -} -/* -------------------------------------------- */ -getLevelRemainingList() { - let options = [] - for (let i = 0; i <= this.system.biodata.maxlevelremaining; i++) { - options.push(``) - } - return options.join("\n") -} + /* -------------------------------------------- */ + addEffects(rollData, isInit = false, isPower = false, isPowerDmg = false) { + let effects = this.items.filter(item => item.type == 'effect') + for (let effect of effects) { + effect = duplicate(effect) + if (!effect.system.hindrance && !effect.system.statdice + && (effect.system.stataffected != "notapplicable" || effect.system.specaffected.length > 0) + && effect.system.stataffected != "special" + && effect.system.stataffected != "powerroll" + && effect.system.stataffected != "powerdmgroll") { + if (effect.system.effectstatlevel) { + effect.system.effectlevel = this.system.statistics[effect.system.effectstat].value + } + this.pushEffect(rollData, effect) + } + if (isPower && effect.system.stataffected == "powerroll") { + this.pushEffect(rollData, effect) + } + if (isPowerDmg && effect.system.stataffected == "powerdmgroll") { + this.pushEffect(rollData, effect) + } -/* -------------------------------------------- */ -getMaxLevelRemainingList() { - let options = [] - for (let i = 0; i <= 12; i++) { - options.push(``) + } + } + + /* -------------------------------------------- */ + addArmorsShields(rollData, statKey = "none", useShield = false, subKey = undefined) { + if (statKey == 'phy' && subKey == "dmg-res") { + let armors = this.getArmors() + for (let armor of armors) { + rollData.armorsList.push({ label: `Armor ${armor.name}`, type: "armor", applied: false, value: armor.system.resistance }) + } + } + if (useShield) { + let shields = this.items.filter(item => item.type == "shield" && item.system.equipped) + for (let sh of shields) { + rollData.armorsList.push({ label: `Shield ${sh.name}`, type: "shield", applied: false, value: sh.system.level }) + } + } + } + addWeapons(rollData, statKey) { + let weapons = this.getWeapons() + for (let weapon of weapons) { + if (weapon.system.equipped && weapon.system.statistic == statKey) { + rollData.weaponsList.push({ label: `Attack ${weapon.name}`, type: "attack", applied: false, weapon: weapon, value: 0, damageDice: PegasusUtility.getDiceFromLevel(0) }) + } + if (weapon.system.equipped && weapon.system.canbethrown && statKey == "agi") { + rollData.weaponsList.push({ label: `Attack ${weapon.name}`, type: "attack", applied: false, weapon: weapon, value: 0, damageDice: PegasusUtility.getDiceFromLevel(0) }) + } + if (weapon.system.equipped && weapon.system.enhanced && weapon.system.enhancedstat == statKey) { + rollData.weaponsList.push({ label: `Enhanced Attack ${weapon.name}`, type: "enhanced", applied: false, weapon: weapon, value: weapon.system.enhancedlevel, damageDice: PegasusUtility.getDiceFromLevel(weapon.system.enhancedlevel) }) + } + if (weapon.system.equipped && weapon.system.damagestatistic == statKey) { + rollData.weaponsList.push({ label: `Damage ${weapon.name}`, type: "damage", applied: false, weapon: weapon, value: weapon.system.damage, damageDice: PegasusUtility.getDiceFromLevel(weapon.system.damage) }) + } + } + } + addEquipments(rollData, statKey) { + let equipments = this.getEquipmentsOnly() + for (let equip of equipments) { + if (equip.system.equipped && equip.system.stataffected == statKey) { + rollData.equipmentsList.push({ label: `Item ${equip.name}`, type: "item", applied: false, equip: equip, value: equip.system.level }) + } + } + } + addVehicleWeapons(rollData, vehicle) { + if (vehicle) { + let modules = vehicle.items.filter(vehicle => vehicle.type == "vehicleweaponmodule") + if (modules && modules.length > 0) { + for (let module of modules) { + rollData.vehicleWeapons.push({ label: `Weapon ${module.name}`, type: "item", applied: false, weapon: module, value: module.system.damagedicevalue }) + } + } + } + } + + /* -------------------------------------------- */ + getCommonRollData(statKey = undefined, useShield = false, isInit = false, isPower = false, subKey = "", vehicle = undefined) { + let rollData = PegasusUtility.getBasicRollData(isInit) + rollData.alias = this.name + rollData.actorImg = this.img + rollData.actorId = this.id + rollData.img = this.img + rollData.traumaState = this.getTraumaState() + rollData.levelRemaining = this.getLevelRemaining() + rollData.activePerks = duplicate(this.getActivePerks()) + rollData.diceList = PegasusUtility.getDiceList() + rollData.noBonusDice = this.checkNoBonusDice() + rollData.dicePool = [] + rollData.subKey = subKey + + if (subKey == "melee-dmg" || subKey == "ranged-dmg" || subKey == "power-dmg") { + rollData.isDamage = true + } + + if (statKey) { + rollData.statKey = statKey + rollData.stat = this.getStat(statKey) + if (rollData.stat.value != undefined) { + rollData.stat.level = rollData.stat.value // Normalize + } + rollData.statDicesLevel = rollData.stat.level + rollData.stat.bonuseffect + rollData.statMod = rollData.stat.mod + if (vehicle) { + rollData.vehicle = duplicate(vehicle) + if (subKey == "melee-dmg") { + if (vehicle.isVehicleFullStop()) { + ui.notifications.warn("MR not added to Melee Damage due to Full Stop.") + } else { + rollData.statVehicle = vehicle.system.statistics.mr + rollData.vehicleKey = "mr" + } + this.addVehicleWeapons(rollData, vehicle) + } + if (subKey == "ranged-atk") { + rollData.statVehicle = vehicle.system.statistics.fc + rollData.vehicleKey = "fc" + } + if (subKey == "ranged-dmg") { + this.addVehicleWeapons(rollData, vehicle) + } + if (subKey == "defence") { + if (vehicle.isVehicleFullStop()) { + ui.notifications.warn("MAN not added to Defense due to Full Stop.") + } else { + rollData.statVehicle = vehicle.system.statistics.man + rollData.vehicleKey = "man" + } + vehicle.addVehicleShields(rollData) + } + vehicle.addEffects(rollData, false, false, false) + //this.addVehiculeHindrances(rollData.effectsList, vehicle) + //this.addVehicleBonus(rollData, vehicle) + } + + rollData.specList = this.getRelevantSpec(statKey) + rollData.selectedSpec = "0" + if (statKey.toLowerCase() == "mr") { + rollData.img = "systems/fvtt-pegasus-rpg/images/icons/MR.webp" + } else { + let abbrev = rollData.stat.abbrev.toUpperCase() + rollData.img = `systems/fvtt-pegasus-rpg/images/icons/${abbrev}.webp` + } + rollData.dicePool = rollData.dicePool.concat(PegasusUtility.buildDicePool("stat", rollData.statDicesLevel, rollData.stat.mod)) + if (rollData.statVehicle) { + rollData.dicePool = rollData.dicePool.concat(PegasusUtility.buildDicePool("statvehicle", rollData.statVehicle.currentlevel, 0)) + } + } + + if (statKey == "mr") { + if (this.type == "character") { + rollData.mrVehicle = PegasusUtility.checkIsVehicleCrew(this.id) + if (rollData.mrVehicle) { + rollData.effectsList.push({ + label: `Vehicle ${rollData.mrVehicle.name} MR Bonus`, + type: "effect", applied: false, isdynamic: true, value: rollData.mrVehicle.system.statistics.mr.currentlevel + }) + } + } + if (this.type == "vehicle") { + for (let member of this.system.crew) { + let actor = game.actors.get(member.id) + let specList = actor.getRelevantSpec("mr") + rollData.effectsList.push({ + label: `Crew ${actor.name} MR Bonus`, + type: "effect", applied: false, isdynamic: true, value: actor.system.mr.value + actor.system.mr.bonuseffect, specList: specList + }) + } + } + } + + this.processSizeBonus(rollData) + this.addEffects(rollData, isInit, isPower, subKey == "power-dmg") + this.addArmorsShields(rollData, statKey, useShield, subKey) + this.addWeapons(rollData, statKey, useShield) + this.addEquipments(rollData, statKey) + console.log("ROLLDATA", rollData) + + return rollData + } + + /* -------------------------------------------- */ + processSizeBonus(rollData) { + if (rollData.defenderTokenId) { + let diffSize = rollData.defenderSize - this.system.biodata.sizenum + this.system.biodata.sizebonus + //console.log("Diffsize", diffSize) + if (rollData.subKey == "melee-atk" || rollData.subKey == "ranged-atk") { + if (diffSize > 0) { + rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: diffSize }) + } + } + if (rollData.subKey == "dmg-res") { + if (diffSize < 0) { + rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: Math.abs(diffSize) }) + } + } + if (rollData.subKey == "defence") { + if (diffSize > 0) { + rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: Math.abs(diffSize) }) + } + } + if (rollData.subKey == "melee-dmg" || rollData.subKey == "ranged-dmg" || rollData.subKey == "power-dmg") { + if (diffSize < 0) { + rollData.effectsList.push({ label: "Size Bonus", type: "effect", applied: false, isdynamic: true, value: Math.abs(diffSize) }) + } + } + } + } + + /* -------------------------------------------- */ + getLevelRemainingList() { + let options = [] + for (let i = 0; i <= this.system.biodata.maxlevelremaining; i++) { + options.push(``) + } + return options.join("\n") + } + + /* -------------------------------------------- */ + getMaxLevelRemainingList() { + let options = [] + for (let i = 0; i <= 12; i++) { + options.push(``) + } + return options.join("\n") } - return options.join("\n") -} /* -------------------------------------------- */ async startRoll(rollData) { - this.syncRoll(rollData); - //console.log("ROLL DATA", rollData) - let rollDialog = await PegasusRollDialog.create(this, rollData) - console.log(rollDialog) - rollDialog.render(true); -} - -/* -------------------------------------------- */ -powerDmgRoll(itemId) { - let power = this.items.get(itemId) - if (power) { - power = duplicate(power) - this.rollPool(power.system.dmgstatistic, false, "power-dmg") + this.syncRoll(rollData); + //console.log("ROLL DATA", rollData) + let rollDialog = await PegasusRollDialog.create(this, rollData) + console.log(rollDialog) + rollDialog.render(true); } -} -/* -------------------------------------------- */ -rollPool(statKey, useShield = false, subKey = "none", vehicle = undefined) { - let stat = this.getStat(statKey) - if (stat) { - let rollData = this.getCommonRollData(statKey, useShield, false, false, subKey, vehicle) - rollData.mode = "stat" - rollData.subKey = subKey - let def = stat.label - if (subKey) { - def = __subkey2title[subKey] + /* -------------------------------------------- */ + powerDmgRoll(itemId) { + let power = this.items.get(itemId) + if (power) { + power = duplicate(power) + this.rollPool(power.system.dmgstatistic, false, "power-dmg") } - rollData.title = `Roll : ${def} ` - rollData.img = "icons/dice/d12black.svg" - this.startRoll(rollData) - } else { - ui.notifications.warn("Statistic not found !"); } -} -/* -------------------------------------------- */ -rollUnarmedAttack() { - let stat = this.getStat('com') - if (stat) { - let rollData = this.getCommonRollData(statKey) - rollData.mode = "stat" - rollData.title = `Unarmed Attack`; - rollData.damages = this.getStat('str'); - - this.startRoll(rollData); - } else { - ui.notifications.warn("Statistic not found !"); + /* -------------------------------------------- */ + rollPool(statKey, useShield = false, subKey = "none", vehicle = undefined) { + let stat = this.getStat(statKey) + if (stat) { + let rollData = this.getCommonRollData(statKey, useShield, false, false, subKey, vehicle) + rollData.mode = "stat" + rollData.subKey = subKey + let def = stat.label + if (subKey) { + def = __subkey2title[subKey] + } + rollData.title = `Roll : ${def} ` + rollData.img = "icons/dice/d12black.svg" + this.startRoll(rollData) + } else { + ui.notifications.warn("Statistic not found !"); + } } -} -/*-------------------------------------------- */ -rollStat(statKey) { - let stat = this.getStat(statKey); - if (stat) { - let rollData = this.getCommonRollData(statKey) - rollData.mode = "stat" - rollData.title = `Stat ${stat.label}`; + /* -------------------------------------------- */ + rollUnarmedAttack() { + let stat = this.getStat('com') + if (stat) { + let rollData = this.getCommonRollData(statKey) + rollData.mode = "stat" + rollData.title = `Unarmed Attack`; + rollData.damages = this.getStat('str'); - this.startRoll(rollData) - } else { - ui.notifications.warn("Statistic not found !"); + this.startRoll(rollData); + } else { + ui.notifications.warn("Statistic not found !"); + } + } + + /*-------------------------------------------- */ + rollStat(statKey) { + let stat = this.getStat(statKey); + if (stat) { + let rollData = this.getCommonRollData(statKey) + rollData.mode = "stat" + rollData.title = `Stat ${stat.label}`; + + this.startRoll(rollData) + } else { + ui.notifications.warn("Statistic not found !"); + } } -} /* -------------------------------------------- */ async rollSpec(specId) { - let spec = this.getOneSpec(specId) - if (spec) { - let rollData = this.getCommonRollData(spec.system.statistic) - rollData.mode = "spec" - rollData.title = `Spec. : ${spec.name} ` - rollData.specList = [spec] - rollData.selectedSpec = spec._id - rollData.specName = spec.name - rollData.img = spec.img - rollData.specDicesLevel = spec.system.level - PegasusUtility.updateSpecDicePool(rollData) - this.startRoll(rollData) - } else { - ui.notifications.warn("Specialisation not found !"); + let spec = this.getOneSpec(specId) + if (spec) { + let rollData = this.getCommonRollData(spec.system.statistic) + rollData.mode = "spec" + rollData.title = `Spec. : ${spec.name} ` + rollData.specList = [spec] + rollData.selectedSpec = spec._id + rollData.specName = spec.name + rollData.img = spec.img + rollData.specDicesLevel = spec.system.level + PegasusUtility.updateSpecDicePool(rollData) + this.startRoll(rollData) + } else { + ui.notifications.warn("Specialisation not found !"); + } } -} /* -------------------------------------------- */ async rollMR(isInit = false, combatId = 0, combatantId = 0) { - let mr = duplicate((this.type == "vehicle") ? this.system.statistics.mr : this.system.mr) - if (mr) { - mr.dice = PegasusUtility.getDiceFromLevel(mr.value); + let mr = duplicate((this.type == "vehicle") ? this.system.statistics.mr : this.system.mr) + if (mr) { + mr.dice = PegasusUtility.getDiceFromLevel(mr.value); - let rollData = this.getCommonRollData("mr", false, isInit) - rollData.mode = "MR" - rollData.img = "systems/fvtt-pegasus-rpg/images/icons/MR.webp" - rollData.isInit = isInit - rollData.combatId = combatId - rollData.combatantId = combatantId - console.log("MR ROLL", rollData) - if (isInit) { - rollData.title = "MR / Initiative" + let rollData = this.getCommonRollData("mr", false, isInit) + rollData.mode = "MR" + rollData.img = "systems/fvtt-pegasus-rpg/images/icons/MR.webp" + rollData.isInit = isInit + rollData.combatId = combatId + rollData.combatantId = combatantId + console.log("MR ROLL", rollData) + if (isInit) { + rollData.title = "MR / Initiative" + } + this.startRoll(rollData); + } else { + ui.notifications.warn("MR not found !"); } - this.startRoll(rollData); - } else { - ui.notifications.warn("MR not found !"); } -} /* -------------------------------------------- */ async rollArmor(armorId) { - let armor = this.items.get(armorId) + let armor = this.items.get(armorId) - if (armor) { - let rollData = this.getCommonRollData(armor.system.statistic) + if (armor) { + let rollData = this.getCommonRollData(armor.system.statistic) - armor = duplicate(armor); - this.checkAndPrepareEquipment(armor); + armor = duplicate(armor); + this.checkAndPrepareEquipment(armor); - rollData.mode = "armor" - rollData.armor = armor - rollData.title = `Armor : ${armor.name}` - rollData.isResistance = true; - rollData.img = armor.img - rollData.damageDiceLevel = armor.system.resistance + rollData.mode = "armor" + rollData.armor = armor + rollData.title = `Armor : ${armor.name}` + rollData.isResistance = true; + rollData.img = armor.img + rollData.damageDiceLevel = armor.system.resistance - this.startRoll(rollData); - } else { - ui.notifications.warn("Armor not found !", weaponId); + this.startRoll(rollData); + } else { + ui.notifications.warn("Armor not found !", weaponId); + } } -} /* -------------------------------------------- */ async rollPower(powerId) { - let power = this.items.get(powerId) + let power = this.items.get(powerId) - if (power) { - power = duplicate(power) - let rollData = this.getCommonRollData(power.system.statistic, false, false, true) + if (power) { + power = duplicate(power) + let rollData = this.getCommonRollData(power.system.statistic, false, false, true) - rollData.mode = "power" - rollData.power = power - rollData.title = `Power : ${power.name}` - rollData.img = power.img + rollData.mode = "power" + rollData.power = power + rollData.title = `Power : ${power.name}` + rollData.img = power.img - this.startRoll(rollData); - } else { - ui.notifications.warn("Power not found !", powerId); + this.startRoll(rollData); + } else { + ui.notifications.warn("Power not found !", powerId); + } } -} /* -------------------------------------------- */ /* VEHICLE STUFF */ async manageCurrentSpeed(speed) { - // Delete any previous effect - let effect = this.items.find(effect => effect.system.isspeed != undefined) - if (effect) { - await this.deleteEmbeddedDocuments("Item", [effect.id]) + // Delete any previous effect + let effect = this.items.find(effect => effect.system.isspeed != undefined) + if (effect) { + await this.deleteEmbeddedDocuments("Item", [effect.id]) + } + + if (speed == "fullstop") { + this.update({ 'system.secondary.moverange': "nomovement" }) + } + if (speed == "crawling") { + await this.update({ 'system.secondary.moverange': "threatzone" }) + await this.manageVehicleSpeedBonus("crawling", "Crawling MAN Bonus", "man", 3) + } + if (speed == "slow") { + await this.update({ 'system.secondary.moverange': "close" }) + await this.manageVehicleSpeedBonus("slow", "Slow MAN Bonus", "man", 1) + } + if (speed == "average") { + await this.update({ 'system.secondary.moverange': "medium" }) + await this.manageVehicleSpeedBonus("average", "Avoid attack Bonus", "all", 1) + } + if (speed == "fast") { + await this.update({ 'system.secondary.moverange': "long" }) + await this.manageVehicleSpeedBonus("fast", "Avoid attack Bonus", "all", 3) + } + if (speed == "extfast") { + await this.update({ 'system.secondary.moverange': "extreme" }) + await this.manageVehicleSpeedBonus("extfast", "Avoid attack Bonus", "all", 5) + } } - if (speed == "fullstop") { - this.update({ 'system.secondary.moverange': "nomovement" }) + /* -------------------------------------------- */ + modifyVehicleStun(incDec) { + let stun = this.system.stun.value + incDec + this.update({ 'system.stun.value': stun }) } - if (speed == "crawling") { - await this.update({ 'system.secondary.moverange': "threatzone" }) - await this.manageVehicleSpeedBonus("crawling", "Crawling MAN Bonus", "man", 3) - } - if (speed == "slow") { - await this.update({ 'system.secondary.moverange': "close" }) - await this.manageVehicleSpeedBonus("slow", "Slow MAN Bonus", "man", 1) - } - if (speed == "average") { - await this.update({ 'system.secondary.moverange': "medium" }) - await this.manageVehicleSpeedBonus("average", "Avoid attack Bonus", "all", 1) - } - if (speed == "fast") { - await this.update({ 'system.secondary.moverange': "long" }) - await this.manageVehicleSpeedBonus("fast", "Avoid attack Bonus", "all", 3) - } - if (speed == "extfast") { - await this.update({ 'system.secondary.moverange': "extreme" }) - await this.manageVehicleSpeedBonus("extfast", "Avoid attack Bonus", "all", 5) - } -} -/* -------------------------------------------- */ -modifyVehicleStun(incDec) { - let stun = this.system.stun.value + incDec - this.update({ 'system.stun.value': stun }) -} - -/* -------------------------------------------- */ -addTopSpeedBonus(topspeed, bonus) { - let num = __speed2Num[topspeed] + Number(bonus) - num = Math.max(0, num) - num = Math.min(num, __num2speed.length - 1) - return __num2speed[num] -} + /* -------------------------------------------- */ + addTopSpeedBonus(topspeed, bonus) { + let num = __speed2Num[topspeed] + Number(bonus) + num = Math.max(0, num) + num = Math.min(num, __num2speed.length - 1) + return __num2speed[num] + } /* -------------------------------------------- */ async manageVehicleSpeedBonus(speed, name, stat, level) { - let effect = duplicate(__bonusEffect) - effect.id = randomID(16) - effect.name = name - effect.system.stataffected = stat - effect.system.effectlevel = level - effect.system.isspeed = speed - await this.createEmbeddedDocuments("Item", [effect]) -} - + let effect = duplicate(__bonusEffect) + effect.id = randomID(16) + effect.name = name + effect.system.stataffected = stat + effect.system.effectlevel = level + effect.system.isspeed = speed + await this.createEmbeddedDocuments("Item", [effect]) + } + /* -------------------------------------------- */ + processVehicleStatEffects() { + let effects = this.items.filter(effect => effect.type == "effect" && effect.system.genre == "positive" && effect.system.statdice) + for (let statKey in this.system.statistics) { + let stat = duplicate(this.system.statistics[statKey]) + let bonus = 0 + for (let effect of effects) { + if (effect.system.stataffected == statKey) { + bonus += Number(effect.system.effectlevel) + } + } + if (bonus != stat.bonuseffect) { + stat.bonuseffect = bonus + this.update({ [`system.statistics.${statKey}`]: stat }) + } + } + } + /* -------------------------------------------- */ async computeVehicleStats() { - if (this.type == "vehicle") { + if (this.type == "vehicle") { - for (let statDef of __statBuild) { - let sum = 0 - let list = [] - for (let moduleType of statDef.modules) { - list = list.concat(this.items.filter(item => item.type == moduleType)) - } - if (list && list.length > 0) { - sum = list.reduce((value, item2) => value + Number(item2.system[statDef.itemfield]), 0) - } - //console.log("Processing", statDef.field, this.system.statistics[statDef.field].level, list, sum) - if (statDef.subfield) { - if (sum != Number(this.system.statistics[statDef.field][statDef.subfield])) { - //console.log("Update", statDef.field, statDef.subfield, sum, this.system.statistics[statDef.field][statDef.subfield]) - this.update({ [`system.statistics.${statDef.field}.${statDef.subfield}`]: sum }) + for (let statDef of __statBuild) { + let sum = 0 + let list = [] + for (let moduleType of statDef.modules) { + list = list.concat(this.items.filter(item => item.type == moduleType)) } + if (list && list.length > 0) { + sum = list.reduce((value, item2) => value + Number(item2.system[statDef.itemfield]), 0) + } + //console.log("Processing", statDef.field, this.system.statistics[statDef.field].level, list, sum) + if (statDef.subfield) { + if (sum != Number(this.system.statistics[statDef.field][statDef.subfield])) { + //console.log("Update", statDef.field, statDef.subfield, sum, this.system.statistics[statDef.field][statDef.subfield]) + this.update({ [`system.statistics.${statDef.field}.${statDef.subfield}`]: sum }) + } + } else { + if (sum != Number(this.system.statistics[statDef.field].level)) { + this.update({ [`system.statistics.${statDef.field}.level`]: sum, [`system.statistics.${statDef.field}.currentlevel`]: sum }) + if (statDef.additionnal1) { + if (sum != Number(this.system.statistics[statDef.field][statDef.additionnal1])) { + this.update({ [`system.statistics.${statDef.field}.${statDef.additionnal1}`]: sum }) + } + } + if (statDef.additionnal2) { + if (sum != Number(this.system.statistics[statDef.field][statDef.additionnal2])) { + this.update({ [`system.statistics.${statDef.field}.${statDef.additionnal2}`]: sum }) + } + } + } + } + } + + // Top speed management + let mobility = this.items.find(item => item.type == "mobilitymodule") + let arcs = duplicate(this.system.arcs) + if (mobility) { + let propulsion = this.items.find(item => item.type == "propulsionmodule") + let bonus = (propulsion) ? propulsion.system.topspeed : 0 + arcs.frontarc.topspeed = this.addTopSpeedBonus(mobility.system.ts_f, bonus) + arcs.rightarc.topspeed = mobility.system.ts_s + arcs.leftarc.topspeed = mobility.system.ts_s + arcs.toparc.topspeed = mobility.system.ts_s + arcs.bottomarc.topspeed = mobility.system.ts_s + arcs.reararc.topspeed = mobility.system.ts_r } else { - if (sum != Number(this.system.statistics[statDef.field].level)) { - this.update({ [`system.statistics.${statDef.field}.level`]: sum, [`system.statistics.${statDef.field}.currentlevel`]: sum }) - if (statDef.additionnal1) { - if (sum != Number(this.system.statistics[statDef.field][statDef.additionnal1])) { - this.update({ [`system.statistics.${statDef.field}.${statDef.additionnal1}`]: sum }) - } - } - if (statDef.additionnal2) { - if (sum != Number(this.system.statistics[statDef.field][statDef.additionnal2])) { - this.update({ [`system.statistics.${statDef.field}.${statDef.additionnal2}`]: sum }) - } - } + arcs.frontarc.topspeed = "fullstop" + arcs.rightarc.topspeed = "fullstop" + arcs.leftarc.topspeed = "fullstop" + arcs.toparc.topspeed = "fullstop" + arcs.bottomarc.topspeed = "fullstop" + arcs.reararc.topspeed = "fullstop" + } + for (let key in this.system.arcs) { + if (this.system.arcs[key].topspeed != arcs[key].topspeed) { + this.update({ 'system.arcs': arcs }) + } + } + + // VMS management + let hull = this.items.find(item => item.type == "vehiclehull") + let modules = duplicate(this.system.modules) + if (hull) { + modules.totalvms = Number(hull.system.vms) + } else { + modules.totalvms = 0 + } + let spaceList = this.items.filter(item => item.type == "vehiclemodule") || [] + spaceList = spaceList.concat(this.items.filter(item => item.type == "vehicleweaponmodule") || []) + let space = 0 + if (spaceList && spaceList.length > 0) { + space = spaceList.reduce((value, item2) => value + Number(item2.system.space), 0) + } + modules.vmsused = space + if (modules.totalvms != this.system.modules.totalvms || modules.usedvms != this.system.modules.vmsused) { + this.update({ 'system.modules': modules }) + } + if (modules.vmsused > modules.totalvms) { + ui.notifications.warn("Warning! No more space available in cargo !!") + } + + // Destroyed + if (this.system.statistics.hr.currentlevel == 0) { + ChatMessage.create({ content: `The vehicle ${this.name} has been destroyed !` }) + } + this.processVehicleArmorShields() + this.processVehicleStatEffects() + } + } + + /* -------------------------------------------- */ + getTotalCost() { + let sumCost = 0 + for (let item of this.items) { + if (__isVehicle[item.type]) { + if (item.system.cost) { + sumCost += Number(item.system.cost) } } } - - // Top speed management - let mobility = this.items.find(item => item.type == "mobilitymodule") - let arcs = duplicate(this.system.arcs) - if (mobility) { - let propulsion = this.items.find(item => item.type == "propulsionmodule") - let bonus = (propulsion) ? propulsion.system.topspeed : 0 - arcs.frontarc.topspeed = this.addTopSpeedBonus(mobility.system.ts_f, bonus) - arcs.rightarc.topspeed = mobility.system.ts_s - arcs.leftarc.topspeed = mobility.system.ts_s - arcs.toparc.topspeed = mobility.system.ts_s - arcs.bottomarc.topspeed = mobility.system.ts_s - arcs.reararc.topspeed = mobility.system.ts_r - } else { - arcs.frontarc.topspeed = "fullstop" - arcs.rightarc.topspeed = "fullstop" - arcs.leftarc.topspeed = "fullstop" - arcs.toparc.topspeed = "fullstop" - arcs.bottomarc.topspeed = "fullstop" - arcs.reararc.topspeed = "fullstop" - } - for (let key in this.system.arcs) { - if (this.system.arcs[key].topspeed != arcs[key].topspeed) { - this.update({ 'system.arcs': arcs }) - } - } - - // VMS management - let hull = this.items.find(item => item.type == "vehiclehull") - let modules = duplicate(this.system.modules) - if (hull) { - modules.totalvms = Number(hull.system.vms) - } else { - modules.totalvms = 0 - } - let spaceList = this.items.filter(item => item.type == "vehiclemodule") || [] - spaceList = spaceList.concat(this.items.filter(item => item.type == "vehicleweaponmodule") || []) - let space = 0 - if (spaceList && spaceList.length > 0) { - space = spaceList.reduce((value, item2) => value + Number(item2.system.space), 0) - } - modules.vmsused = space - if (modules.totalvms != this.system.modules.totalvms || modules.usedvms != this.system.modules.vmsused) { - this.update({ 'system.modules': modules }) - } - if (modules.vmsused > modules.totalvms) { - ui.notifications.warn("Warning! No more space available in cargo !!") - } - - // Destroyed - if (this.system.statistics.hr.currentlevel == 0) { - ChatMessage.create({ content: `The vehicle ${this.name} has been destroyed !` }) - } - this.processVehicleArmorShields() + return sumCost } -} - -/* -------------------------------------------- */ -getTotalCost() { - let sumCost = 0 - for (let item of this.items) { - if (__isVehicle[item.type]) { - if (item.system.cost) { - sumCost += Number(item.system.cost) - } - } - } - return sumCost -} /* -------------------------------------------- */ async preprocessItemVehicle(event, item, onDrop = false) { - if (item.type != "effect" && !__isVehicle[item.type]) { - ui.notifications.warn("You can't drop Character items over a vehicle sheet.") - return - } + if (item.type != "effect" && !__isVehicle[item.type]) { + ui.notifications.warn("You can't drop Character items over a vehicle sheet.") + return + } - //console.log(">>>>> item", item.type, __isVehicleUnique[item.type]) - if (__isVehicleUnique[item.type]) { - let toDelList = [] - for (let toDel of this.items) { - if (toDel.type == item.type) { - toDelList.push(toDel.id) + //console.log(">>>>> item", item.type, __isVehicleUnique[item.type]) + if (__isVehicleUnique[item.type]) { + let toDelList = [] + for (let toDel of this.items) { + if (toDel.type == item.type) { + toDelList.push(toDel.id) + } + } + //console.log("TODEL : ", toDelList) + if (toDelList.length > 0) { + await this.deleteEmbeddedDocuments('Item', toDelList) } } - //console.log("TODEL : ", toDelList) - if (toDelList.length > 0) { - await this.deleteEmbeddedDocuments('Item', toDelList) + // Check size + if (item.type == "vehiclemodule" || item.type == "vehicleweaponmodule") { + item.system.space = item.system?.space || 0 + if (this.system.modules.usedvms + Number(item.system.space) > this.system.modules.totalvms) { + ChatMessage.create({ content: `No more room available to host module ${item.name}. Module is not added to the vehicle.` }) + return false + } } + // Cargo management + if (__isVehicleCargo[item.type]) { + let capacity = this.getCurrentCargoCapacity() + if (item.type == "cargo") { + capacity += Number(item.system.capacity) + } else { + let q = item.system.quantity || 1 + capacity += Number(q) * Number(item.system.weight) + } + console.log("capa", capacity, this.system.cargo.cargocapacity) + if (capacity > this.system.cargo.cargocapacity) { + ui.notifications.warn("Your cargo capacity is already full, unable to add this content : " + item.name) + return false + } + } + + return true } - // Check size - if (item.type == "vehiclemodule" || item.type == "vehicleweaponmodule") { - item.system.space = item.system?.space || 0 - if (this.system.modules.usedvms + Number(item.system.space) > this.system.modules.totalvms) { - ChatMessage.create({ content: `No more room available to host module ${item.name}. Module is not added to the vehicle.` }) - return false + + /* -------------------------------------------- */ + getCrewList() { + let crew = [] + for (let actorDef of this.system.crew) { + let actor = game.actors.get(actorDef.id) + if (actor) { + crew.push({ name: actor.name, img: actor.img, id: actor.id }) + } } + return crew } - // Cargo management - if (__isVehicleCargo[item.type]) { - let capacity = this.getCurrentCargoCapacity() - if (item.type == "cargo") { - capacity += Number(item.system.capacity) - } else { - let q = item.system.quantity || 1 - capacity += Number(q) * Number(item.system.weight) + + addCrew(actorId) { + if (this.system.crew.length >= this.system.crewmax) { + ui.notifications.warn("Vehicle crew is already full.") + return } - console.log("capa", capacity, this.system.cargo.cargocapacity) - if (capacity > this.system.cargo.cargocapacity) { - ui.notifications.warn("Your cargo capacity is already full, unable to add this content : " + item.name) - return false + let crewList = duplicate(this.system.crew.filter(actorDef => actorDef.id != actorId) || []) + crewList.push({ id: actorId }) + this.update({ 'system.crew': crewList }) + } + delCrew(actorId) { + let crewList = duplicate(this.system.crew.filter(actorDef => actorDef.id != actorId) || []) + this.update({ 'system.crew': crewList }) + } + inCrew(actorId) { + return this.system.crew.find(member => member.id == actorId) + } + + /* -------------------------------------------- */ + isVehicleFullStop() { + return this.system.statistics.ad.currentspeed == "fullstop" + } + isVehicleCrawling() { + return this.system.statistics.ad.currentspeed == "crawling" + } + isVehicleSlow() { + return this.system.statistics.ad.currentspeed == "slow" + } + isVehicleAverage() { + return this.system.statistics.ad.currentspeed == "average" + } + isVehicleFast() { + return this.system.statistics.ad.currentspeed == "fast" + } + isVehicleExFast() { + return this.system.statistics.ad.currentspeed == "extfast" + } + + /* -------------------------------------------- */ + isValidActor() { + // Find relevant actor + let actor + for (let actorDef of this.system.crew) { + let actorTest = game.actors.get(actorDef.id) + if (actorTest.testUserPermission(game.user, "OWNER")) { + return actorTest + } + } + if (!actor) { + ui.notifications.warn("You do no own any actors in the crew of this vehicle.") + return + } } - return true -} - -/* -------------------------------------------- */ -getCrewList() { - let crew = [] - for (let actorDef of this.system.crew) { - let actor = game.actors.get(actorDef.id) + /* -------------------------------------------- */ + rollPoolFromVehicle(statKey, useShield = false, subKey = "none") { + let actor = this.isValidActor() if (actor) { - crew.push({ name: actor.name, img: actor.img, id: actor.id }) + actor.rollPool(statKey, useShield, subKey, this) } } - return crew -} -addCrew(actorId) { - if (this.system.crew.length >= this.system.crewmax) { - ui.notifications.warn("Vehicle crew is already full.") - return - } - let crewList = duplicate(this.system.crew.filter(actorDef => actorDef.id != actorId) || []) - crewList.push({ id: actorId }) - this.update({ 'system.crew': crewList }) -} -delCrew(actorId) { - let crewList = duplicate(this.system.crew.filter(actorDef => actorDef.id != actorId) || []) - this.update({ 'system.crew': crewList }) -} -inCrew(actorId) { - return this.system.crew.find(member => member.id == actorId) -} - -/* -------------------------------------------- */ -isVehicleFullStop() { - return this.system.statistics.ad.currentspeed == "fullstop" -} -isVehicleCrawling() { - return this.system.statistics.ad.currentspeed == "crawling" -} -isVehicleSlow() { - return this.system.statistics.ad.currentspeed == "slow" -} -isVehicleAverage() { - return this.system.statistics.ad.currentspeed == "average" -} -isVehicleFast() { - return this.system.statistics.ad.currentspeed == "fast" -} -isVehicleExFast() { - return this.system.statistics.ad.currentspeed == "extfast" -} - -/* -------------------------------------------- */ -isValidActor() { - // Find relevant actor - let actor - for (let actorDef of this.system.crew) { - let actorTest = game.actors.get(actorDef.id) - if (actorTest.testUserPermission(game.user, "OWNER")) { - return actorTest + /* -------------------------------------------- */ + addVehicleShields(rollData) { + for (let arcKey in this.system.arcs) { + let arc = this.system.arcs[arcKey] + if (arc.shieldlevel > 0) { + rollData.vehicleShieldList.push({ label: `${arc.label} Shield`, type: "vehicleshield", applied: false, value: arc.shieldlevel }) + } } } - if (!actor) { - ui.notifications.warn("You do no own any actors in the crew of this vehicle.") - return - } -} - -/* -------------------------------------------- */ -rollPoolFromVehicle(statKey, useShield = false, subKey = "none") { - let actor = this.isValidActor() - if (actor) { - actor.rollPool(statKey, useShield, subKey, this) - } -} - -/* -------------------------------------------- */ -addVehicleShields(rollData) { - for (let arcKey in this.system.arcs) { - let arc = this.system.arcs[arcKey] - if (arc.shieldlevel > 0) { - rollData.vehicleShieldList.push({ label: `${arc.label} Shield`, type: "vehicleshield", applied: false, value: arc.shieldlevel }) + /* -------------------------------------------- */ + addVehicleArmors(rollData) { + for (let arcKey in this.system.arcs) { + let arc = this.system.arcs[arcKey] + if (arc.armourlevel > 0) { + rollData.vehicleShieldList.push({ label: `${arc.label} Armor`, type: "vehicleshield", applied: false, value: arc.armourlevel }) + } } } -} -/* -------------------------------------------- */ -addVehicleArmors(rollData) { - for (let arcKey in this.system.arcs) { - let arc = this.system.arcs[arcKey] - if (arc.armourlevel > 0) { - rollData.vehicleShieldList.push({ label: `${arc.label} Armor`, type: "vehicleshield", applied: false, value: arc.armourlevel }) + /* -------------------------------------------- */ + rollVehicleDamageResistance() { + let actor = this.isValidActor() + if (actor) { + let stat = this.getStat("hr") + let rollData = this.getCommonRollData("hr") + rollData.vehicle = duplicate(this) + rollData.isVehicleStun = true + rollData.mode = "stat" + rollData.title = `Stat ${stat.label}` + + this.addVehicleArmors(rollData) + this.startRoll(rollData) } } -} - -/* -------------------------------------------- */ -rollVehicleDamageResistance() { - let actor = this.isValidActor() - if (actor) { - let stat = this.getStat("hr") - let rollData = this.getCommonRollData("hr") - rollData.vehicle = duplicate(this) - rollData.isVehicleStun = true - rollData.mode = "stat" - rollData.title = `Stat ${stat.label}` - - this.addVehicleArmors(rollData) - this.startRoll(rollData) - } -} /* -------------------------------------------- */ async activateVehicleModule(itemId) { - let mod = this.items.get(itemId) - if (mod) { - if (mod.system.nrg && mod.system.nrg > 0) { - let pc = duplicate(this.system.statistics.pc) - if (!mod.system.activated) { // Previous state was non activated -> activated now - if (mod.system.nrg > pc.curnrg) { - ChatMessage.create({ content: `The Vehicle ${this.name} does not have enough Energy to Activate this module at this time.` }) - return + let mod = this.items.get(itemId) + if (mod) { + if (mod.system.nrg && mod.system.nrg > 0) { + let pc = duplicate(this.system.statistics.pc) + if (!mod.system.activated) { // Previous state was non activated -> activated now + if (mod.system.nrg > pc.curnrg) { + ChatMessage.create({ content: `The Vehicle ${this.name} does not have enough Energy to Activate this module at this time.` }) + return + } + await this.updateEmbeddedDocuments('Item', [{ _id: mod.id, 'system.activated': !mod.system.activated }]) + pc.actnrg += Number(mod.system.nrg) + pc.maxnrg -= Number(mod.system.nrg) + pc.curnrg -= Number(mod.system.nrg) + this.update({ 'system.statistics.pc': pc }) + } else { // Now deactivated + pc.actnrg -= Number(mod.system.nrg) + pc.maxnrg += Number(mod.system.nrg) + this.update({ 'system.statistics.pc': pc }) + await this.updateEmbeddedDocuments('Item', [{ _id: mod.id, 'system.activated': !mod.system.activated }]) } - await this.updateEmbeddedDocuments('Item', [{ _id: mod.id, 'system.activated': !mod.system.activated }]) - pc.actnrg += Number(mod.system.nrg) - pc.maxnrg -= Number(mod.system.nrg) - pc.curnrg -= Number(mod.system.nrg) - this.update({ 'system.statistics.pc': pc }) - } else { // Now deactivated - pc.actnrg -= Number(mod.system.nrg) - pc.maxnrg += Number(mod.system.nrg) - this.update({ 'system.statistics.pc': pc }) + } else { await this.updateEmbeddedDocuments('Item', [{ _id: mod.id, 'system.activated': !mod.system.activated }]) } - } else { - await this.updateEmbeddedDocuments('Item', [{ _id: mod.id, 'system.activated': !mod.system.activated }]) } + + this.processVehicleArmorShields() } - this.processVehicleArmorShields() -} - -/* -------------------------------------------- */ -processVehicleArmorShields() { - // Shield management - let shieldsList = this.items.filter(item => item.type == "vehiclemodule" && item.system.category == "shield" && item.system.activated) || [] - let level = 0 - for (let armour of shieldsList) { - if (armour.system.shielddicevalue > 0) { - level += Number(armour.system.shielddicevalue) - } - } - let shift = 500 - for (let loc of __LocationsArmour) { - let arcKey = loc + "arc" - let arc = duplicate(this.system.arcs[arcKey]) - if (level != Number(arc.shieldlevel)) { - arc.shieldlevel = level - setTimeout(shift, this.update({ [`system.arcs.${arcKey}`]: arc })) - shift += 200 - } - } - - // Armour management - let armorsList = this.items.filter(item => item.type == "vehiclemodule" && item.system.category == "armor" && item.system.activated) || [] - for (let loc of __LocationsArmour) { - let arcKey = loc + "arc" - let arc = duplicate(this.system.arcs[arcKey]) + /* -------------------------------------------- */ + processVehicleArmorShields() { + // Shield management + let shieldsList = this.items.filter(item => item.type == "vehiclemodule" && item.system.category == "shield" && item.system.activated) || [] let level = 0 - for (let armour of armorsList) { - if (armour.system.location == loc && armour.system.armourdicevalue > 0) { - level += Number(armour.system.armourdicevalue) + for (let armour of shieldsList) { + if (armour.system.shielddicevalue > 0) { + level += Number(armour.system.shielddicevalue) } } - if (level != Number(arc.armourlevel)) { - arc.armourlevel = level - setTimeout(500, this.update({ [`system.arcs.${arcKey}`]: arc })) + let shift = 500 + for (let loc of __LocationsArmour) { + let arcKey = loc + "arc" + let arc = duplicate(this.system.arcs[arcKey]) + if (level != Number(arc.shieldlevel)) { + arc.shieldlevel = level + setTimeout(shift, this.update({ [`system.arcs.${arcKey}`]: arc })) + shift += 200 + } + } + + // Armour management + let armorsList = this.items.filter(item => item.type == "vehiclemodule" && item.system.category == "armor" && item.system.activated) || [] + for (let loc of __LocationsArmour) { + let arcKey = loc + "arc" + let arc = duplicate(this.system.arcs[arcKey]) + let level = 0 + for (let armour of armorsList) { + if (armour.system.location == loc && armour.system.armourdicevalue > 0) { + level += Number(armour.system.armourdicevalue) + } + } + if (level != Number(arc.armourlevel)) { + arc.armourlevel = level + setTimeout(500, this.update({ [`system.arcs.${arcKey}`]: arc })) + } } } -} -/* -------------------------------------------- */ -updateMaxNrg(currentLevel) { - this.update({ 'system.statistics.pc.maxnrg': Number(currentLevel) }) -} -/* -------------------------------------------- */ -setTurningArc(currentLevel) { - this.update({ 'system.statistics.man.turningarc45': Number(currentLevel) }) -} - -/* -------------------------------------------- */ -getCurrentCargoCapacity() { - let capacity = 0 - for (let cargo of this.items) { - if (cargo.type == "equipment" || cargo.type == "weapon" || cargo.type == "armor" || cargo.type == "money" || cargo.type == "shield") { - let q = cargo.system.quantity || 1 - capacity += Number(q) * Number(cargo.system.weight) - } - if (cargo.type == "cargo") { - capacity += Number(cargo.system.capacity) - } + /* -------------------------------------------- */ + updateMaxNrg(currentLevel) { + this.update({ 'system.statistics.pc.maxnrg': Number(currentLevel) }) + } + /* -------------------------------------------- */ + setTurningArc(currentLevel) { + this.update({ 'system.statistics.man.turningarc45': Number(currentLevel) }) + } + + /* -------------------------------------------- */ + getCurrentCargoCapacity() { + let capacity = 0 + for (let cargo of this.items) { + if (cargo.type == "equipment" || cargo.type == "weapon" || cargo.type == "armor" || cargo.type == "money" || cargo.type == "shield") { + let q = cargo.system.quantity || 1 + capacity += Number(q) * Number(cargo.system.weight) + } + if (cargo.type == "cargo") { + capacity += Number(cargo.system.capacity) + } + } + return capacity } - return capacity -} } diff --git a/templates/partial-vehicle-stat-block.html b/templates/partial-vehicle-stat-block.html index 1196ff3..8ebed7a 100644 --- a/templates/partial-vehicle-stat-block.html +++ b/templates/partial-vehicle-stat-block.html @@ -14,7 +14,7 @@