diff --git a/.history/modules/mournblade-cyd2-actor_20251026001301.js b/.history/modules/mournblade-cyd2-actor_20251026001301.js deleted file mode 100644 index 24a1abe..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026001301.js +++ /dev/null @@ -1,811 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026001548.js b/.history/modules/mournblade-cyd2-actor_20251026001548.js deleted file mode 100644 index 24a1abe..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026001548.js +++ /dev/null @@ -1,811 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026002613.js b/.history/modules/mournblade-cyd2-actor_20251026002613.js deleted file mode 100644 index fcbc134..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026002613.js +++ /dev/null @@ -1,822 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026002719.js b/.history/modules/mournblade-cyd2-actor_20251026002719.js deleted file mode 100644 index fcbc134..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026002719.js +++ /dev/null @@ -1,822 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082021.js b/.history/modules/mournblade-cyd2-actor_20251026082021.js deleted file mode 100644 index 2657656..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082021.js +++ /dev/null @@ -1,828 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082036.js b/.history/modules/mournblade-cyd2-actor_20251026082036.js deleted file mode 100644 index 81caa70..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082036.js +++ /dev/null @@ -1,847 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082126.js b/.history/modules/mournblade-cyd2-actor_20251026082126.js deleted file mode 100644 index b07a59e..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082126.js +++ /dev/null @@ -1,852 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082146.js b/.history/modules/mournblade-cyd2-actor_20251026082146.js deleted file mode 100644 index 6907fbb..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082146.js +++ /dev/null @@ -1,867 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == this.system.ame.nbame - 3 || ame.etat == this.system.ame.nbame - 2 || ame.etat == this.system.ame.nbame - 1) { - if (ame.etat == this.system.ame.nbame - 3) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 2) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 1) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082203.js b/.history/modules/mournblade-cyd2-actor_20251026082203.js deleted file mode 100644 index 7b6f6ef..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082203.js +++ /dev/null @@ -1,882 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - ame.etat = Math.min(ame.etat, this.system.ame.nbame - 1) - this.update({ 'system.ame': ame }) - if (ame.etat == this.system.ame.nbame - 1) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == this.system.ame.nbame - 3 || ame.etat == this.system.ame.nbame - 2 || ame.etat == this.system.ame.nbame - 1) { - if (ame.etat == this.system.ame.nbame - 3) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 2) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 1) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082310.js b/.history/modules/mournblade-cyd2-actor_20251026082310.js deleted file mode 100644 index d8049de..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082310.js +++ /dev/null @@ -1,882 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - ame.etat = Math.min(ame.etat, this.system.ame.nbame - 1) - this.update({ 'system.ame': ame }) - if (ame.etat == this.system.ame.nbame - 1) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == this.system.ame.nbame - 3 || ame.etat == this.system.ame.nbame - 2 || ame.etat == this.system.ame.nbame - 1) { - if (ame.etat == this.system.ame.nbame - 3) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 2) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 1) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082551.js b/.history/modules/mournblade-cyd2-actor_20251026082551.js deleted file mode 100644 index 2b6b4d9..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082551.js +++ /dev/null @@ -1,884 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == this.system.ame.nbame - 3 || ame.etat == this.system.ame.nbame - 2 || ame.etat == this.system.ame.nbame - 1) { - if (ame.etat == this.system.ame.nbame - 3) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 2) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat == this.system.ame.nbame - 1) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082604.js b/.history/modules/mournblade-cyd2-actor_20251026082604.js deleted file mode 100644 index dfe8444..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082604.js +++ /dev/null @@ -1,888 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082619.js b/.history/modules/mournblade-cyd2-actor_20251026082619.js deleted file mode 100644 index d2dabe2..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082619.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026082724.js b/.history/modules/mournblade-cyd2-actor_20251026082724.js deleted file mode 100644 index d2dabe2..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026082724.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083107.js b/.history/modules/mournblade-cyd2-actor_20251026083107.js deleted file mode 100644 index 137cd4c..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083107.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // S'assurer que l'état ne dépasse pas le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - if (changed.system.ame.etat < 0) { - changed.system.ame.etat = 0 - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le maximum d'âme change, s'assurer que l'état actuel ne le dépasse pas - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083143.js b/.history/modules/mournblade-cyd2-actor_20251026083143.js deleted file mode 100644 index 6d2b2cd..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083143.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // S'assurer que l'état ne dépasse pas le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - if (changed.system.ame.etat < 0) { - changed.system.ame.etat = 0 - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le maximum d'âme change, s'assurer que l'état actuel ne le dépasse pas - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083155.js b/.history/modules/mournblade-cyd2-actor_20251026083155.js deleted file mode 100644 index 6d2b2cd..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083155.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // S'assurer que l'état ne dépasse pas le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - if (changed.system.ame.etat < 0) { - changed.system.ame.etat = 0 - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le maximum d'âme change, s'assurer que l'état actuel ne le dépasse pas - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083156.js b/.history/modules/mournblade-cyd2-actor_20251026083156.js deleted file mode 100644 index 8955866..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083156.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // S'assurer que l'état ne dépasse pas le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - if (changed.system.ame.etat < 0) { - changed.system.ame.etat = 0 - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le maximum d'âme change, s'assurer que l'état actuel ne le dépasse pas - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083157.js b/.history/modules/mournblade-cyd2-actor_20251026083157.js deleted file mode 100644 index 8955866..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083157.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // S'assurer que l'état ne dépasse pas le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - if (changed.system.ame.etat < 0) { - changed.system.ame.etat = 0 - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le maximum d'âme change, s'assurer que l'état actuel ne le dépasse pas - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083444.js b/.history/modules/mournblade-cyd2-actor_20251026083444.js deleted file mode 100644 index 7d1b577..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083444.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083447.js b/.history/modules/mournblade-cyd2-actor_20251026083447.js deleted file mode 100644 index 249612f..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083447.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083449.js b/.history/modules/mournblade-cyd2-actor_20251026083449.js deleted file mode 100644 index d2dabe2..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083449.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083504.js b/.history/modules/mournblade-cyd2-actor_20251026083504.js deleted file mode 100644 index d2dabe2..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083504.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083833.js b/.history/modules/mournblade-cyd2-actor_20251026083833.js deleted file mode 100644 index 972b12a..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083833.js +++ /dev/null @@ -1,904 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // Limiter l'état d'Âme au maximum défini - let maxAme = this.system.ame.max || this.system.ame.nbame - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083905.js b/.history/modules/mournblade-cyd2-actor_20251026083905.js deleted file mode 100644 index ebef197..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083905.js +++ /dev/null @@ -1,904 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // Limiter l'état d'Âme au maximum défini - let maxAme = this.system.ame.max || this.system.ame.nbame - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = this.system.ame.max || this.system.ame.nbame - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame - 1) - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 2 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083918.js b/.history/modules/mournblade-cyd2-actor_20251026083918.js deleted file mode 100644 index 2188fb5..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083918.js +++ /dev/null @@ -1,904 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // Limiter l'état d'Âme au maximum défini - let maxAme = this.system.ame.max || this.system.ame.nbame - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = this.system.ame.max || this.system.ame.nbame - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = this.system.ame.max || this.system.ame.nbame - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026083937.js b/.history/modules/mournblade-cyd2-actor_20251026083937.js deleted file mode 100644 index 2188fb5..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026083937.js +++ /dev/null @@ -1,904 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // Limiter l'état d'Âme au maximum défini - let maxAme = this.system.ame.max || this.system.ame.nbame - if (changed.system.ame.etat > maxAme) { - changed.system.ame.etat = maxAme - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat > changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = this.system.ame.max || this.system.ame.nbame - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = this.system.ame.max || this.system.ame.nbame - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026084242.js b/.history/modules/mournblade-cyd2-actor_20251026084242.js deleted file mode 100644 index 53ac75e..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026084242.js +++ /dev/null @@ -1,908 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - ame.etat = Math.max(ame.etat, 0) - // L'état ne peut pas dépasser le maximum actuel d'âme - let maxAme = this.system.ame.max || this.system.ame.nbame - ame.etat = Math.min(ame.etat, maxAme) - this.update({ 'system.ame': ame }) - if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = this.system.ame.max || this.system.ame.nbame - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026084254.js b/.history/modules/mournblade-cyd2-actor_20251026084254.js deleted file mode 100644 index e8feba3..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026084254.js +++ /dev/null @@ -1,909 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let maxAme = this.system.ame.max || this.system.ame.nbame - // Gestion des états Traumatisé, Très Traumatisé et Brisé en fonction du maximum actuel - // Les seuils sont calculés par rapport au maximum d'âme actuel - if (maxAme >= 3 && ame.etat >= maxAme - 2) { - if (ame.etat == maxAme - 2) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == maxAme - 1) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } else if (ame.etat >= maxAme) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026084306.js b/.history/modules/mournblade-cyd2-actor_20251026084306.js deleted file mode 100644 index 16df549..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026084306.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026084418.js b/.history/modules/mournblade-cyd2-actor_20251026084418.js deleted file mode 100644 index d0baf54..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026084418.js +++ /dev/null @@ -1,907 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - return Math.min(this.system.ame.max || this.system.ame.nbame, this.system.ame.nbame) - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026084727.js b/.history/modules/mournblade-cyd2-actor_20251026084727.js deleted file mode 100644 index b0b3dc0..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026084727.js +++ /dev/null @@ -1,908 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026084815.js b/.history/modules/mournblade-cyd2-actor_20251026084815.js deleted file mode 100644 index b0b3dc0..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026084815.js +++ /dev/null @@ -1,908 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - if (this.type == "cellule") { - return arme - } - - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026095752.js b/.history/modules/mournblade-cyd2-actor_20251026095752.js deleted file mode 100644 index 3660760..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026095752.js +++ /dev/null @@ -1,904 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - if (this.type == "cellule") { - return { - initBase: 0, - initTotal: 0, - bonusDegats: 0, - bonusDegatsTotal: 0, - vitesseBase: 0, - vitesseTotal: 0, - defenseBase: 0, - protection: 0, - defenseTotal: 0 - } - } - - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026095804.js b/.history/modules/mournblade-cyd2-actor_20251026095804.js deleted file mode 100644 index ab7746f..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026095804.js +++ /dev/null @@ -1,890 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026100139.js b/.history/modules/mournblade-cyd2-actor_20251026100139.js deleted file mode 100644 index ab7746f..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026100139.js +++ /dev/null @@ -1,890 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé !` }) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé !` }) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé !` }) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026100634.js b/.history/modules/mournblade-cyd2-actor_20251026100634.js deleted file mode 100644 index a2c5c87..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026100634.js +++ /dev/null @@ -1,895 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026100656.js b/.history/modules/mournblade-cyd2-actor_20251026100656.js deleted file mode 100644 index a2c5c87..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026100656.js +++ /dev/null @@ -1,895 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026103947.js b/.history/modules/mournblade-cyd2-actor_20251026103947.js deleted file mode 100644 index f7301cf..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026103947.js +++ /dev/null @@ -1,896 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - cons - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026132457.js b/.history/modules/mournblade-cyd2-actor_20251026132457.js deleted file mode 100644 index 0520df0..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026132457.js +++ /dev/null @@ -1,893 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026132651.js b/.history/modules/mournblade-cyd2-actor_20251026132651.js deleted file mode 100644 index d1f46ec..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026132651.js +++ /dev/null @@ -1,890 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026132939.js b/.history/modules/mournblade-cyd2-actor_20251026132939.js deleted file mode 100644 index d1f46ec..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026132939.js +++ /dev/null @@ -1,890 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getContacts() { - return this.getItemSorted(["contact"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026133228.js b/.history/modules/mournblade-cyd2-actor_20251026133228.js deleted file mode 100644 index 6a5a8a8..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026133228.js +++ /dev/null @@ -1,887 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026133244.js b/.history/modules/mournblade-cyd2-actor_20251026133244.js deleted file mode 100644 index 6a5a8a8..0000000 --- a/.history/modules/mournblade-cyd2-actor_20251026133244.js +++ /dev/null @@ -1,887 +0,0 @@ -/* -------------------------------------------- */ -import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; - -/* -------------------------------------------- */ -const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] -const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8] - -/* -------------------------------------------- */ -/** - * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. - * @extends {Actor} - */ -export class MournbladeCYD2Actor extends Actor { - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional SoS functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} data Barebones actor data which this function adds onto. - * @param {Object} options (Unused) Additional options which customize the creation workflow. - * - */ - - static async create(data, options) { - - // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); - } - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); - return actor; - } - - if (data.type == 'personnage') { - console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") - data.items = skills.map(i => i.toObject()) - } - if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") - data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - } - - return super.create(data, options); - } - - /* -------------------------------------------- */ - getBonusDefenseFromTalents() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - prepareArme(arme) { - arme = foundry.utils.duplicate(arme) - let combat = this.getCombatValues() - if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { - let bonusDefense = this.getBonusDefenseFromTalents() - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")) - arme.system.attrKey = "pui" - arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal - arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0) - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0) - console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense) - arme.system.isdefense = true - arme.system.isMelee = true - arme.system.isDistance = false - } - if (arme.system.typearme == "jet" || arme.system.typearme == "tir") { - arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")) - arme.system.attrKey = "adr" - arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff - arme.system.totalDegats = arme.system.degats - arme.system.isMelee = false - arme.system.isDistance = true - if (arme.system.isdefense) { - arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense - } - } - return arme - } - - /* -------------------------------------------- */ - getItemSorted(types) { - let items = this.items.filter(item => types.includes(item.type)) || [] - MournbladeCYD2Utility.sortArrayObjectsByName(items) - return items - } - getWeapons() { - let armes = [] - for (let arme of this.items) { - if (arme.type == "arme") { - armes.push(this.prepareArme(arme)) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(armes) - return armes - } - getMonnaies() { - return this.getItemSorted(["monnaie"]) - } - getEquipments() { - return this.getItemSorted(["equipement"]) - } - getArmors() { - return this.getItemSorted(["protection"]) - } - getHistoriques() { - return this.getItemSorted(["historique"]) - } - getProfils() { - return this.getItemSorted(["profil"]) - } - getTalents() { - return this.getItemSorted(["talent"]) - } - getRessources() { - return this.getItemSorted(["ressource"]) - } - getDons() { - return this.getItemSorted(["don"]) - } - getPactes() { - return this.getItemSorted(["pacte"]) - } - getTendances() { - return this.getItemSorted(["tendance"]) - } - getRunes() { - return this.getItemSorted(["rune"]) - } - getTraitsChaotiques() { - return this.getItemSorted(["traitchaotique"]) - } - getTraitsEspeces() { - return this.getItemSorted(["traitespece"]) - } - - /* -------------------------------------------- */ - getAspect() { - return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos - } - getMarge() { - return Math.abs(this.system.balance.loi - this.system.balance.chaos) - } - getAlignement() { - return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique" - } - - /* -------------------------------------------- */ - getSkills() { - let comp = [] - for (let item of this.items) { - item = foundry.utils.duplicate(item) - if (item.type == "competence") { - item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0) - item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0) - item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0) - if (item.system.niveau == 0) { - item.system.attribut1total -= 3 - item.system.attribut2total -= 3 - item.system.attribut3total -= 3 - } - item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || "" - item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || "" - item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || "" - comp.push(item) - } - } - MournbladeCYD2Utility.sortArrayObjectsByName(comp) - return comp - } - - /* ----------------------- --------------------- */ - addMember(actorId) { - let members = foundry.utils.duplicate(this.system.members) - members.push({ id: actorId }) - this.update({ 'system.members': members }) - } - async removeMember(actorId) { - let members = this.system.members.filter(it => it.id != actorId) - this.update({ 'system.members': members }) - } - - /* -------------------------------------------- */ - getDefenseBase() { - return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value) - } - - /* -------------------------------------------- */ - getVitesseBase() { - return 5 + __vitesseBonus[this.system.attributs.adr.value] - } - /* -------------------------------------------- */ - getProtection() { - let equipProtection = 0 - for (let armor of this.items) { - if (armor.type == "protection" && armor.system.equipped) { - equipProtection += Number(armor.system.protection) - } - } - if (equipProtection < 4) { - return 4 + equipProtection // Cas des boucliers + sans armure - } - return equipProtection // Uniquement la protection des armures + boucliers - } - - /* -------------------------------------------- */ - getCombatValues() { - let combat = { - initBase: this.system.attributs.adr.value, - initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, - bonusDegats: this.getBonusDegats(), - bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats, - vitesseBase: this.getVitesseBase(), - vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus, - defenseBase: this.getDefenseBase(), - protection: this.getProtection(), - defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0) - } - return combat - } - - /* -------------------------------------------- */ - prepareBaseData() { - } - - /* -------------------------------------------- */ - async prepareData() { - super.prepareData(); - } - - /* -------------------------------------------- */ - prepareDerivedData() { - - if (this.type == 'personnage') { - let talentBonus = this.getVigueurBonus() - let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier - if (vigueur != this.system.sante.vigueur) { - this.update({ 'system.sante.vigueur': vigueur }) - } - - let seuilPouvoirBonus = this.getSeuilPouvoirBonus() - let seuilPouvoir = Math.floor((this.system.attributs.tre.value + this.system.attributs.cla.value) / 2) + seuilPouvoirBonus + this.system.ame.seuilpouvoirmodifier - if (seuilPouvoir != this.system.ame.seuilpouvoir) { - this.update({ 'system.ame.seuilpouvoir': seuilPouvoir }) - } - } - super.prepareDerivedData() - } - - /* -------------------------------------------- */ - _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { - setTimeout(() => { - this.processCombativite(changed.system.sante) - }, 800) - } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { - // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - if (changed.system.ame.etat < minAme) { - changed.system.ame.etat = minAme - } - // L'état d'Âme ne peut pas dépasser nbame (Brisé) - if (changed.system.ame.etat > this.system.ame.nbame) { - changed.system.ame.etat = this.system.ame.nbame - } - setTimeout(() => { - this.processAme(changed.system.ame) - }, 800) - } - // Si le max d'Âme change, ajuster l'état actuel si nécessaire - if (changed?.system?.ame?.max !== undefined && changed.system.ame.max != this.system.ame.max) { - if (this.system.ame.etat < changed.system.ame.max) { - changed.system.ame.etat = changed.system.ame.max - } - } - super._preUpdate(changed, options, user); - } - - /* -------------------------------------------- */ - _onUpdate(data, options, user) { - super._onUpdate(data, options, user); - } - /* -------------------------------------------- */ - getItemById(id) { - let item = this.items.find(item => item.id == id); - if (item) { - item = foundry.utils.duplicate(item) - } - return item; - } - - /* -------------------------------------------- */ - async equipItem(itemId) { - let item = this.items.find(item => item.id == itemId) - if (item && item.system) { - let update = { _id: item.id, "system.equipped": !item.system.equipped } - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - editItemField(itemId, itemType, itemField, dataType, value) { - let item = this.items.find(item => item.id == itemId) - if (item) { - console.log("Item ", item, itemField, dataType, value) - if (dataType.toLowerCase() == "number") { - value = Number(value) - } else { - value = String(value) - } - let update = { _id: item.id, [`system.${itemField}`]: value }; - this.updateEmbeddedDocuments("Item", [update]) - } - } - - /* -------------------------------------------- */ - checkAttribut(attribut, minLevel) { - let attr = this.system.attributs.find(at => at.labelnorm == attribut.toLowerCase()) - if (attr && attr.value >= minLevel) { - return { isValid: true, attr: foundry.utils.duplicate(attr) } - } - return { isValid: false } - } - /* -------------------------------------------- */ - checkAttributOrCompetenceLevel(compName, minLevel) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel) - if (comp) { - return { isValid: true, item: foundry.utils.duplicate(comp) } - } else { - for (let attrKey in this.system.attributs) { - if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) { - return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) } - } - } - } - return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` } - } - /* -------------------------------------------- */ - addCompetenceBonus(compName, bonus, baCost) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - comp = foundry.utils.duplicate(comp) - comp.system.bonus = bonus - comp.system.baCost = baCost - return { isValid: true, item: comp } - } - return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` } - } - /* -------------------------------------------- */ - checkIfCompetence(compName) { - let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase()) - if (comp) { - return { isValid: true, item: comp } - } - return { isValid: false } - } - /* -------------------------------------------- */ - getVigueur() { - return this.system.sante.vigueur - } - - /* -------------------------------------------- */ - getVigueurBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getSeuilPouvoir() { - return this.system.ame.seuilpouvoir - } - - /* -------------------------------------------- */ - getSeuilPouvoirBonus() { - let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated) - let bonus = 0 - for (let talent of talents) { - for (let auto of talent.system.automations) { - if (auto.eventtype == "bonus-permanent" && auto.bonusname == "seuilpouvoir") { - bonus += Number(auto.bonus || 0) - } - } - } - return bonus - } - - /* -------------------------------------------- */ - getAmeMax() { - // Utiliser une vérification stricte car 0 (Serein) est une valeur valide - return this.system.ame.max !== undefined ? this.system.ame.max : this.system.ame.nbame - } - - /* -------------------------------------------- */ - getBonneAventure() { - return this.system.bonneaventure.actuelle - } - /* -------------------------------------------- */ - checkBonneAventure(cost) { - return (this.system.bonneaventure.actuelle >= cost) - } - /* -------------------------------------------- */ - changeBonneAventure(value) { - let newBA = this.system.bonneaventure.actuelle - newBA += value - this.update({ 'system.bonneaventure.actuelle': newBA }) - } - - /* -------------------------------------------- */ - getEclat() { - return this.system.eclat.value - } - - /* -------------------------------------------- */ - changeEclat(value) { - let newE = this.system.eclat.value - newE += value - this.update({ 'system.eclat.value': newE }) - } - - /* -------------------------------------------- */ - compareName(a, b) { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - } - - /* -------------------------------------------- */ - getAttribute(attrKey) { - return this.system.attributes[attrKey] - } - - /* -------------------------------------------- */ - getBonusDegats() { - return 0; - } - - /* -------------------------------------------- */ - changeEtatCombativite(value) { - if (value === "vaincu") { - value = 200 - } - let sante = foundry.utils.duplicate(this.system.sante) - sante.etat += Number(value) - sante.etat = Math.max(sante.etat, 0) - sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite) - this.update({ 'system.sante': sante }) - if (sante.etat == this.system.sante.nbcombativite) { - ChatMessage.create({ content: `${this.name} est vaincu !` }) - } - // Duplicated ! this.processCombativite(sante) - } - - /* -------------------------------------------- */ - changeEtatAme(value) { - if (value === "brise") { - value = 200 - } - let ame = foundry.utils.duplicate(this.system.ame) - ame.etat += Number(value) - // L'état ne peut pas être inférieur au minimum (max dans le système) - let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 - ame.etat = Math.max(ame.etat, minAme) - // L'état ne peut pas dépasser nbame (Brisé) - ame.etat = Math.min(ame.etat, this.system.ame.nbame) - this.update({ 'system.ame': ame }) - if (ame.etat >= this.system.ame.nbame) { - ChatMessage.create({ content: `${this.name} est brisé !` }) - } - } - - /* -------------------------------------------- */ - processCombativite(sante) { - sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) - } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) - this.incDecAdversite("rouge", 2) - } - } - } - - /* -------------------------------------------- */ - processAme(ame) { - ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame - - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { - ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { - ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) - this.incDecAdversite("bleue", 1) - this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { - ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) - this.incDecAdversite("noire", 1) - } - } - - /* -------------------------------------------- */ - async equipGear(equipmentId) { - let item = this.items.find(item => item.id == equipmentId); - if (item?.system?.data) { - let update = { _id: item.id, "system.equipped": !item.system.equipped }; - await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - getSubActors() { - let subActors = []; - for (let id of this.system.subactors) { - subActors.push(foundry.utils.duplicate(game.actors.get(id))); - } - return subActors; - } - /* -------------------------------------------- */ - async addSubActor(subActorId) { - let subActors = foundry.utils.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 }); - } - - /* -------------------------------------------- */ - getTotalAdversite() { - return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire - } - - /* -------------------------------------------- */ - async incDecAdversite(adv, incDec = 0) { - let adversite = foundry.utils.duplicate(this.system.adversite) - adversite[adv] += Number(incDec) - adversite[adv] = Math.max(adversite[adv], 0) - adversite[adv] = Math.min(adversite[adv], 20) - this.update({ 'system.adversite': adversite }) - } - /* -------------------------------------------- */ - async incDecQuantity(objetId, incDec = 0) { - let objetQ = this.items.get(objetId) - if (objetQ) { - let newQ = objetQ.system.quantite + incDec - newQ = Math.max(newQ, 0) - await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity - } - } - - /* -------------------------------------------- */ - computeRichesse() { - let valueSC = 0 - for (let monnaie of this.items) { - if (monnaie.type == "monnaie") { - valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite) - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - computeValeurEquipement() { - let valueSC = 0 - for (let equip of this.items) { - if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") { - valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1) - valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20 - valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400 - } - } - return MournbladeCYD2Utility.computeMonnaieDetails(valueSC) - } - - /* -------------------------------------------- */ - getCompetence(compId) { - return this.items.get(compId) - } - - /* -------------------------------------------- */ - async setPredilectionUsed(compId, predIdx) { - let comp = this.items.get(compId) - let pred = foundry.utils.duplicate(comp.system.predilections) - pred[predIdx].used = true - await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }]) - } - - /* -------------------------------------------- */ - getInitiativeScore() { - let init = this.getFlag("world", "last-initiative") - return init || -1 - } - - /* -------------------------------------------- */ - getBestAttackValue() { - let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped) - let maxOff = 0 - let bestArme - for (let arme of attackList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalOffensif > maxOff) { - maxOff = arme.system.totalOffensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - getBestDefenseValue() { - let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) - let maxDef = 0 - let bestArme - for (let arme of defenseList) { - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - if (arme.system.totalDefensif > maxDef) { - maxDef = arme.system.totalDefensif - bestArme = foundry.utils.duplicate(arme) - } - } - return bestArme - } - - /* -------------------------------------------- */ - searchRelevantTalents(competence) { - let talents = [] - - for (let talent of this.items) { - if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) { - for (let auto of talent.system.automations) { - if (auto.eventtype === "prepare-roll") { - if (auto.competence.toLowerCase() == competence.name.toLowerCase()) { - talent = foundry.utils.duplicate(talent) - talent.system.bonus = auto.bonus - talent.system.baCost = auto.baCost - talents.push(talent) - } - } - } - } - } - return talents - } - - /* -------------------------------------------- */ - buildListeAdversites() { - return [] - } - - /* -------------------------------------------- */ - getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) { - let rollData = MournbladeCYD2Utility.getBasicRollData() - rollData.alias = this.name - rollData.actorImg = this.img - rollData.actorId = this.id - rollData.tokenId = this.token?.id - rollData.img = this.img - rollData.attributs = MournbladeCYD2Utility.getAttributs() - rollData.maitriseId = "none" - rollData.nbEclat = this.system.eclat.value - rollData.nbBA = this.system.bonneaventure.actuelle - rollData.nbAdversites = this.getTotalAdversite() - rollData.talents = [] - rollData.attrKey2 = "none" - rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used) - rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre") - rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte") - rollData.isMonte = this.system.combat.monte - rollData.config = game.system.mournbladecyd2.config - - if (attrKey) { - rollData.attrKey = attrKey - if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" - rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) - } - } - if (compId) { - rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {}) - let maitrises = [{ key: "none", label: "Aucune" }] - rollData.competence.system.predilections.forEach(function (item) { - if (item.maitrise) { - maitrises.push({ key: item.id, label: item.name }); - } - }) - rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise) - rollData.actionImg = rollData.competence?.img - rollData.talents = this.searchRelevantTalents(rollData.competence) - } - if (compName) { - rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {}) - rollData.actionImg = rollData.competence?.img - } - return rollData - } - - /* -------------------------------------------- */ - async rollAttribut(attrKey, isInit = false) { - let rollData = this.getCommonRollData(attrKey) - rollData.multiplier = (isInit) ? 1 : 2 - rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollCompetence(attrKey, compId) { - let rollData = this.getCommonRollData(attrKey, compId) - rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode - console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeOffensif(armeId) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) - rollData.arme = arme - MournbladeCYD2Utility.updateWithTarget(rollData) - console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollAssommer() { - let rollData = this.getCommonRollData("pui", undefined, "Filouterie") - rollData.assomer = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollCoupBas() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.coupBas = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollImmobiliser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.immobiliser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollRepousser() { - let rollData = this.getCommonRollData("pui", undefined, "Mêlée") - rollData.repousser = true - rollData.conditionsCommunes = true - rollData.cibleconsciente = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - /* -------------------------------------------- */ - async rollDesengager() { - let rollData = this.getCommonRollData("adr", undefined, "Mouvements") - rollData.desengager = true - rollData.conditionsCommunes = true - MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) - } - - /* -------------------------------------------- */ - async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { - let arme = this.items.get(armeId) - if (arme.type == "arme") { - arme = this.prepareArme(arme) - } - console.log("DEGATS", arme, targetVigueur, rollDataInput) - let roll - let bonus = 0 - let bonus2 = 0 - - if (rollDataInput?.applyCoupDevastateur) { - bonus2 = Math.floor(this.system.attributs.pui.value / 2) - let talent = this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "coup dévastateur") - this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]) - } - - if (rollDataInput?.isHeroique) { - if (rollDataInput?.attaqueCharge) { - bonus = 5 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 6 - } - roll = await new Roll("2d10rr10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } else { - if (rollDataInput?.attaqueCharge) { - bonus = 3 - } - if (rollDataInput?.chargeCavalerie) { - bonus = 4 - } - roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() - } - await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); - let nbEtatPerdus = 0 - if (targetVigueur) { - nbEtatPerdus = Math.floor(roll.total / targetVigueur) - } - //console.log(roll) - let rollData = { - arme: arme, - finalResult: roll.total, - formula: roll.formula, - alias: this.name, - actorImg: this.img, - actorId: this.id, - defenderTokenId: rollDataInput?.defenderTokenId, - actionImg: arme.img, - targetVigueur: targetVigueur, - nbEtatPerdus: nbEtatPerdus - } - MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.html`, rollData) - }) - - if (rollDataInput?.defenderTokenId && nbEtatPerdus) { - MournbladeCYD2Utility.applyCombativite(rollDataInput, nbEtatPerdus) - } - - } -} diff --git a/.history/modules/mournblade-cyd2-actor_20251026132127.js b/.history/modules/mournblade-cyd2-actor_20260402224326.js similarity index 90% rename from .history/modules/mournblade-cyd2-actor_20251026132127.js rename to .history/modules/mournblade-cyd2-actor_20260402224326.js index 0520df0..33b6479 100644 --- a/.history/modules/mournblade-cyd2-actor_20251026132127.js +++ b/.history/modules/mournblade-cyd2-actor_20260402224326.js @@ -1,6 +1,6 @@ /* -------------------------------------------- */ import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; -import { MournbladeCYD2RollDialog } from "./mournblade-cyd2-roll-dialog.js"; +import { MournbladeCYD2RollDialog } from "./applications/mournblade-cyd2-roll-dialog.mjs"; /* -------------------------------------------- */ const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] @@ -39,14 +39,14 @@ export class MournbladeCYD2Actor extends Actor { if (data.type == 'personnage') { console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") + const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.skills") data.items = skills.map(i => i.toObject()) } if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") + const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.skills-creatures") data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) + data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) + data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) } return super.create(data, options); @@ -133,12 +133,6 @@ export class MournbladeCYD2Actor extends Actor { getRessources() { return this.getItemSorted(["ressource"]) } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } getDons() { return this.getItemSorted(["don"]) } @@ -151,6 +145,12 @@ export class MournbladeCYD2Actor extends Actor { getRunes() { return this.getItemSorted(["rune"]) } + getRuneEffects() { + return this.getItemSorted(["runeeffect"]) + } + getProfil() { + return this.getProfils()[0] ?? null + } getTraitsChaotiques() { return this.getItemSorted(["traitchaotique"]) } @@ -226,6 +226,9 @@ export class MournbladeCYD2Actor extends Actor { } return equipProtection // Uniquement la protection des armures + boucliers } + getProtectionTotal() { + return this.getProtection() + } /* -------------------------------------------- */ getCombatValues() { @@ -243,9 +246,6 @@ export class MournbladeCYD2Actor extends Actor { return combat } - /* -------------------------------------------- */ - prepareBaseData() { - } /* -------------------------------------------- */ async prepareData() { @@ -273,12 +273,13 @@ export class MournbladeCYD2Actor extends Actor { /* -------------------------------------------- */ _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { + if (changed?.system?.sante?.etat !== undefined && changed.system.sante.etat != this.system.sante.etat) { + const oldEtat = this.system.sante.etat setTimeout(() => { - this.processCombativite(changed.system.sante) + this.processCombativite(changed.system.sante, oldEtat) }, 800) } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { + if (changed?.system?.ame?.etat !== undefined && changed.system.ame.etat != this.system.ame.etat) { // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 if (changed.system.ame.etat < minAme) { @@ -288,8 +289,9 @@ export class MournbladeCYD2Actor extends Actor { if (changed.system.ame.etat > this.system.ame.nbame) { changed.system.ame.etat = this.system.ame.nbame } + const oldEtat = this.system.ame.etat setTimeout(() => { - this.processAme(changed.system.ame) + this.processAme(changed.system.ame, oldEtat) }, 800) } // Si le max d'Âme change, ajuster l'état actuel si nécessaire @@ -506,38 +508,57 @@ export class MournbladeCYD2Actor extends Actor { } /* -------------------------------------------- */ - processCombativite(sante) { + processCombativite(sante, oldEtat = undefined) { sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) + const affaibli = this.system.sante.nbcombativite - 2 + const tresAffaibli = this.system.sante.nbcombativite - 1 + // oldEtat permet de détecter les sauts qui franchissent Affaibli ou Très Affaibli + // sans y atterrir exactement (ex: 0 → 5 doit déclencher les deux seuils) + const prev = oldEtat !== undefined ? oldEtat : sante.etat + const curr = sante.etat + + const passedAffaibli = curr >= affaibli && prev < affaibli + const passedTresAffaibli = curr >= tresAffaibli && prev < tresAffaibli + + if (passedAffaibli) { + if (this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { + ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge (Affaibli) grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) + ChatMessage.create({ content: `${this.name} est Affaibli et subit 2 adversités rouge !` }) + this.incDecAdversite("rouge", 2) + } + } + if (passedTresAffaibli) { + if (this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { + ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge (Très Affaibli) grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) + } else { + ChatMessage.create({ content: `${this.name} est Très Affaibli et subit 2 adversités rouge supplémentaires !` }) this.incDecAdversite("rouge", 2) } } } /* -------------------------------------------- */ - processAme(ame) { + processAme(ame, oldEtat = undefined) { ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame + const traumatiseValue = this.system.ame.nbame - 2 + const tresTraumatiseValue = this.system.ame.nbame - 1 + const briseValue = this.system.ame.nbame + const prev = oldEtat !== undefined ? oldEtat : ame.etat + const curr = ame.etat - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { + // Déclencher pour chaque seuil franchi ou atteint, même en cas de saut + if (curr >= traumatiseValue && prev < traumatiseValue) { ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) this.incDecAdversite("bleue", 1) this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { + } + if (curr >= tresTraumatiseValue && prev < tresTraumatiseValue) { ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) this.incDecAdversite("bleue", 1) this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { + } + if (curr >= briseValue && prev < briseValue) { ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) this.incDecAdversite("noire", 1) } @@ -727,7 +748,7 @@ export class MournbladeCYD2Actor extends Actor { if (attrKey) { rollData.attrKey = attrKey if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" + rollData.actionImg = "systems/fvtt-mournblade-cyd-2-0/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) } } @@ -864,6 +885,8 @@ export class MournbladeCYD2Actor extends Actor { roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() } await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); + // CYD 2.0: états SUPPLÉMENTAIRES au-delà du -1 automatique à la réussite. + // Math.floor(total/SV) = 0 ( i.toObject()) } if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") + const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.skills-creatures") data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) + data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) + data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) } return super.create(data, options); @@ -118,9 +118,6 @@ export class MournbladeCYD2Actor extends Actor { getEquipments() { return this.getItemSorted(["equipement"]) } - getArtefacts() { - return this.getItemSorted(["artefact"]) - } getArmors() { return this.getItemSorted(["protection"]) } @@ -136,12 +133,6 @@ export class MournbladeCYD2Actor extends Actor { getRessources() { return this.getItemSorted(["ressource"]) } - getContacts() { - return this.getItemSorted(["contact"]) - } - getMutations() { - return this.getItemSorted(["mutation"]) - } getDons() { return this.getItemSorted(["don"]) } @@ -154,6 +145,12 @@ export class MournbladeCYD2Actor extends Actor { getRunes() { return this.getItemSorted(["rune"]) } + getRuneEffects() { + return this.getItemSorted(["runeeffect"]) + } + getProfil() { + return this.getProfils()[0] ?? null + } getTraitsChaotiques() { return this.getItemSorted(["traitchaotique"]) } @@ -229,6 +226,9 @@ export class MournbladeCYD2Actor extends Actor { } return equipProtection // Uniquement la protection des armures + boucliers } + getProtectionTotal() { + return this.getProtection() + } /* -------------------------------------------- */ getCombatValues() { @@ -246,9 +246,6 @@ export class MournbladeCYD2Actor extends Actor { return combat } - /* -------------------------------------------- */ - prepareBaseData() { - } /* -------------------------------------------- */ async prepareData() { @@ -276,12 +273,13 @@ export class MournbladeCYD2Actor extends Actor { /* -------------------------------------------- */ _preUpdate(changed, options, user) { - if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) { + if (changed?.system?.sante?.etat !== undefined && changed.system.sante.etat != this.system.sante.etat) { + const oldEtat = this.system.sante.etat setTimeout(() => { - this.processCombativite(changed.system.sante) + this.processCombativite(changed.system.sante, oldEtat) }, 800) } - if (changed?.system?.ame?.etat && changed?.system?.ame?.etat != this.system.ame.etat) { + if (changed?.system?.ame?.etat !== undefined && changed.system.ame.etat != this.system.ame.etat) { // L'état d'Âme ne peut pas être inférieur au minimum (max dans le système) let minAme = this.system.ame.max !== undefined ? this.system.ame.max : 0 if (changed.system.ame.etat < minAme) { @@ -291,8 +289,9 @@ export class MournbladeCYD2Actor extends Actor { if (changed.system.ame.etat > this.system.ame.nbame) { changed.system.ame.etat = this.system.ame.nbame } + const oldEtat = this.system.ame.etat setTimeout(() => { - this.processAme(changed.system.ame) + this.processAme(changed.system.ame, oldEtat) }, 800) } // Si le max d'Âme change, ajuster l'état actuel si nécessaire @@ -509,38 +508,57 @@ export class MournbladeCYD2Actor extends Actor { } /* -------------------------------------------- */ - processCombativite(sante) { + processCombativite(sante, oldEtat = undefined) { sante = sante || foundry.utils.duplicate(this.system.sante) - // Gestion des états affaibli et très affaibli - if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) { - if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) - } else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { - ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) + const affaibli = this.system.sante.nbcombativite - 2 + const tresAffaibli = this.system.sante.nbcombativite - 1 + // oldEtat permet de détecter les sauts qui franchissent Affaibli ou Très Affaibli + // sans y atterrir exactement (ex: 0 → 5 doit déclencher les deux seuils) + const prev = oldEtat !== undefined ? oldEtat : sante.etat + const curr = sante.etat + + const passedAffaibli = curr >= affaibli && prev < affaibli + const passedTresAffaibli = curr >= tresAffaibli && prev < tresAffaibli + + if (passedAffaibli) { + if (this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) { + ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge (Affaibli) grâce à Encaissement. Pensez à les ajouter à la fin de la scène !` }) } else { - ChatMessage.create({ content: `${this.name} subit 2 adversités rouge !` }) + ChatMessage.create({ content: `${this.name} est Affaibli et subit 2 adversités rouge !` }) + this.incDecAdversite("rouge", 2) + } + } + if (passedTresAffaibli) { + if (this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) { + ChatMessage.create({ content: `${this.name} ne subit pas les 2 adversités rouge (Très Affaibli) grâce à Vaillant. Pensez à les ajouter à la fin de la scène !` }) + } else { + ChatMessage.create({ content: `${this.name} est Très Affaibli et subit 2 adversités rouge supplémentaires !` }) this.incDecAdversite("rouge", 2) } } } /* -------------------------------------------- */ - processAme(ame) { + processAme(ame, oldEtat = undefined) { ame = ame || foundry.utils.duplicate(this.system.ame) - let traumatiseValue = this.system.ame.nbame - 2 - let tresTraumatiseValue = this.system.ame.nbame - 1 - let briseValue = this.system.ame.nbame + const traumatiseValue = this.system.ame.nbame - 2 + const tresTraumatiseValue = this.system.ame.nbame - 1 + const briseValue = this.system.ame.nbame + const prev = oldEtat !== undefined ? oldEtat : ame.etat + const curr = ame.etat - // Gestion des états Traumatisé, Très Traumatisé et Brisé - if (ame.etat == traumatiseValue) { + // Déclencher pour chaque seuil franchi ou atteint, même en cas de saut + if (curr >= traumatiseValue && prev < traumatiseValue) { ChatMessage.create({ content: `${this.name} est Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) this.incDecAdversite("bleue", 1) this.incDecAdversite("noire", 1) - } else if (ame.etat == tresTraumatiseValue) { + } + if (curr >= tresTraumatiseValue && prev < tresTraumatiseValue) { ChatMessage.create({ content: `${this.name} est Très Traumatisé et subit 1 adversité bleue et 1 adversité noire !` }) this.incDecAdversite("bleue", 1) this.incDecAdversite("noire", 1) - } else if (ame.etat >= briseValue) { + } + if (curr >= briseValue && prev < briseValue) { ChatMessage.create({ content: `${this.name} est Brisé et subit 1 adversité noire !` }) this.incDecAdversite("noire", 1) } @@ -730,7 +748,7 @@ export class MournbladeCYD2Actor extends Actor { if (attrKey) { rollData.attrKey = attrKey if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" + rollData.actionImg = "systems/fvtt-mournblade-cyd-2-0/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) } } @@ -867,6 +885,8 @@ export class MournbladeCYD2Actor extends Actor { roll = await new Roll("1d10+" + arme.system.totalDegats + "+" + bonus + "+" + bonus2).roll() } await MournbladeCYD2Utility.showDiceSoNice(roll, game.settings.get("core", "rollMode")); + // CYD 2.0: états SUPPLÉMENTAIRES au-delà du -1 automatique à la réussite. + // Math.floor(total/SV) = 0 ( section { - height: 100%; display: flex; flex-direction: column; flex: 1; @@ -176,6 +160,26 @@ } .header-fields { + // Force single-line stat rows — prevent Foundry's .flexrow wrap and h4 margins from breaking layout + .item.flexrow { + flex-wrap: nowrap !important; + align-items: center !important; + + h4 { + margin: 0 !important; + padding-top: 0 !important; + } + } + + h4.item-name-label.competence-name, + .item-name-label.competence-name, + label.item-name-label.competence-name { + color: #1a1008 !important; + text-shadow: none !important; + font-weight: bold !important; + background: none !important; + } + h4.item-name-label.competence-name { font-size: 0.75rem; padding-top: 3px; @@ -197,6 +201,25 @@ font-size: 0.8rem; } } + + .sheet-mode-toggle { + background: transparent; + border: none; + color: #fff; + padding: 2px 6px; + cursor: pointer; + font-size: 0.75rem; + transition: all 0.2s ease; + margin-left: 8px; + height: auto; + line-height: 1.2; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); + + &:hover { + color: #ffd700; + text-shadow: 0 0 8px rgba(255, 215, 0, 0.8); + } + } } // Sheet navigation tabs @@ -689,7 +712,7 @@ } /* ==================== Creature Sheet Specific Styles ==================== */ -.fvtt-mournblade.actor.creature-sheet { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet { // Variant background pour creatures - teinte légèrement différente .background-sheet-header-creature { @@ -745,7 +768,7 @@ // PNJ Sheet - Orange/Copper theme for visual distinction -.fvtt-mournblade.actor.pnj-sheet { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet { // Variant background pour PNJs - teinte orange/cuivre .background-sheet-header-creature { diff --git a/less/item-styles.less b/less/item-styles.less index 6568dff..a9f4c2a 100644 --- a/less/item-styles.less +++ b/less/item-styles.less @@ -1,7 +1,7 @@ /* ==================== Item Sheet Styles ==================== */ /* Item header with image and name */ -.fvtt-mournblade.item { +.fvtt-mournblade-cyd-2-0.item { /* Background pour toute la fiche d'item */ background: url("../assets/ui/pc_sheet_bg.webp") repeat; display: flex; diff --git a/less/simple-converted.less b/less/simple-converted.less index 9643c3f..511ad68 100644 --- a/less/simple-converted.less +++ b/less/simple-converted.less @@ -82,7 +82,7 @@ /* For nav and title */ .window-app input, - .fvtt-mournblade .item-form, + .fvtt-mournblade-cyd-2-0 .item-form, .sheet header.sheet-header .flex-group-center.flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, @@ -244,7 +244,7 @@ /* Styles limited to foundryvtt-vadentis sheets */ - .fvtt-mournblade .sheet-header { + .fvtt-mournblade-cyd-2-0 .sheet-header { -webkit-box-flex: 0; -ms-flex: 0 0 210px; flex: 0 0 210px; @@ -264,15 +264,16 @@ margin-bottom: 10px; } - .fvtt-mournblade .sheet-header .profile-img { + .fvtt-mournblade-cyd-2-0 .sheet-header .profile-img { -webkit-box-flex: 0; - -ms-flex: 0 0 128px; - flex: 0 0 128px; - height: 128px; - width: 128px; + -ms-flex: 0 0 80px; + flex: 0 0 80px; + height: 80px; + width: 80px; margin-right: 10px; object-fit: cover; object-position: 50% 0; + cursor: pointer; } .button-img { @@ -305,13 +306,13 @@ vertical-align: bottom; } - .fvtt-mournblade .sheet-header .header-fields { + .fvtt-mournblade-cyd-2-0 .sheet-header .header-fields { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } - .fvtt-mournblade .sheet-header h1.charname { + .fvtt-mournblade-cyd-2-0 .sheet-header h1.charname { height: 50px; padding: 0px; margin: 5px 0; @@ -321,7 +322,7 @@ font-family: "CentaurMT"; } - .fvtt-mournblade .sheet-header h1.charname input { + .fvtt-mournblade-cyd-2-0 .sheet-header h1.charname input { width: 100%; height: 100%; margin: 0; @@ -331,19 +332,19 @@ text-align: left; } - .fvtt-mournblade .sheet-tabs { + .fvtt-mournblade-cyd-2-0 .sheet-tabs { -webkit-box-flex: 0; -ms-flex: 0; flex: 0; } - .fvtt-mournblade .sheet-body, - .fvtt-mournblade .sheet-body .tab { + .fvtt-mournblade-cyd-2-0 .sheet-body, + .fvtt-mournblade-cyd-2-0 .sheet-body .tab { height: auto; font-size: 0.9rem; } - .fvtt-mournblade .sheet-body .tab .editor { + .fvtt-mournblade-cyd-2-0 .sheet-body .tab .editor { height: 100%; font-size: 0.9rem; } @@ -372,70 +373,83 @@ padding: 0 3px; } - .fvtt-mournblade .tox .tox-editor-container { + .fvtt-mournblade-cyd-2-0 .tox .tox-editor-container { background: #fff; } - .fvtt-mournblade .tox .tox-edit-area { + .fvtt-mournblade-cyd-2-0 .tox .tox-edit-area { padding: 0 8px; } - .fvtt-mournblade .resource-label { + .fvtt-mournblade-cyd-2-0 .resource-label { font-weight: bold; text-transform: uppercase; } - .fvtt-mournblade .tabs { + .fvtt-mournblade-cyd-2-0 .tabs { height: 40px; border-top: 1px solid #AAA; border-bottom: 1px solid #AAA; color: #000000; } - .fvtt-mournblade .tabs .item { - line-height: 40px; - font-weight: bold; + .fvtt-mournblade-cyd-2-0 nav.sheet-tabs { + justify-content: flex-start !important; + gap: 0 !important; + padding: 0 !important; } - .fvtt-mournblade .tabs .item.active { + .fvtt-mournblade-cyd-2-0 .tabs .item { + line-height: 40px; + font-size: 10px; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1 1 0; + text-align: center; + padding: 0 4px; + } + + .fvtt-mournblade-cyd-2-0 .tabs .item.active { text-decoration: underline; text-shadow: none; } - .fvtt-mournblade .items-list { + .fvtt-mournblade-cyd-2-0 .items-list { list-style: none; margin: 1px 0; padding: 0; overflow-y: auto; } - .fvtt-mournblade .items-list .item-header { + .fvtt-mournblade-cyd-2-0 .items-list .item-header { font-weight: bold; } - .fvtt-mournblade .items-list .item { + .fvtt-mournblade-cyd-2-0 .items-list .item { height: 30px; line-height: 24px; padding: 1px 0; border-bottom: 1px solid #BBB; } - .fvtt-mournblade .items-list .item .item-image { + .fvtt-mournblade-cyd-2-0 .items-list .item .item-image { -webkit-box-flex: 0; -ms-flex: 0 0 24px; flex: 0 0 24px; margin-right: 5px; } - .fvtt-mournblade .items-list .item img { + .fvtt-mournblade-cyd-2-0 .items-list .item img { display: block; } - .fvtt-mournblade .items-list .item-name { + .fvtt-mournblade-cyd-2-0 .items-list .item-name { margin: 0; } - .fvtt-mournblade .items-list .item-controls { + .fvtt-mournblade-cyd-2-0 .items-list .item-controls { -webkit-box-flex: 0; -ms-flex: 0 0 86px; flex: 0 0 86px; @@ -1532,7 +1546,7 @@ .item-field-label-long { flex-grow: 1; - max-width: 8rem; + max-width: 10rem; min-width: 8rem; } diff --git a/modules/applications/mournblade-cyd2-roll-dialog.mjs b/modules/applications/mournblade-cyd2-roll-dialog.mjs index d4fc750..100571a 100644 --- a/modules/applications/mournblade-cyd2-roll-dialog.mjs +++ b/modules/applications/mournblade-cyd2-roll-dialog.mjs @@ -16,15 +16,12 @@ export class MournbladeCYD2RollDialog { difficulte: String(rollData.difficulte || 0), img: actor.img, name: actor.name, - config: game.system.mournbladecyd2.config + config: game.system.mournbladecyd2.config, + attributs: game.system.mournbladecyd2.config.attributs, }; - if (rollData.attrKey === "tochoose") { - context.selectableAttributes = actor.system.attributs; - } - const content = await foundry.applications.handlebars.renderTemplate( - "systems/fvtt-mournblade-cyd2/templates/roll-dialog-generic.hbs", + "systems/fvtt-mournblade-cyd-2-0/templates/roll-dialog-generic.hbs", context ); diff --git a/modules/applications/sheets/base-actor-sheet.mjs b/modules/applications/sheets/base-actor-sheet.mjs index 76c2154..656b57d 100644 --- a/modules/applications/sheets/base-actor-sheet.mjs +++ b/modules/applications/sheets/base-actor-sheet.mjs @@ -16,10 +16,10 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix /** @override */ static DEFAULT_OPTIONS = { - classes: ["fvtt-mournblade-cyd2", "sheet", "actor"], + classes: ["fvtt-mournblade-cyd-2-0", "sheet", "actor"], position: { - width: 640, - height: 720, + width: 750, + height: 820, }, form: { submitOnChange: true, @@ -44,6 +44,7 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix createItem: MournbladeCYD2ActorSheetV2.#onCreateItem, equipItem: MournbladeCYD2ActorSheetV2.#onEquipItem, modifyQuantity: MournbladeCYD2ActorSheetV2.#onModifyQuantity, + modifyAdversite: MournbladeCYD2ActorSheetV2.#onModifyAdversite, modifySante: MournbladeCYD2ActorSheetV2.#onModifySante, modifyAme: MournbladeCYD2ActorSheetV2.#onModifyAme, rollAttribut: MournbladeCYD2ActorSheetV2.#onRollAttribut, @@ -53,7 +54,11 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix rollArmeSpecial: MournbladeCYD2ActorSheetV2.#onRollArmeSpecial, rollArmeDegats: MournbladeCYD2ActorSheetV2.#onRollArmeDegats, rollAssommer: MournbladeCYD2ActorSheetV2.#onRollAssommer, + rollCoupBas: MournbladeCYD2ActorSheetV2.#onRollCoupBas, rollImmobiliser: MournbladeCYD2ActorSheetV2.#onRollImmobiliser, + rollRepousser: MournbladeCYD2ActorSheetV2.#onRollRepousser, + rollDesengager: MournbladeCYD2ActorSheetV2.#onRollDesengager, + rollInitiative: MournbladeCYD2ActorSheetV2.#onRollInitiative, rollFuir: MournbladeCYD2ActorSheetV2.#onRollFuir, }, }; @@ -226,6 +231,15 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix } } + static async #onModifyAdversite(event, target) { + const li = target.closest('[data-adversite]'); + const adversiteKey = li?.dataset.adversite; + if (!adversiteKey) return; + const value = Number.parseInt(target.dataset.adversiteValue); + const current = this.document.system.adversite[adversiteKey] || 0; + await this.document.update({ [`system.adversite.${adversiteKey}`]: Math.max(0, current + value) }); + } + static async #onModifySante(event, target) { const type = target.dataset.type; const value = Number.parseInt(target.dataset.value); @@ -254,25 +268,44 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix } static async #onRollArmeOffensif(event, target) { - await this.document.rollArmeOffensif(target.dataset.armeId); + const li = target.closest('[data-item-id]'); + await this.document.rollArmeOffensif(target.dataset.armeId ?? li?.dataset.itemId); } static async #onRollArmeSpecial(event, target) { - await this.document.rollArmeSpecial(target.dataset.armeId); + const li = target.closest('[data-item-id]'); + await this.document.rollArmeSpecial(target.dataset.armeId ?? li?.dataset.itemId); } static async #onRollArmeDegats(event, target) { - await this.document.rollArmeDegats(target.dataset.armeId); + const li = target.closest('[data-item-id]'); + await this.document.rollArmeDegats(target.dataset.armeId ?? li?.dataset.itemId); } static async #onRollAssommer(event, target) { await this.document.rollAssomer(); } + static async #onRollCoupBas(event, target) { + await this.document.rollCoupBas(); + } + static async #onRollImmobiliser(event, target) { await this.document.rollImmobiliser(); } + static async #onRollRepousser(event, target) { + await this.document.rollRepousser(); + } + + static async #onRollDesengager(event, target) { + await this.document.rollDesengager(); + } + + static async #onRollInitiative(event, target) { + await this.document.rollAttribut("adr", true); + } + static async #onRollFuir(event, target) { await this.document.rollFuir(); } diff --git a/modules/applications/sheets/base-item-sheet.mjs b/modules/applications/sheets/base-item-sheet.mjs index f3f264b..6a4b705 100644 --- a/modules/applications/sheets/base-item-sheet.mjs +++ b/modules/applications/sheets/base-item-sheet.mjs @@ -13,7 +13,7 @@ export default class MournbladeCYD2ItemSheetV2 extends HandlebarsApplicationMixi /** @override */ static DEFAULT_OPTIONS = { - classes: ["fvtt-mournblade-cyd2", "item"], + classes: ["fvtt-mournblade-cyd-2-0", "item"], position: { width: 620, height: 600, @@ -107,7 +107,24 @@ export default class MournbladeCYD2ItemSheetV2 extends HandlebarsApplicationMixi } static async #onPostItem(event) { - await this.document.toChat?.(); + event.preventDefault(); + const item = this.document; + const chatData = foundry.utils.duplicate(item); + if (item.actor) { + chatData.actor = { id: item.actor.id }; + } + if (chatData.img?.includes("/blank.png")) { + chatData.img = null; + } + chatData.jsondata = JSON.stringify({ + compendium: "postedItem", + payload: chatData, + }); + const html = await foundry.applications.handlebars.renderTemplate( + "systems/fvtt-mournblade-cyd-2-0/templates/post-item.hbs", + chatData + ); + ChatMessage.create({ user: game.user.id, content: html }); } static async #onAddPredilection(event) { diff --git a/modules/applications/sheets/mournblade-cyd2-arme-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-arme-sheet.mjs index abbee8e..c7f4b9a 100644 --- a/modules/applications/sheets/mournblade-cyd2-arme-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-arme-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2ArmeSheet extends MournbladeCYD2ItemSheetV2 { /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-arme-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-arme-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-competence-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-competence-sheet.mjs index 3d7d343..3dcbd5c 100644 --- a/modules/applications/sheets/mournblade-cyd2-competence-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-competence-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2CompetenceSheet extends MournbladeCYD2ItemShe /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-competence-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-competence-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-creature-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-creature-sheet.mjs index 22a442a..dd86406 100644 --- a/modules/applications/sheets/mournblade-cyd2-creature-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-creature-sheet.mjs @@ -1,4 +1,5 @@ import MournbladeCYD2ActorSheetV2 from "./base-actor-sheet.mjs"; +import { MournbladeCYD2Utility } from "../../mournblade-cyd2-utility.js"; export default class MournbladeCYD2CreatureSheet extends MournbladeCYD2ActorSheetV2 { @@ -15,7 +16,7 @@ export default class MournbladeCYD2CreatureSheet extends MournbladeCYD2ActorShee /** @override */ static PARTS = { sheet: { - template: "systems/fvtt-mournblade-cyd2/templates/creature-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/creature-sheet.hbs", }, }; @@ -28,6 +29,7 @@ export default class MournbladeCYD2CreatureSheet extends MournbladeCYD2ActorShee const actor = this.document; context.skills = actor.getSkills?.() ?? []; + context.combativiteList = MournbladeCYD2Utility.getCombativiteList(actor.system.sante?.nbcombativite || 0); context.armes = foundry.utils.duplicate(actor.getWeapons?.() ?? []); context.protections = foundry.utils.duplicate(actor.getArmors?.() ?? []); context.runes = foundry.utils.duplicate(actor.getRunes?.() ?? []); diff --git a/modules/applications/sheets/mournblade-cyd2-don-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-don-sheet.mjs index 1f954ba..1786c80 100644 --- a/modules/applications/sheets/mournblade-cyd2-don-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-don-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2DonSheet extends MournbladeCYD2ItemSheetV2 { /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-don-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-don-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-equipement-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-equipement-sheet.mjs index e6f04f7..2133837 100644 --- a/modules/applications/sheets/mournblade-cyd2-equipement-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-equipement-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2EquipementSheet extends MournbladeCYD2ItemShe /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-equipement-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-equipement-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-historique-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-historique-sheet.mjs index 3cd8d39..4e38865 100644 --- a/modules/applications/sheets/mournblade-cyd2-historique-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-historique-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2HistoriqueSheet extends MournbladeCYD2ItemShe /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-historique-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-historique-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-monnaie-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-monnaie-sheet.mjs index b1d0d9e..73af19c 100644 --- a/modules/applications/sheets/mournblade-cyd2-monnaie-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-monnaie-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2MonnaieSheet extends MournbladeCYD2ItemSheetV /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-monnaie-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-monnaie-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-pacte-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-pacte-sheet.mjs index 07707b0..181f087 100644 --- a/modules/applications/sheets/mournblade-cyd2-pacte-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-pacte-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2PacteSheet extends MournbladeCYD2ItemSheetV2 /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-pacte-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-pacte-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-personnage-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-personnage-sheet.mjs index 38144a0..06e5019 100644 --- a/modules/applications/sheets/mournblade-cyd2-personnage-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-personnage-sheet.mjs @@ -1,4 +1,5 @@ import MournbladeCYD2ActorSheetV2 from "./base-actor-sheet.mjs"; +import { MournbladeCYD2Utility } from "../../mournblade-cyd2-utility.js"; export default class MournbladeCYD2PersonnageSheet extends MournbladeCYD2ActorSheetV2 { @@ -15,7 +16,7 @@ export default class MournbladeCYD2PersonnageSheet extends MournbladeCYD2ActorSh /** @override */ static PARTS = { sheet: { - template: "systems/fvtt-mournblade-cyd2/templates/actor-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/actor-sheet.hbs", }, }; @@ -27,6 +28,10 @@ export default class MournbladeCYD2PersonnageSheet extends MournbladeCYD2ActorSh const context = await super._prepareContext(); const actor = this.document; + context.combativiteList = MournbladeCYD2Utility.getCombativiteList(actor.system.sante.nbcombativite); + context.ameList = MournbladeCYD2Utility.getAmeList(actor.system.ame.nbame, actor.getAmeMax?.() ?? 0); + context.ameMaxList = MournbladeCYD2Utility.getAmeMaxList(actor.system.ame.nbame); + context.skills = actor.getSkills?.() ?? []; context.armes = foundry.utils.duplicate(actor.getWeapons?.() ?? []); context.protections = foundry.utils.duplicate(actor.getArmors?.() ?? []); diff --git a/modules/applications/sheets/mournblade-cyd2-profil-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-profil-sheet.mjs index 4b94ce5..eace14a 100644 --- a/modules/applications/sheets/mournblade-cyd2-profil-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-profil-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2ProfilSheet extends MournbladeCYD2ItemSheetV2 /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-profil-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-profil-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-protection-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-protection-sheet.mjs index 343fe13..d8c9f15 100644 --- a/modules/applications/sheets/mournblade-cyd2-protection-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-protection-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2ProtectionSheet extends MournbladeCYD2ItemShe /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-protection-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-protection-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-ressource-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-ressource-sheet.mjs index ade6e82..213b138 100644 --- a/modules/applications/sheets/mournblade-cyd2-ressource-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-ressource-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2RessourceSheet extends MournbladeCYD2ItemShee /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-ressource-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-ressource-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-rune-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-rune-sheet.mjs index 568375b..8a7de57 100644 --- a/modules/applications/sheets/mournblade-cyd2-rune-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-rune-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2RuneSheet extends MournbladeCYD2ItemSheetV2 { /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-rune-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-rune-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-runeeffect-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-runeeffect-sheet.mjs index 2a2f22f..5f1cdd0 100644 --- a/modules/applications/sheets/mournblade-cyd2-runeeffect-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-runeeffect-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2RuneEffectSheet extends MournbladeCYD2ItemShe /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-runeeffect-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-runeeffect-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-talent-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-talent-sheet.mjs index 4fe8265..38ef8ed 100644 --- a/modules/applications/sheets/mournblade-cyd2-talent-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-talent-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2TalentSheet extends MournbladeCYD2ItemSheetV2 /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-talent-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-talent-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-tendance-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-tendance-sheet.mjs index bc31582..df766d9 100644 --- a/modules/applications/sheets/mournblade-cyd2-tendance-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-tendance-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2TendanceSheet extends MournbladeCYD2ItemSheet /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-tendance-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-tendance-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-traitchaotique-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-traitchaotique-sheet.mjs index 4ab322e..7c93c90 100644 --- a/modules/applications/sheets/mournblade-cyd2-traitchaotique-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-traitchaotique-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2TraitChaotiqueSheet extends MournbladeCYD2Ite /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-traitchaotique-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-traitchaotique-sheet.hbs", }, }; diff --git a/modules/applications/sheets/mournblade-cyd2-traitespece-sheet.mjs b/modules/applications/sheets/mournblade-cyd2-traitespece-sheet.mjs index d0d967d..4b5ec09 100644 --- a/modules/applications/sheets/mournblade-cyd2-traitespece-sheet.mjs +++ b/modules/applications/sheets/mournblade-cyd2-traitespece-sheet.mjs @@ -15,7 +15,7 @@ export default class MournbladeCYD2TraitEspeceSheet extends MournbladeCYD2ItemSh /** @override */ static PARTS = { main: { - template: "systems/fvtt-mournblade-cyd2/templates/item-traitespece-sheet.hbs", + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-traitespece-sheet.hbs", }, }; diff --git a/modules/macro-replace-images.js b/modules/macro-replace-images.js index 6cfc9ec..3236ed4 100644 --- a/modules/macro-replace-images.js +++ b/modules/macro-replace-images.js @@ -1,6 +1,6 @@ /** * Macro pour remplacer les chemins d'images dans les compendiums - * Remplace "fvtt-hawkmoon-cyd" par "fvtt-mournblade-cyd2" dans tous les champs 'img' + * Remplace "fvtt-hawkmoon-cyd" par "fvtt-mournblade-cyd-2-0" dans tous les champs 'img' */ (async () => { @@ -10,7 +10,7 @@ content: `

