fix: retours review - validation de phase, drop de véhicule et dés de Réserve

- resetPhaseLimits ne touche plus au compteur de phase (seul le
  dialogue d'attribution du MJ l'avance) : évite le double-incrément
  quand joueur et MJ valident la même phase.
- _onDropActor : import d'une copie monde pour un véhicule déposé
  depuis un compendium, confirmation avant de transférer un véhicule
  déjà rattaché à un autre Groupe, try/catch avec retour utilisateur.
- #onClickRadioHexa : garde isEditable (pas d'erreur de permission
  pour un utilisateur non éditeur).
This commit is contained in:
2026-08-05 21:24:33 +02:00
parent 282fb2794a
commit c96e8d69d7
6 changed files with 56 additions and 14 deletions
@@ -311,6 +311,11 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
static #onClickRadioHexa(event, target) {
event.preventDefault()
event.stopPropagation()
// Évite une erreur de permission pour un utilisateur non éditeur.
if (!this.isEditable) {
ui.notifications.warn(game.i18n.localize("VERMINE.error_not_editable"))
return
}
const input = target
const update = {}
let current = this.document
@@ -130,7 +130,7 @@ export default class VermineCharacterSheetV2 extends VermineBaseActorSheet {
/** Valide la phase d'Expérience courante et réinitialise les limites. */
static async #onValidatePhase() {
const { VermineExperience } = await import("../../system/experience.mjs")
await VermineExperience.completePhase(this.document)
await VermineExperience.resetPhaseLimits(this.document)
ui.notifications.info(game.i18n.localize("VERMINE.validate_phase_done"))
}
}
+34 -5
View File
@@ -113,16 +113,45 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
/**
* Dépôt d'un acteur Véhicule sur la fiche : lie le véhicule au Groupe
* (system.ownerId) au lieu de le dupliquer, puis affiche la liste.
* Gère les dépôts depuis un compendium (copie importée dans le monde)
* et demande confirmation si le véhicule appartient déjà à un autre Groupe.
* @override
*/
async _onDropActor(event, data) {
const actor = data instanceof foundry.abstract.Document ? data : await fromUuid(data.uuid)
if (actor?.type === "vehicle") {
let actor = data instanceof foundry.abstract.Document ? data : await fromUuid(data.uuid)
if (actor?.type !== "vehicle") {
return super._onDropActor?.(event, data)
}
// Véhicule issu d'un compendium : importer une copie dans le monde.
if (actor.compendium) {
try {
const copy = await game.actors.importFromCompendium(actor.compendium, actor._id, { renderSheet: false })
if (!copy) return
actor = copy
} catch {
ui.notifications.warn(game.i18n.localize("VERMINE.vehicle_import_failed"))
return
}
}
// Véhicule déjà rattaché à un autre Groupe : confirmation avant transfert.
const currentOwner = actor.system?.ownerId
if (currentOwner && currentOwner !== this.document.id) {
const other = game.actors.get(currentOwner)
const content = game.i18n.localize("VERMINE.vehicle_assign_confirm").replace("{group}", other?.name ?? currentOwner)
const confirmed = await Dialog.confirm({
title: game.i18n.localize("VERMINE.vehicle_assign"),
content,
defaultYes: false
})
if (!confirmed) return
}
try {
await actor.update({ "system.ownerId": this.document.id })
this.render()
} catch {
ui.notifications.warn(game.i18n.localize("VERMINE.vehicle_assign_failed"))
return
}
return super._onDropActor?.(event, data)
this.render()
}
// Actions : délégation aux applications AppV1 existantes pour TotemPicker/ActorPicker
@@ -192,7 +221,7 @@ export default class VermineGroupSheetV2 extends VermineBaseActorSheet {
/** Valide la phase d'Expérience courante du Groupe et réinitialise les limites. */
static async #onValidatePhase() {
const { VermineExperience } = await import("../../system/experience.mjs")
await VermineExperience.completePhase(this.document)
await VermineExperience.resetPhaseLimits(this.document)
ui.notifications.info(game.i18n.localize("VERMINE.validate_phase_done"))
}
}
+6 -8
View File
@@ -215,24 +215,22 @@ export class VermineExperience {
}
/**
* Valide la phase d'Expérience courante : passe à la phase suivante et
* réinitialise toutes les limites d'apprentissage (learned.*), pour un
* personnage ou un Groupe.
* Réinitialise les limites d'apprentissage (learned.*) de la phase
* courante, pour un personnage ou un Groupe, sans toucher au compteur
* de phase (avancé uniquement par le dialogue d'attribution du MJ).
* @param {foundry.abstract.Document} actor personnage ou Groupe
* @returns {Promise<void>}
*/
static async completePhase(actor) {
static async resetPhaseLimits(actor) {
const ex = actor.system?.experience
if (!ex) return
const phase = (ex.phase || 0) + 1
const update = { "system.experience.phase": phase }
const update = {}
if (ex.learned && typeof ex.learned === "object") {
update["system.experience.learned.phase"] = phase
for (const key of Object.keys(ex.learned)) {
if (key === "phase") continue
update[`system.experience.learned.${key}`] = false
}
}
await actor.update(update)
if (Object.keys(update).length) await actor.update(update)
}
}