Gestion défense et compteur de possession

This commit is contained in:
2025-12-05 20:12:14 +01:00
parent 706aa657b1
commit 19cabe816e
18 changed files with 282 additions and 137 deletions
+1 -18
View File
@@ -600,24 +600,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
rollPossession() { rollPossession() {
Targets.selectOneTargetToken(async target => { RdDPossessionV2.rollAttaquePossession(this)
const selectedToken = RdDUtility.getSelectedToken(this)
RollDialog.create(
{
ids: {
actorId: this.id,
actorTokenId: selectedToken.id,
opponentId: target.actor.id,
opponentTokenId: target.id
},
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.ATTAQUE } },
passeArme: foundry.utils.randomID(16),
},
{
onRollDone: RollDialog.onRollDoneClose,
callbacks: [async (roll) => await RdDPossessionV2.chatMessageDefensePossession(roll)]
})
})
} }
verifierForceMin(item) { } verifierForceMin(item) { }
+9
View File
@@ -76,6 +76,15 @@ export class ChatUtility {
ChatUtility.removeMessages({ part: part }); ChatUtility.removeMessages({ part: part });
} }
static remover(chatMessage) {
const messageId = chatMessage.id;
if (messageId) {
return (..._) => ChatUtility.removeMessages({ messageId: messageId });
}
return (..._) => { }
}
static removeChatMessageId(messageId) { static removeChatMessageId(messageId) {
if (messageId) { if (messageId) {
ChatUtility.removeMessages({ messageId: messageId }); ChatUtility.removeMessages({ messageId: messageId });
+2 -4
View File
@@ -369,8 +369,7 @@ export class RdDCombat {
} }
static rddCombatForAttackV2(attackerRoll) { static rddCombatForAttackV2(attackerRoll) {
const defenderRoll = RollBasicParts.prepareDefense(attackerRoll) return RdDCombat.rddCombatForDefenseV2(RollBasicParts.prepareDefense(attackerRoll))
return RdDCombat.rddCombatForDefenseV2(defenderRoll)
} }
static rddCombatForDefenseV2(defenderRoll) { static rddCombatForDefenseV2(defenderRoll) {
@@ -755,7 +754,7 @@ export class RdDCombat {
} }
async _chatMessageDefenseV2(paramDemandeDefense) { async _chatMessageDefenseV2(paramDemandeDefense) {
const attackerRoll = paramDemandeDefense.attackerRoll; const attackerRoll = paramDemandeDefense.attackerRoll
RollBasicParts.loadSurprises(attackerRoll) RollBasicParts.loadSurprises(attackerRoll)
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque) attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
@@ -1086,7 +1085,6 @@ export class RdDCombat {
async defenseV2(attackerRoll, callbacks = []) { async defenseV2(attackerRoll, callbacks = []) {
// this._prepareParade(attackerRoll, arme, competence); // this._prepareParade(attackerRoll, arme, competence);
RollDialog.loadRollData(attackerRoll)
await this.doRollDefense({ await this.doRollDefense({
ids: { ids: {
actorId: this.defender.id, actorId: this.defender.id,
+3 -3
View File
@@ -89,20 +89,20 @@ export class RdDEmpoignade {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.entrainerAuSol(rollData) RdDEmpoignade.entrainerAuSol(rollData)
ChatUtility.removeChatMessageId(chatMessage.id) ChatUtility.remover(chatMessage)()
}); });
$(html).on("click", '.empoignade-projeter-sol', event => { $(html).on("click", '.empoignade-projeter-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.projeterAuSol(rollData) RdDEmpoignade.projeterAuSol(rollData)
ChatUtility.removeChatMessageId(chatMessage.id) ChatUtility.remover(chatMessage)()
}); });
$(html).on("change", '.empoignade-perte-endurance', event => { $(html).on("change", '.empoignade-perte-endurance', event => {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
if (event.currentTarget.value && event.currentTarget.value != "none") { if (event.currentTarget.value && event.currentTarget.value != "none") {
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value) RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
//ChatUtility.removeChatMessageId(chatMessage.id) ChatUtility.remover(chatMessage)()
} }
}); });
} }
+106 -32
View File
@@ -1,8 +1,10 @@
import { ITEM_TYPES, RDD_CONFIG } from "./constants.js"; import { ITEM_TYPES, RDD_CONFIG } from "./constants.js";
import { RdDRollResult } from "./rdd-roll-result.js";
import { RollBasicParts } from "./roll/roll-basic-parts.mjs"; import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import RollDialog from "./roll/roll-dialog.mjs"; import RollDialog from "./roll/roll-dialog.mjs";
import { Targets } from "./targets.js";
import { RdDUtility } from "./rdd-utility.js";
import { ROLL_TYPE_POSSESSION } from "./roll/roll-constants.mjs";
export const ACTIONS_POSSESSION = { export const ACTIONS_POSSESSION = {
ATTAQUE: 'attaque', ATTAQUE: 'attaque',
@@ -30,9 +32,9 @@ export class RdDPossessionV2 {
return victime.itemTypes[ITEM_TYPES.possession].find(poss => poss.system.entiteid == entite.id) return victime.itemTypes[ITEM_TYPES.possession].find(poss => poss.system.entiteid == entite.id)
} }
static async createPossession(entite, victime) { static async createPossessionIfMissing(entite, victime) {
if (RdDPossessionV2.$isInverse(entite, victime)) { if (RdDPossessionV2.$isInverse(entite, victime)) {
return await RdDPossessionV2.createPossession(victime, entite) return await RdDPossessionV2.createPossessionIfMissing(victime, entite)
} }
const existing = RdDPossessionV2.findPossession(entite, victime) const existing = RdDPossessionV2.findPossession(entite, victime)
if (!existing) { if (!existing) {
@@ -45,21 +47,24 @@ export class RdDPossessionV2 {
} }
} }
static getPossessionDetails(rollData, action) { static getTypePossession(activeActor, opponentActor) {
const isEntite = rollData.active.actor.isEntiteNonIncarnee() && !rollData.opponent.actor.isEntiteNonIncarnee() const isEntite = activeActor.isEntiteNonIncarnee() && !opponentActor.isEntiteNonIncarnee();
const itemPossession = RdDPossessionV2.findPossession(rollData.active.actor, rollData.opponent.actor) const itemPossession = RdDPossessionV2.findPossession(activeActor, opponentActor);
const compteur = itemPossession?.system.compteur ?? 0 const compteur = itemPossession?.system.compteur ?? 0;
const isAttaque = RdDPossessionV2.isAttaque(action)
action = RdDPossessionV2.$getAction(isAttaque, isEntite)
return { return {
action: action,
isEntite: isEntite, isEntite: isEntite,
isAttaque: isAttaque, isPersonnage: activeActor.isPersonnage(),
isPersonnage: rollData.active.actor.isPersonnage(),
isCompteurPossession: Math.sign(compteur) >= 0, isCompteurPossession: Math.sign(compteur) >= 0,
compteur: Math.abs(compteur) compteur: Math.abs(compteur)
} };
}
static getTypePossessionAction(roll, action) {
const possession = RdDPossessionV2.getTypePossession(roll.active.actor, roll.opponent.actor)
possession.isAttaque = RdDPossessionV2.isAttaque(action)
possession.action = RdDPossessionV2.$getAction(possession.isAttaque, possession.isEntite)
return possession
} }
static $getAction(isAttaque, isEntite) { static $getAction(isAttaque, isEntite) {
@@ -80,34 +85,106 @@ export class RdDPossessionV2 {
return "lutte contre" return "lutte contre"
} }
static isDefense(action) {
return [ACTIONS_POSSESSION.DEFENSE, ACTIONS_POSSESSION.DEFENSE_POSSESSION, ACTIONS_POSSESSION.DEFENSE_CONJURATION].includes(action)
}
static isAttaque(action) { static isAttaque(action) {
return ![ACTIONS_POSSESSION.DEFENSE, ACTIONS_POSSESSION.DEFENSE_POSSESSION, ACTIONS_POSSESSION.DEFENSE_CONJURATION].includes(action) return [ACTIONS_POSSESSION.ATTAQUE, ACTIONS_POSSESSION.POSSEDER, ACTIONS_POSSESSION.CONJURER].includes(action)
} }
static async addPointPossession(entite, victime, add) { static async rollAttaquePossession(actor) {
Targets.selectOneTargetToken(async target => {
const selectedToken = RdDUtility.getSelectedToken(actor)
RollDialog.create(
{
ids: {
actorId: actor.id,
actorTokenId: selectedToken.id,
opponentId: target.actor.id,
opponentTokenId: target.id
},
passeArme: foundry.utils.randomID(16),
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.ATTAQUE } },
},
{
onRollDone: RollDialog.onRollDoneClose,
callbacks: [
async (roll) => await RdDPossessionV2.createPossessionIfMissing(roll.active.actor, roll.opponent.actor),
async (roll) => RdDPossessionV2.$setParticuliereFinesse(roll),
async (roll) => await RdDPossessionV2.chatMessageDefensePossession(roll)
]
})
})
}
static $setParticuliereFinesse(roll) {
if (roll.rolled.isPart) {
roll.particuliere = RDD_CONFIG.particuliere.finesse.key
}
}
static async rollDefensePossession(savedRoll, chatMessage) {
RollBasicParts.restore(savedRoll)
const attackerRoll = savedRoll.attackerRoll
RollDialog.create(
{
ids: savedRoll.ids,
passeArme: attackerRoll.passeArme,
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.DEFENSE } },
selected: { diff: { value: attackerRoll.selected?.diff?.value ?? 0 } },
attackerRoll: attackerRoll
},
{
onRollDone: RollDialog.onRollDoneClose, callbacks: [
async roll => await RdDPossessionV2.onRollDefense(roll),
ChatUtility.remover(chatMessage)
]
});
}
static async onRollDefense(defense) {
if (defense.rolled.isEchec) {
await RdDPossessionV2.addPointPossession(defense.opponent.actor, defense.active.actor)
}
RdDPossessionV2.resetPossession(defense)
}
static async onMarquerPointPossession(roll) {
roll.type = {}
await RdDPossessionV2.addPointPossession(roll.opponent.actor, roll.active.actor)
RdDPossessionV2.resetPossession(roll)
await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker({ actor: roll.active.actor, token: roll.active.token }),
alias: roll.opponent.name,
whisper: ChatUtility.getOwners(roll.active.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/possession/chat-message-marquer.hbs`, roll)
})
}
static resetPossession(roll) {
roll.type.possession = foundry.utils.mergeObject(
roll.type.possession ?? {},
RdDPossessionV2.getTypePossession(roll.opponent.actor, roll.active.actor))
}
static async addPointPossession(entite, victime, points = 1) {
if (RdDPossessionV2.$isInverse(entite, victime)) { if (RdDPossessionV2.$isInverse(entite, victime)) {
return await RdDPossessionV2.addPointPossession(victime, entite, /* negate?*/ add) return await RdDPossessionV2.addPointPossession(victime, entite, - points)
} }
const existing = RdDPossessionV2.findPossession(entite, victime) const existing = RdDPossessionV2.findPossession(entite, victime)
if (!existing) { if (existing) {
return const compteur = (existing.system.compteur ?? 0) + points
await victime.updateEmbeddedDocuments('Item', [{ _id: existing.id, 'system.compteur': compteur }])
} }
const points = add ? 1 : -1
const compteur = (existing.system.compteur ?? 0) + points
await victime.updateEmbeddedDocuments('Item', [{ id: existing.id, 'system.compteur': compteur }])
}
static callbacksOnDefensePossession() {
return [async roll => {
}]
} }
static async chatMessageDefensePossession(attackerRoll) { static async chatMessageDefensePossession(attackerRoll) {
const defense = RollBasicParts.prepareDefense(attackerRoll) const defense = RollBasicParts.prepareDefense(attackerRoll)
defense.type = { defense.type = {
possession: RdDPossessionV2.getPossessionDetails(defense, ACTIONS_POSSESSION.DEFENSE) possession: RdDPossessionV2.getTypePossessionAction(defense, ACTIONS_POSSESSION.DEFENSE)
} }
const chatDemandeDefense = await ChatMessage.create({ const chatDemandeDefense = await ChatMessage.create({
@@ -115,7 +192,7 @@ export class RdDPossessionV2 {
speaker: ChatMessage.getSpeaker({ actor: defense.active.actor, token: defense.active.token }), speaker: ChatMessage.getSpeaker({ actor: defense.active.actor, token: defense.active.token }),
alias: attackerRoll.active.name, alias: attackerRoll.active.name,
whisper: ChatUtility.getOwners(defense.active.actor), whisper: ChatUtility.getOwners(defense.active.actor),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense-possession.hbs', defense) content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/possession/chat-demande-defense.hbs', defense)
}); });
ChatUtility.setMessageData(chatDemandeDefense, 'demande-defense', true) ChatUtility.setMessageData(chatDemandeDefense, 'demande-defense', true)
// // flag pour garder les jets d'attaque/defense // // flag pour garder les jets d'attaque/defense
@@ -126,7 +203,4 @@ export class RdDPossessionV2 {
}) })
} }
static async chatMarquerPointPossession(roll) {
}
} }
+3 -2
View File
@@ -776,8 +776,9 @@ export class RdDUtility {
let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0); let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0);
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:"); let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
if (actor) { if (actor) {
actor.payerSols(sommeAPayer); actor.payerSols(sommeAPayer)
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget)); const chatMessage = RdDUtility.findChatMessageId(event.currentTarget)
ChatUtility.remover(chatMessage)()
} }
}); });
$(html).on("click", '.rdd-world-content-link', async event => { $(html).on("click", '.rdd-world-content-link', async event => {
+23 -3
View File
@@ -13,6 +13,8 @@ import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RdDRollTables } from "../rdd-rolltables.js" import { RdDRollTables } from "../rdd-rolltables.js"
import { RdDEmpoignade } from "../rdd-empoignade.js" import { RdDEmpoignade } from "../rdd-empoignade.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { RollBasicParts } from "./roll-basic-parts.mjs"
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
export default class ChatRollResult { export default class ChatRollResult {
static init() { static init() {
@@ -134,6 +136,8 @@ export default class ChatRollResult {
$(html).on("click", '.appel-chance', event => this.onClickAppelChance(event)) $(html).on("click", '.appel-chance', event => this.onClickAppelChance(event))
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event)) $(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
$(html).on("click", '.button-defense', event => this.onClickDefense(event)) $(html).on("click", '.button-defense', event => this.onClickDefense(event))
$(html).on("click", '.button-defense-possession', event => this.onClickDefensePossession(event))
$(html).on("click", '.marquer-point-possession', event => this.onClickMarquerPointPossession(event))
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event)) $(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
$(html).on("click", '.resister-recul', event => this.onClickRecul(event)) $(html).on("click", '.resister-recul', event => this.onClickRecul(event))
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event)) $(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
@@ -187,7 +191,7 @@ export default class ChatRollResult {
console.log('onAppelChanceSuccess savedRoll', savedRoll) console.log('onAppelChanceSuccess savedRoll', savedRoll)
reRoll.type.retry = true reRoll.type.retry = true
await this.updateChatMessage(chatMessage, reRoll) await this.updateChatMessage(chatMessage, reRoll)
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)] const callbacks = [ChatUtility.remover(chatMessage)]
// TODO: annuler les effets // TODO: annuler les effets
switch (reRoll.type.current) { switch (reRoll.type.current) {
@@ -226,12 +230,28 @@ export default class ChatRollResult {
async onClickDefense(event) { async onClickDefense(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
RollBasicParts.restore(savedRoll)
const attackerRoll = savedRoll.attackerRoll const attackerRoll = savedRoll.attackerRoll
RollDialog.loadRollData(attackerRoll)
this.getCombat(attackerRoll)?.defenseV2(attackerRoll, this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
[roll => { ChatUtility.removeChatMessageId(chatMessage.id) }] [ChatUtility.remover(chatMessage)]
) )
} }
async onClickDefensePossession(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
await RdDPossessionV2.rollDefensePossession(savedRoll, chatMessage)
}
async onClickMarquerPointPossession(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
RollBasicParts.restore(savedRoll)
await RdDPossessionV2.onMarquerPointPossession(savedRoll)
ChatUtility.remover(chatMessage)()
}
async onClickEncaissement(event) { async onClickEncaissement(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const isMessageDemande = ChatUtility.getMessageData(chatMessage, 'demande-defense') const isMessageDemande = ChatUtility.getMessageData(chatMessage, 'demande-defense')
@@ -254,7 +274,7 @@ export default class ChatRollResult {
break break
} }
if (isMessageDemande) { if (isMessageDemande) {
ChatUtility.removeChatMessageId(chatMessage.id) ChatUtility.remover(chatMessage)()
} else { } else {
savedRoll.done.encaissement = true savedRoll.done.encaissement = true
await this.updateChatMessage(chatMessage, savedRoll) await this.updateChatMessage(chatMessage, savedRoll)
+5 -5
View File
@@ -11,7 +11,7 @@ export class RollBasicParts {
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
rollData.active = RollBasicParts.getTokenActor(rollData) rollData.active = RollBasicParts.getTokenActor(rollData)
rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData) rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData)
if (rollData.type.opposed == undefined) { if (rollData.type && rollData.type.opposed == undefined) {
rollData.type.opposed = rollData.opponent != null rollData.type.opposed = rollData.opponent != null
} }
} }
@@ -46,10 +46,10 @@ export class RollBasicParts {
type: rollData.type, type: rollData.type,
ids: { ids: {
sceneId: rollData.ids.sceneId, sceneId: rollData.ids.sceneId,
actorId: rollData.active.id, actorId: rollData.ids.actorId,
actorTokenId: rollData.active.tokenId, actorTokenId: rollData.ids.actorTokenId,
opponentId: isOpposed ? rollData.opponent.id : undefined, opponentId: isOpposed ? rollData.ids.opponentId : undefined,
opponentTokenId: isOpposed ? rollData.opponent.tokenId : undefined, opponentTokenId: isOpposed ? rollData.ids.opponentTokenId : undefined,
} }
} }
} }
+28 -9
View File
@@ -318,15 +318,33 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData return rollData
} }
static saveParts(rollData, impacts) { static saveParts(rollData, impacts = undefined) {
if (rollData == undefined) {
return undefined
}
function saveBasics(from, to) {
if (from) {
to.passeArme = from.passeArme
to.rolled = from.rolled
to.particuliere = from.particuliere
to.result = from.result
to.done = from.done ?? {}
to.dmg = from.dmg
if (from.attackerRoll) {
to.attackerRoll = {}
saveBasics(from.attackerRoll, to.attackerRoll)
}
}
}
const target = RollBasicParts.initFrom(rollData) const target = RollBasicParts.initFrom(rollData)
ROLL_PARTS.filter(p => p.isActive(rollData)) if (rollData.current) {
.forEach(p => p.storeClean(rollData, target)) // stockage de current
target.attackerRoll = rollData.attackerRoll ROLL_PARTS.filter(p => p.isActive(rollData))
target.rolled = rollData.rolled .forEach(p => p.storeClean(rollData, target))
target.result = rollData.result }
target.done = rollData.done ?? {} saveBasics(rollData, target)
target.dmg = rollData.dmg
if (impacts) { if (impacts) {
target.reverse = { target.reverse = {
active: impacts.active?.reverseImpacts(), active: impacts.active?.reverseImpacts(),
@@ -334,6 +352,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
} }
} }
return target return target
} }
constructor(rollData, rollOptions) { constructor(rollData, rollOptions) {
@@ -352,7 +371,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
} }
this.chatRollResult = new ChatRollResult() this.chatRollResult = new ChatRollResult()
this.selectType() this.selectType()
this.registerHooks(rollData); this.registerHooks(rollData)
} }
registerHooks(rollData) { registerHooks(rollData) {
+2 -2
View File
@@ -16,8 +16,8 @@ export class RollPartDefense extends RollPartSelect {
get code() { return PART_DEFENSE } get code() { return PART_DEFENSE }
get section() { return ROLLDIALOG_SECTION.CHOIX } get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.attackerRoll != undefined } isValid(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) } visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
static getDiffAttaque(attackerRoll) { static getDiffAttaque(attackerRoll) {
// TODO: rollDataV2? // TODO: rollDataV2?
+1 -1
View File
@@ -62,7 +62,7 @@ export class RollPartPossession extends RollPartSelect {
}) })
button?.addEventListener("click", async e => { button?.addEventListener("click", async e => {
e.preventDefault() e.preventDefault()
await RdDPossessionV2.createPossession(rollData.active.actor, rollData.opponent.actor) await RdDPossessionV2.createPossessionIfMissing(rollData.active.actor, rollData.opponent.actor)
rollDialog.render() rollDialog.render()
}) })
} }
+15 -5
View File
@@ -1,8 +1,9 @@
import { RDD_CONFIG } from "../constants.js" import { RDD_CONFIG } from "../constants.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js" import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { demiReveStatusEffect, StatusEffects } from "../settings/status-effects.js" import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs" import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE, ROLL_TYPE_POSSESSION } from "./roll-constants.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs" import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_SIGN = "sign" export const PART_SIGN = "sign"
@@ -25,7 +26,7 @@ export class RollPartSign extends RollPart {
} }
isCombat(rollData) { isCombat(rollData) {
return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE].includes(rollData.type.current) || rollData.type.isCombat return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE, ROLL_TYPE_POSSESSION].includes(rollData.type.current)
} }
prepareContext(rollData) { prepareContext(rollData) {
@@ -40,7 +41,7 @@ export class RollPartSign extends RollPart {
const isCombat = this.isCombat(rollData) const isCombat = this.isCombat(rollData)
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
current.armeDisparate = isCombat && current.armeDisparate current.armeDisparate = isCombat && current.armeDisparate
current.surprise = actor.getSurprise(isCombat, current.forceRequise ?? 0) current.surprise = actor.getSurprise(isCombat, current.forceRequise ?? 0)
current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it, isCombat) > 0, current.forceRequise ?? 0) current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it, isCombat) > 0, current.forceRequise ?? 0)
.map(it => { return { img: it.img, label: game.i18n.localize(it.name) } }) .map(it => { return { img: it.img, label: game.i18n.localize(it.name) } })
current.diviseur = 1 current.diviseur = 1
@@ -67,7 +68,16 @@ export class RollPartSign extends RollPart {
} }
isAttaqueFinesse(rollData) { isAttaqueFinesse(rollData) {
return ROLL_TYPE_DEFENSE == rollData.type.current && rollData.attaque?.particuliere == 'finesse' const attackerRoll = rollData.attackerRoll
if (rollData.attackerRoll){
switch (rollData.type.current) {
case ROLL_TYPE_DEFENSE:
return attackerRoll?.particuliere == RDD_CONFIG.particuliere.finesse.key
case ROLL_TYPE_POSSESSION:
return RdDPossessionV2.isDefense(rollData.type.possession.action) && attackerRoll?.particuliere == RDD_CONFIG.particuliere.finesse.key
}
}
return false
} }
isParadeArmeDisparate(current) { isParadeArmeDisparate(current) {
+1 -1
View File
@@ -7,7 +7,7 @@ export class RollTypePossession extends RollType {
get name() { return "Posséder" } get name() { return "Posséder" }
prepare(rollData) { prepare(rollData) {
rollData.type.possession = RdDPossessionV2.getPossessionDetails(rollData, rollData.type.possession?.action) rollData.type.possession = RdDPossessionV2.getTypePossessionAction(rollData, rollData.type.possession?.action)
} }
title(rollData) { title(rollData) {
@@ -1,39 +0,0 @@
<div class="roll-chat" data-passearme="{{passeArme}}">
<div class="chat-img">
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
</div>
<div class="chat-header">
<h4>Défense de {{active.name}}</h4>
</div>
<div class="chat-resume">
{{log 'chat-resultat-possession' this}}
{{#if type.possession.isEntite}}
{{!-- {{#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}}
{{/if}} --}}
{{/if}}
<p>Points de {{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}: {{type.possession.compteur}}</p>
</div>
<div class="chat-details">
</div>
<div class="chat-actions">
<a class='chat-card-button button-defense-possession'
data-attackerId='{{ids.opponentId}}'
data-attackerTokenId='{{ids.opponentTokenId}}'
data-defenderId='{{ids.actorId}}'
data-defenderTokenId='{{ids.actorTokenId}}'
>
{{#if type.possession.isEntite}}
Résister à la conjuration
{{else}}
Résister à la possession
{{/if}}
</a>
</div>
</div>
+2 -7
View File
@@ -28,13 +28,8 @@
<div class="chat-actions"> <div class="chat-actions">
{{#unless (eq active.surprise.key 'totale')}} {{#unless (eq active.surprise.key 'totale')}}
<a class='chat-card-button button-defense' <a class='chat-card-button button-defense'>
data-attackerId='{{ids.opponentId}}' <img src="systems/foundryvtt-reve-de-dragon/assets/actions/defense.svg"/>
data-attackerTokenId='{{ids.opponentTokenId}}'
data-defenderId='{{ids.actorId}}'
data-defenderTokenId='{{ids.actorTokenId}}'
>
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/defense.svg"/>
Se défendre Se défendre
{{#if (or (eq attackerRoll.attaqueCategorie 'tir') (eq attackerRoll.attaqueCategorie 'lancer'))}} {{#if (or (eq attackerRoll.attaqueCategorie 'tir') (eq attackerRoll.attaqueCategorie 'lancer'))}}
(difficulté à déterminer) (difficulté à déterminer)
@@ -0,0 +1,36 @@
<div class="roll-chat" data-passearme="{{passeArme}}">
<div class="chat-img">
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/possession.svg" data-tooltip="Possession" />
</div>
<div class="chat-header">
<h4>Défense de {{active.name}}</h4>
</div>
<div class="chat-resume">
<p>
{{active.name}} doit se défendre d'une {{#if type.possession.isEntite}}conjuration{{else}}possession{{/if}}
{{#if attackerRoll.particuliere}}<strong>particulière en finesse</strong>{{/if}} de {{opponent.name}}
</p>
<p>
Points de <strong>{{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}</strong>
actuels: {{type.possession.compteur}}
</p>
</div>
<div class="chat-details">
</div>
<div class="chat-actions">
<a class='chat-card-button button-defense-possession'>
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/possession.svg"/>
Résister à la {{#if type.possession.isEntite}}conjuration{{else}}possession{{/if}}
</a>
<a class='chat-card-button marquer-point-possession'>
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/possession.svg"/>
Marquer un point de {{#if type.possession.isEntite}}conjuration{{else}}possession{{/if}}
</a>
</div>
</div>
@@ -0,0 +1,24 @@
<div class="roll-chat" data-passearme="{{passeArme}}">
<div class="chat-img">
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/possession.svg" data-tooltip="Possession" />
</div>
<div class="chat-header">
<h4>Pas de défense de {{active.name}}</h4>
</div>
<div class="chat-resume">
<p>Un point de {{#if type.possession.isEntite}}conjuration{{else}}possession{{/if}} a été ajouté.</p>
<p>
Points de <strong>{{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}</strong>
actuels: {{type.possession.compteur}}
</p>
</div>
<div class="chat-details">
</div>
<div class="chat-actions">
</div>
</div>
+21 -6
View File
@@ -1,4 +1,4 @@
{{log 'roll-chat-possession' this}} {{log 'chat-possession' this}}
<div class="roll-chat"> <div class="roll-chat">
<div class="chat-img"> <div class="chat-img">
<img src="{{active.img}}" data-tooltip="{{active.name}}" /> <img src="{{active.img}}" data-tooltip="{{active.name}}" />
@@ -13,14 +13,29 @@
</div> </div>
<div class="chat-details"> <div class="chat-details">
<p>
{{#if rolled.isSuccess}}
{{#if type.possession.isAttaque}}
La tentative a réussi, l'adversaire peut tenter de contrer.
{{else}}
La tentative de contre a réussi, pas de changements des points de {{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}.
{{/if}}
{{else}}
{{#if type.possession.isAttaque}}
La tentative a échoué, pas de changements des points de {{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}.
{{else}}
La tentative de contre a échoué. Les points de {{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}
sont ajustés.
{{/if}}
{{/if}}
</p>
<p>
Points de <strong>{{#if type.possession.isCompteurPossession}}possession{{else}}conjuration{{/if}}</strong>
actuels: {{type.possession.compteur}}
</p>
</div> </div>
<div class="chat-actions"> <div class="chat-actions">
{{#if roll.type.possession.isAttaque}}
proposer defense
{{else}}
proposer marquer points
{{/if}}
</div> </div>
<div class="chat-buttons"> <div class="chat-buttons">