fvtt-vadentis/modules/vadentis-actor.js

414 lines
16 KiB
JavaScript
Raw Normal View History

2021-04-08 13:58:51 +02:00
/* -------------------------------------------- */
2021-04-01 21:18:36 +02:00
import { VadentisUtility } from "./vadentis-utility.js";
2021-04-08 13:58:51 +02:00
/* -------------------------------------------- */
const MIN_PV = -50;
const MIN_PE = -50;
2021-04-01 21:18:36 +02:00
/* -------------------------------------------- */
/**
* 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();
2021-04-02 14:59:58 +02:00
}
/* -------------------------------------------- */
getCompetences() {
return this.data.items.filter( item => item.type == 'competence');
}
2021-04-01 21:18:36 +02:00
2021-04-02 14:59:58 +02:00
/* -------------------------------------------- */
getDonnees() {
return this.data.items.filter( item => item.type == 'donnee');
2021-04-01 21:18:36 +02:00
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
getEglises() {
return this.data.items.filter( item => item.type == 'eglise');
}
2021-04-02 16:47:38 +02:00
/* -------------------------------------------- */
getSorts() {
return this.data.items.filter( item => item.type == 'sort');
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
getAttributs() {
return this.data.items.filter( item => item.type == 'attribut');
}
/* -------------------------------------------- */
getTechniques() {
return this.data.items.filter( item => item.type == 'technique');
}
2021-04-02 16:47:38 +02:00
/* -------------------------------------------- */
getDevotions() {
return this.data.items.filter( item => item.type == 'devotion');
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
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' );
}
2021-04-02 16:47:38 +02:00
2021-04-02 14:59:58 +02:00
/* -------------------------------------------- */
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 });
}
}
2021-04-02 16:47:38 +02:00
/* -------------------------------------------- */
2021-04-03 22:48:02 +02:00
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);
}
}
2021-04-02 16:47:38 +02:00
2021-04-13 14:01:22 +02:00
/* -------------------------------------------- */
calculerSommeStats( ) {
for (const key in this.data.data.combat) {
let combatData = this.data.data.combat[key];
combatData.total = combatData.base + combatData.malus + combatData.bonus;
}
for (const key in this.data.data.magie) {
let magieData = this.data.data.magie[key];
magieData.total = magieData.base + magieData.malus + magieData.bonus;
}
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
async processSortDevotion( name, devotionSort ) {
2021-04-03 22:52:43 +02:00
if ( this.data.data.stats.pointsenergie.value == 0) { // Vérification du ~ de points d'énergie
2021-04-03 22:48:02 +02:00
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;
2021-04-13 14:01:22 +02:00
let formulaFull = this.buildTexteFormula( scores );
let myRoll = await VadentisUtility.processRoll("1d20+"+statValue );
let msgData = {
alias: this.name,
title: `Sort ${devotionSort.name}`,
isSort: true
}
2021-04-08 13:58:51 +02:00
if (myRoll.results[0] > 1 && myRoll.total >= devotionSort.data.difficulty) {
2021-04-13 14:01:22 +02:00
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_sort_réussi.webp';
msgData.msg = `${this.name} a réussi son ${name} et perd ${devotionSort.data.pe} Points d'Energie (lancer : ${formulaFull} => <strong>${myRoll.total} / ${devotionSort.data.difficulty}</strong>).`;
let maintain = (devotionSort.data.ismaintain)?"Oui":"Non";
let complex = (devotionSort.data.complexactions)?"Oui":"Non";
msgData.msg += `<br>Peut être maintenu: ${maintain}<br>Actions complexes : ${complex}`;
msgData.msg += `<br><strong>Description : </strong>${devotionSort.data.notes.replace(/<\/?[^>]+(>|$)/g, "")}`;
2021-04-03 22:48:02 +02:00
let newEnergie = this.data.data.stats.pointsenergie.value - devotionSort.data.pe;
await this.update( {'data.stats.pointsenergie.value': newEnergie });
2021-04-13 20:19:32 +02:00
if (myRoll.results[0] >= devotionSort.data.valuecritical ) { // Critique ?
2021-04-13 14:01:22 +02:00
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_réussite_critique.webp';
msgData.msg += "<br>C'est une <strong>réussite critique</strong> !";
msgData.msg += `<br><strong>Effet critique : </strong>${devotionSort.data.criticaleffect.replace(/<\/?[^>]+(>|$)/g, "")}`;
} else {
msgData.msg += `<br><strong>Effet : </strong>${devotionSort.data.effect.replace(/<\/?[^>]+(>|$)/g, "")}`;
2021-04-13 14:01:22 +02:00
}
2021-04-03 22:48:02 +02:00
if ( devotionSort.data.damage != "") {
2021-04-08 13:58:51 +02:00
let formula = devotionSort.data.damage;
if (myRoll.results[0] >= devotionSort.data.valuecritical ) { // Critique ?
2021-04-13 14:01:22 +02:00
msgData.msg += `<br>Et provoque les dégats critiques suivants : `;
2021-04-08 13:58:51 +02:00
formula = devotionSort.data.damagecritical;
2021-04-13 14:01:22 +02:00
} else {
msgData.msg += `<br>Et provoque les dégats suivants : `;
2021-04-02 16:47:38 +02:00
}
}
2021-04-03 22:48:02 +02:00
if ( newEnergie < 0) {
2021-04-13 14:01:22 +02:00
msgData.msg += `<br><strong>Attention</strong> : Les Points d'Energie de ${this.name} sont négatifs ! Il convient d'éditer ses Points de Vie en conséquence.`;
2021-04-03 22:48:02 +02:00
}
} else {
2021-04-13 14:01:22 +02:00
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_sort_échoué.webp';
2021-04-08 13:58:51 +02:00
if (myRoll.results[0] == 1 ) { // Critique ?
2021-04-13 14:01:22 +02:00
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_échec_critique.webp';
msgData.msg = `${this.name} a fait un <strong>échec critique</strong> à son lancer de ${name}`;
2021-04-08 13:58:51 +02:00
} else {
2021-04-13 14:01:22 +02:00
msgData.msg = `${this.name} a échoué son lancer de ${name}`;
2021-04-08 13:58:51 +02:00
}
2021-04-03 22:48:02 +02:00
}
console.log(devotionSort.data.description, msgData);
2021-04-13 14:01:22 +02:00
ChatMessage.create({
//whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
});
}
2021-04-03 22:48:02 +02:00
2021-04-08 13:58:51 +02:00
/* -------------------------------------------- */
async rollDamage( weapon, damageType ) {
let formula = VadentisUtility.processDamageString( weapon.data.data[damageType], this );
let degatsRoll = await VadentisUtility.processRoll( formula );
2021-04-13 14:01:22 +02:00
let msgData = {
alias: this.name,
img: "systems/foundryvtt-vadentis/images/icons/tchat_dégâts_infligés.webp",
title: `Dégâts de ${weapon.name}`,
msg: `${this.name} frappe avec ${weapon.name} et produit <strong>${degatsRoll.total} Points de Dégâts</strong> (${formula}).`
}
ChatMessage.create({
//whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
});
2021-04-08 13:58:51 +02:00
}
/* -------------------------------------------- */
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 });
2021-04-13 14:01:22 +02:00
let msgData = {
alias: this.name,
img: "systems/foundryvtt-vadentis/images/icons/tchat_dégâts_infligés.webp",
title: `${this.name} encaisse des dégâts !`,
2021-04-22 16:03:51 +02:00
msg: `${this.name} encaisse ${damageValue} dégâts !`
2021-04-13 14:01:22 +02:00
}
2021-04-22 16:03:51 +02:00
if ( game.user.isGM) {
msgData.msg += `<br>Ses Points de Vie actuels sont désormais de ${newValue}.`;
}
2021-04-13 14:01:22 +02:00
ChatMessage.create({
//whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
});
2021-04-08 13:58:51 +02:00
}
/* -------------------------------------------- */
_getCombatValue(mydata) {
2021-04-13 14:01:22 +02:00
if ( typeof mydata.base == 'number' ) {
2021-04-08 13:58:51 +02:00
return mydata.base + mydata.malus + mydata.bonus;
2021-04-13 20:19:32 +02:00
} else {
2021-04-08 13:58:51 +02:00
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);
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
getDefenseScore( ) {
let defenseData = this.data.data.combat.defense;
2021-04-08 13:58:51 +02:00
return this._getCombatValue( defenseData);
}
/* -------------------------------------------- */
getForceScore( ) {
let forceData = this.data.data.combat.force;
return this._getCombatValue( forceData);
2021-04-03 22:48:02 +02:00
}
/* -------------------------------------------- */
getAttaqueScore( ) {
let attaqueData = this.data.data.combat.attaque;
2021-04-08 13:58:51 +02:00
return this._getCombatValue( attaqueData);
2021-04-03 22:48:02 +02:00
}
2021-04-13 14:01:22 +02:00
/* -------------------------------------------- */
buildTexteFormula( stat) {
let signMalus = (stat.malus < 0) ? "" : "+";
return `1d20+ ${stat.base} ${signMalus} ${stat.malus} + ${stat.bonus}`;
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
async rollSort( sortId ) {
let sort = this.data.items.find( item => item.type == 'sort' && item._id == sortId );
if ( sort ) {
this.processSortDevotion( "sort", sort);
2021-04-02 16:47:38 +02:00
}
}
/* -------------------------------------------- */
2021-04-03 22:48:02 +02:00
async rollDevotion( devotionId ) {
2021-04-02 16:47:38 +02:00
let devotion = this.data.items.find( item => item.type == 'devotion' && item._id == devotionId );
if ( devotion ) {
2021-04-03 22:48:02 +02:00
this.processSortDevotion( "devotion", devotion);
}
}
2021-04-02 16:47:38 +02:00
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
async rollTechnique( techniqueId ) {
let technique = this.data.items.find( item => item.type == 'technique' && item._id == techniqueId );
if (technique) {
2021-04-13 14:01:22 +02:00
let msgData = {
alias: this.name,
img: technique.img,
title: `Technique ${technique.name}`
}
2021-04-03 22:48:02 +02:00
if ( this.data.data.stats.pointsadrenaline.value < technique.data.pacost) { // Vérification du ~ de points d'adrénaline
2021-04-13 14:01:22 +02:00
msgData.msg = `${this.name} n'a pas assez de Points d'Adrénaline pour éxecuter sa technique ${technique.name}`;
} else {
let newAdrenaline = this.data.data.stats.pointsadrenaline.value - technique.data.pacost;
await this.update( {'data.stats.pointsadrenaline.value': newAdrenaline });
msgData.msg = `${this.name} execute sa technique ${technique.name}, pour un côut de ${technique.data.pacost} Points d'Adrénaline<br>
Les effets sont : ${technique.data.effect}`;
2021-04-02 16:47:38 +02:00
}
2021-04-13 14:01:22 +02:00
ChatMessage.create({
//whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
});
} else {
ui.notifications.warn("Technique non trouvée");
2021-04-02 16:47:38 +02:00
}
}
2021-04-02 14:59:58 +02:00
/* -------------------------------------------- */
2021-04-13 14:01:22 +02:00
async rollCompetence( competenceId ) {
2021-04-02 14:59:58 +02:00
let competence = this.data.items.find( item => item.type == 'competence' && item._id == competenceId);
if ( competence) {
2021-04-13 14:01:22 +02:00
let msgData = {
alias: this.name,
img: competence.img,
2021-04-22 16:03:51 +02:00
rollMode: game.settings.get("core", "rollMode"),
2021-04-13 14:01:22 +02:00
title: `Compétence ${competence.name}`
}
2021-04-02 14:59:58 +02:00
let statValue = competence.data.base + competence.data.malus + competence.data.bonus;
2021-04-13 14:01:22 +02:00
let formulaFull = this.buildTexteFormula( competence.data );
2021-04-22 16:03:51 +02:00
let myRoll = await VadentisUtility.processRoll("1d20+"+statValue, msgData.rollMode );
2021-04-13 14:01:22 +02:00
msgData.msg = `${formulaFull} => <strong>${myRoll.total}</strong>`;
if (myRoll.results[0] == 1 ) { // Critique ?
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_échec_critique.webp';
msgData.msg += `<br>C'est un <strong>échec critique</strong> !`;
}
if (myRoll.results[0] == 20 ) { // Critique ?
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_réussite_critique.webp';
msgData.msg += `<br>C'est une <strong>réussite critique</strong> !`;
}
2021-04-22 16:03:51 +02:00
if (["gmroll", "blindroll"].includes(msgData.rollMode)) msgData["whisper"] = ChatMessage.getWhisperRecipients("GM").map(u => u.id);
if (msgData.rollMode === "blindroll") msgData["blind"] = true;
else if (msgData.rollMode === "selfroll") msgData["whisper"] = [game.user];
2021-04-13 14:01:22 +02:00
ChatMessage.create({
2021-04-22 16:03:51 +02:00
whisper: msgData["whisper"],
2021-04-13 14:01:22 +02:00
content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
});
} else {
ui.notifications.warn("Compétence non trouvée");
2021-04-02 14:59:58 +02:00
}
}
/* -------------------------------------------- */
async genericRoll( stat, key ) {
2021-04-08 13:58:51 +02:00
let statValue = this._getCombatValue( stat );
2021-04-13 14:01:22 +02:00
let formulaFull = this.buildTexteFormula( stat );
2021-04-13 20:19:32 +02:00
2021-04-13 14:01:22 +02:00
let myRoll = await VadentisUtility.processRoll("1d20+"+statValue );
let msgData = {
alias: this.name,
img: `systems/foundryvtt-vadentis/images/icons/feuille_perso_${key}.webp`,
2021-04-13 20:19:32 +02:00
title: VadentisUtility.buildJetText( stat),
2021-04-13 14:01:22 +02:00
msg: `${formulaFull} => <strong>${myRoll.total}</strong>`
}
if (myRoll.results[0] == 1 ) { // Critique ?
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_échec_critique.webp';
msgData.msg += `<br>C'est un <strong>échec critique</strong> !`;
}
if (myRoll.results[0] == 20 ) { // Critique ?
msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_réussite_critique.webp';
msgData.msg += `<br>C'est une <strong>réussite critique</strong> !`;
}
ChatMessage.create({
//whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
});
}
/* -------------------------------------------- */
async rollCombat( combatName ) {
let stat = this.data.data.combat[combatName];
this.genericRoll( stat, combatName );
2021-04-13 14:01:22 +02:00
}
/* -------------------------------------------- */
rollMagie( magieName ) {
let stat = this.data.data.magie[magieName];
this.genericRoll( stat, magieName );
2021-04-03 22:48:02 +02:00
}
2021-04-22 16:03:51 +02:00
/* -------------------------------------------- */
async decrementeMunition( arme ) {
let armeTir = this.data.items.find( item => item.type == 'tir' && item.name == arme.name);
if (armeTir) {
let newMunition = armeTir.data.munition - 1;
await this.updateOwnedItem( { _id: armeTir._id, 'data.munition': newMunition } );
}
}
2021-04-03 22:48:02 +02:00
/* -------------------------------------------- */
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) {
2021-04-22 16:03:51 +02:00
if ( arme == 'tir' && arme.data.munition <= 0 ) {
ui.notifications.warn("Vous n'avez plus de munitions avec cette arme.");
return;
}
2021-04-03 22:48:02 +02:00
let combatData = {
attackerActorId: this._id,
targetActorId: target.actor._id,
arme: duplicate(arme)
}
if (game.user.isGM) {
VadentisUtility.performAttack( combatData);
} else {
2021-04-18 18:14:31 +02:00
game.socket.emit("system.foundryvtt-vadentis", { name: "msg_attack", data: combatData } );
2021-04-03 22:48:02 +02:00
}
}
} else {
ui.notifications.warn("Vous devez désigner une cible pour attaquer avec une arme.")
}
2021-04-02 14:59:58 +02:00
}
2021-04-01 21:18:36 +02:00
}