Fix: protection sur actions sans acteur/propriété

Cas rencontré une fois, un jet de chance d'un autre
joueur, pouvait être tenté.

Cas plus étrange, un jet de chance alors que le jet sauvegardé
n'avait pas d'actorId
This commit is contained in:
2025-12-09 23:35:27 +01:00
parent 894161c0bf
commit 697247e931
4 changed files with 65 additions and 44 deletions

View File

@@ -9,7 +9,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js"; import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { MAINS_DIRECTRICES } from "./actor.js"; import { MAINS_DIRECTRICES } from "./actor.js";
import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js"; import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js";
import { ITEM_TYPES } from "./constants.js"; import { ACTOR_TYPES, ITEM_TYPES } from "./constants.js";
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemBlessure } from "./item/blessure.js"; import { RdDItemBlessure } from "./item/blessure.js";
@@ -58,7 +58,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.timerRecherche = undefined; this.timerRecherche = undefined;
if (formData.type == 'personnage') { if (formData.type == ACTOR_TYPES.personnage) {
formData.options.mainsDirectrices = MAINS_DIRECTRICES; formData.options.mainsDirectrices = MAINS_DIRECTRICES;
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie) formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences); formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);

View File

@@ -233,16 +233,16 @@ export class Misc {
if (Misc.isOwnerPlayer(document)) { if (Misc.isOwnerPlayer(document)) {
return await action(document) return await action(document)
} else { } else {
return await orElse(document) return await orElse(document ?? {name: '<aucune sélection>'})
} }
} }
static isOwnerPlayer(document) { static isOwnerPlayer(document) {
return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) return document && document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
} }
static isFirstOwnerPlayer(document) { static isFirstOwnerPlayer(document) {
if (!document.testUserPermission) { if (!document?.testUserPermission) {
return false return false
} }
return game.users.find(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user return game.users.find(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user

View File

@@ -1084,7 +1084,7 @@ export class RdDCombat {
} }
async defenseV2(attackerRoll, callbacks = []) { async defenseV2(attackerRoll, callbacks = []) {
// this._prepareParade(attackerRoll, arme, competence);
await this.doRollDefense({ await this.doRollDefense({
ids: { ids: {
actorId: this.defender.id, actorId: this.defender.id,

View File

@@ -162,12 +162,18 @@ export default class ChatRollResult {
return undefined return undefined
} }
getActiveActor(roll) {
return roll.active?.actor ?? (roll.ids?.actorId ? game.actors.get(roll.ids.actorId) : undefined)
}
async saveChatMessageRoll(chatMessage, savedRoll) { async saveChatMessageRoll(chatMessage, savedRoll) {
await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll) await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
} }
loadChatMessageRoll(chatMessage) { loadChatMessageRoll(chatMessage) {
return ChatUtility.getMessageData(chatMessage, 'rollData') const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
RollBasicParts.restore(savedRoll)
return savedRoll
} }
async updateChatMessage(chatMessage, savedRoll) { async updateChatMessage(chatMessage, savedRoll) {
@@ -184,7 +190,7 @@ export default class ChatRollResult {
event.preventDefault() event.preventDefault()
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId) const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.rollAppelChance( Misc.doIfOwner(actor, it => it.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage), () => this.onAppelChanceSuccess(savedRoll, chatMessage),
() => this.onAppelChanceEchec(savedRoll, chatMessage)) () => this.onAppelChanceEchec(savedRoll, chatMessage))
@@ -193,7 +199,6 @@ export default class ChatRollResult {
async onAppelChanceSuccess(savedRoll, chatMessage) { async onAppelChanceSuccess(savedRoll, chatMessage) {
const reRoll = foundry.utils.duplicate(savedRoll) const reRoll = foundry.utils.duplicate(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 = [ChatUtility.remover(chatMessage)] const callbacks = [ChatUtility.remover(chatMessage)]
@@ -222,7 +227,7 @@ export default class ChatRollResult {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId) const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.appelDestinee(async () => { Misc.doIfOwner(actor, it => it.appelDestinee(async () => {
const reRoll = foundry.utils.duplicate(savedRoll) const reRoll = foundry.utils.duplicate(savedRoll)
@@ -235,36 +240,41 @@ 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 actor = this.getActiveActor(savedRoll)
const attackerRoll = savedRoll.attackerRoll Misc.doIfOwner(actor, it => {
RollDialog.loadRollData(attackerRoll) const attackerRoll = savedRoll.attackerRoll
this.getCombat(attackerRoll)?.defenseV2(attackerRoll, RollDialog.loadRollData(attackerRoll)
[ChatUtility.remover(chatMessage)] this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
) [ChatUtility.remover(chatMessage)]
)
})
} }
async onClickDefensePossession(event) { async onClickDefensePossession(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
await RdDPossessionV2.rollDefensePossession(savedRoll, chatMessage) const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => RdDPossessionV2.rollDefensePossession(savedRoll, chatMessage))
} }
async onClickMarquerPointPossession(event) { async onClickMarquerPointPossession(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 actor = this.getActiveActor(savedRoll)
await RdDPossessionV2.onMarquerPointPossession(savedRoll) Misc.doIfOwner(actor, async it => {
ChatUtility.remover(chatMessage)() 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')
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
const attaque = savedRoll.attackerRoll const actor = this.getActiveActor(savedRoll)
const defenderToken = savedRoll.ids.actorTokenId ? canvas.tokens.get(savedRoll.ids.actorTokenId) : undefined Misc.doIfOwner(actor, async defender => {
const defender = defenderToken?.actor ?? game.actors.get(savedRoll.ids.actorId) const defenderToken = savedRoll.active.token
Misc.doIfOwner(defender, async defender => { const attaque = savedRoll.attackerRoll
const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
const attacker = attackerToken?.actor ?? game.actors.get(savedRoll.ids.opponentId) const attacker = attackerToken?.actor ?? game.actors.get(savedRoll.ids.opponentId)
switch (attaque.dmg.mortalite) { switch (attaque.dmg.mortalite) {
@@ -290,9 +300,8 @@ export default class ChatRollResult {
async onClickRecul(event) { async onClickRecul(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
// TODO: gestion sur token non liés? const actor = this.getActiveActor(savedRoll)
const defender = game.actors.get(savedRoll.ids.actorId) Misc.doIfOwner(actor, async defender => {
Misc.doIfOwner(defender, async defender => {
const attacker = game.actors.get(savedRoll.ids.opponentId) const attacker = game.actors.get(savedRoll.ids.opponentId)
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme) savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
await this.updateChatMessage(chatMessage, savedRoll) await this.updateChatMessage(chatMessage, savedRoll)
@@ -303,42 +312,54 @@ export default class ChatRollResult {
const choix = event.currentTarget.attributes['data-particuliere'].value const choix = event.currentTarget.attributes['data-particuliere'].value
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
savedRoll.particuliere = choix const actor = this.getActiveActor(savedRoll)
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]] Misc.doIfOwner(actor, async it => {
await this.updateChatMessage(chatMessage, savedRoll) savedRoll.particuliere = choix
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll) savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
await this.updateChatMessage(chatMessage, savedRoll)
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll)
})
} }
async onClickFaireGouter(event) { async onClickFaireGouter(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
if (!savedRoll.type.retry) { const actor = this.getActiveActor(savedRoll)
savedRoll.type.retry = true Misc.doIfOwner(actor, async it => {
await this.updateChatMessage(chatMessage, savedRoll) if (!savedRoll.type.retry) {
} savedRoll.type.retry = true
await new RollTypeCuisine().onFaireGouter(savedRoll) await this.updateChatMessage(chatMessage, savedRoll)
}
await new RollTypeCuisine().onFaireGouter(savedRoll)
})
} }
async onClickApprecier(event) { async onClickApprecier(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
await Apprecier.onClickApprecier(savedRoll) Apprecier.onClickApprecier(savedRoll)
} }
async onClickMonteeTMR(event, mode) { async onClickMonteeTMR(event, mode) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) { const actor = this.getActiveActor(savedRoll)
savedRoll.done.meditation = true Misc.doIfOwner(actor, async it => {
await this.updateChatMessage(chatMessage, savedRoll) if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) {
} savedRoll.done.meditation = true
await this.updateChatMessage(chatMessage, savedRoll)
}
})
} }
async onClickTirerMaladresse(event) { async onClickTirerMaladresse(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const typeMaladresse = event.currentTarget.attributes['data-maladresse'].value const typeMaladresse = event.currentTarget.attributes['data-maladresse'].value
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
savedRoll.maladresse = await RdDRollTables.getMaladresse({ arme: typeMaladresse == 'avec-arme', toChat: false }) const actor = this.getActiveActor(savedRoll)
savedRoll.type.retry = true Misc.doIfOwner(actor, async it => {
await this.updateChatMessage(chatMessage, savedRoll) savedRoll.maladresse = await RdDRollTables.getMaladresse({ arme: typeMaladresse == 'avec-arme', toChat: false })
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
})
} }
} }