Gestion des difficultés de Possession

- 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
This commit is contained in:
Vincent Vandemeulebrouck 2023-06-14 01:48:32 +02:00
parent e46f35ef92
commit 2db6895c76
8 changed files with 146 additions and 67 deletions

View File

@ -45,7 +45,7 @@ const POSSESSION_SANS_DRACONIC = {
name: 'Sans draconic', name: 'Sans draconic',
system: { system: {
niveau: 0, 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)) .sort(Misc.descending(it => it.system.niveau))
.find(it=>true); .find(it=>true);
if (possession) { 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] POSSESSION_SANS_DRACONIC]
.sort(Misc.descending(it => it.system.niveau)); .sort(Misc.descending(it => it.system.niveau));
return duplicate(draconics[0]); return draconics[0];
} }
getPossession(possessionId) { getPossession(possessionId) {
@ -780,7 +780,7 @@ export class RdDActor extends RdDBaseActor {
async combattreReveDeDragon(force) { async combattreReveDeDragon(force) {
let rollData = { let rollData = {
actor: this, actor: this,
competence: duplicate(this.getDraconicOuPossession()), competence: this.getDraconicOuPossession(),
canClose: false, canClose: false,
rencontre: await game.system.rdd.rencontresTMR.getReveDeDragon(force), rencontre: await game.system.rdd.rencontresTMR.getReveDeDragon(force),
tmr: true, tmr: true,
@ -2301,14 +2301,14 @@ export class RdDActor extends RdDBaseActor {
carac: this.system.carac, carac: this.system.carac,
competence: this.getCompetence(idOrName) competence: this.getCompetence(idOrName)
} }
if (rollData.competence.type == 'competencecreature') { if (rollData.competence.type == TYPES.competencecreature) {
if (rollData.competence.system.iscombat && options.tryTarget && Targets.hasTargets()) { const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence)
if (arme && options.tryTarget && Targets.hasTargets()) {
Targets.selectOneToken(target => { Targets.selectOneToken(target => {
if (rollData.competence.system.ispossession) { if (arme.action == "possession") {
RdDPossession.onAttaquePossession(target, this, rollData.competence) RdDPossession.onAttaquePossession(target, this, rollData.competence)
} }
else { else {
const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence)
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme) RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
} }
}); });
@ -3135,9 +3135,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
conjurerPossession(possession) { conjurerPossession(possession) {
// TODO: choix de la compétence de draconic ou de possession RdDPossession.onConjurerPossession(this, possession)
let draconic = this.getDraconicOuPossession();
RdDPossession.onConjurerPossession(this, draconic, possession)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -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 { export class Migrations {
static getMigrations() { static getMigrations() {
return [ return [
@ -512,6 +531,7 @@ export class Migrations {
new _10_5_0_UpdatePeriodicite(), new _10_5_0_UpdatePeriodicite(),
new _10_7_0_MigrationBlessures(), new _10_7_0_MigrationBlessures(),
new _10_7_19_CategorieCompetenceCreature(), new _10_7_19_CategorieCompetenceCreature(),
new _10_7_19_PossessionsEntiteVictime(),
]; ];
} }

View File

@ -1,4 +1,5 @@
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
import { RdDPossession } from "./rdd-possession.js";
const conditionsTactiques = [ const conditionsTactiques = [
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true }, { type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
@ -27,6 +28,9 @@ export class RdDBonus {
if (rollData.isEmpoignade && rollData.rolled?.isPart) { if (rollData.isEmpoignade && rollData.rolled?.isPart) {
return true return true
} }
if (RdDPossession.isDefensePossession(rollData)) {
return RdDPossession.isPossessionFinesse(rollData)
}
return rollData.attackerRoll?.particuliere == 'finesse'; return rollData.attackerRoll?.particuliere == 'finesse';
} }
@ -74,7 +78,7 @@ export class RdDBonus {
/* -------------------------------------------- */ /* -------------------------------------------- */
static _dmgArme(rollData) { static _dmgArme(rollData) {
if ( rollData.arme) { if (rollData.arme) {
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0); 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) //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); return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);

View File

@ -1,9 +1,9 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { RdDCombat } from "./rdd-combat.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { Targets } from "./targets.js"; import { Targets } from "./targets.js";
import { TYPES } from "./item.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* On part du principe qu'une entité démarre tjs /* On part du principe qu'une entité démarre tjs
@ -20,9 +20,9 @@ export class RdDPossession {
/* -------------------------------------------- */ /* -------------------------------------------- */
static searchPossessionFromEntite(attacker, defender) { 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) { 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; return poss && duplicate(poss) || undefined;
} }
@ -31,13 +31,13 @@ export class RdDPossession {
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) { static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
const defender = target.actor; const defender = target.actor;
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender); const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
const isNouvelle = !suitePossession && ! fromEntite; const isNouvelle = !suitePossession && !fromEntite;
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender))); const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
RdDPossession.$updateEtatPossession(possession) RdDPossession.$updateEtatPossession(possession)
let rollData = { let rollData = {
mode: "possession", mode: "attaque",
isECNIDefender: false, isECNIDefender: false,
competence: competence.clone(), competence: competence.clone(),
possession: possession, possession: possession,
@ -45,25 +45,26 @@ export class RdDPossession {
defender: defender, defender: defender,
targetToken: Targets.extractTokenData(target) targetToken: Targets.extractTokenData(target)
}; };
if (attacker.isCreatureEntite()) { RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
RdDItemCompetenceCreature.setRollDataCreature(rollData)
}
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle); await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onConjurerPossession(attacker, competence, possession) { static async onConjurerPossession(attacker, possession) {
possession = duplicate(possession); possession = duplicate(possession);
RdDPossession.$updateEtatPossession(possession) RdDPossession.$updateEtatPossession(possession)
const defender = game.actors.get(possession.system.entite.actorid);
let rollData = { let rollData = {
mode: "possession", mode: "attaque",
isECNIDefender: true, isECNIDefender: true,
competence: competence,
possession: possession, possession: possession,
attacker: attacker, attacker: attacker,
defender: game.actors.get(possession.system.possesseurid) defender: defender,
}; };
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
await RdDPossession.$rollAttaquePossession(attacker, rollData); await RdDPossession.$rollAttaquePossession(attacker, rollData);
} }
@ -71,7 +72,7 @@ export class RdDPossession {
static async onDefensePossession(attackerId, defenderId, possessionId) { static async onDefensePossession(attackerId, defenderId, possessionId) {
let attacker = game.actors.get(attackerId) let attacker = game.actors.get(attackerId)
let possession = attacker?.getPossession(possessionId) let possession = attacker?.getPossession(possessionId)
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined defenderId = defenderId ?? possession?.system.entite.actorid ?? undefined
let defender = game.actors.get(defenderId) let defender = game.actors.get(defenderId)
possession = possession ?? defender?.getPossession(possessionId) ?? undefined; possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
@ -82,19 +83,29 @@ export class RdDPossession {
possession = duplicate(possession) possession = duplicate(possession)
// Update for draconic roll // Update for draconic roll
let rollData = { let rollData = {
mode: "conjuration", mode: "defense",
isECNIDefender: defender.type == "entite", isECNIDefender: defender.type == "entite",
possession: possession, possession: possession,
attacker: attacker, attacker: attacker,
defender: defender, 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); 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) { static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
@ -104,21 +115,22 @@ export class RdDPossession {
name: 'jet-possession', name: 'jet-possession',
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession', label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
callbacks: [ callbacks: [
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) }, { action: async (r) => await RdDPossession.$onRollPossession(r, isNouvelle) },
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
] ]
}); });
dialog.render(true); dialog.render(true);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) { static async $onRollPossession(rollData, isNouvelle = false) {
rollData.possession.isSuccess = isSuccess; rollData.possession.isSuccess = rollData.rolled.isSuccess;
RdDPossession.$updateEtatPossession(rollData.possession); RdDPossession.$updateEtatPossession(rollData.possession, rollData);
if (isNouvelle) { if (isNouvelle) {
// Creer la possession sur le defenseur // 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'); await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
} }
@ -131,31 +143,38 @@ export class RdDPossession {
label: 'Conjurer une Possession', label: 'Conjurer une Possession',
callbacks: [ callbacks: [
{ action: async (r) => await RdDPossession.$onRollConjuration(r) } { action: async (r) => await RdDPossession.$onRollConjuration(r) }
] ]
} }
); );
dialog.render(true); dialog.render(true);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $onRollConjuration(rollData) { 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.rolled.isSuccess) {
if (rollData.isECNIDefender) { if (rollData.isECNIDefender) {
rollData.possession.system.compteur-- compteur--
} else { } 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) 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) { if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration // 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) { static async createPossession(attacker, defender) {
return await Item.create({ return await Item.create({
name: "Possession en cours de " + attacker.name, type: 'possession', name: "Possession en cours de " + attacker.name, type: 'possession',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", 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 } system: {
}, description: "", typepossession: attacker.name,
possede: false,
possessionid: randomID(16),
entite: { actorid: attacker.id },
victime: { actorid: defender.id },
compteur: 0
}
},
{ {
temporary: true temporary: true
}) })

View File

@ -75,8 +75,8 @@ export class RdDTokenHud {
(event) => { (event) => {
const actionIndex = event.currentTarget.attributes['data-action-index']?.value; const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
const action = hudData.actions[actionIndex]; const action = hudData.actions[actionIndex];
if (action.action == 'possession') { const possession = action.action == 'possession' ? combatant.actor.getPossession(action.system.possessionid) : undefined;
const possession = combatant.actor.getPossession(action.system.possessionid); if (possession) {
combatant.actor.conjurerPossession(possession); combatant.actor.conjurerPossession(possession);
} }
else { else {

View File

@ -5,6 +5,7 @@ import { RdDItemSort } from "./item-sort.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js"; import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
import { RdDPossession } from "./rdd-possession.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js"; import { ReglesOptionelles } from "./settings/regles-optionelles.js";
@ -30,7 +31,7 @@ export const referenceAjustements = {
}, },
diffLibre: { diffLibre: {
isUsed: (rollData, actor) => rollData.diffLibre != undefined, 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 getValue: (rollData, actor) => rollData.selectedSort
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre) ? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0 : rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0

View File

@ -611,10 +611,17 @@
"typepossession": "", "typepossession": "",
"possede": false, "possede": false,
"possessionid": "", "possessionid": "",
"possesseurid": "", "entite": {
"possedeid": "", "actorid": "",
"compteur": 0, "diffLibre": 0,
"date": 0 "finesse": false
},
"victime": {
"actorid": "",
"diffLibre": 0,
"finesse": false
},
"compteur": 0
}, },
"blessure": { "blessure": {
"templates": ["temporel"], "templates": ["temporel"],

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" /> <img class="chat-icon" src="{{competence.img}}" />
<h4> <h4>
{{#if (eq mode "possession")}} {{#if (eq mode "attaque")}}
{{attacker.name}} tente de {{#if isECNIDefender}}conjurer la possession de{{else}}posséder{{/if}} {{defender.name}} {{attacker.name}} tente de {{#if isECNIDefender}}conjurer la possession de{{else}}posséder{{/if}} {{defender.name}}
{{else}} {{else}}
{{defender.name}} tente de {{#if isECNIDefender}}résister à{{else}}conjurer la possession de{{/if}} {{attacker.name}} {{defender.name}} tente de {{#if isECNIDefender}}résister à{{else}}conjurer la possession de{{/if}} {{attacker.name}}
@ -12,7 +12,7 @@
<div> <div>
<span class='chat-card-button-area'> <span class='chat-card-button-area'>
<br> <br>
{{#if (eq mode "possession")}} {{#if (eq mode "attaque")}}
{{#if possession.isSuccess}} {{#if possession.isSuccess}}
<a class='defense-possession chat-card-button' <a class='defense-possession chat-card-button'
data-attackerId='{{attacker.id}}' data-attackerId='{{attacker.id}}'