Cette macro va :

Voulez-vous continuer ?

`, @@ -49,14 +49,14 @@ // Vérifier le champ img principal if (doc.img && doc.img.includes("fvtt-hawkmoon-cyd")) { - updateData.img = doc.img.replace(/fvtt-hawkmoon-cyd/g, "fvtt-mournblade-cyd2"); + updateData.img = doc.img.replace(/fvtt-hawkmoon-cyd/g, "fvtt-mournblade-cyd-2-0"); needsUpdate = true; } // Pour les acteurs, vérifier aussi prototypeToken.texture.src if (doc.documentName === "Actor" && doc.prototypeToken?.texture?.src) { if (doc.prototypeToken.texture.src.includes("fvtt-hawkmoon-cyd")) { - updateData["prototypeToken.texture.src"] = doc.prototypeToken.texture.src.replace(/fvtt-hawkmoon-cyd/g, "fvtt-mournblade-cyd2"); + updateData["prototypeToken.texture.src"] = doc.prototypeToken.texture.src.replace(/fvtt-hawkmoon-cyd/g, "fvtt-mournblade-cyd-2-0"); needsUpdate = true; } } @@ -74,7 +74,7 @@ // Pour les scènes, vérifier background.src et les tokens if (doc.documentName === "Scene") { if (doc.background?.src && doc.background.src.includes("fvtt-hawkmoon-cyd")) { - updateData["background.src"] = doc.background.src.replace(/fvtt-hawkmoon-cyd/g, "fvtt-mournblade-cyd2"); + updateData["background.src"] = doc.background.src.replace(/fvtt-hawkmoon-cyd/g, "fvtt-mournblade-cyd-2-0"); needsUpdate = true; } } diff --git a/modules/mournblade-cyd2-actor-sheet.js b/modules/mournblade-cyd2-actor-sheet.js index f4385fc..296bd32 100644 --- a/modules/mournblade-cyd2-actor-sheet.js +++ b/modules/mournblade-cyd2-actor-sheet.js @@ -13,8 +13,8 @@ export class MournbladeCYD2ActorSheet extends foundry.appv1.sheets.ActorSheet { static get defaultOptions() { return foundry.utils.mergeObject(super.defaultOptions, { - classes: ["fvtt-mournblade-cyd2", "sheet", "actor"], - template: "systems/fvtt-mournblade-cyd2/templates/actor-sheet.hbs", + classes: ["fvtt-mournblade-cyd-2-0", "sheet", "actor"], + template: "systems/fvtt-mournblade-cyd-2-0/templates/actor-sheet.hbs", width: 640, height: 720, tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }], diff --git a/modules/mournblade-cyd2-actor.js b/modules/mournblade-cyd2-actor.js index 2bf1453..78247ca 100644 --- a/modules/mournblade-cyd2-actor.js +++ b/modules/mournblade-cyd2-actor.js @@ -39,14 +39,14 @@ export class MournbladeCYD2Actor extends Actor { if (data.type == 'personnage') { console.log("Loading skills for personnage") - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") + const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.skills") data.items = skills.map(i => i.toObject()) } if (data.type == 'creature') { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills-creatures") + const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.skills-creatures") data.items = skills.map(i => i.toObject()) - data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) - data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) + data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) + data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } }) } return super.create(data, options); @@ -246,9 +246,6 @@ export class MournbladeCYD2Actor extends Actor { return combat } - /* -------------------------------------------- */ - prepareBaseData() { - } /* -------------------------------------------- */ async prepareData() { @@ -751,7 +748,7 @@ export class MournbladeCYD2Actor extends Actor { if (attrKey) { rollData.attrKey = attrKey if (attrKey != "tochoose") { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" + rollData.actionImg = "systems/fvtt-mournblade-cyd-2-0/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp" rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey]) } } @@ -779,8 +776,7 @@ export class MournbladeCYD2Actor extends Actor { let rollData = this.getCommonRollData(attrKey) rollData.multiplier = (isInit) ? 1 : 2 rollData.isInit = isInit - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ @@ -788,8 +784,7 @@ export class MournbladeCYD2Actor extends Actor { let rollData = this.getCommonRollData(attrKey, compId) rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode console.log("RollDatra", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ @@ -802,8 +797,7 @@ export class MournbladeCYD2Actor extends Actor { rollData.arme = arme MournbladeCYD2Utility.updateWithTarget(rollData) console.log("ARME!", rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ async rollAssommer() { @@ -811,8 +805,7 @@ export class MournbladeCYD2Actor extends Actor { rollData.assomer = true rollData.conditionsCommunes = true MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ async rollCoupBas() { @@ -820,8 +813,7 @@ export class MournbladeCYD2Actor extends Actor { rollData.coupBas = true rollData.conditionsCommunes = true MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ async rollImmobiliser() { @@ -830,8 +822,7 @@ export class MournbladeCYD2Actor extends Actor { rollData.conditionsCommunes = true rollData.cibleconsciente = true MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ async rollRepousser() { @@ -840,8 +831,7 @@ export class MournbladeCYD2Actor extends Actor { rollData.conditionsCommunes = true rollData.cibleconsciente = true MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ async rollDesengager() { @@ -849,8 +839,7 @@ export class MournbladeCYD2Actor extends Actor { rollData.desengager = true rollData.conditionsCommunes = true MournbladeCYD2Utility.updateWithTarget(rollData) - let rollDialog = await MournbladeCYD2RollDialog.create(this, rollData) - rollDialog.render(true) + await MournbladeCYD2RollDialog.create(this, rollData) } /* -------------------------------------------- */ @@ -908,7 +897,7 @@ export class MournbladeCYD2Actor extends Actor { nbEtatPerdus: nbEtatPerdus } MournbladeCYD2Utility.createChatWithRollMode(rollData.alias, { - content: await renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-degats-result.hbs`, rollData) + content: await renderTemplate(`systems/fvtt-mournblade-cyd-2-0/templates/chat-degats-result.hbs`, rollData) }) if (rollDataInput?.defenderTokenId && nbEtatPerdus) { diff --git a/modules/mournblade-cyd2-config.js b/modules/mournblade-cyd2-config.js index ff95f8b..e62a721 100644 --- a/modules/mournblade-cyd2-config.js +++ b/modules/mournblade-cyd2-config.js @@ -1,4 +1,11 @@ export const MOURNBLADECYD2_CONFIG = { + attributs: { + adr: "Adresse", + pui: "Puissance", + cla: "Clairvoyance", + pre: "Présence", + tre: "Trempe" + }, allegeanceOptions: { tous: 'Tous', chaos: 'Chaos', diff --git a/modules/mournblade-cyd2-creature-sheet.js b/modules/mournblade-cyd2-creature-sheet.js index 8edcd5e..e3fcd2d 100644 --- a/modules/mournblade-cyd2-creature-sheet.js +++ b/modules/mournblade-cyd2-creature-sheet.js @@ -14,8 +14,8 @@ export class MournbladeCYD2CreatureSheet extends MournbladeCYD2ActorSheet { static get defaultOptions() { return foundry.utils.mergeObject(super.defaultOptions, { - classes: ["fvtt-mournblade-cyd2", "sheet", "actor"], - template: "systems/fvtt-mournblade-cyd2/templates/creature-sheet.hbs", + classes: ["fvtt-mournblade-cyd-2-0", "sheet", "actor"], + template: "systems/fvtt-mournblade-cyd-2-0/templates/creature-sheet.hbs", width: 640, height: 720, tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }], diff --git a/modules/mournblade-cyd2-hud.js b/modules/mournblade-cyd2-hud.js index 815203b..a7c6bf4 100644 --- a/modules/mournblade-cyd2-hud.js +++ b/modules/mournblade-cyd2-hud.js @@ -24,7 +24,7 @@ export class MournbladeCYD2TokenHud { const controlIconActions = $(html).find('.control-icon[data-action=combat]'); // initiative - await MournbladeCYD2TokenHud._configureSubMenu(controlIconActions, 'systems/fvtt-mournblade-cyd2/templates/hud-adversites.hbs', hudData, + await MournbladeCYD2TokenHud._configureSubMenu(controlIconActions, 'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs', hudData, (event) => { let adversite = event.currentTarget.attributes['data-action-index'].value let value = Number(event.currentTarget.attributes['data-action-value'].value) diff --git a/modules/mournblade-cyd2-item-sheet.js b/modules/mournblade-cyd2-item-sheet.js index 59071f2..b60967b 100644 --- a/modules/mournblade-cyd2-item-sheet.js +++ b/modules/mournblade-cyd2-item-sheet.js @@ -10,8 +10,8 @@ export class MournbladeCYD2ItemSheet extends foundry.appv1.sheets.ItemSheet { static get defaultOptions() { return foundry.utils.mergeObject(super.defaultOptions, { - classes: ["fvtt-mournblade-cyd2", "sheet", "item"], - template: "systems/fvtt-mournblade-cyd2/templates/item-sheet.hbs", + classes: ["fvtt-mournblade-cyd-2-0", "sheet", "item"], + template: "systems/fvtt-mournblade-cyd-2-0/templates/item-sheet.hbs", dragDrop: [{ dragSelector: null, dropSelector: null }], width: 620, height: 550, @@ -105,7 +105,7 @@ export class MournbladeCYD2ItemSheet extends foundry.appv1.sheets.ItemSheet { payload: chatData, }); - renderTemplate('systems/fvtt-mournblade-cyd2/templates/post-item.hbs', chatData).then(html => { + renderTemplate('systems/fvtt-mournblade-cyd-2-0/templates/post-item.hbs', chatData).then(html => { let chatOptions = MournbladeCYD2Utility.chatDataSetup(html); ChatMessage.create(chatOptions) }); @@ -217,7 +217,7 @@ export class MournbladeCYD2ItemSheet extends foundry.appv1.sheets.ItemSheet { /* -------------------------------------------- */ get template() { let type = this.item.type; - return `systems/fvtt-mournblade-cyd2/templates/item-${type}-sheet.hbs`; + return `systems/fvtt-mournblade-cyd-2-0/templates/item-${type}-sheet.hbs`; } /* -------------------------------------------- */ diff --git a/modules/mournblade-cyd2-item.js b/modules/mournblade-cyd2-item.js index 97fab6d..537fd5b 100644 --- a/modules/mournblade-cyd2-item.js +++ b/modules/mournblade-cyd2-item.js @@ -1,22 +1,22 @@ import { MournbladeCYD2Utility } from "./mournblade-cyd2-utility.js"; export const defaultItemImg = { - competence: "systems/fvtt-mournblade-cyd2/assets/icons/competence.webp", - arme: "systems/fvtt-mournblade-cyd2/assets/icons/melee.webp", - equipement: "systems/fvtt-mournblade-cyd2/assets/icons/equipement.webp", - monnaie: "systems/fvtt-mournblade-cyd2/assets/icons/monnaie.webp", - predilection: "systems/fvtt-mournblade-cyd2/assets/icons/predilection.webp", - protection: "systems/fvtt-mournblade-cyd2/assets/icons/protection.webp", - talent: "systems/fvtt-mournblade-cyd2/assets/icons/talent.webp", - historique: "systems/fvtt-mournblade-cyd2/assets/icons/historique.webp", - profil: "systems/fvtt-mournblade-cyd2/assets/icons/profil.webp", - ressource: "systems/fvtt-mournblade-cyd2/assets/icons/ressources.webp", - traitchaotique: "systems/fvtt-mournblade-cyd2/assets/icons/traitchaotique.webp", - traitespece: "systems/fvtt-mournblade-cyd2/assets/icons/traitespece.webp", - don: "systems/fvtt-mournblade-cyd2/assets/icons/don.webp", - pacte: "systems/fvtt-mournblade-cyd2/assets/icons/pacte.webp", - rune: "systems/fvtt-mournblade-cyd2/assets/icons/rune.webp", - tendance: "systems/fvtt-mournblade-cyd2/assets/icons/tendance.webp", + competence: "systems/fvtt-mournblade-cyd-2-0/assets/icons/competence.webp", + arme: "systems/fvtt-mournblade-cyd-2-0/assets/icons/melee.webp", + equipement: "systems/fvtt-mournblade-cyd-2-0/assets/icons/equipement.webp", + monnaie: "systems/fvtt-mournblade-cyd-2-0/assets/icons/monnaie.webp", + predilection: "systems/fvtt-mournblade-cyd-2-0/assets/icons/predilection.webp", + protection: "systems/fvtt-mournblade-cyd-2-0/assets/icons/protection.webp", + talent: "systems/fvtt-mournblade-cyd-2-0/assets/icons/talent.webp", + historique: "systems/fvtt-mournblade-cyd-2-0/assets/icons/historique.webp", + profil: "systems/fvtt-mournblade-cyd-2-0/assets/icons/profil.webp", + ressource: "systems/fvtt-mournblade-cyd-2-0/assets/icons/ressources.webp", + traitchaotique: "systems/fvtt-mournblade-cyd-2-0/assets/icons/traitchaotique.webp", + traitespece: "systems/fvtt-mournblade-cyd-2-0/assets/icons/traitespece.webp", + don: "systems/fvtt-mournblade-cyd-2-0/assets/icons/don.webp", + pacte: "systems/fvtt-mournblade-cyd-2-0/assets/icons/pacte.webp", + rune: "systems/fvtt-mournblade-cyd-2-0/assets/icons/rune.webp", + tendance: "systems/fvtt-mournblade-cyd-2-0/assets/icons/tendance.webp", } /** diff --git a/modules/mournblade-cyd2-main.js b/modules/mournblade-cyd2-main.js index b604f07..920a1c2 100644 --- a/modules/mournblade-cyd2-main.js +++ b/modules/mournblade-cyd2-main.js @@ -40,7 +40,7 @@ Hooks.once("init", async function () { }; /* -------------------------------------------- */ - game.socket.on("system.fvtt-mournblade-cyd2", data => { + game.socket.on("system.fvtt-mournblade-cyd-2-0", data => { MournbladeCYD2Utility.onSocketMesssage(data) }); @@ -79,26 +79,26 @@ Hooks.once("init", async function () { // Register sheet application classes (AppV2) foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet); - foundry.documents.collections.Actors.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2PersonnageSheet, { types: ["personnage"], makeDefault: true }); - foundry.documents.collections.Actors.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2CreatureSheet, { types: ["creature"], makeDefault: true }); + foundry.documents.collections.Actors.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2PersonnageSheet, { types: ["personnage"], makeDefault: true }); + foundry.documents.collections.Actors.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2CreatureSheet, { types: ["creature"], makeDefault: true }); foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2CompetenceSheet, { types: ["competence"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2TalentSheet, { types: ["talent"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2HistoriqueSheet, { types: ["historique"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2ProfilSheet, { types: ["profil"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2ArmeSheet, { types: ["arme"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2ProtectionSheet, { types: ["protection"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2MonnaieSheet, { types: ["monnaie"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2EquipementSheet, { types: ["equipement"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2RessourceSheet, { types: ["ressource"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2DonSheet, { types: ["don"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2PacteSheet, { types: ["pacte"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2RuneSheet, { types: ["rune"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2RuneEffectSheet, { types: ["runeeffect"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2TendanceSheet, { types: ["tendance"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2TraitChaotiqueSheet, { types: ["traitchaotique"], makeDefault: true }); - foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd2", sheets.MournbladeCYD2TraitEspeceSheet, { types: ["traitespece"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2CompetenceSheet, { types: ["competence"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TalentSheet, { types: ["talent"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2HistoriqueSheet, { types: ["historique"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2ProfilSheet, { types: ["profil"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2ArmeSheet, { types: ["arme"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2ProtectionSheet, { types: ["protection"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2MonnaieSheet, { types: ["monnaie"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2EquipementSheet, { types: ["equipement"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2RessourceSheet, { types: ["ressource"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2DonSheet, { types: ["don"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2PacteSheet, { types: ["pacte"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2RuneSheet, { types: ["rune"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2RuneEffectSheet, { types: ["runeeffect"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TendanceSheet, { types: ["tendance"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitChaotiqueSheet, { types: ["traitchaotique"], makeDefault: true }); + foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitEspeceSheet, { types: ["traitespece"], makeDefault: true }); MournbladeCYD2Utility.init() MournbladeCYD2Automation.init() @@ -123,7 +123,7 @@ function welcomeMessage() { async function importDefaultScene() { let exists = game.scenes.find(j => j.name == "Accueil"); if (!exists) { - const scenes = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.scenes") + const scenes = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.scenes") let newDocuments = scenes.filter(i => i.name == "Accueil"); if (newDocuments) { await game.scenes.documentClass.create(newDocuments); diff --git a/modules/mournblade-cyd2-roll-dialog.js b/modules/mournblade-cyd2-roll-dialog.js index 6ac2d72..10015c5 100644 --- a/modules/mournblade-cyd2-roll-dialog.js +++ b/modules/mournblade-cyd2-roll-dialog.js @@ -6,7 +6,7 @@ export class MournbladeCYD2RollDialog extends Dialog { static async create(actor, rollData ) { let options = { classes: ["MournbladeCYD2Dialog"], width: 320, height: 'fit-content', 'z-index': 99999 }; - let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade-cyd2/templates/roll-dialog-generic.hbs', rollData); + let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade-cyd-2-0/templates/roll-dialog-generic.hbs', rollData); return new MournbladeCYD2RollDialog(actor, rollData, html, options ); } diff --git a/modules/mournblade-cyd2-utility.js b/modules/mournblade-cyd2-utility.js index cf232c0..d3ae838 100644 --- a/modules/mournblade-cyd2-utility.js +++ b/modules/mournblade-cyd2-utility.js @@ -47,7 +47,7 @@ export class MournbladeCYD2Utility { return parseInt(a) * parseInt(b); }) - game.settings.register("fvtt-mournblade-cyd2", "mournblade-cyd2-pause-logo", { + game.settings.register("fvtt-mournblade-cyd-2-0", "mournblade-cyd2-pause-logo", { name: "Logo de pause", scope: "world", config: true, @@ -60,6 +60,10 @@ export class MournbladeCYD2Utility { }, }) + // Initialise les listes de sélection dès le hook init (avant le rendu des fiches) + game.system.mournbladecyd2.config.listeNiveauSkill = this.createDirectOptionList(0, 10) + game.system.mournbladecyd2.config.listeNiveauCreature = this.createDirectOptionList(0, 35) + } /* -------------------------------------------- */ @@ -102,16 +106,13 @@ export class MournbladeCYD2Utility { /* -------------------------------------------- */ static async ready() { - const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd2.skills") + const skills = await MournbladeCYD2Utility.loadCompendium("fvtt-mournblade-cyd-2-0.skills") this.skills = skills.map(i => i.toObject()) // Setup pause logo - let logoPause = "systems/fvtt-mournblade-cyd2/assets/logos/" + game.settings.get("fvtt-mournblade-cyd2", "mournblade-cyd2-pause-logo") + ".webp" + let logoPause = "systems/fvtt-mournblade-cyd-2-0/assets/logos/" + game.settings.get("fvtt-mournblade-cyd-2-0", "mournblade-cyd2-pause-logo") + ".webp" let logoImg = document.querySelector('#pause').children[0] logoImg.setAttribute('style', `content: url(${logoPause})`) - - game.system.mournbladecyd2.config.listeNiveauSkill = this.createDirectOptionList(0, 10) - game.system.mournbladecyd2.config.listeNiveauCreature = this.createDirectOptionList(0, 35) } /* -------------------------------------------- */ @@ -182,13 +183,13 @@ export class MournbladeCYD2Utility { static async preloadHandlebarsTemplates() { const templatePaths = [ - 'systems/fvtt-mournblade-cyd2/templates/editor-notes-gm.hbs', - 'systems/fvtt-mournblade-cyd2/templates/partial-item-header.hbs', - 'systems/fvtt-mournblade-cyd2/templates/partial-item-description.hbs', - 'systems/fvtt-mournblade-cyd2/templates/partial-item-nav.hbs', - 'systems/fvtt-mournblade-cyd2/templates/partial-item-prix.hbs', - 'systems/fvtt-mournblade-cyd2/templates/partial-automation.hbs', - 'systems/fvtt-mournblade-cyd2/templates/hud-adversites.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/editor-notes-gm.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs', + 'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs', ] return foundry.applications.handlebars.loadTemplates(templatePaths); } @@ -372,7 +373,7 @@ export class MournbladeCYD2Utility { let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor defender.changeEtatCombativite(value) } else { - game.socket.emit("system.fvtt-mournblade-cyd2", { msg: "msg_apply_combativite", data: { defenderTokenId: rollData.defenderTokenId, value } }); + game.socket.emit("system.fvtt-mournblade-cyd-2-0", { msg: "msg_apply_combativite", data: { defenderTokenId: rollData.defenderTokenId, value } }); } } /* -------------------------------------------- */ @@ -383,7 +384,7 @@ export class MournbladeCYD2Utility { rollData.attrKey = "adr" } if (!rollData.attr) { - rollData.actionImg = "systems/fvtt-mournblade-cyd2/assets/icons/" + actor.system.attributs[rollData.attrKey].labelnorm + ".webp" + rollData.actionImg = "systems/fvtt-mournblade-cyd-2-0/assets/icons/" + actor.system.attributs[rollData.attrKey].labelnorm + ".webp" rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey]) } if (rollData.attrKey2 != "none") { @@ -503,7 +504,7 @@ export class MournbladeCYD2Utility { } this.createChatWithRollMode(rollData.alias, { - content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-generic-result.hbs`, rollData) + content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade-cyd-2-0/templates/chat-generic-result.hbs`, rollData) }, rollData) if ((rollData.coupBas || rollData.arme) && rollData.isSuccess && rollData.defenderTokenId) { @@ -610,7 +611,7 @@ export class MournbladeCYD2Utility { this.computeResultQuality(rollData) this.createChatWithRollMode(rollData.alias, { - content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade-cyd2/templates/chat-generic-result.hbs`, rollData) + content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade-cyd-2-0/templates/chat-generic-result.hbs`, rollData) }, rollData) } @@ -641,7 +642,7 @@ export class MournbladeCYD2Utility { chatGM.whisper = this.getUsers(user => user.isGM); chatGM.content = "Blinde message of " + game.user.name + "
" + chatOptions.content; console.log("blindMessageToGM", chatGM); - game.socket.emit("system.fvtt-mournblade-cyd2", { msg: "msg_gm_chat_message", data: chatGM }); + game.socket.emit("system.fvtt-mournblade-cyd-2-0", { msg: "msg_gm_chat_message", data: chatGM }); } /* -------------------------------------------- */ diff --git a/package.json b/package.json index d688130..5e8ad67 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "fvtt-mournblade-cyd2", + "name": "fvtt-mournblade-cyd-2-0", "version": "2.0.0", "description": "Mournblade CYD 2.0 RPG for FoundryVTT - French", "scripts": { diff --git a/packs/aides-de-jeu/000378.log b/packs/aides-de-jeu/000385.log similarity index 100% rename from packs/aides-de-jeu/000378.log rename to packs/aides-de-jeu/000385.log diff --git a/packs/aides-de-jeu/CURRENT b/packs/aides-de-jeu/CURRENT index 561f1eb..70d8a3a 100644 --- a/packs/aides-de-jeu/CURRENT +++ b/packs/aides-de-jeu/CURRENT @@ -1 +1 @@ -MANIFEST-000376 +MANIFEST-000384 diff --git a/packs/aides-de-jeu/LOG b/packs/aides-de-jeu/LOG index afe3f5c..06ea44c 100644 --- a/packs/aides-de-jeu/LOG +++ b/packs/aides-de-jeu/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.773579 7f05877fe6c0 Recovering log #374 -2025/10/26-14:44:35.783336 7f05877fe6c0 Delete type=3 #372 -2025/10/26-14:44:35.783390 7f05877fe6c0 Delete type=0 #374 -2025/10/26-14:44:53.282449 7f0586bff6c0 Level-0 table #379: started -2025/10/26-14:44:53.282474 7f0586bff6c0 Level-0 table #379: 0 bytes OK -2025/10/26-14:44:53.288360 7f0586bff6c0 Delete type=0 #377 -2025/10/26-14:44:53.308451 7f0586bff6c0 Manual compaction at level-0 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.308507 7f0586bff6c0 Manual compaction at level-1 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.886542 7feec8bfd6c0 Recovering log #382 +2026/04/02-22:42:22.897444 7feec8bfd6c0 Delete type=3 #380 +2026/04/02-22:42:22.897515 7feec8bfd6c0 Delete type=0 #382 diff --git a/packs/aides-de-jeu/LOG.old b/packs/aides-de-jeu/LOG.old index cbbd66e..88fa664 100644 --- a/packs/aides-de-jeu/LOG.old +++ b/packs/aides-de-jeu/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:34.089807 7f058c9f96c0 Recovering log #370 -2025/10/26-14:17:34.150991 7f058c9f96c0 Delete type=3 #368 -2025/10/26-14:17:34.151050 7f058c9f96c0 Delete type=0 #370 -2025/10/26-14:43:50.641754 7f0586bff6c0 Level-0 table #375: started -2025/10/26-14:43:50.641778 7f0586bff6c0 Level-0 table #375: 0 bytes OK -2025/10/26-14:43:50.648553 7f0586bff6c0 Delete type=0 #373 -2025/10/26-14:43:50.648712 7f0586bff6c0 Manual compaction at level-0 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.648735 7f0586bff6c0 Manual compaction at level-1 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.995579 7feec93fe6c0 Recovering log #378 +2026/04/02-22:23:12.005529 7feec93fe6c0 Delete type=3 #376 +2026/04/02-22:23:12.005581 7feec93fe6c0 Delete type=0 #378 +2026/04/02-22:41:03.722884 7feeb37fe6c0 Level-0 table #383: started +2026/04/02-22:41:03.722902 7feeb37fe6c0 Level-0 table #383: 0 bytes OK +2026/04/02-22:41:03.728999 7feeb37fe6c0 Delete type=0 #381 +2026/04/02-22:41:03.736041 7feeb37fe6c0 Manual compaction at level-0 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.745674 7feeb37fe6c0 Manual compaction at level-1 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) diff --git a/packs/aides-de-jeu/MANIFEST-000376 b/packs/aides-de-jeu/MANIFEST-000384 similarity index 84% rename from packs/aides-de-jeu/MANIFEST-000376 rename to packs/aides-de-jeu/MANIFEST-000384 index 6da865b..3e50fce 100644 Binary files a/packs/aides-de-jeu/MANIFEST-000376 and b/packs/aides-de-jeu/MANIFEST-000384 differ diff --git a/packs/armes/000375.log b/packs/armes/000382.log similarity index 100% rename from packs/armes/000375.log rename to packs/armes/000382.log diff --git a/packs/armes/CURRENT b/packs/armes/CURRENT index 1ca0e83..9a9c819 100644 --- a/packs/armes/CURRENT +++ b/packs/armes/CURRENT @@ -1 +1 @@ -MANIFEST-000373 +MANIFEST-000381 diff --git a/packs/armes/LOG b/packs/armes/LOG index c369281..7cc49ea 100644 --- a/packs/armes/LOG +++ b/packs/armes/LOG @@ -1,9 +1,3 @@ -2025/10/26-14:44:35.634587 7f05877fe6c0 Recovering log #371 -2025/10/26-14:44:35.644088 7f05877fe6c0 Delete type=3 #367 -2025/10/26-14:44:35.644144 7f05877fe6c0 Delete type=3 #252 -2025/10/26-14:44:35.644177 7f05877fe6c0 Delete type=0 #371 -2025/10/26-14:44:53.218055 7f0586bff6c0 Level-0 table #376: started -2025/10/26-14:44:53.218081 7f0586bff6c0 Level-0 table #376: 0 bytes OK -2025/10/26-14:44:53.224298 7f0586bff6c0 Delete type=0 #374 -2025/10/26-14:44:53.231605 7f0586bff6c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.231650 7f0586bff6c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.751579 7feeb3fff6c0 Recovering log #379 +2026/04/02-22:42:22.761248 7feeb3fff6c0 Delete type=3 #377 +2026/04/02-22:42:22.761291 7feeb3fff6c0 Delete type=0 #379 diff --git a/packs/armes/LOG.old b/packs/armes/LOG.old index 36e80d3..1c1ad4e 100644 --- a/packs/armes/LOG.old +++ b/packs/armes/LOG.old @@ -1,11 +1,8 @@ -2025/10/26-14:17:33.329160 7f0587fff6c0 Recovering log #250 -2025/10/26-14:17:33.329199 7f0587fff6c0 Recovering log #369 -2025/10/26-14:17:33.500980 7f0587fff6c0 Delete type=2 #352 -2025/10/26-14:17:33.501082 7f0587fff6c0 Delete type=0 #369 -2025/10/26-14:17:33.501136 7f0587fff6c0 Delete type=3 #248 -2025/10/26-14:17:33.501178 7f0587fff6c0 Delete type=0 #250 -2025/10/26-14:43:50.551774 7f0586bff6c0 Level-0 table #372: started -2025/10/26-14:43:50.551804 7f0586bff6c0 Level-0 table #372: 0 bytes OK -2025/10/26-14:43:50.557801 7f0586bff6c0 Delete type=0 #370 -2025/10/26-14:43:50.570810 7f0586bff6c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.570851 7f0586bff6c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.844533 7feec8bfd6c0 Recovering log #375 +2026/04/02-22:23:11.854182 7feec8bfd6c0 Delete type=3 #373 +2026/04/02-22:23:11.854243 7feec8bfd6c0 Delete type=0 #375 +2026/04/02-22:41:03.650062 7feeb37fe6c0 Level-0 table #380: started +2026/04/02-22:41:03.650092 7feeb37fe6c0 Level-0 table #380: 0 bytes OK +2026/04/02-22:41:03.656009 7feeb37fe6c0 Delete type=0 #378 +2026/04/02-22:41:03.656115 7feeb37fe6c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.656130 7feeb37fe6c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end) diff --git a/packs/armes/MANIFEST-000373 b/packs/armes/MANIFEST-000381 similarity index 73% rename from packs/armes/MANIFEST-000373 rename to packs/armes/MANIFEST-000381 index db0b7de..7c1b4d5 100644 Binary files a/packs/armes/MANIFEST-000373 and b/packs/armes/MANIFEST-000381 differ diff --git a/packs/dons/000257.log b/packs/dons/000264.log similarity index 100% rename from packs/dons/000257.log rename to packs/dons/000264.log diff --git a/packs/dons/CURRENT b/packs/dons/CURRENT index 380474a..45bcdf0 100644 --- a/packs/dons/CURRENT +++ b/packs/dons/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/dons/LOG b/packs/dons/LOG index 17a7306..378062e 100644 --- a/packs/dons/LOG +++ b/packs/dons/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.670450 7f05877fe6c0 Recovering log #253 -2025/10/26-14:44:35.680591 7f05877fe6c0 Delete type=3 #251 -2025/10/26-14:44:35.680668 7f05877fe6c0 Delete type=0 #253 -2025/10/26-14:44:53.250029 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.250057 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.256904 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.257116 7f0586bff6c0 Manual compaction at level-0 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.257149 7f0586bff6c0 Manual compaction at level-1 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.787186 7feec8bfd6c0 Recovering log #261 +2026/04/02-22:42:22.797121 7feec8bfd6c0 Delete type=3 #259 +2026/04/02-22:42:22.797203 7feec8bfd6c0 Delete type=0 #261 diff --git a/packs/dons/LOG.old b/packs/dons/LOG.old index 513843c..e8a18e4 100644 --- a/packs/dons/LOG.old +++ b/packs/dons/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.616386 7f05877fe6c0 Recovering log #249 -2025/10/26-14:17:33.676039 7f05877fe6c0 Delete type=3 #247 -2025/10/26-14:17:33.676103 7f05877fe6c0 Delete type=0 #249 -2025/10/26-14:43:50.589531 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.589558 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.595890 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.596069 7f0586bff6c0 Manual compaction at level-0 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.596098 7f0586bff6c0 Manual compaction at level-1 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.881302 7feec93fe6c0 Recovering log #257 +2026/04/02-22:23:11.891971 7feec93fe6c0 Delete type=3 #255 +2026/04/02-22:23:11.892014 7feec93fe6c0 Delete type=0 #257 +2026/04/02-22:41:03.662117 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.662146 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.668307 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.680730 7feeb37fe6c0 Manual compaction at level-0 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.680782 7feeb37fe6c0 Manual compaction at level-1 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end) diff --git a/packs/dons/MANIFEST-000255 b/packs/dons/MANIFEST-000263 similarity index 73% rename from packs/dons/MANIFEST-000255 rename to packs/dons/MANIFEST-000263 index 54b14e5..8f4504f 100644 Binary files a/packs/dons/MANIFEST-000255 and b/packs/dons/MANIFEST-000263 differ diff --git a/packs/equipement/000257.log b/packs/equipement/000264.log similarity index 100% rename from packs/equipement/000257.log rename to packs/equipement/000264.log diff --git a/packs/equipement/CURRENT b/packs/equipement/CURRENT index 380474a..45bcdf0 100644 --- a/packs/equipement/CURRENT +++ b/packs/equipement/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/equipement/LOG b/packs/equipement/LOG index a4bbeb1..fb93e61 100644 --- a/packs/equipement/LOG +++ b/packs/equipement/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.658462 7f058d1fa6c0 Recovering log #253 -2025/10/26-14:44:35.668414 7f058d1fa6c0 Delete type=3 #251 -2025/10/26-14:44:35.668489 7f058d1fa6c0 Delete type=0 #253 -2025/10/26-14:44:53.237798 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.237817 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.243746 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.257084 7f0586bff6c0 Manual compaction at level-0 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.257137 7f0586bff6c0 Manual compaction at level-1 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.774883 7feec93fe6c0 Recovering log #261 +2026/04/02-22:42:22.785249 7feec93fe6c0 Delete type=3 #259 +2026/04/02-22:42:22.785297 7feec93fe6c0 Delete type=0 #261 diff --git a/packs/equipement/LOG.old b/packs/equipement/LOG.old index 999519c..99f5923 100644 --- a/packs/equipement/LOG.old +++ b/packs/equipement/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.560253 7f058d1fa6c0 Recovering log #249 -2025/10/26-14:17:33.613553 7f058d1fa6c0 Delete type=3 #247 -2025/10/26-14:17:33.613627 7f058d1fa6c0 Delete type=0 #249 -2025/10/26-14:43:50.577372 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.577440 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.583481 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.596035 7f0586bff6c0 Manual compaction at level-0 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.596079 7f0586bff6c0 Manual compaction at level-1 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.869572 7feec8bfd6c0 Recovering log #257 +2026/04/02-22:23:11.878854 7feec8bfd6c0 Delete type=3 #255 +2026/04/02-22:23:11.878924 7feec8bfd6c0 Delete type=0 #257 +2026/04/02-22:41:03.674670 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.674691 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.680561 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.680749 7feeb37fe6c0 Manual compaction at level-0 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.680776 7feeb37fe6c0 Manual compaction at level-1 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end) diff --git a/packs/equipement/MANIFEST-000255 b/packs/equipement/MANIFEST-000263 similarity index 73% rename from packs/equipement/MANIFEST-000255 rename to packs/equipement/MANIFEST-000263 index f41db3d..10c3971 100644 Binary files a/packs/equipement/MANIFEST-000255 and b/packs/equipement/MANIFEST-000263 differ diff --git a/packs/historiques/000377.log b/packs/historiques/000384.log similarity index 100% rename from packs/historiques/000377.log rename to packs/historiques/000384.log diff --git a/packs/historiques/CURRENT b/packs/historiques/CURRENT index 741abc7..25e3b7f 100644 --- a/packs/historiques/CURRENT +++ b/packs/historiques/CURRENT @@ -1 +1 @@ -MANIFEST-000375 +MANIFEST-000383 diff --git a/packs/historiques/LOG b/packs/historiques/LOG index 705a706..78973e4 100644 --- a/packs/historiques/LOG +++ b/packs/historiques/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.622083 7f0587fff6c0 Recovering log #373 -2025/10/26-14:44:35.632124 7f0587fff6c0 Delete type=3 #371 -2025/10/26-14:44:35.632194 7f0587fff6c0 Delete type=0 #373 -2025/10/26-14:44:53.205925 7f0586bff6c0 Level-0 table #378: started -2025/10/26-14:44:53.205967 7f0586bff6c0 Level-0 table #378: 0 bytes OK -2025/10/26-14:44:53.211891 7f0586bff6c0 Delete type=0 #376 -2025/10/26-14:44:53.231573 7f0586bff6c0 Manual compaction at level-0 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.231629 7f0586bff6c0 Manual compaction at level-1 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.739027 7feec8bfd6c0 Recovering log #381 +2026/04/02-22:42:22.749357 7feec8bfd6c0 Delete type=3 #379 +2026/04/02-22:42:22.749468 7feec8bfd6c0 Delete type=0 #381 diff --git a/packs/historiques/LOG.old b/packs/historiques/LOG.old index 59724bb..7cbab3d 100644 --- a/packs/historiques/LOG.old +++ b/packs/historiques/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.238795 7f058d1fa6c0 Recovering log #369 -2025/10/26-14:17:33.326213 7f058d1fa6c0 Delete type=3 #367 -2025/10/26-14:17:33.326289 7f058d1fa6c0 Delete type=0 #369 -2025/10/26-14:43:50.557940 7f0586bff6c0 Level-0 table #374: started -2025/10/26-14:43:50.557971 7f0586bff6c0 Level-0 table #374: 0 bytes OK -2025/10/26-14:43:50.563944 7f0586bff6c0 Delete type=0 #372 -2025/10/26-14:43:50.570822 7f0586bff6c0 Manual compaction at level-0 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.570858 7f0586bff6c0 Manual compaction at level-1 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.832014 7feec93fe6c0 Recovering log #377 +2026/04/02-22:23:11.841719 7feec93fe6c0 Delete type=3 #375 +2026/04/02-22:23:11.841777 7feec93fe6c0 Delete type=0 #377 +2026/04/02-22:41:03.636791 7feeb37fe6c0 Level-0 table #382: started +2026/04/02-22:41:03.636818 7feeb37fe6c0 Level-0 table #382: 0 bytes OK +2026/04/02-22:41:03.642955 7feeb37fe6c0 Delete type=0 #380 +2026/04/02-22:41:03.656101 7feeb37fe6c0 Manual compaction at level-0 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.656120 7feeb37fe6c0 Manual compaction at level-1 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end) diff --git a/packs/historiques/MANIFEST-000375 b/packs/historiques/MANIFEST-000383 similarity index 72% rename from packs/historiques/MANIFEST-000375 rename to packs/historiques/MANIFEST-000383 index 1edf243..a81aac4 100644 Binary files a/packs/historiques/MANIFEST-000375 and b/packs/historiques/MANIFEST-000383 differ diff --git a/packs/profils/000377.log b/packs/profils/000384.log similarity index 100% rename from packs/profils/000377.log rename to packs/profils/000384.log diff --git a/packs/profils/CURRENT b/packs/profils/CURRENT index 741abc7..25e3b7f 100644 --- a/packs/profils/CURRENT +++ b/packs/profils/CURRENT @@ -1 +1 @@ -MANIFEST-000375 +MANIFEST-000383 diff --git a/packs/profils/LOG b/packs/profils/LOG index 8b05353..fefd735 100644 --- a/packs/profils/LOG +++ b/packs/profils/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.721136 7f058c9f96c0 Recovering log #373 -2025/10/26-14:44:35.731166 7f058c9f96c0 Delete type=3 #371 -2025/10/26-14:44:35.731245 7f058c9f96c0 Delete type=0 #373 -2025/10/26-14:44:53.263565 7f0586bff6c0 Level-0 table #378: started -2025/10/26-14:44:53.263592 7f0586bff6c0 Level-0 table #378: 0 bytes OK -2025/10/26-14:44:53.269403 7f0586bff6c0 Delete type=0 #376 -2025/10/26-14:44:53.282273 7f0586bff6c0 Manual compaction at level-0 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.282328 7f0586bff6c0 Manual compaction at level-1 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.835807 7feec8bfd6c0 Recovering log #381 +2026/04/02-22:42:22.845258 7feec8bfd6c0 Delete type=3 #379 +2026/04/02-22:42:22.845300 7feec8bfd6c0 Delete type=0 #381 diff --git a/packs/profils/LOG.old b/packs/profils/LOG.old index 74bce7e..b7a6f82 100644 --- a/packs/profils/LOG.old +++ b/packs/profils/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.844186 7f058d1fa6c0 Recovering log #369 -2025/10/26-14:17:33.904254 7f058d1fa6c0 Delete type=3 #367 -2025/10/26-14:17:33.904322 7f058d1fa6c0 Delete type=0 #369 -2025/10/26-14:43:50.615369 7f0586bff6c0 Level-0 table #374: started -2025/10/26-14:43:50.615397 7f0586bff6c0 Level-0 table #374: 0 bytes OK -2025/10/26-14:43:50.621407 7f0586bff6c0 Delete type=0 #372 -2025/10/26-14:43:50.621524 7f0586bff6c0 Manual compaction at level-0 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.621543 7f0586bff6c0 Manual compaction at level-1 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.945566 7feec93fe6c0 Recovering log #377 +2026/04/02-22:23:11.954859 7feec93fe6c0 Delete type=3 #375 +2026/04/02-22:23:11.954911 7feec93fe6c0 Delete type=0 #377 +2026/04/02-22:41:03.686833 7feeb37fe6c0 Level-0 table #382: started +2026/04/02-22:41:03.686856 7feeb37fe6c0 Level-0 table #382: 0 bytes OK +2026/04/02-22:41:03.693649 7feeb37fe6c0 Delete type=0 #380 +2026/04/02-22:41:03.706286 7feeb37fe6c0 Manual compaction at level-0 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.706323 7feeb37fe6c0 Manual compaction at level-1 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end) diff --git a/packs/profils/MANIFEST-000375 b/packs/profils/MANIFEST-000383 similarity index 73% rename from packs/profils/MANIFEST-000375 rename to packs/profils/MANIFEST-000383 index f0543c8..16c85f2 100644 Binary files a/packs/profils/MANIFEST-000375 and b/packs/profils/MANIFEST-000383 differ diff --git a/packs/protections/000257.log b/packs/protections/000264.log similarity index 100% rename from packs/protections/000257.log rename to packs/protections/000264.log diff --git a/packs/protections/CURRENT b/packs/protections/CURRENT index 380474a..45bcdf0 100644 --- a/packs/protections/CURRENT +++ b/packs/protections/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/protections/LOG b/packs/protections/LOG index 954f888..9ac80e5 100644 --- a/packs/protections/LOG +++ b/packs/protections/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.646347 7f058c9f96c0 Recovering log #253 -2025/10/26-14:44:35.656365 7f058c9f96c0 Delete type=3 #251 -2025/10/26-14:44:35.656455 7f058c9f96c0 Delete type=0 #253 -2025/10/26-14:44:53.231745 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.231785 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.237694 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.257064 7f0586bff6c0 Manual compaction at level-0 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.257127 7f0586bff6c0 Manual compaction at level-1 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.763267 7feec9bff6c0 Recovering log #261 +2026/04/02-22:42:22.772907 7feec9bff6c0 Delete type=3 #259 +2026/04/02-22:42:22.772976 7feec9bff6c0 Delete type=0 #261 diff --git a/packs/protections/LOG.old b/packs/protections/LOG.old index 16616da..7250dea 100644 --- a/packs/protections/LOG.old +++ b/packs/protections/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.504597 7f058c9f96c0 Recovering log #249 -2025/10/26-14:17:33.557486 7f058c9f96c0 Delete type=3 #247 -2025/10/26-14:17:33.557559 7f058c9f96c0 Delete type=0 #249 -2025/10/26-14:43:50.570973 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.571024 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.577238 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.596020 7f0586bff6c0 Manual compaction at level-0 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.596059 7f0586bff6c0 Manual compaction at level-1 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.856417 7feec93fe6c0 Recovering log #257 +2026/04/02-22:23:11.867162 7feec93fe6c0 Delete type=3 #255 +2026/04/02-22:23:11.867225 7feec93fe6c0 Delete type=0 #257 +2026/04/02-22:41:03.656206 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.656226 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.662021 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.680712 7feeb37fe6c0 Manual compaction at level-0 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.680794 7feeb37fe6c0 Manual compaction at level-1 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end) diff --git a/packs/protections/MANIFEST-000255 b/packs/protections/MANIFEST-000263 similarity index 73% rename from packs/protections/MANIFEST-000255 rename to packs/protections/MANIFEST-000263 index c2b44d9..b4ac06a 100644 Binary files a/packs/protections/MANIFEST-000255 and b/packs/protections/MANIFEST-000263 differ diff --git a/packs/runes/000257.log b/packs/runes/000264.log similarity index 100% rename from packs/runes/000257.log rename to packs/runes/000264.log diff --git a/packs/runes/CURRENT b/packs/runes/CURRENT index 380474a..45bcdf0 100644 --- a/packs/runes/CURRENT +++ b/packs/runes/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/runes/LOG b/packs/runes/LOG index 969738a..c7a90df 100644 --- a/packs/runes/LOG +++ b/packs/runes/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.708614 7f05877fe6c0 Recovering log #253 -2025/10/26-14:44:35.719212 7f05877fe6c0 Delete type=3 #251 -2025/10/26-14:44:35.719271 7f05877fe6c0 Delete type=0 #253 -2025/10/26-14:44:53.257366 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.257411 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.263459 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.282260 7f0586bff6c0 Manual compaction at level-0 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.282308 7f0586bff6c0 Manual compaction at level-1 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.823423 7feeb3fff6c0 Recovering log #261 +2026/04/02-22:42:22.833361 7feeb3fff6c0 Delete type=3 #259 +2026/04/02-22:42:22.833424 7feeb3fff6c0 Delete type=0 #261 diff --git a/packs/runes/LOG.old b/packs/runes/LOG.old index 861a736..72b5d4a 100644 --- a/packs/runes/LOG.old +++ b/packs/runes/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.790087 7f05877fe6c0 Recovering log #249 -2025/10/26-14:17:33.841786 7f05877fe6c0 Delete type=3 #247 -2025/10/26-14:17:33.841849 7f05877fe6c0 Delete type=0 #249 -2025/10/26-14:43:50.602350 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.602383 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.608645 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.621507 7f0586bff6c0 Manual compaction at level-0 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.621536 7f0586bff6c0 Manual compaction at level-1 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.918116 7feeb3fff6c0 Recovering log #257 +2026/04/02-22:23:11.928729 7feeb3fff6c0 Delete type=3 #255 +2026/04/02-22:23:11.928772 7feeb3fff6c0 Delete type=0 #257 +2026/04/02-22:41:03.680892 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.680922 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.686757 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.706277 7feeb37fe6c0 Manual compaction at level-0 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.706313 7feeb37fe6c0 Manual compaction at level-1 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end) diff --git a/packs/runes/MANIFEST-000255 b/packs/runes/MANIFEST-000263 similarity index 72% rename from packs/runes/MANIFEST-000255 rename to packs/runes/MANIFEST-000263 index 70e07dd..8703f99 100644 Binary files a/packs/runes/MANIFEST-000255 and b/packs/runes/MANIFEST-000263 differ diff --git a/packs/scenes/000200.ldb b/packs/scenes/000200.ldb deleted file mode 100644 index acba567..0000000 Binary files a/packs/scenes/000200.ldb and /dev/null differ diff --git a/packs/scenes/000223.ldb b/packs/scenes/000223.ldb new file mode 100644 index 0000000..a4d14b9 Binary files /dev/null and b/packs/scenes/000223.ldb differ diff --git a/packs/scenes/000217.log b/packs/scenes/000225.log similarity index 100% rename from packs/scenes/000217.log rename to packs/scenes/000225.log diff --git a/packs/scenes/CURRENT b/packs/scenes/CURRENT index 68076bd..4d5019e 100644 --- a/packs/scenes/CURRENT +++ b/packs/scenes/CURRENT @@ -1 +1 @@ -MANIFEST-000215 +MANIFEST-000224 diff --git a/packs/scenes/LOG b/packs/scenes/LOG index cec6dab..1e3d339 100644 --- a/packs/scenes/LOG +++ b/packs/scenes/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.760670 7f058d1fa6c0 Recovering log #213 -2025/10/26-14:44:35.770100 7f058d1fa6c0 Delete type=3 #211 -2025/10/26-14:44:35.770150 7f058d1fa6c0 Delete type=0 #213 -2025/10/26-14:44:53.294614 7f0586bff6c0 Level-0 table #218: started -2025/10/26-14:44:53.294640 7f0586bff6c0 Level-0 table #218: 0 bytes OK -2025/10/26-14:44:53.302067 7f0586bff6c0 Delete type=0 #216 -2025/10/26-14:44:53.308488 7f0586bff6c0 Manual compaction at level-0 from '!scenes!mfosNsLsHN5Pf4TO' @ 72057594037927935 : 1 .. '!scenes!mfosNsLsHN5Pf4TO' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.308516 7f0586bff6c0 Manual compaction at level-1 from '!scenes!mfosNsLsHN5Pf4TO' @ 72057594037927935 : 1 .. '!scenes!mfosNsLsHN5Pf4TO' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.872560 7feec93fe6c0 Recovering log #221 +2026/04/02-22:42:22.882205 7feec93fe6c0 Delete type=3 #219 +2026/04/02-22:42:22.882248 7feec93fe6c0 Delete type=0 #221 diff --git a/packs/scenes/LOG.old b/packs/scenes/LOG.old index 7080410..a1901bd 100644 --- a/packs/scenes/LOG.old +++ b/packs/scenes/LOG.old @@ -1,8 +1,15 @@ -2025/10/26-14:17:34.026248 7f058d1fa6c0 Recovering log #209 -2025/10/26-14:17:34.085478 7f058d1fa6c0 Delete type=3 #207 -2025/10/26-14:17:34.085544 7f058d1fa6c0 Delete type=0 #209 -2025/10/26-14:43:50.635471 7f0586bff6c0 Level-0 table #214: started -2025/10/26-14:43:50.635508 7f0586bff6c0 Level-0 table #214: 0 bytes OK -2025/10/26-14:43:50.641648 7f0586bff6c0 Delete type=0 #212 -2025/10/26-14:43:50.648703 7f0586bff6c0 Manual compaction at level-0 from '!scenes!mfosNsLsHN5Pf4TO' @ 72057594037927935 : 1 .. '!scenes!mfosNsLsHN5Pf4TO' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.648748 7f0586bff6c0 Manual compaction at level-1 from '!scenes!mfosNsLsHN5Pf4TO' @ 72057594037927935 : 1 .. '!scenes!mfosNsLsHN5Pf4TO' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.983507 7feeb3fff6c0 Recovering log #217 +2026/04/02-22:23:11.992802 7feeb3fff6c0 Delete type=3 #215 +2026/04/02-22:23:11.992847 7feeb3fff6c0 Delete type=0 #217 +2026/04/02-22:41:03.713063 7feeb37fe6c0 Level-0 table #222: started +2026/04/02-22:41:03.716879 7feeb37fe6c0 Level-0 table #222: 1619 bytes OK +2026/04/02-22:41:03.722798 7feeb37fe6c0 Delete type=0 #220 +2026/04/02-22:41:03.736032 7feeb37fe6c0 Manual compaction at level-0 from '!scenes!mfosNsLsHN5Pf4TO' @ 72057594037927935 : 1 .. '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.736071 7feeb37fe6c0 Manual compaction at level-1 from '!scenes!mfosNsLsHN5Pf4TO' @ 72057594037927935 : 1 .. '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 0 : 0; will stop at '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 102 : 1 +2026/04/02-22:41:03.736077 7feeb37fe6c0 Compacting 1@1 + 1@2 files +2026/04/02-22:41:03.739208 7feeb37fe6c0 Generated table #223@1: 2 keys, 1619 bytes +2026/04/02-22:41:03.739222 7feeb37fe6c0 Compacted 1@1 + 1@2 files => 1619 bytes +2026/04/02-22:41:03.745387 7feeb37fe6c0 compacted to: files[ 0 0 1 0 0 0 0 ] +2026/04/02-22:41:03.745489 7feeb37fe6c0 Delete type=2 #200 +2026/04/02-22:41:03.745601 7feeb37fe6c0 Delete type=2 #222 +2026/04/02-22:41:03.758550 7feeb37fe6c0 Manual compaction at level-1 from '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 102 : 1 .. '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 0 : 0; will stop at (end) diff --git a/packs/scenes/MANIFEST-000215 b/packs/scenes/MANIFEST-000215 deleted file mode 100644 index b202611..0000000 Binary files a/packs/scenes/MANIFEST-000215 and /dev/null differ diff --git a/packs/scenes/MANIFEST-000224 b/packs/scenes/MANIFEST-000224 new file mode 100644 index 0000000..b8acdd6 Binary files /dev/null and b/packs/scenes/MANIFEST-000224 differ diff --git a/packs/skills-creatures/000165.log b/packs/skills-creatures/000172.log similarity index 100% rename from packs/skills-creatures/000165.log rename to packs/skills-creatures/000172.log diff --git a/packs/skills-creatures/CURRENT b/packs/skills-creatures/CURRENT index abf5eb3..91e41f4 100644 --- a/packs/skills-creatures/CURRENT +++ b/packs/skills-creatures/CURRENT @@ -1 +1 @@ -MANIFEST-000163 +MANIFEST-000171 diff --git a/packs/skills-creatures/LOG b/packs/skills-creatures/LOG index 0f43ce8..774594e 100644 --- a/packs/skills-creatures/LOG +++ b/packs/skills-creatures/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.609943 7f058c9f96c0 Recovering log #161 -2025/10/26-14:44:35.620061 7f058c9f96c0 Delete type=3 #159 -2025/10/26-14:44:35.620112 7f058c9f96c0 Delete type=0 #161 -2025/10/26-14:44:53.224450 7f0586bff6c0 Level-0 table #166: started -2025/10/26-14:44:53.224482 7f0586bff6c0 Level-0 table #166: 0 bytes OK -2025/10/26-14:44:53.231453 7f0586bff6c0 Delete type=0 #164 -2025/10/26-14:44:53.231618 7f0586bff6c0 Manual compaction at level-0 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.231660 7f0586bff6c0 Manual compaction at level-1 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.727378 7feeb3fff6c0 Recovering log #169 +2026/04/02-22:42:22.736950 7feeb3fff6c0 Delete type=3 #167 +2026/04/02-22:42:22.737015 7feeb3fff6c0 Delete type=0 #169 diff --git a/packs/skills-creatures/LOG.old b/packs/skills-creatures/LOG.old index e59df36..e567db4 100644 --- a/packs/skills-creatures/LOG.old +++ b/packs/skills-creatures/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.157252 7f05877fe6c0 Recovering log #157 -2025/10/26-14:17:33.236823 7f05877fe6c0 Delete type=3 #155 -2025/10/26-14:17:33.236895 7f05877fe6c0 Delete type=0 #157 -2025/10/26-14:43:50.544974 7f0586bff6c0 Level-0 table #162: started -2025/10/26-14:43:50.545049 7f0586bff6c0 Level-0 table #162: 0 bytes OK -2025/10/26-14:43:50.551670 7f0586bff6c0 Delete type=0 #160 -2025/10/26-14:43:50.570795 7f0586bff6c0 Manual compaction at level-0 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.570842 7f0586bff6c0 Manual compaction at level-1 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.820127 7feeb3fff6c0 Recovering log #165 +2026/04/02-22:23:11.829802 7feeb3fff6c0 Delete type=3 #163 +2026/04/02-22:23:11.829871 7feeb3fff6c0 Delete type=0 #165 +2026/04/02-22:41:03.643069 7feeb37fe6c0 Level-0 table #170: started +2026/04/02-22:41:03.643094 7feeb37fe6c0 Level-0 table #170: 0 bytes OK +2026/04/02-22:41:03.649929 7feeb37fe6c0 Delete type=0 #168 +2026/04/02-22:41:03.656108 7feeb37fe6c0 Manual compaction at level-0 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.656141 7feeb37fe6c0 Manual compaction at level-1 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end) diff --git a/packs/skills-creatures/MANIFEST-000163 b/packs/skills-creatures/MANIFEST-000171 similarity index 73% rename from packs/skills-creatures/MANIFEST-000163 rename to packs/skills-creatures/MANIFEST-000171 index 4c7eb17..2997f77 100644 Binary files a/packs/skills-creatures/MANIFEST-000163 and b/packs/skills-creatures/MANIFEST-000171 differ diff --git a/packs/skills/000257.log b/packs/skills/000264.log similarity index 100% rename from packs/skills/000257.log rename to packs/skills/000264.log diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT index 380474a..45bcdf0 100644 --- a/packs/skills/CURRENT +++ b/packs/skills/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/skills/LOG b/packs/skills/LOG index 8981689..3289dc9 100644 --- a/packs/skills/LOG +++ b/packs/skills/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.598401 7f05877fe6c0 Recovering log #253 -2025/10/26-14:44:35.607893 7f05877fe6c0 Delete type=3 #251 -2025/10/26-14:44:35.607941 7f05877fe6c0 Delete type=0 #253 -2025/10/26-14:44:53.212036 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.212073 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.217965 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.231590 7f0586bff6c0 Manual compaction at level-0 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.231639 7f0586bff6c0 Manual compaction at level-1 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.715339 7feec8bfd6c0 Recovering log #261 +2026/04/02-22:42:22.725110 7feec8bfd6c0 Delete type=3 #259 +2026/04/02-22:42:22.725152 7feec8bfd6c0 Delete type=0 #261 diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old index c168e39..bd64a57 100644 --- a/packs/skills/LOG.old +++ b/packs/skills/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.083511 7f058c9f96c0 Recovering log #249 -2025/10/26-14:17:33.155121 7f058c9f96c0 Delete type=3 #247 -2025/10/26-14:17:33.155197 7f058c9f96c0 Delete type=0 #249 -2025/10/26-14:43:50.564078 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.564116 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.570661 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.570833 7f0586bff6c0 Manual compaction at level-0 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.570867 7f0586bff6c0 Manual compaction at level-1 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.808380 7feec9bff6c0 Recovering log #257 +2026/04/02-22:23:11.817785 7feec9bff6c0 Delete type=3 #255 +2026/04/02-22:23:11.817833 7feec9bff6c0 Delete type=0 #257 +2026/04/02-22:41:03.630634 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.630678 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.636689 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.656092 7feeb37fe6c0 Manual compaction at level-0 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.656125 7feeb37fe6c0 Manual compaction at level-1 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end) diff --git a/packs/skills/MANIFEST-000255 b/packs/skills/MANIFEST-000263 similarity index 73% rename from packs/skills/MANIFEST-000255 rename to packs/skills/MANIFEST-000263 index d136a35..09afeba 100644 Binary files a/packs/skills/MANIFEST-000255 and b/packs/skills/MANIFEST-000263 differ diff --git a/packs/tables/000372.log b/packs/tables/000379.log similarity index 100% rename from packs/tables/000372.log rename to packs/tables/000379.log diff --git a/packs/tables/CURRENT b/packs/tables/CURRENT index 460ff32..5a3fb87 100644 --- a/packs/tables/CURRENT +++ b/packs/tables/CURRENT @@ -1 +1 @@ -MANIFEST-000370 +MANIFEST-000378 diff --git a/packs/tables/LOG b/packs/tables/LOG index 432afa0..12f9ee8 100644 --- a/packs/tables/LOG +++ b/packs/tables/LOG @@ -1,7 +1,3 @@ -2025/10/26-14:44:35.747136 7f05877fe6c0 Recovering log #368 -2025/10/26-14:44:35.758006 7f05877fe6c0 Delete type=3 #366 -2025/10/26-14:44:35.758071 7f05877fe6c0 Delete type=0 #368 -2025/10/26-14:44:53.288438 7f0586bff6c0 Level-0 table #373: started -2025/10/26-14:44:53.288457 7f0586bff6c0 Level-0 table #373: 0 bytes OK -2025/10/26-14:44:53.294493 7f0586bff6c0 Delete type=0 #371 -2025/10/26-14:44:53.308473 7f0586bff6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.860656 7feec9bff6c0 Recovering log #376 +2026/04/02-22:42:22.870238 7feec9bff6c0 Delete type=3 #374 +2026/04/02-22:42:22.870287 7feec9bff6c0 Delete type=0 #376 diff --git a/packs/tables/LOG.old b/packs/tables/LOG.old index 8e00e3e..105acfb 100644 --- a/packs/tables/LOG.old +++ b/packs/tables/LOG.old @@ -1,7 +1,7 @@ -2025/10/26-14:17:33.964490 7f0587fff6c0 Recovering log #364 -2025/10/26-14:17:34.023594 7f0587fff6c0 Delete type=3 #362 -2025/10/26-14:17:34.023664 7f0587fff6c0 Delete type=0 #364 -2025/10/26-14:43:50.621643 7f0586bff6c0 Level-0 table #369: started -2025/10/26-14:43:50.621665 7f0586bff6c0 Level-0 table #369: 0 bytes OK -2025/10/26-14:43:50.628955 7f0586bff6c0 Delete type=0 #367 -2025/10/26-14:43:50.648683 7f0586bff6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.970070 7feec93fe6c0 Recovering log #372 +2026/04/02-22:23:11.980922 7feec93fe6c0 Delete type=3 #370 +2026/04/02-22:23:11.980982 7feec93fe6c0 Delete type=0 #372 +2026/04/02-22:41:03.706419 7feeb37fe6c0 Level-0 table #377: started +2026/04/02-22:41:03.706450 7feeb37fe6c0 Level-0 table #377: 0 bytes OK +2026/04/02-22:41:03.712908 7feeb37fe6c0 Delete type=0 #375 +2026/04/02-22:41:03.736020 7feeb37fe6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end) diff --git a/packs/tables/MANIFEST-000370 b/packs/tables/MANIFEST-000370 deleted file mode 100644 index 446ee38..0000000 Binary files a/packs/tables/MANIFEST-000370 and /dev/null differ diff --git a/packs/tables/MANIFEST-000378 b/packs/tables/MANIFEST-000378 new file mode 100644 index 0000000..b3c08e1 Binary files /dev/null and b/packs/tables/MANIFEST-000378 differ diff --git a/packs/talents/000378.log b/packs/talents/000385.log similarity index 100% rename from packs/talents/000378.log rename to packs/talents/000385.log diff --git a/packs/talents/CURRENT b/packs/talents/CURRENT index 561f1eb..70d8a3a 100644 --- a/packs/talents/CURRENT +++ b/packs/talents/CURRENT @@ -1 +1 @@ -MANIFEST-000376 +MANIFEST-000384 diff --git a/packs/talents/LOG b/packs/talents/LOG index abd66f1..b27b28d 100644 --- a/packs/talents/LOG +++ b/packs/talents/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.733973 7f0587fff6c0 Recovering log #374 -2025/10/26-14:44:35.744053 7f0587fff6c0 Delete type=3 #372 -2025/10/26-14:44:35.744110 7f0587fff6c0 Delete type=0 #374 -2025/10/26-14:44:53.269501 7f0586bff6c0 Level-0 table #379: started -2025/10/26-14:44:53.269524 7f0586bff6c0 Level-0 table #379: 0 bytes OK -2025/10/26-14:44:53.275723 7f0586bff6c0 Delete type=0 #377 -2025/10/26-14:44:53.282286 7f0586bff6c0 Manual compaction at level-0 from '!items!07bq0fsbn653i81y' @ 72057594037927935 : 1 .. '!items!zKvlDHBalR4UdwUx' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.282318 7f0586bff6c0 Manual compaction at level-1 from '!items!07bq0fsbn653i81y' @ 72057594037927935 : 1 .. '!items!zKvlDHBalR4UdwUx' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.847185 7feec93fe6c0 Recovering log #382 +2026/04/02-22:42:22.858002 7feec93fe6c0 Delete type=3 #380 +2026/04/02-22:42:22.858062 7feec93fe6c0 Delete type=0 #382 diff --git a/packs/talents/LOG.old b/packs/talents/LOG.old index 8338fe9..1895c2d 100644 --- a/packs/talents/LOG.old +++ b/packs/talents/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.906646 7f058c9f96c0 Recovering log #370 -2025/10/26-14:17:33.961055 7f058c9f96c0 Delete type=3 #368 -2025/10/26-14:17:33.961113 7f058c9f96c0 Delete type=0 #370 -2025/10/26-14:43:50.608740 7f0586bff6c0 Level-0 table #375: started -2025/10/26-14:43:50.608767 7f0586bff6c0 Level-0 table #375: 0 bytes OK -2025/10/26-14:43:50.615235 7f0586bff6c0 Delete type=0 #373 -2025/10/26-14:43:50.621516 7f0586bff6c0 Manual compaction at level-0 from '!items!07bq0fsbn653i81y' @ 72057594037927935 : 1 .. '!items!zKvlDHBalR4UdwUx' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.621549 7f0586bff6c0 Manual compaction at level-1 from '!items!07bq0fsbn653i81y' @ 72057594037927935 : 1 .. '!items!zKvlDHBalR4UdwUx' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.957088 7feeb3fff6c0 Recovering log #378 +2026/04/02-22:23:11.966998 7feeb3fff6c0 Delete type=3 #376 +2026/04/02-22:23:11.967052 7feeb3fff6c0 Delete type=0 #378 +2026/04/02-22:41:03.700257 7feeb37fe6c0 Level-0 table #383: started +2026/04/02-22:41:03.700299 7feeb37fe6c0 Level-0 table #383: 0 bytes OK +2026/04/02-22:41:03.706198 7feeb37fe6c0 Delete type=0 #381 +2026/04/02-22:41:03.706300 7feeb37fe6c0 Manual compaction at level-0 from '!items!07bq0fsbn653i81y' @ 72057594037927935 : 1 .. '!items!zKvlDHBalR4UdwUx' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.706318 7feeb37fe6c0 Manual compaction at level-1 from '!items!07bq0fsbn653i81y' @ 72057594037927935 : 1 .. '!items!zKvlDHBalR4UdwUx' @ 0 : 0; will stop at (end) diff --git a/packs/talents/MANIFEST-000376 b/packs/talents/MANIFEST-000384 similarity index 72% rename from packs/talents/MANIFEST-000376 rename to packs/talents/MANIFEST-000384 index 959140d..0e94d11 100644 Binary files a/packs/talents/MANIFEST-000376 and b/packs/talents/MANIFEST-000384 differ diff --git a/packs/tendances/000257.log b/packs/tendances/000264.log similarity index 100% rename from packs/tendances/000257.log rename to packs/tendances/000264.log diff --git a/packs/tendances/CURRENT b/packs/tendances/CURRENT index 380474a..45bcdf0 100644 --- a/packs/tendances/CURRENT +++ b/packs/tendances/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/tendances/LOG b/packs/tendances/LOG index 9e1d44d..d497faf 100644 --- a/packs/tendances/LOG +++ b/packs/tendances/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.683164 7f058c9f96c0 Recovering log #253 -2025/10/26-14:44:35.694143 7f058c9f96c0 Delete type=3 #251 -2025/10/26-14:44:35.694192 7f058c9f96c0 Delete type=0 #253 -2025/10/26-14:44:53.243853 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.243873 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.249962 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.257101 7f0586bff6c0 Manual compaction at level-0 from '!items!0CYP1JpZu9mst5tK' @ 72057594037927935 : 1 .. '!items!zhPPsmTtLv7cyNHJ' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.257159 7f0586bff6c0 Manual compaction at level-1 from '!items!0CYP1JpZu9mst5tK' @ 72057594037927935 : 1 .. '!items!zhPPsmTtLv7cyNHJ' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.799253 7feec93fe6c0 Recovering log #261 +2026/04/02-22:42:22.808694 7feec93fe6c0 Delete type=3 #259 +2026/04/02-22:42:22.808753 7feec93fe6c0 Delete type=0 #261 diff --git a/packs/tendances/LOG.old b/packs/tendances/LOG.old index ef3a534..e750811 100644 --- a/packs/tendances/LOG.old +++ b/packs/tendances/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.678678 7f0587fff6c0 Recovering log #249 -2025/10/26-14:17:33.731346 7f0587fff6c0 Delete type=3 #247 -2025/10/26-14:17:33.731455 7f0587fff6c0 Delete type=0 #249 -2025/10/26-14:43:50.583563 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.583591 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.589444 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.596047 7f0586bff6c0 Manual compaction at level-0 from '!items!0CYP1JpZu9mst5tK' @ 72057594037927935 : 1 .. '!items!zhPPsmTtLv7cyNHJ' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.596088 7f0586bff6c0 Manual compaction at level-1 from '!items!0CYP1JpZu9mst5tK' @ 72057594037927935 : 1 .. '!items!zhPPsmTtLv7cyNHJ' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.894124 7feeb3fff6c0 Recovering log #257 +2026/04/02-22:23:11.903854 7feeb3fff6c0 Delete type=3 #255 +2026/04/02-22:23:11.903907 7feeb3fff6c0 Delete type=0 #257 +2026/04/02-22:41:03.668376 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.668395 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.674598 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.680742 7feeb37fe6c0 Manual compaction at level-0 from '!items!0CYP1JpZu9mst5tK' @ 72057594037927935 : 1 .. '!items!zhPPsmTtLv7cyNHJ' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.680788 7feeb37fe6c0 Manual compaction at level-1 from '!items!0CYP1JpZu9mst5tK' @ 72057594037927935 : 1 .. '!items!zhPPsmTtLv7cyNHJ' @ 0 : 0; will stop at (end) diff --git a/packs/tendances/MANIFEST-000255 b/packs/tendances/MANIFEST-000263 similarity index 72% rename from packs/tendances/MANIFEST-000255 rename to packs/tendances/MANIFEST-000263 index 518b685..b4e54bc 100644 Binary files a/packs/tendances/MANIFEST-000255 and b/packs/tendances/MANIFEST-000263 differ diff --git a/packs/traits-chaotiques/000257.log b/packs/traits-chaotiques/000264.log similarity index 100% rename from packs/traits-chaotiques/000257.log rename to packs/traits-chaotiques/000264.log diff --git a/packs/traits-chaotiques/CURRENT b/packs/traits-chaotiques/CURRENT index 380474a..45bcdf0 100644 --- a/packs/traits-chaotiques/CURRENT +++ b/packs/traits-chaotiques/CURRENT @@ -1 +1 @@ -MANIFEST-000255 +MANIFEST-000263 diff --git a/packs/traits-chaotiques/LOG b/packs/traits-chaotiques/LOG index 34e6f8e..a36a23a 100644 --- a/packs/traits-chaotiques/LOG +++ b/packs/traits-chaotiques/LOG @@ -1,8 +1,3 @@ -2025/10/26-14:44:35.696475 7f058d1fa6c0 Recovering log #253 -2025/10/26-14:44:35.706242 7f058d1fa6c0 Delete type=3 #251 -2025/10/26-14:44:35.706313 7f058d1fa6c0 Delete type=0 #253 -2025/10/26-14:44:53.275829 7f0586bff6c0 Level-0 table #258: started -2025/10/26-14:44:53.275850 7f0586bff6c0 Level-0 table #258: 0 bytes OK -2025/10/26-14:44:53.282151 7f0586bff6c0 Delete type=0 #256 -2025/10/26-14:44:53.282297 7f0586bff6c0 Manual compaction at level-0 from '!items!3J0HKjcVtBT39BiR' @ 72057594037927935 : 1 .. '!items!zeOtWz6oscp8Su5l' @ 0 : 0; will stop at (end) -2025/10/26-14:44:53.282339 7f0586bff6c0 Manual compaction at level-1 from '!items!3J0HKjcVtBT39BiR' @ 72057594037927935 : 1 .. '!items!zeOtWz6oscp8Su5l' @ 0 : 0; will stop at (end) +2026/04/02-22:42:22.810618 7feec8bfd6c0 Recovering log #261 +2026/04/02-22:42:22.821256 7feec8bfd6c0 Delete type=3 #259 +2026/04/02-22:42:22.821311 7feec8bfd6c0 Delete type=0 #261 diff --git a/packs/traits-chaotiques/LOG.old b/packs/traits-chaotiques/LOG.old index afe7964..a64c2ca 100644 --- a/packs/traits-chaotiques/LOG.old +++ b/packs/traits-chaotiques/LOG.old @@ -1,8 +1,8 @@ -2025/10/26-14:17:33.734638 7f058c9f96c0 Recovering log #249 -2025/10/26-14:17:33.787813 7f058c9f96c0 Delete type=3 #247 -2025/10/26-14:17:33.787886 7f058c9f96c0 Delete type=0 #249 -2025/10/26-14:43:50.596168 7f0586bff6c0 Level-0 table #254: started -2025/10/26-14:43:50.596199 7f0586bff6c0 Level-0 table #254: 0 bytes OK -2025/10/26-14:43:50.602232 7f0586bff6c0 Delete type=0 #252 -2025/10/26-14:43:50.621497 7f0586bff6c0 Manual compaction at level-0 from '!items!3J0HKjcVtBT39BiR' @ 72057594037927935 : 1 .. '!items!zeOtWz6oscp8Su5l' @ 0 : 0; will stop at (end) -2025/10/26-14:43:50.621530 7f0586bff6c0 Manual compaction at level-1 from '!items!3J0HKjcVtBT39BiR' @ 72057594037927935 : 1 .. '!items!zeOtWz6oscp8Su5l' @ 0 : 0; will stop at (end) +2026/04/02-22:23:11.906122 7feec93fe6c0 Recovering log #257 +2026/04/02-22:23:11.916026 7feec93fe6c0 Delete type=3 #255 +2026/04/02-22:23:11.916071 7feec93fe6c0 Delete type=0 #257 +2026/04/02-22:41:03.693733 7feeb37fe6c0 Level-0 table #262: started +2026/04/02-22:41:03.693757 7feeb37fe6c0 Level-0 table #262: 0 bytes OK +2026/04/02-22:41:03.700114 7feeb37fe6c0 Delete type=0 #260 +2026/04/02-22:41:03.706293 7feeb37fe6c0 Manual compaction at level-0 from '!items!3J0HKjcVtBT39BiR' @ 72057594037927935 : 1 .. '!items!zeOtWz6oscp8Su5l' @ 0 : 0; will stop at (end) +2026/04/02-22:41:03.706328 7feeb37fe6c0 Manual compaction at level-1 from '!items!3J0HKjcVtBT39BiR' @ 72057594037927935 : 1 .. '!items!zeOtWz6oscp8Su5l' @ 0 : 0; will stop at (end) diff --git a/packs/traits-chaotiques/MANIFEST-000255 b/packs/traits-chaotiques/MANIFEST-000263 similarity index 73% rename from packs/traits-chaotiques/MANIFEST-000255 rename to packs/traits-chaotiques/MANIFEST-000263 index ea46fd0..ead50ba 100644 Binary files a/packs/traits-chaotiques/MANIFEST-000255 and b/packs/traits-chaotiques/MANIFEST-000263 differ diff --git a/styles/mournblade-cyd2.css b/styles/mournblade-cyd2.css index 232dc90..e44349a 100644 --- a/styles/mournblade-cyd2.css +++ b/styles/mournblade-cyd2.css @@ -67,7 +67,7 @@ } /* For nav and title */ .window-app input, -.fvtt-mournblade .item-form, +.fvtt-mournblade-cyd-2-0 .item-form, .sheet header.sheet-header .flex-group-center.flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, @@ -202,7 +202,7 @@ table { flex: 'flex-shrink'; } /* Styles limited to foundryvtt-vadentis sheets */ -.fvtt-mournblade .sheet-header { +.fvtt-mournblade-cyd-2-0 .sheet-header { -webkit-box-flex: 0; -ms-flex: 0 0 210px; flex: 0 0 210px; @@ -221,15 +221,16 @@ table { justify-content: flex-start; margin-bottom: 10px; } -.fvtt-mournblade .sheet-header .profile-img { +.fvtt-mournblade-cyd-2-0 .sheet-header .profile-img { -webkit-box-flex: 0; - -ms-flex: 0 0 128px; - flex: 0 0 128px; - height: 128px; - width: 128px; + -ms-flex: 0 0 80px; + flex: 0 0 80px; + height: 80px; + width: 80px; margin-right: 10px; object-fit: cover; object-position: 50% 0; + cursor: pointer; } .button-img { vertical-align: baseline; @@ -257,12 +258,12 @@ table { border: 0; vertical-align: bottom; } -.fvtt-mournblade .sheet-header .header-fields { +.fvtt-mournblade-cyd-2-0 .sheet-header .header-fields { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } -.fvtt-mournblade .sheet-header h1.charname { +.fvtt-mournblade-cyd-2-0 .sheet-header h1.charname { height: 50px; padding: 0px; margin: 5px 0; @@ -271,7 +272,7 @@ table { font-size: 2rem; font-family: "CentaurMT"; } -.fvtt-mournblade .sheet-header h1.charname input { +.fvtt-mournblade-cyd-2-0 .sheet-header h1.charname input { width: 100%; height: 100%; margin: 0; @@ -280,17 +281,17 @@ table { font-size: 2rem; text-align: left; } -.fvtt-mournblade .sheet-tabs { +.fvtt-mournblade-cyd-2-0 .sheet-tabs { -webkit-box-flex: 0; -ms-flex: 0; flex: 0; } -.fvtt-mournblade .sheet-body, -.fvtt-mournblade .sheet-body .tab { +.fvtt-mournblade-cyd-2-0 .sheet-body, +.fvtt-mournblade-cyd-2-0 .sheet-body .tab { height: auto; font-size: 0.9rem; } -.fvtt-mournblade .sheet-body .tab .editor { +.fvtt-mournblade-cyd-2-0 .sheet-body .tab .editor { height: 100%; font-size: 0.9rem; } @@ -314,58 +315,70 @@ table { height: 120px; padding: 0 3px; } -.fvtt-mournblade .tox .tox-editor-container { +.fvtt-mournblade-cyd-2-0 .tox .tox-editor-container { background: #fff; } -.fvtt-mournblade .tox .tox-edit-area { +.fvtt-mournblade-cyd-2-0 .tox .tox-edit-area { padding: 0 8px; } -.fvtt-mournblade .resource-label { +.fvtt-mournblade-cyd-2-0 .resource-label { font-weight: bold; text-transform: uppercase; } -.fvtt-mournblade .tabs { +.fvtt-mournblade-cyd-2-0 .tabs { height: 40px; border-top: 1px solid #AAA; border-bottom: 1px solid #AAA; color: #000000; } -.fvtt-mournblade .tabs .item { - line-height: 40px; - font-weight: bold; +.fvtt-mournblade-cyd-2-0 nav.sheet-tabs { + justify-content: flex-start !important; + gap: 0 !important; + padding: 0 !important; } -.fvtt-mournblade .tabs .item.active { +.fvtt-mournblade-cyd-2-0 .tabs .item { + line-height: 40px; + font-size: 10px; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1 1 0; + text-align: center; + padding: 0 4px; +} +.fvtt-mournblade-cyd-2-0 .tabs .item.active { text-decoration: underline; text-shadow: none; } -.fvtt-mournblade .items-list { +.fvtt-mournblade-cyd-2-0 .items-list { list-style: none; margin: 1px 0; padding: 0; overflow-y: auto; } -.fvtt-mournblade .items-list .item-header { +.fvtt-mournblade-cyd-2-0 .items-list .item-header { font-weight: bold; } -.fvtt-mournblade .items-list .item { +.fvtt-mournblade-cyd-2-0 .items-list .item { height: 30px; line-height: 24px; padding: 1px 0; border-bottom: 1px solid #BBB; } -.fvtt-mournblade .items-list .item .item-image { +.fvtt-mournblade-cyd-2-0 .items-list .item .item-image { -webkit-box-flex: 0; -ms-flex: 0 0 24px; flex: 0 0 24px; margin-right: 5px; } -.fvtt-mournblade .items-list .item img { +.fvtt-mournblade-cyd-2-0 .items-list .item img { display: block; } -.fvtt-mournblade .items-list .item-name { +.fvtt-mournblade-cyd-2-0 .items-list .item-name { margin: 0; } -.fvtt-mournblade .items-list .item-controls { +.fvtt-mournblade-cyd-2-0 .items-list .item-controls { -webkit-box-flex: 0; -ms-flex: 0 0 86px; flex: 0 0 86px; @@ -1296,7 +1309,7 @@ li { } .item-field-label-long { flex-grow: 1; - max-width: 8rem; + max-width: 10rem; min-width: 8rem; } .item-control-end { @@ -2117,7 +2130,7 @@ li { } /* ==================== Item Sheet Styles ==================== */ /* Item header with image and name */ -.fvtt-mournblade.item { +.fvtt-mournblade-cyd-2-0.item { /* Background pour toute la fiche d'item */ background: url("../assets/ui/pc_sheet_bg.webp") repeat; display: flex; @@ -2136,11 +2149,11 @@ li { /* Field labels */ /* Editor fields */ } -.fvtt-mournblade.item .window-content { +.fvtt-mournblade-cyd-2-0.item .window-content { padding: 0; margin: 0; } -.fvtt-mournblade.item section { +.fvtt-mournblade-cyd-2-0.item section { background: url("../assets/ui/pc_sheet_bg.webp") repeat-y; color: black; display: flex; @@ -2150,15 +2163,15 @@ li { padding: 0; margin: 0; } -.fvtt-mournblade.item input:disabled, -.fvtt-mournblade.item select:disabled { +.fvtt-mournblade-cyd-2-0.item input:disabled, +.fvtt-mournblade-cyd-2-0.item select:disabled { color: #000000; opacity: 0.8; background-color: rgba(255, 255, 255, 0.5); } -.fvtt-mournblade.item input[type="text"], -.fvtt-mournblade.item input[type="number"], -.fvtt-mournblade.item select { +.fvtt-mournblade-cyd-2-0.item input[type="text"], +.fvtt-mournblade-cyd-2-0.item input[type="number"], +.fvtt-mournblade-cyd-2-0.item select { color: #000000; background-color: rgba(255, 255, 255, 0.7); border: 1px solid #999999; @@ -2167,22 +2180,22 @@ li { font-family: "CentaurMT", serif; font-size: 0.85rem; } -.fvtt-mournblade.item textarea { +.fvtt-mournblade-cyd-2-0.item textarea { margin: 0; padding: 2px 4px; } -.fvtt-mournblade.item input[type="checkbox"] { +.fvtt-mournblade-cyd-2-0.item input[type="checkbox"] { width: auto; height: auto; margin: 0 4px; align-self: center; } -.fvtt-mournblade.item .header { +.fvtt-mournblade-cyd-2-0.item .header { flex: 0 0 auto; border-bottom: 1px solid #999; margin: 0; } -.fvtt-mournblade.item .sheet-header { +.fvtt-mournblade-cyd-2-0.item .sheet-header { display: flex; flex-direction: row; align-items: center; @@ -2191,7 +2204,7 @@ li { background: url("../assets/ui/pc_sheet_bg.webp") repeat; flex: 0 0 auto; } -.fvtt-mournblade.item .item-sheet-img { +.fvtt-mournblade-cyd-2-0.item .item-sheet-img { flex: 0 0 64px; width: 64px; height: 64px; @@ -2200,52 +2213,52 @@ li { border-radius: 4px; cursor: pointer; } -.fvtt-mournblade.item .item-sheet-img:hover { +.fvtt-mournblade-cyd-2-0.item .item-sheet-img:hover { box-shadow: 0 0 8px rgba(255, 102, 0, 0.8); } -.fvtt-mournblade.item .header-fields { +.fvtt-mournblade-cyd-2-0.item .header-fields { flex: 1; display: flex; flex-direction: column; gap: 0.25rem; } -.fvtt-mournblade.item .header-actions { +.fvtt-mournblade-cyd-2-0.item .header-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 0.5rem; } -.fvtt-mournblade.item .header-actions button { +.fvtt-mournblade-cyd-2-0.item .header-actions button { background: rgba(0, 0, 0, 0.1); border: 1px solid #999; padding: 0.25rem 0.5rem; cursor: pointer; font-family: "CentaurMT", serif; } -.fvtt-mournblade.item .header-actions button:hover { +.fvtt-mournblade-cyd-2-0.item .header-actions button:hover { background: rgba(255, 102, 0, 0.2); box-shadow: 0 0 5px rgba(255, 102, 0, 0.5); } -.fvtt-mournblade.item .header-actions .chat-card-button { +.fvtt-mournblade-cyd-2-0.item .header-actions .chat-card-button { background: linear-gradient(to bottom, #21374afc 5%, #152833ab 100%); border: 2px ridge #846109; color: #d4b5a8; padding: 0.3rem 0.5rem; transition: all 0.2s ease; } -.fvtt-mournblade.item .header-actions .chat-card-button i { +.fvtt-mournblade-cyd-2-0.item .header-actions .chat-card-button i { font-size: 0.9rem; } -.fvtt-mournblade.item .header-actions .chat-card-button:hover { +.fvtt-mournblade-cyd-2-0.item .header-actions .chat-card-button:hover { background: linear-gradient(to bottom, #800000 5%, #3e0101 100%); color: #ffffff; box-shadow: 0 0 8px rgba(128, 0, 0, 0.6); } -.fvtt-mournblade.item .header-actions .chat-card-button:active { +.fvtt-mournblade-cyd-2-0.item .header-actions .chat-card-button:active { position: relative; top: 1px; } -.fvtt-mournblade.item .sheet-header h1.charname { +.fvtt-mournblade-cyd-2-0.item .sheet-header h1.charname { height: 50px; padding: 0; margin: 5px 0; @@ -2254,7 +2267,7 @@ li { font-size: 2rem; font-family: "CentaurMT"; } -.fvtt-mournblade.item .sheet-header h1.charname input { +.fvtt-mournblade-cyd-2-0.item .sheet-header h1.charname input { width: 100%; height: 100%; margin: 0; @@ -2264,10 +2277,10 @@ li { text-align: left; border: 0 none; } -.fvtt-mournblade.item .sheet-header h1.charname input:focus { +.fvtt-mournblade-cyd-2-0.item .sheet-header h1.charname input:focus { outline: 1px solid #ff6600; } -.fvtt-mournblade.item nav.tabs { +.fvtt-mournblade-cyd-2-0.item nav.tabs { display: flex; border-bottom: 1px solid #7a7971; margin: 0; @@ -2275,7 +2288,7 @@ li { background-color: #1c1c1c; flex: 0 0 auto; } -.fvtt-mournblade.item nav.tabs a.item { +.fvtt-mournblade-cyd-2-0.item nav.tabs a.item { padding: 6px 12px; color: #d4af37; text-decoration: none; @@ -2284,32 +2297,32 @@ li { margin-right: 4px; transition: all 0.2s; } -.fvtt-mournblade.item nav.tabs a.item i { +.fvtt-mournblade-cyd-2-0.item nav.tabs a.item i { display: none; } -.fvtt-mournblade.item nav.tabs a.item:hover { +.fvtt-mournblade-cyd-2-0.item nav.tabs a.item:hover { background-color: rgba(212, 175, 55, 0.1); } -.fvtt-mournblade.item nav.tabs a.item.active { +.fvtt-mournblade-cyd-2-0.item nav.tabs a.item.active { background-color: #2a2a2a; border-bottom-color: #d4af37; color: #f5f5f5; } -.fvtt-mournblade.item .tab { +.fvtt-mournblade-cyd-2-0.item .tab { display: none; padding: 4px 8px; overflow-y: auto; flex: 1 1 auto; } -.fvtt-mournblade.item .tab.active { +.fvtt-mournblade-cyd-2-0.item .tab.active { display: block; } -.fvtt-mournblade.item .item-list { +.fvtt-mournblade-cyd-2-0.item .item-list { list-style: none; margin: 0; padding: 0; } -.fvtt-mournblade.item .item-list li.item { +.fvtt-mournblade-cyd-2-0.item .item-list li.item { display: flex; align-items: center; margin-bottom: 2px; @@ -2317,13 +2330,13 @@ li { min-height: 24px; border-bottom: none; } -.fvtt-mournblade.item .item-list li.item.flexrow { +.fvtt-mournblade-cyd-2-0.item .item-list li.item.flexrow { display: flex; flex-direction: row; align-items: center; gap: 4px; } -.fvtt-mournblade.item .generic-label { +.fvtt-mournblade-cyd-2-0.item .generic-label { display: inline-block; white-space: nowrap; font-weight: 700; @@ -2333,51 +2346,51 @@ li { margin: 0; padding: 0 4px 0 0; } -.fvtt-mournblade.item .item-field-label-short { +.fvtt-mournblade-cyd-2-0.item .item-field-label-short { flex: 0 0 60px; max-width: 60px; } -.fvtt-mournblade.item .item-field-label-medium { +.fvtt-mournblade-cyd-2-0.item .item-field-label-medium { flex: 0 0 100px; max-width: 100px; } -.fvtt-mournblade.item .item-field-label-long { +.fvtt-mournblade-cyd-2-0.item .item-field-label-long { flex: 1; min-width: 150px; } -.fvtt-mournblade.item .item-field-label-long1 { +.fvtt-mournblade-cyd-2-0.item .item-field-label-long1 { flex: 1; min-width: 200px; } -.fvtt-mournblade.item .item-field-label-long2 { +.fvtt-mournblade-cyd-2-0.item .item-field-label-long2 { flex: 1; min-width: 250px; max-width: 250px; } -.fvtt-mournblade.item .item-field-label-long3 { +.fvtt-mournblade-cyd-2-0.item .item-field-label-long3 { flex: 1; min-width: 350px; max-width: 350px; } -.fvtt-mournblade.item .numeric-input { +.fvtt-mournblade-cyd-2-0.item .numeric-input { text-align: center; width: 60px; } -.fvtt-mournblade.item .editor { +.fvtt-mournblade-cyd-2-0.item .editor { height: 300px; border: 1px solid #999; background: rgba(255, 255, 255, 0.9); } -.fvtt-mournblade.item .editor .editor-content { +.fvtt-mournblade-cyd-2-0.item .editor .editor-content { height: 100%; padding: 0.5rem; color: #000; } /* ==================== Actor Sheet Styles ==================== */ -.fvtt-mournblade.actor { +.fvtt-mournblade-cyd-2-0.actor { background: url("../assets/ui/pc_sheet_bg.webp") repeat; } -.fvtt-mournblade.actor .window-content { +.fvtt-mournblade-cyd-2-0.actor .window-content { height: 100%; padding: 0; margin: 0; @@ -2385,45 +2398,30 @@ li { flex-direction: column; overflow: hidden; } -.fvtt-mournblade.actor form, -.fvtt-mournblade.actor .sheet-form-layout { - height: 100%; - background: url("../assets/ui/pc_sheet_bg.webp") repeat-y; - color: black; - display: flex; - flex-direction: column; - flex: 1; - min-height: 0; - overflow: hidden; - padding: 0; - margin: 0; -} -.fvtt-mournblade.actor form > section, -.fvtt-mournblade.actor .sheet-form-layout > section { - height: 100%; +.fvtt-mournblade-cyd-2-0.actor .window-content > section { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; } -.fvtt-mournblade.actor .sheet-header { +.fvtt-mournblade-cyd-2-0.actor .sheet-header { background: url("../assets/ui/pc_sheet_bg.webp") repeat; padding: 0.5rem; margin: 0; flex: 0 0 auto !important; overflow: visible !important; } -.fvtt-mournblade.actor .sheet-header .background-sheet-header { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .background-sheet-header { background: transparent; } -.fvtt-mournblade.actor .sheet-header .header-main-content { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-main-content { flex: 1; display: flex; flex-direction: column; gap: 0.5rem; } -.fvtt-mournblade.actor .sheet-header .header-stats-grid { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-stats-grid { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 0.75rem; @@ -2432,7 +2430,7 @@ li { border: 2px solid rgba(139, 69, 19, 0.5); border-radius: 4px; } -.fvtt-mournblade.actor .sheet-header .stat-group { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-group { display: flex; flex-direction: column; gap: 0.3rem; @@ -2441,11 +2439,11 @@ li { border: 1px solid rgba(139, 69, 19, 0.4); border-radius: 3px; } -.fvtt-mournblade.actor .sheet-header .stat-group.stat-group-health { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-group.stat-group-health { border-left: 3px solid rgba(200, 0, 0, 0.6); background: rgba(40, 0, 0, 0.15); } -.fvtt-mournblade.actor .sheet-header .stat-title { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-title { font-size: 0.75rem; font-weight: bold; color: #f5e6d3; @@ -2457,14 +2455,14 @@ li { font-family: "CentaurMT", serif; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); } -.fvtt-mournblade.actor .sheet-header .stat-values { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-values { display: flex; flex-direction: row; gap: 0.5rem; flex-wrap: wrap; justify-content: center; } -.fvtt-mournblade.actor .sheet-header .stat-item { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-item { display: flex; flex-direction: column; gap: 0.2rem; @@ -2472,14 +2470,14 @@ li { flex: 1; min-width: 0; } -.fvtt-mournblade.actor .sheet-header .stat-label { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-label { font-size: 0.7rem; color: #d4c5b0; margin: 0; font-weight: 600; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.7); } -.fvtt-mournblade.actor .sheet-header .stat-value { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-value { font-size: 0.85rem; font-weight: bold; color: #fff; @@ -2492,7 +2490,7 @@ li { text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); width: 100%; } -.fvtt-mournblade.actor .sheet-header .stat-input { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-input { font-size: 0.8rem; font-weight: 600; padding: 0.25rem 0.4rem; @@ -2507,98 +2505,131 @@ li { text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); } -.fvtt-mournblade.actor .sheet-header .stat-input.stat-input-single { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-input.stat-input-single { min-width: 3.5rem; } -.fvtt-mournblade.actor .sheet-header .stat-input.stat-input-damage { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-input.stat-input-damage { border-color: rgba(200, 0, 0, 0.8); background: rgba(80, 0, 0, 0.5); } -.fvtt-mournblade.actor .sheet-header .stat-input:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-input:hover { background: rgba(60, 45, 30, 0.8); border-color: rgba(255, 102, 0, 0.6); } -.fvtt-mournblade.actor .sheet-header .stat-input:focus { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .stat-input:focus { outline: none; border-color: #ff6600; box-shadow: 0 0 6px rgba(255, 102, 0, 0.5), inset 0 1px 3px rgba(0, 0, 0, 0.3); background: rgba(70, 50, 35, 0.9); } -.fvtt-mournblade.actor .sheet-header .header-fields h4.item-name-label.competence-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields .item.flexrow { + flex-wrap: nowrap !important; + align-items: center !important; +} +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields .item.flexrow h4 { + margin: 0 !important; + padding-top: 0 !important; +} +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields h4.item-name-label.competence-name, +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields .item-name-label.competence-name, +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields label.item-name-label.competence-name { + color: #1a1008 !important; + text-shadow: none !important; + font-weight: bold !important; + background: none !important; +} +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields h4.item-name-label.competence-name { font-size: 0.75rem; padding-top: 3px; } -.fvtt-mournblade.actor .sheet-header .header-fields .item-name-label.competence-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields .item-name-label.competence-name { font-size: 0.75rem; } -.fvtt-mournblade.actor .sheet-header .header-fields label.item-name-label.competence-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields label.item-name-label.competence-name { font-size: 0.7rem; } -.fvtt-mournblade.actor .sheet-header .header-fields .item-field-label-short { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields .item-field-label-short { font-size: 0.8rem; } -.fvtt-mournblade.actor .sheet-header .header-fields .status-small-label { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .header-fields .status-small-label { font-size: 0.8rem; } -.fvtt-mournblade.actor .sheet-tabs { +.fvtt-mournblade-cyd-2-0.actor .sheet-header .sheet-mode-toggle { + background: transparent; + border: none; + color: #fff; + padding: 2px 6px; + cursor: pointer; + font-size: 0.75rem; + transition: all 0.2s ease; + margin-left: 8px; + height: auto; + line-height: 1.2; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); +} +.fvtt-mournblade-cyd-2-0.actor .sheet-header .sheet-mode-toggle:hover { + color: #ffd700; + text-shadow: 0 0 8px rgba(255, 215, 0, 0.8); +} +.fvtt-mournblade-cyd-2-0.actor .sheet-tabs { margin: 0; padding: 0 0.5rem; flex: 0 0 auto !important; } -.fvtt-mournblade.actor .sheet-body { +.fvtt-mournblade-cyd-2-0.actor .sheet-body { margin: 0; padding: 0.5rem; flex: 1 !important; min-height: 0 !important; overflow-y: auto !important; } -.fvtt-mournblade.actor .sheet-body .tab { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .tab { padding: 0; height: auto !important; } -.fvtt-mournblade.actor .sheet-body .tab:not(.active) { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .tab:not(.active) { display: none; } -.fvtt-mournblade.actor .sheet-body .tab .grid, -.fvtt-mournblade.actor .sheet-body .tab .grid-2col { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .tab .grid, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .tab .grid-2col { height: auto; overflow: visible; } -.fvtt-mournblade.actor .sheet-body .tab .sheet-box { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .tab .sheet-box { height: auto; } -.fvtt-mournblade.actor .sheet-body .compact-list { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .compact-list { list-style: none; margin: 0; padding: 0; } -.fvtt-mournblade.actor .sheet-body .compact-list li.item { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .compact-list li.item { padding: 0.2rem 0.4rem; margin-bottom: 0.15rem; background: rgba(0, 0, 0, 0.1); border: 1px solid rgba(139, 69, 19, 0.3); border-radius: 3px; } -.fvtt-mournblade.actor .sheet-body .compact-list li.item:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .compact-list li.item:hover { background: rgba(0, 0, 0, 0.15); } -.fvtt-mournblade.actor .sheet-body .compact-list li.item.items-title-bg { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .compact-list li.item.items-title-bg { background: rgba(0, 0, 0, 0.3); border-color: rgba(139, 69, 19, 0.5); font-weight: 600; margin-bottom: 0.3rem; } -.fvtt-mournblade.actor .sheet-body .compact-list li.item.items-title-bg .item-name-label-header { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .compact-list li.item.items-title-bg .item-name-label-header { color: #f5e6d3; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.7); } -.fvtt-mournblade.actor .sheet-body .item-controls { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls { display: flex; align-items: center; gap: 0.3rem; justify-content: flex-end; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control { display: inline-flex; align-items: center; justify-content: center; @@ -2610,70 +2641,70 @@ li { border-radius: 3px; transition: all 0.2s; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control:hover { color: #2a1a0a; background: rgba(139, 69, 19, 0.2); transform: scale(1.1); } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control i { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control i { font-size: 0.85rem; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-edit { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-edit { color: #4a7c59; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-edit:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-edit:hover { color: #2d5a3a; background: rgba(74, 124, 89, 0.2); } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-delete { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-delete { color: #a04040; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-delete:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-delete:hover { color: #802020; background: rgba(160, 64, 64, 0.2); } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-equip { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-equip { color: #6b5b3a; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-equip:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-equip:hover { color: #4a3a1a; background: rgba(107, 91, 58, 0.2); } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-equip i.fa-circle { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-equip i.fa-circle { color: #4a7c59; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-equip i.fa-genderless { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-equip i.fa-genderless { color: #8a6a4a; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-add { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-add { color: #4a7c59; } -.fvtt-mournblade.actor .sheet-body .item-controls .item-control.item-add:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls .item-control.item-add:hover { color: #2d5a3a; background: rgba(74, 124, 89, 0.2); } -.fvtt-mournblade.actor .sheet-body .item-controls-fixed { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-controls-fixed { min-width: 3.2rem; max-width: 3.2rem; } -.fvtt-mournblade.actor .sheet-body h4, -.fvtt-mournblade.actor .sheet-body h3, -.fvtt-mournblade.actor .sheet-body label, -.fvtt-mournblade.actor .sheet-body span.item-name-label, -.fvtt-mournblade.actor .sheet-body span.competence-name, -.fvtt-mournblade.actor .sheet-body .label-name, -.fvtt-mournblade.actor .sheet-body .generic-label, -.fvtt-mournblade.actor .sheet-body .item-field-label-short, -.fvtt-mournblade.actor .sheet-body .item-field-label-medium, -.fvtt-mournblade.actor .sheet-body .item-field-label-long, -.fvtt-mournblade.actor .sheet-body .short-label, -.fvtt-mournblade.actor .sheet-body .items-title-text { +.fvtt-mournblade-cyd-2-0.actor .sheet-body h4, +.fvtt-mournblade-cyd-2-0.actor .sheet-body h3, +.fvtt-mournblade-cyd-2-0.actor .sheet-body label, +.fvtt-mournblade-cyd-2-0.actor .sheet-body span.item-name-label, +.fvtt-mournblade-cyd-2-0.actor .sheet-body span.competence-name, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .label-name, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .generic-label, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-field-label-short, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-field-label-medium, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .item-field-label-long, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .short-label, +.fvtt-mournblade-cyd-2-0.actor .sheet-body .items-title-text { color: #3a2a1a !important; text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.3); } -.fvtt-mournblade.actor .sheet-body input[type="text"], -.fvtt-mournblade.actor .sheet-body input[type="number"], -.fvtt-mournblade.actor .sheet-body select { +.fvtt-mournblade-cyd-2-0.actor .sheet-body input[type="text"], +.fvtt-mournblade-cyd-2-0.actor .sheet-body input[type="number"], +.fvtt-mournblade-cyd-2-0.actor .sheet-body select { color: #2a1a0a; background: rgba(255, 250, 240, 0.8); border: 1px solid rgba(139, 69, 19, 0.5); @@ -2681,24 +2712,24 @@ li { padding: 0.15rem 0.3rem; line-height: 1.2; } -.fvtt-mournblade.actor .sheet-body input[type="text"]:focus, -.fvtt-mournblade.actor .sheet-body input[type="number"]:focus, -.fvtt-mournblade.actor .sheet-body select:focus { +.fvtt-mournblade-cyd-2-0.actor .sheet-body input[type="text"]:focus, +.fvtt-mournblade-cyd-2-0.actor .sheet-body input[type="number"]:focus, +.fvtt-mournblade-cyd-2-0.actor .sheet-body select:focus { background: rgba(255, 255, 245, 0.95); border-color: rgba(139, 69, 19, 0.8); } -.fvtt-mournblade.actor .sheet-body h3, -.fvtt-mournblade.actor .sheet-body h4 { +.fvtt-mournblade-cyd-2-0.actor .sheet-body h3, +.fvtt-mournblade-cyd-2-0.actor .sheet-body h4 { font-weight: bold; color: #2a1a0a !important; } -.fvtt-mournblade.actor .sheet-body h4.item-name-label.competence-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-body h4.item-name-label.competence-name { font-size: 0.85rem; margin-top: 0.2rem; margin-bottom: 0.3rem; padding-top: 0; } -.fvtt-mournblade.actor .sheet-body .section-grid { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid { display: flex; flex-direction: column; gap: 0.2rem; @@ -2708,7 +2739,7 @@ li { border: 2px solid rgba(139, 69, 19, 0.5); border-radius: 4px; } -.fvtt-mournblade.actor .sheet-body .section-grid .section-title { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .section-title { font-size: 0.85rem; font-weight: bold; color: #f5e6d3; @@ -2721,7 +2752,7 @@ li { border-radius: 2px; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row { display: grid; grid-template-columns: 1fr 1fr; align-items: center; @@ -2731,50 +2762,50 @@ li { border: 1px solid rgba(139, 69, 19, 0.4); border-radius: 3px; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row input { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row input { width: 60px; min-width: 60px; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.attr-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.attr-row { grid-template-columns: 40px 1fr auto; gap: 0.5rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.attr-row .item-name-img { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.attr-row .item-name-img { width: 32px; height: 32px; border-radius: 3px; border: 1px solid rgba(139, 69, 19, 0.5); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.attr-row .label-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.attr-row .label-name { display: flex; align-items: center; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.attr-row .label-name a { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.attr-row .label-name a { color: #f5e6d3; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.7); font-weight: 600; cursor: pointer; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.attr-row .label-name a:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.attr-row .label-name a:hover { color: #fff; text-shadow: 0 0 4px rgba(255, 200, 100, 0.8); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.attr-row select { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.attr-row select { width: 80px; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row .label-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row .label-name { font-weight: 600; font-size: 0.9rem; color: #d4c5b0; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.7); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row .stat-label { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row .stat-label { font-weight: 600; font-size: 0.9rem; color: #d4c5b0; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.7); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row .value-display { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row .value-display { text-align: center; font-weight: bold; font-size: 1rem; @@ -2785,7 +2816,7 @@ li { border: 1px solid rgba(139, 69, 19, 0.6); text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row .malus-value { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row .malus-value { text-align: center; font-weight: bold; font-size: 1rem; @@ -2796,20 +2827,20 @@ li { border: 1px solid rgba(200, 50, 50, 0.6); text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row { grid-template-columns: 120px 1fr; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row .damage-label { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row .damage-label { font-size: 0.95rem; font-weight: 600; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls { display: flex; align-items: center; justify-content: center; gap: 0.4rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls input { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls input { width: 60px; min-width: 60px; flex-shrink: 0; @@ -2817,7 +2848,7 @@ li { font-size: 1.1rem; font-weight: bold; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls .plus-minus-button { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls .plus-minus-button { width: 30px; height: 30px; display: flex; @@ -2832,51 +2863,51 @@ li { cursor: pointer; transition: all 0.15s; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls .plus-minus-button:hover { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls .plus-minus-button:hover { background: linear-gradient(to bottom, rgba(230, 200, 160, 0.95), rgba(200, 170, 130, 0.95)); border-color: rgba(139, 69, 19, 0.8); transform: scale(1.08); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls .plus-minus-button:active { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.damage-row .damage-controls .plus-minus-button:active { transform: scale(0.95); } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.soul-consumed-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.soul-consumed-row { grid-template-columns: 120px 1fr; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.soul-malus-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.soul-malus-row { grid-template-columns: 90px 1fr; gap: 0.4rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.soul-malus-row .label-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.soul-malus-row .label-name { font-size: 0.85rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.soul-malus-row .malus-value { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.soul-malus-row .malus-value { font-size: 0.9rem; padding: 0.2rem 0.3rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.malus-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.malus-row { grid-template-columns: 55px 60px 75px 50px; gap: 0.3rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.malus-row .label-name { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.malus-row .label-name { font-size: 0.85rem; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.malus-row input { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.malus-row input { width: 100%; min-width: unset; } -.fvtt-mournblade.actor .sheet-body .section-grid .grid-row.malus-row .malus-value { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid .grid-row.malus-row .malus-value { font-size: 0.9rem; padding: 0.2rem 0.3rem; } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat { grid-template-columns: 85px 50px 60px 55px; gap: 0.4rem; } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat .stat-label { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat .stat-label { font-size: 0.85rem; } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat .stat-base { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat .stat-base { text-align: center; font-weight: bold; font-size: 0.85rem; @@ -2887,12 +2918,12 @@ li { border: 1px solid rgba(139, 69, 19, 0.6); text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat input { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat input { width: 50px; min-width: 50px; text-align: center; } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat .stat-total { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.combat-stat .stat-total { text-align: center; font-weight: bold; font-size: 0.85rem; @@ -2903,10 +2934,10 @@ li { border: 1px solid rgba(139, 69, 19, 0.6); text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.protection-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.protection-row { grid-template-columns: 1fr 1fr; } -.fvtt-mournblade.actor .sheet-body .section-grid.combat-grid .grid-row.protection-row .protection-value { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .section-grid.combat-grid .grid-row.protection-row .protection-value { text-align: center; font-weight: bold; font-size: 1.2rem; @@ -2917,56 +2948,56 @@ li { border: 1px solid rgba(139, 69, 19, 0.6); text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9); } -.fvtt-mournblade.actor .sheet-body .action-buttons { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons { display: flex; flex-direction: column; gap: 0.3rem; padding: 0.3rem 0; } -.fvtt-mournblade.actor .sheet-body .action-buttons button { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons button { margin: 0; } -.fvtt-mournblade.actor .sheet-body .action-buttons-row { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons-row { display: flex; flex-direction: row; align-items: center; gap: 0.5rem; padding: 0.3rem 0; } -.fvtt-mournblade.actor .sheet-body .action-buttons-row button { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons-row button { margin: 0; flex: 1; } -.fvtt-mournblade.actor .sheet-body .action-buttons-row .mounted-checkbox { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons-row .mounted-checkbox { display: flex; align-items: center; gap: 0.4rem; padding: 0.3rem 0.6rem; white-space: nowrap; } -.fvtt-mournblade.actor .sheet-body .action-buttons-row .mounted-checkbox label { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons-row .mounted-checkbox label { margin: 0; font-size: 0.9rem; } -.fvtt-mournblade.actor .sheet-body .action-buttons-row .mounted-checkbox input[type="checkbox"] { +.fvtt-mournblade-cyd-2-0.actor .sheet-body .action-buttons-row .mounted-checkbox input[type="checkbox"] { margin: 0; cursor: pointer; } /* ==================== Creature Sheet Specific Styles ==================== */ -.fvtt-mournblade.actor.creature-sheet .background-sheet-header-creature { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet .background-sheet-header-creature { background: linear-gradient(135deg, rgba(0, 60, 0, 0.15) 0%, rgba(20, 80, 20, 0.1) 100%); border: 2px solid rgba(34, 139, 34, 0.5); border-radius: 4px; padding: 0; } -.fvtt-mournblade.actor.creature-sheet .sheet-box.color-bg-archetype { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet .sheet-box.color-bg-archetype { background: linear-gradient(135deg, rgba(0, 40, 0, 0.08) 0%, rgba(20, 60, 20, 0.05) 100%); } -.fvtt-mournblade.actor.creature-sheet .sheet-header { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet .sheet-header { flex: 0 0 auto !important; padding: 0; } -.fvtt-mournblade.actor.creature-sheet .profile-img { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet .profile-img { width: 80px; height: 80px; border-radius: 8px; @@ -2975,32 +3006,32 @@ li { cursor: pointer; flex-shrink: 0; } -.fvtt-mournblade.actor.creature-sheet nav.tabs .item.active { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet nav.tabs .item.active { border-bottom-color: rgba(34, 139, 34, 0.8); color: #228b22; } -.fvtt-mournblade.actor.creature-sheet .section-title { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet .section-title { color: #1a5a1a; border-bottom-color: rgba(34, 139, 34, 0.3); } -.fvtt-mournblade.actor.creature-sheet .items-title-bg { +.fvtt-mournblade-cyd-2-0.actor.creature-sheet .items-title-bg { background: linear-gradient(135deg, rgba(0, 60, 0, 0.15) 0%, rgba(20, 80, 20, 0.1) 100%); border-bottom: 1px solid rgba(34, 139, 34, 0.3); } -.fvtt-mournblade.actor.pnj-sheet .background-sheet-header-creature { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet .background-sheet-header-creature { background: linear-gradient(135deg, rgba(80, 40, 0, 0.15) 0%, rgba(100, 50, 0, 0.1) 100%); border: 2px solid rgba(205, 127, 50, 0.5); border-radius: 4px; padding: 0; } -.fvtt-mournblade.actor.pnj-sheet .sheet-box.color-bg-archetype { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet .sheet-box.color-bg-archetype { background: linear-gradient(135deg, rgba(60, 30, 0, 0.08) 0%, rgba(80, 40, 0, 0.05) 100%); } -.fvtt-mournblade.actor.pnj-sheet .sheet-header { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet .sheet-header { flex: 0 0 auto !important; padding: 0; } -.fvtt-mournblade.actor.pnj-sheet .profile-img { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet .profile-img { width: 80px; height: 80px; border-radius: 8px; @@ -3009,15 +3040,15 @@ li { cursor: pointer; flex-shrink: 0; } -.fvtt-mournblade.actor.pnj-sheet nav.tabs .item.active { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet nav.tabs .item.active { border-bottom-color: rgba(205, 127, 50, 0.8); color: #cd7f32; } -.fvtt-mournblade.actor.pnj-sheet .section-title { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet .section-title { color: #b8734d; border-bottom-color: rgba(205, 127, 50, 0.3); } -.fvtt-mournblade.actor.pnj-sheet .items-title-bg { +.fvtt-mournblade-cyd-2-0.actor.pnj-sheet .items-title-bg { background: linear-gradient(135deg, rgba(80, 40, 0, 0.15) 0%, rgba(100, 50, 0, 0.1) 100%); border-bottom: 1px solid rgba(205, 127, 50, 0.3); } diff --git a/styles/simple.css b/styles/simple.css index 3f8c471..b3a5a0f 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -110,7 +110,7 @@ /* For nav and title */ .window-app input, - .fvtt-mournblade-cyd2 .item-form, + .fvtt-mournblade-cyd-2-0 .item-form, .sheet header.sheet-header .flex-group-center.flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, @@ -122,15 +122,15 @@ font-size: 0.8rem; } - .fvtt-mournblade-cyd2 .sheet-header input, - .fvtt-mournblade-cyd2 .sheet-header select { + .fvtt-mournblade-cyd-2-0 .sheet-header input, + .fvtt-mournblade-cyd-2-0 .sheet-header select { color: black; min-width: 3rem; max-width: 3rem; text-align: center; } - .fvtt-mournblade-cyd2 .sheet-header .liste-etat { + .fvtt-mournblade-cyd-2-0 .sheet-header .liste-etat { min-width: 6rem; max-width: 6rem; } @@ -288,7 +288,7 @@ /* Styles limited to foundryvtt-vadentis sheets */ - .fvtt-mournblade-cyd2 .sheet-header { + .fvtt-mournblade-cyd-2-0 .sheet-header { -webkit-box-flex: 0; -ms-flex: 0 0 210px; flex: 0 0 210px; @@ -318,7 +318,7 @@ width: 100%; } - .fvtt-mournblade-cyd2 .sheet-header .profile-img { + .fvtt-mournblade-cyd-2-0 .sheet-header .profile-img { -webkit-box-flex: 0; -ms-flex: 0 0 128px; flex: 0 0 128px; @@ -359,13 +359,13 @@ vertical-align: bottom; } - .fvtt-mournblade-cyd2 .sheet-header .header-fields { + .fvtt-mournblade-cyd-2-0 .sheet-header .header-fields { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } - .fvtt-mournblade-cyd2 .sheet-header h1.charname { + .fvtt-mournblade-cyd-2-0 .sheet-header h1.charname { height: 50px; padding: 0px; margin: 5px 0; @@ -375,7 +375,7 @@ font-family: "CentaurMT"; } - .fvtt-mournblade-cyd2 .sheet-header h1.charname input { + .fvtt-mournblade-cyd-2-0 .sheet-header h1.charname input { width: 100%; height: 100%; margin: 0; @@ -386,22 +386,22 @@ text-align: left; } - .fvtt-mournblade-cyd2 .sheet-tabs { + .fvtt-mournblade-cyd-2-0 .sheet-tabs { -webkit-box-flex: 0; -ms-flex: 0; flex: 0; } - .fvtt-mournblade-cyd2 .sheet-body, - .fvtt-mournblade-cyd2 .sheet-body .tab, - .fvtt-mournblade-cyd2 .sheet-body .tab .editor { + .fvtt-mournblade-cyd-2-0 .sheet-body, + .fvtt-mournblade-cyd-2-0 .sheet-body .tab, + .fvtt-mournblade-cyd-2-0 .sheet-body .tab .editor { height: 100%; font-size: 0.8rem; color: rgba(0, 0, 0, 0.9) } - .fvtt-mournblade-cyd2 .sheet-body input, - .fvtt-mournblade-cyd2 .sheet-body select { + .fvtt-mournblade-cyd-2-0 .sheet-body input, + .fvtt-mournblade-cyd-2-0 .sheet-body select { color: rgba(0, 0, 0, 0.9) } @@ -423,70 +423,70 @@ padding: 0 3px; } - .fvtt-mournblade-cyd2 .tox .tox-editor-container { + .fvtt-mournblade-cyd-2-0 .tox .tox-editor-container { background: #fff; } - .fvtt-mournblade-cyd2 .tox .tox-edit-area { + .fvtt-mournblade-cyd-2-0 .tox .tox-edit-area { padding: 0 8px; } - .fvtt-mournblade-cyd2 .resource-label { + .fvtt-mournblade-cyd-2-0 .resource-label { font-weight: bold; text-transform: uppercase; } - .fvtt-mournblade-cyd2 .tabs { + .fvtt-mournblade-cyd-2-0 .tabs { height: 40px; border-top: 1px solid #AAA; border-bottom: 1px solid #AAA; color: #000000; } - .fvtt-mournblade-cyd2 .tabs .item { + .fvtt-mournblade-cyd-2-0 .tabs .item { /*line-height: 40px;*/ font-weight: bold; } - .fvtt-mournblade-cyd2 .tabs .item.active { + .fvtt-mournblade-cyd-2-0 .tabs .item.active { text-decoration: underline; text-shadow: none; } - .fvtt-mournblade-cyd2 .items-list { + .fvtt-mournblade-cyd-2-0 .items-list { list-style: none; margin: 1px 0; padding: 0; overflow-y: auto; } - .fvtt-mournblade-cyd2 .items-list .item-header { + .fvtt-mournblade-cyd-2-0 .items-list .item-header { font-weight: bold; } - .fvtt-mournblade-cyd2 .items-list .item { + .fvtt-mournblade-cyd-2-0 .items-list .item { height: 30px; line-height: 24px; padding: 1px 0; border-bottom: 1px solid #BBB; } - .fvtt-mournblade-cyd2 .items-list .item .item-image { + .fvtt-mournblade-cyd-2-0 .items-list .item .item-image { -webkit-box-flex: 0; -ms-flex: 0 0 24px; flex: 0 0 24px; margin-right: 5px; } - .fvtt-mournblade-cyd2 .items-list .item img { + .fvtt-mournblade-cyd-2-0 .items-list .item img { display: block; } - .fvtt-mournblade-cyd2 .items-list .item-name { + .fvtt-mournblade-cyd-2-0 .items-list .item-name { margin: 0; } - .fvtt-mournblade-cyd2 .items-list .item-controls { + .fvtt-mournblade-cyd-2-0 .items-list .item-controls { -webkit-box-flex: 0; -ms-flex: 0 0 86px; flex: 0 0 86px; diff --git a/system.json b/system.json index e969eea..9ff08ab 100644 --- a/system.json +++ b/system.json @@ -26,6 +26,40 @@ "flags": {} } ], + "documentTypes": { + "Actor": { + "personnage": { + "htmlFields": ["biodata.description", "biodata.notes", "biodata.gmnotes"] + }, + "creature": { + "htmlFields": ["biodata.description", "biodata.notes", "biodata.gmnotes"] + } + }, + "Item": { + "competence": { "htmlFields": ["description"] }, + "talent": { "htmlFields": ["description"] }, + "historique": { "htmlFields": ["description"] }, + "profil": { "htmlFields": ["description"] }, + "arme": { "htmlFields": ["description"] }, + "protection": { "htmlFields": ["description"] }, + "monnaie": { "htmlFields": ["description"] }, + "equipement": { "htmlFields": ["description"] }, + "ressource": { "htmlFields": ["description"] }, + "don": { "htmlFields": ["description"] }, + "pacte": { "htmlFields": ["description"] }, + "rune": { "htmlFields": ["description"] }, + "runeeffect": { "htmlFields": ["description"] }, + "tendance": { "htmlFields": ["description"] }, + "traitchaotique": { "htmlFields": ["description"] }, + "traitespece": { "htmlFields": ["description"] } + } + }, + "flags": { + "hotReload": { + "extensions": ["css", "hbs", "json"], + "paths": ["styles", "templates", "lang/fr.json"] + } + }, "packFolders": [ { "name": "MournbladeCYD2", diff --git a/templates/actor-sheet.hbs b/templates/actor-sheet.hbs index 8ce5bdb..a8bed8d 100644 --- a/templates/actor-sheet.hbs +++ b/templates/actor-sheet.hbs @@ -1,12 +1,12 @@ -
+
{{!-- Sheet Header --}}
- +
-

+

    @@ -21,7 +21,7 @@ name="system.balance.pointsloi" value="{{system.balance.pointsloi}}" data-dtype="Number"> {{selectOptions config.listeNiveauSkill selected=system.balance.pointsloi}} - +
  • @@ -34,7 +34,7 @@ name="system.balance.pointschaos" value="{{system.balance.pointschaos}}" data-dtype="Number"> {{selectOptions config.listeNiveauSkill selected=system.balance.pointschaos}} - +
  • @@ -75,6 +75,9 @@ value="{{system.ame.max}}" data-dtype="Number"> {{selectOptions ameMaxList selected=system.ame.max valueAttr="value" nameAttr="value" labelAttr="label"}} +
@@ -109,9 +112,9 @@
    {{#each system.attributs as |attr key|}}
  • - + {{attr.label}} + data-action="rollAttribut" data-attr-key="{{key}}">{{attr.label}} @@ -135,12 +138,12 @@
      {{#each system.adversite as |adv key|}}
    • - - + -
      - +
      {{adv}}
      - + + +
       
       
       
      @@ -173,7 +176,7 @@
       
      -
    • @@ -185,8 +188,8 @@
       
      - - + +
      {{/each}} @@ -217,7 +220,7 @@
      - {{skill.name}} @@ -235,22 +238,22 @@ {{#if (ne skill.system.attribut1 "none")}} - {{/if}} {{#if (ne skill.system.attribut2 "none")}} - {{/if}} {{#if (ne skill.system.attribut3 "none")}} - {{/if}}
       
      - - + +
      {{/each}} @@ -277,7 +280,7 @@
       
      - +
      {{#each dons as |don key|}} @@ -287,8 +290,8 @@ {{don.system.allegeance}}
       
      - - + +
      {{/each}} @@ -306,7 +309,7 @@
       
      - +
      {{#each pactes as |pacte key|}} @@ -316,8 +319,8 @@ {{pacte.system.allegeance}}
       
      - - + +
      {{/each}} @@ -338,7 +341,7 @@
       
      - +
      {{#each runes as |rune key|}} @@ -349,8 +352,8 @@ {{rune.system.seuil}}
       
      - - + +
      {{/each}} @@ -368,7 +371,7 @@
       
      - +
      {{#each tendances as |tendance key|}} @@ -378,8 +381,8 @@ {{tendance.system.allegeance}}
       
      - - + +
      {{/each}} @@ -394,7 +397,7 @@
       
      - +
      {{#each traitsChaotiques as |trait key|}} @@ -403,8 +406,8 @@ {{trait.name}}
       
      - - + +
      {{/each}} @@ -419,7 +422,7 @@
       
      - +
      {{#each traitsEspeces as |trait key|}} @@ -428,8 +431,8 @@ {{trait.name}}
       
      - - + +
      {{/each}} @@ -445,7 +448,7 @@
      • - + @@ -454,11 +457,11 @@
      • - - - - - + + + + +
      @@ -481,7 +484,7 @@
       
      -
      @@ -492,9 +495,9 @@ {{#if arme.system.equipped}} - + {{else}} - + {{/if}} @@ -508,18 +511,18 @@ {{#if arme.system.equipped}} - + {{else}} - + {{/if}}
       
      {{/each}} @@ -537,7 +540,7 @@
       
      -
      @@ -550,10 +553,10 @@
       
      {{/each}} @@ -589,7 +592,7 @@
       
      -
      @@ -603,8 +606,8 @@
       
      - - + +
      {{/each}} @@ -633,7 +636,7 @@
       
      -
      @@ -647,8 +650,8 @@
       
      - - + +
      {{/each}} @@ -671,8 +674,8 @@
      - - + +
      {{/each}} @@ -682,8 +685,8 @@
      - - + +
      {{/each}} @@ -755,4 +758,4 @@
- \ No newline at end of file + \ No newline at end of file diff --git a/templates/creature-sheet.hbs b/templates/creature-sheet.hbs index e33c83c..5d1ec52 100644 --- a/templates/creature-sheet.hbs +++ b/templates/creature-sheet.hbs @@ -1,12 +1,12 @@ -
+
{{!-- Sheet Header --}}
- +
-

+

    @@ -45,7 +45,7 @@
      {{#each system.attributs as |attr key|}}
    • - + {{attr.label}} @@ -94,7 +94,7 @@
    • -
      - +
      {{adv}}
      + @@ -372,4 +372,4 @@
-
\ No newline at end of file + \ No newline at end of file diff --git a/templates/hud-adversites.hbs b/templates/hud-adversites.hbs index 61f9075..e8aa79d 100644 --- a/templates/hud-adversites.hbs +++ b/templates/hud-adversites.hbs @@ -5,13 +5,13 @@
- +
 -1
- +
 +1
@@ -19,13 +19,13 @@
- +
 -1
- +
 +1
@@ -33,13 +33,13 @@
- +
 -1
- +
 +1
diff --git a/templates/item-arme-sheet.hbs b/templates/item-arme-sheet.hbs index 25cd57c..bdf2418 100644 --- a/templates/item-arme-sheet.hbs +++ b/templates/item-arme-sheet.hbs @@ -1,12 +1,12 @@ -
- {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
+ {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
- {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
@@ -84,10 +84,10 @@ data-dtype="Number" /> - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-prix.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs}}
- \ No newline at end of file +
\ No newline at end of file diff --git a/templates/item-competence-sheet.hbs b/templates/item-competence-sheet.hbs index 262b648..accabb9 100644 --- a/templates/item-competence-sheet.hbs +++ b/templates/item-competence-sheet.hbs @@ -1,12 +1,12 @@ -
- {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
+ {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
- {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
@@ -20,7 +20,7 @@
  • @@ -28,7 +28,7 @@
  • @@ -36,7 +36,7 @@
  • @@ -76,4 +76,4 @@
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-don-sheet.hbs b/templates/item-don-sheet.hbs index e727d2c..6f07124 100644 --- a/templates/item-don-sheet.hbs +++ b/templates/item-don-sheet.hbs @@ -1,10 +1,10 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    @@ -43,4 +43,4 @@
    - +
    diff --git a/templates/item-equipement-sheet.hbs b/templates/item-equipement-sheet.hbs index 8f1ca0c..515c3e5 100644 --- a/templates/item-equipement-sheet.hbs +++ b/templates/item-equipement-sheet.hbs @@ -1,22 +1,22 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
      - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-prix.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs}}
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-historique-sheet.hbs b/templates/item-historique-sheet.hbs index 98b9725..20a4497 100644 --- a/templates/item-historique-sheet.hbs +++ b/templates/item-historique-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
      @@ -21,4 +21,4 @@
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-monnaie-sheet.hbs b/templates/item-monnaie-sheet.hbs index b7ec78e..c7ac927 100644 --- a/templates/item-monnaie-sheet.hbs +++ b/templates/item-monnaie-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    @@ -31,4 +31,4 @@
    - +
    diff --git a/templates/item-pacte-sheet.hbs b/templates/item-pacte-sheet.hbs index 9f547a8..935403a 100644 --- a/templates/item-pacte-sheet.hbs +++ b/templates/item-pacte-sheet.hbs @@ -1,10 +1,10 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
      @@ -26,4 +26,4 @@
    - +
    diff --git a/templates/item-profil-sheet.hbs b/templates/item-profil-sheet.hbs index 6a00fe9..91a697e 100644 --- a/templates/item-profil-sheet.hbs +++ b/templates/item-profil-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
      @@ -21,7 +21,7 @@
    • @@ -29,7 +29,7 @@
    • @@ -37,7 +37,7 @@
    • @@ -97,4 +97,4 @@
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-protection-sheet.hbs b/templates/item-protection-sheet.hbs index cc63134..ca4e3c7 100644 --- a/templates/item-protection-sheet.hbs +++ b/templates/item-protection-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    @@ -22,9 +22,9 @@ value="{{system.adversitepoids}}" data-dtype="Number" /> - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-prix.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs}}
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-ressource-sheet.hbs b/templates/item-ressource-sheet.hbs index 152b7c5..c0ef875 100644 --- a/templates/item-ressource-sheet.hbs +++ b/templates/item-ressource-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    @@ -23,4 +23,4 @@
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-rune-sheet.hbs b/templates/item-rune-sheet.hbs index 9a89c21..a9443ba 100644 --- a/templates/item-rune-sheet.hbs +++ b/templates/item-rune-sheet.hbs @@ -1,10 +1,10 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
      @@ -60,4 +60,4 @@
    - +
    diff --git a/templates/item-runeeffect-sheet.hbs b/templates/item-runeeffect-sheet.hbs index 51d794e..756614c 100644 --- a/templates/item-runeeffect-sheet.hbs +++ b/templates/item-runeeffect-sheet.hbs @@ -1,12 +1,12 @@ -
    +
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    @@ -18,7 +18,7 @@ type="text" class="padd-right status-small-label color-class-common item-field-label-long" name="system.rune" - value="{{data.rune}}" + value="{{system.rune}}" data-dtype="String" /> @@ -29,10 +29,10 @@ class="status-small-label color-class-common item-field-label-long" type="text" name="system.mode" - value="{{data.mode}}" + value="{{system.mode}}" data-dtype="string" > - {{selectOptions config.effetRuneOptions selected=data.mode}} + {{selectOptions config.effetRuneOptions selected=system.mode}} @@ -42,7 +42,7 @@ type="text" class="status-small-label color-class-common item-field-label-long" name="system.pointame" - value="{{data.pointame}}" + value="{{system.pointame}}" data-dtype="Number" /> @@ -53,10 +53,10 @@ type="text" class="status-small-label color-class-common item-field-label-long" name="system.duree" - value="{{data.duree}}" + value="{{system.duree}}" data-dtype="String" />
    - +
    diff --git a/templates/item-talent-sheet.hbs b/templates/item-talent-sheet.hbs index 6adb163..7e0a742 100644 --- a/templates/item-talent-sheet.hbs +++ b/templates/item-talent-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    @@ -49,10 +49,10 @@ - {{> systems/fvtt-mournblade-cyd2/templates/partial-automation.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs}}
    - \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/item-tendance-sheet.hbs b/templates/item-tendance-sheet.hbs index 9f547a8..935403a 100644 --- a/templates/item-tendance-sheet.hbs +++ b/templates/item-tendance-sheet.hbs @@ -1,10 +1,10 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
      @@ -26,4 +26,4 @@
    - +
    diff --git a/templates/item-traitchaotique-sheet.hbs b/templates/item-traitchaotique-sheet.hbs index 102c96c..ff77d51 100644 --- a/templates/item-traitchaotique-sheet.hbs +++ b/templates/item-traitchaotique-sheet.hbs @@ -1,12 +1,12 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    - +
    diff --git a/templates/item-traitespece-sheet.hbs b/templates/item-traitespece-sheet.hbs index 40c1856..27b95cc 100644 --- a/templates/item-traitespece-sheet.hbs +++ b/templates/item-traitespece-sheet.hbs @@ -1,11 +1,11 @@ -
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-header.html}} {{> - systems/fvtt-mournblade-cyd2/templates/partial-item-nav.html}} {{!-- Sheet +
    + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs}} {{> + systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs}} {{!-- Sheet Body --}}
    - {{> systems/fvtt-mournblade-cyd2/templates/partial-item-description.html}} + {{> systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs}}
    - +
    diff --git a/templates/partial-item-description.hbs b/templates/partial-item-description.hbs index 541eb68..fa4f751 100644 --- a/templates/partial-item-description.hbs +++ b/templates/partial-item-description.hbs @@ -1,5 +1,5 @@
    - {{editor description target="system.description" button=true owner=owner editable=editable}} + {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
    diff --git a/templates/partial-item-header.hbs b/templates/partial-item-header.hbs index 8b4c994..0264c5c 100644 --- a/templates/partial-item-header.hbs +++ b/templates/partial-item-header.hbs @@ -1,8 +1,20 @@ -
    -
    - +
    +
    +
    -

    +

    + +

    -
    -
    +
    + +
    + +