From 5baa94b3f0f960ab35b0eeb62d2a157893403d65 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 14 Jun 2023 01:48:32 +0200 Subject: [PATCH] =?UTF-8?q?Gestion=20des=20difficult=C3=A9s=20de=20Possess?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - gestion de la difficulté imposée sur la défense - gestion des particulières en attaque considérées en finesse - utilisation du rêve actuel pour les personnages --- module/actor.js | 22 ++-- module/migrations.js | 20 ++++ module/rdd-bonus.js | 6 +- module/rdd-possession.js | 139 ++++++++++++++++-------- module/rdd-token-hud.js | 4 +- module/rolldata-ajustements.js | 3 +- template.json | 15 ++- templates/chat-resultat-possession.html | 4 +- 8 files changed, 146 insertions(+), 67 deletions(-) diff --git a/module/actor.js b/module/actor.js index b2354b38..0e2e31f9 100644 --- a/module/actor.js +++ b/module/actor.js @@ -45,7 +45,7 @@ const POSSESSION_SANS_DRACONIC = { name: 'Sans draconic', system: { niveau: 0, - defaut_carac: "reve", + defaut_carac: "reve-actuel", } }; @@ -275,12 +275,12 @@ export class RdDActor extends RdDBaseActor { .sort(Misc.descending(it => it.system.niveau)) .find(it=>true); if (possession) { - return duplicate(possession); + return possession.clone(); } - const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0), + const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it =>it.clone()), POSSESSION_SANS_DRACONIC] .sort(Misc.descending(it => it.system.niveau)); - return duplicate(draconics[0]); + return draconics[0]; } getPossession(possessionId) { @@ -780,7 +780,7 @@ export class RdDActor extends RdDBaseActor { async combattreReveDeDragon(force) { let rollData = { actor: this, - competence: duplicate(this.getDraconicOuPossession()), + competence: this.getDraconicOuPossession(), canClose: false, rencontre: await game.system.rdd.rencontresTMR.getReveDeDragon(force), tmr: true, @@ -2301,14 +2301,14 @@ export class RdDActor extends RdDBaseActor { carac: this.system.carac, competence: this.getCompetence(idOrName) } - if (rollData.competence.type == 'competencecreature') { - if (rollData.competence.system.iscombat && options.tryTarget && Targets.hasTargets()) { + if (rollData.competence.type == TYPES.competencecreature) { + const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence) + if (arme && options.tryTarget && Targets.hasTargets()) { Targets.selectOneToken(target => { - if (rollData.competence.system.ispossession) { + if (arme.action == "possession") { RdDPossession.onAttaquePossession(target, this, rollData.competence) } else { - const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence) RdDCombat.rddCombatTarget(target, this).attaque(competence, arme) } }); @@ -3135,9 +3135,7 @@ export class RdDActor extends RdDBaseActor { /* -------------------------------------------- */ conjurerPossession(possession) { - // TODO: choix de la compétence de draconic ou de possession - let draconic = this.getDraconicOuPossession(); - RdDPossession.onConjurerPossession(this, draconic, possession) + RdDPossession.onConjurerPossession(this, possession) } /* -------------------------------------------- */ diff --git a/module/migrations.js b/module/migrations.js index 38216c07..5af2629b 100644 --- a/module/migrations.js +++ b/module/migrations.js @@ -495,6 +495,25 @@ class _10_7_19_CategorieCompetenceCreature extends Migration { } } +class _10_7_19_PossessionsEntiteVictime extends Migration { + get code() { return "possessions-entite-victime"; } + get version() { return "10.7.19"; } + + async migrate() { + await this.applyItemsUpdates(items => items + .filter(it => TYPES.possession == it.type) + .map(it => this.migratePossession(it)) + ); + } + + migratePossession(it) { + return { _id: it.id, + 'system.entite.actorid': it.system.possesseurid, + 'system.victime.actorid': it.system.possedeid + } + } +} + export class Migrations { static getMigrations() { return [ @@ -512,6 +531,7 @@ export class Migrations { new _10_5_0_UpdatePeriodicite(), new _10_7_0_MigrationBlessures(), new _10_7_19_CategorieCompetenceCreature(), + new _10_7_19_PossessionsEntiteVictime(), ]; } diff --git a/module/rdd-bonus.js b/module/rdd-bonus.js index 2cf31e25..74a03a49 100644 --- a/module/rdd-bonus.js +++ b/module/rdd-bonus.js @@ -1,4 +1,5 @@ import { RdDCarac } from "./rdd-carac.js"; +import { RdDPossession } from "./rdd-possession.js"; const conditionsTactiques = [ { type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true }, @@ -27,6 +28,9 @@ export class RdDBonus { if (rollData.isEmpoignade && rollData.rolled?.isPart) { return true } + if (RdDPossession.isDefensePossession(rollData)) { + return RdDPossession.isPossessionFinesse(rollData) + } return rollData.attackerRoll?.particuliere == 'finesse'; } @@ -74,7 +78,7 @@ export class RdDBonus { /* -------------------------------------------- */ static _dmgArme(rollData) { - if ( rollData.arme) { + if (rollData.arme) { let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0); //Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278) return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0); diff --git a/module/rdd-possession.js b/module/rdd-possession.js index ed028d41..06bee19c 100644 --- a/module/rdd-possession.js +++ b/module/rdd-possession.js @@ -1,9 +1,9 @@ /* -------------------------------------------- */ -import { RdDCombat } from "./rdd-combat.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDRoll } from "./rdd-roll.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { Targets } from "./targets.js"; +import { TYPES } from "./item.js"; /* -------------------------------------------- */ /* On part du principe qu'une entité démarre tjs @@ -20,9 +20,9 @@ export class RdDPossession { /* -------------------------------------------- */ static searchPossessionFromEntite(attacker, defender) { - let poss = attacker.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id); + let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); if (!poss) { - poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id); + poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); } return poss && duplicate(poss) || undefined; } @@ -31,13 +31,13 @@ export class RdDPossession { static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) { const defender = target.actor; const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender); - const isNouvelle = !suitePossession && ! fromEntite; + const isNouvelle = !suitePossession && !fromEntite; const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender))); - + RdDPossession.$updateEtatPossession(possession) let rollData = { - mode: "possession", + mode: "attaque", isECNIDefender: false, competence: competence.clone(), possession: possession, @@ -45,25 +45,26 @@ export class RdDPossession { defender: defender, targetToken: Targets.extractTokenData(target) }; - if (attacker.isCreatureEntite()) { - RdDItemCompetenceCreature.setRollDataCreature(rollData) - } - + RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker) + await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle); } - + /* -------------------------------------------- */ - static async onConjurerPossession(attacker, competence, possession) { + static async onConjurerPossession(attacker, possession) { possession = duplicate(possession); RdDPossession.$updateEtatPossession(possession) + + const defender = game.actors.get(possession.system.entite.actorid); let rollData = { - mode: "possession", + mode: "attaque", isECNIDefender: true, - competence: competence, possession: possession, attacker: attacker, - defender: game.actors.get(possession.system.possesseurid) + defender: defender, }; + RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker) + await RdDPossession.$rollAttaquePossession(attacker, rollData); } @@ -71,7 +72,7 @@ export class RdDPossession { static async onDefensePossession(attackerId, defenderId, possessionId) { let attacker = game.actors.get(attackerId) let possession = attacker?.getPossession(possessionId) - defenderId = defenderId ?? possession?.system.possesseurid ?? undefined + defenderId = defenderId ?? possession?.system.entite.actorid ?? undefined let defender = game.actors.get(defenderId) possession = possession ?? defender?.getPossession(possessionId) ?? undefined; @@ -82,19 +83,29 @@ export class RdDPossession { possession = duplicate(possession) // Update for draconic roll let rollData = { - mode: "conjuration", + mode: "defense", isECNIDefender: defender.type == "entite", possession: possession, attacker: attacker, defender: defender, - competence: defender.getDraconicOuPossession(), - selectedCarac: defender.system.carac.reve, - forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } } } - rollData.competence.system.defaut_carac = 'reve-actuel' - + RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender) + rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre + await RdDPossession.$rollDefensePossession(defender, rollData); } + + static selectCompetenceDraconicOuPossession(rollData, rollingActor) { + rollData.competence = rollingActor.getDraconicOuPossession(); + if (rollingActor.isCreatureEntite()) { + RdDItemCompetenceCreature.setRollDataCreature(rollData) + } + else { + rollData.selectedCarac = rollingActor.system.carac.reve + rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } + rollData.competence.system.defaut_carac = 'reve-actuel' + } + } /* -------------------------------------------- */ static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) { @@ -104,21 +115,22 @@ export class RdDPossession { name: 'jet-possession', label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession', callbacks: [ - { condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) }, - { condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) }, + { action: async (r) => await RdDPossession.$onRollPossession(r, isNouvelle) }, ] }); - dialog.render(true); + dialog.render(true); } /* -------------------------------------------- */ - static async $onRollPossession(rollData, isSuccess, isNouvelle = false) { - rollData.possession.isSuccess = isSuccess; - RdDPossession.$updateEtatPossession(rollData.possession); + static async $onRollPossession(rollData, isNouvelle = false) { + rollData.possession.isSuccess = rollData.rolled.isSuccess; + RdDPossession.$updateEtatPossession(rollData.possession, rollData); if (isNouvelle) { // Creer la possession sur le defenseur - rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()]) + await rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()]) } + const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid) + RdDPossession.storePossessionAttaque(possession, rollData) await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html'); } @@ -131,31 +143,38 @@ export class RdDPossession { label: 'Conjurer une Possession', callbacks: [ { action: async (r) => await RdDPossession.$onRollConjuration(r) } - ] - } - ); + ] + } + ); dialog.render(true); - } + } /* -------------------------------------------- */ static async $onRollConjuration(rollData) { - let actor = game.actors.get(rollData.possession.system.possedeid) + let victime = game.actors.get(rollData.possession.system.victime.actorid) + let compteur = rollData.possession.system.compteur if (!rollData.rolled.isSuccess) { if (rollData.isECNIDefender) { - rollData.possession.system.compteur-- + compteur-- } else { - rollData.possession.system.compteur++ + compteur++ } - let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur } - await actor.updateEmbeddedDocuments('Item', [update]) } - + const possession = victime.getPossession(rollData.possession.system.possessionid) + await possession.update({ + system: { + compteur: compteur, + entite: { diffLibre: 0, finesse: false }, + victime: { diffLibre: 0, finesse: false } + } + }) + rollData.possession = possession RdDPossession.$updateEtatPossession(rollData.possession) - await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html') + await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html') if (rollData.possession.isPosseder || rollData.possession.isConjurer) { // conjuration - actor.deleteEmbeddedDocuments("Item", [rollData.possession._id]) + victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) } } @@ -180,13 +199,43 @@ export class RdDPossession { } } + /* -------------------------------------------- */ + static isPossessionFinesse(rollData) { + return RdDPossession.getInfoAttaque(rollData).finesse + } + /* -------------------------------------------- */ + static getInfoAttaque(rollData) { + return rollData.possession.system[rollData.isECNIDefender ? 'victime' : 'entite']; + } + /* -------------------------------------------- */ + static isDefensePossession(rollData) { + return rollData.possession && rollData.mode == "defense" + } + /* -------------------------------------------- */ + static storePossessionAttaque(possession, rollData = undefined) { + const attaquant = rollData?.isECNIDefender ? 'victime' : 'entite' + possession.update({ + [`system.${attaquant}`]: { + diffLibre: rollData?.diffLibre ?? 0, + finesse: rollData?.rolled.isPart ?? false + } + }) + } + /* -------------------------------------------- */ static async createPossession(attacker, defender) { return await Item.create({ - name: "Possession en cours de " + attacker.name, type: 'possession', - img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", - system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 } - }, + name: "Possession en cours de " + attacker.name, type: 'possession', + img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", + system: { + description: "", typepossession: attacker.name, + possede: false, + possessionid: randomID(16), + entite: { actorid: attacker.id }, + victime: { actorid: defender.id }, + compteur: 0 + } + }, { temporary: true }) diff --git a/module/rdd-token-hud.js b/module/rdd-token-hud.js index c5e5972a..cbefeab8 100644 --- a/module/rdd-token-hud.js +++ b/module/rdd-token-hud.js @@ -75,8 +75,8 @@ export class RdDTokenHud { (event) => { const actionIndex = event.currentTarget.attributes['data-action-index']?.value; const action = hudData.actions[actionIndex]; - if (action.action == 'possession') { - const possession = combatant.actor.getPossession(action.system.possessionid); + const possession = action.action == 'possession' ? combatant.actor.getPossession(action.system.possessionid) : undefined; + if (possession) { combatant.actor.conjurerPossession(possession); } else { diff --git a/module/rolldata-ajustements.js b/module/rolldata-ajustements.js index 71879f2a..a141cae0 100644 --- a/module/rolldata-ajustements.js +++ b/module/rolldata-ajustements.js @@ -5,6 +5,7 @@ import { RdDItemSort } from "./item-sort.js"; import { Misc } from "./misc.js"; import { RdDBonus } from "./rdd-bonus.js"; import { RdDCarac } from "./rdd-carac.js"; +import { RdDPossession } from "./rdd-possession.js"; import { RdDUtility } from "./rdd-utility.js"; import { ReglesOptionelles } from "./settings/regles-optionelles.js"; @@ -30,7 +31,7 @@ export const referenceAjustements = { }, diffLibre: { isUsed: (rollData, actor) => rollData.diffLibre != undefined, - getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre', + getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ?? RdDPossession.isDefensePossession(rollData) ? 'Imposée' : 'Libre', getValue: (rollData, actor) => rollData.selectedSort ? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre) : rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0 diff --git a/template.json b/template.json index 7b4e0b49..470190bf 100644 --- a/template.json +++ b/template.json @@ -611,10 +611,17 @@ "typepossession": "", "possede": false, "possessionid": "", - "possesseurid": "", - "possedeid": "", - "compteur": 0, - "date": 0 + "entite": { + "actorid": "", + "diffLibre": 0, + "finesse": false + }, + "victime": { + "actorid": "", + "diffLibre": 0, + "finesse": false + }, + "compteur": 0 }, "blessure": { "templates": ["temporel"], diff --git a/templates/chat-resultat-possession.html b/templates/chat-resultat-possession.html index af440f0d..1a647f40 100644 --- a/templates/chat-resultat-possession.html +++ b/templates/chat-resultat-possession.html @@ -1,6 +1,6 @@

- {{#if (eq mode "possession")}} + {{#if (eq mode "attaque")}} {{attacker.name}} tente de {{#if isECNIDefender}}conjurer la possession de{{else}}posséder{{/if}} {{defender.name}} {{else}} {{defender.name}} tente de {{#if isECNIDefender}}résister à{{else}}conjurer la possession de{{/if}} {{attacker.name}} @@ -12,7 +12,7 @@

- {{#if (eq mode "possession")}} + {{#if (eq mode "attaque")}} {{#if possession.isSuccess}}