/* -------------------------------------------- */ import { VadentisUtility } from "./vadentis-utility.js"; /* -------------------------------------------- */ const MIN_PV = -50; const MIN_PE = -50; /* -------------------------------------------- */ /** * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. * @extends {Actor} */ export class VadentisActor 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; } return super.create(data, options); } /* -------------------------------------------- */ async prepareData() { super.prepareData(); } /* -------------------------------------------- */ getCompetences() { return this.data.items.filter( item => item.type == 'competence'); } /* -------------------------------------------- */ getDonnees() { return this.data.items.filter( item => item.type == 'donnee'); } /* -------------------------------------------- */ getEglises() { return this.data.items.filter( item => item.type == 'eglise'); } /* -------------------------------------------- */ getSorts() { return this.data.items.filter( item => item.type == 'sort'); } /* -------------------------------------------- */ getAttributs() { return this.data.items.filter( item => item.type == 'attribut'); } /* -------------------------------------------- */ getTechniques() { return this.data.items.filter( item => item.type == 'technique'); } /* -------------------------------------------- */ getDevotions() { return this.data.items.filter( item => item.type == 'devotion'); } /* -------------------------------------------- */ getEquipements() { return this.data.items.filter( item => item.type == 'equipement' ); } /* -------------------------------------------- */ getArmes() { return this.data.items.filter( item => item.type == 'armecc' || item.type == 'tir' ); } /* -------------------------------------------- */ getArmures() { return this.data.items.filter( item => item.type == 'armurebouclier' ); } /* -------------------------------------------- */ async updateCompetence( name, field, value) { let competence = this.data.items.find( item => item.type == 'competence' && item.name == name); if (competence) { let dataPath = 'data.'+field; await this.updateOwnedItem( { _id: competence._id, [dataPath]:value }); } } /* -------------------------------------------- */ async equiperObject( equipementId ) { let item = this.getOwnedItem(equipementId); if (item && item.data.data) { let update = { _id: item._id, "data.equipee": !item.data.data.equipee }; await this.updateEmbeddedEntity("OwnedItem", update); } } /* -------------------------------------------- */ async processSortDevotion( name, devotionSort ) { if ( this.data.data.stats.pointsenergie.value == 0) { // Vérification du ~ de points d'énergie ChatMessage.create({ content: `${this.name} n'a pas assez de Points d'Energie pour lancer ${name} ${devotionSort.name}` } ); return; } let scores = this.data.data.magie[(name =="devotion") ? 'devotion': 'matriseelementaire']; let statValue = scores.base + scores.malus + scores.bonus; let formulaFull = `1d20+${scores.base}+${scores.malus}+${scores.bonus}`; let myRoll = new Roll("1d20+"+statValue); myRoll.evaluate(); myRoll.toMessage( { flavor: `Lancer de ${name} : ${devotionSort.name} (${formulaFull})` } ); if (myRoll.results[0] > 1 && myRoll.total >= devotionSort.data.difficulty) { let content = `${this.name} a réussi son ${name} et perd ${devotionSort.data.pe} Points d'Energie. L'effet suivant se produit:
${devotionSort.data.effect}`; let newEnergie = this.data.data.stats.pointsenergie.value - devotionSort.data.pe; await this.update( {'data.stats.pointsenergie.value': newEnergie }); if ( devotionSort.data.damage != "") { let degatsText = `
Et provoque les dégats suivants : `; let formula = devotionSort.data.damage; if (myRoll.results[0] == 20 ) { // Critique ? degatsText += `
Et provoque les dégats critiques suivants : `; formula = devotionSort.data.damagecritical; } content += degatsText; /*let myRoll = new Roll(formula); myRoll.evaluate(); if (game.modules.get("dice-so-nice") && game.modules.get("dice-so-nice").active) { await game.dice3d.showForRoll(degatsRoll, game.user, true); } content += myRoll.total + `(${devotionSort.data.damagecritical})`; */ content += `${devotionSort.data.damagecritical}`; } if ( newEnergie < 0) { content += `
Attention : Les Points d'Energie de ${this.name} sont négatifs ! Il convient d'éditer ses Points de Vie en conséquence.`; } ChatMessage.create( { content: content} ); } else { if (myRoll.results[0] == 1 ) { // Critique ? ChatMessage.create( { content: `${this.name} a fait un échec critique à son lancer de ${name}` } ); } else { ChatMessage.create( { content: `${this.name} a échoué son lancer de ${name}` } ); } } } /* -------------------------------------------- */ async rollDamage( weapon, damageType ) { let formula = VadentisUtility.processDamageString( weapon.data.data[damageType], this ); let degatsRoll = await VadentisUtility.processRoll( formula ); ChatMessage.create( { content: `${this.name} frappe avec ${weapon.name} et produit ${degatsRoll.total} Points de Dégâts (${formula}).` } ); } /* -------------------------------------------- */ async applyDamage( damageValue ) { let pvData = this.data.data.stats.pointsvie; let newValue = Math.max( pvData.value - damageValue, MIN_PV); await this.update( {'data.stats.pointsvie.value': newValue }); ChatMessage.create( { content: `${this.name} vient de perdre ${damageValue} Points de Vie. Ses Points de Vie actuels sont désormais de ${newValue}.` } ); } /* -------------------------------------------- */ _getCombatValue(mydata) { if ( Number(mydata.base)) { return mydata.base + mydata.malus + mydata.bonus; }else { return Number(mydata.base[0]) + Number(mydata.malus[0]) + Number(mydata.bonus[0]); } } /* -------------------------------------------- */ getInitiativeScore( ) { let initData = this.data.data.combat.initiative; return this._getCombatValue( initData); } /* -------------------------------------------- */ getDefenseScore( ) { let defenseData = this.data.data.combat.defense; return this._getCombatValue( defenseData); } /* -------------------------------------------- */ getForceScore( ) { let forceData = this.data.data.combat.force; return this._getCombatValue( forceData); } /* -------------------------------------------- */ getAttaqueScore( ) { let attaqueData = this.data.data.combat.attaque; return this._getCombatValue( attaqueData); } /* -------------------------------------------- */ async rollSort( sortId ) { let sort = this.data.items.find( item => item.type == 'sort' && item._id == sortId ); if ( sort ) { this.processSortDevotion( "sort", sort); } } /* -------------------------------------------- */ async rollDevotion( devotionId ) { let devotion = this.data.items.find( item => item.type == 'devotion' && item._id == devotionId ); if ( devotion ) { this.processSortDevotion( "devotion", devotion); } } /* -------------------------------------------- */ async rollTechnique( techniqueId ) { let technique = this.data.items.find( item => item.type == 'technique' && item._id == techniqueId ); if (technique) { if ( this.data.data.stats.pointsadrenaline.value < technique.data.pacost) { // Vérification du ~ de points d'adrénaline ChatMessage.create({ content: `${this.name} n'a pas assez de Points d'Adrénaline pour éxecuter sa technique ${technique.name}` } ); return; } let newAdrenaline = this.data.data.stats.pointsadrenaline.value - technique.data.pacost; await this.update( {'data.stats.pointsadrenaline.value': newAdrenaline }); ChatMessage.create( { content: `${this.name} execute sa technique ${technique.name}, pour un côut de ${technique.data.pacost} Points d'Adrénaline
Les effets sont : ${technique.data.effect}`} ); } } /* -------------------------------------------- */ rollCompetence( competenceId ) { let competence = this.data.items.find( item => item.type == 'competence' && item._id == competenceId); if ( competence) { let statValue = competence.data.base + competence.data.malus + competence.data.bonus; let formulaFull = `1d20+${competence.data.base}+${competence.data.malus}+${competence.data.bonus}`; let myRoll = new Roll("1d20+"+statValue); myRoll.evaluate(); myRoll.toMessage( { flavor: `Jet de compétence : ${competence.name} (${formulaFull})` } ); } } /* -------------------------------------------- */ rollCombat( combatName ) { let stat = this.data.data.combat[combatName]; let statValue = this._getCombatValue( stat ); let formulaFull = `1d20+${stat.base}+${stat.malus}+${stat.bonus}`; let myRoll = new Roll("1d20+"+statValue); myRoll.evaluate(); myRoll.toMessage( { title: "Test !",flavor: `Jet de ${stat.label} (${formulaFull})` } ); } /* -------------------------------------------- */ rollArme(armeId) { let target = VadentisUtility.getTarget(); if ( target ) { let arme = this.data.items.find( item => (item.type == 'armecc' || item.type == 'tir') && item._id == armeId); if (arme) { let combatData = { attackerActorId: this._id, targetActorId: target.actor._id, arme: duplicate(arme) } if (game.user.isGM) { VadentisUtility.performAttack( combatData); } else { game.socket.emit("system.foundryvtt-vadentis", { name: "msg_attack", data: { combatData } } ); } } } else { ui.notifications.warn("Vous devez désigner une cible pour attaquer avec une arme.") } } }