diff --git a/fvtt-hamalron.mjs b/fvtt-hamalron.mjs index 3ea1b3e..f087d53 100644 --- a/fvtt-hamalron.mjs +++ b/fvtt-hamalron.mjs @@ -243,15 +243,42 @@ Hooks.on("createChatMessage", async (message, options, userId) => { }) -/** - * Create a macro when dropping an entity on the hotbar - * Item - open roll dialog - * Actor - open actor sheet - * Journal - open journal sheet - */ Hooks.on("hotbarDrop", (bar, data, slot) => { - if (["Actor", "Item", "JournalEntry", "skill", "weapon"].includes(data.type)) { - // TODO -> Manage this + if (data.type === "Actor") { + const actor = fromUuidSync(data.uuid) + if (!actor) return false + Macro.create({ + name: actor.name, + type: "script", + img: actor.img, + command: `game.actors.get("${actor.id}")?.sheet?.render(true)`, + scope: "global", + }).then(macro => bar.assignMacro(macro, slot)) + return false + } + if (data.type === "Item") { + const item = fromUuidSync(data.uuid) + if (!item) return false + const actor = item.parent + let command = "" + if (item.type === "competence") { + command = `const a = game.actors.get("${actor?.id}"); const i = a?.items?.get("${item.id}"); if (i) a?.system?.roll?.("competence", i)` + } else if (item.type === "sortilege") { + command = `const { default: Cast } = await import("${game.system.id}/module/applications/sortilege-casting.mjs"); const a = game.actors.get("${actor?.id}"); const i = a?.items?.get("${item.id}"); if (i) Cast.prompt(i, a)` + } else if (item.type === "arme") { + command = `const a = game.actors.get("${actor?.id}"); const i = a?.items?.get("${item.id}"); if (i) a?.system?.roll?.("weapon", i)` + } else { + command = `const a = game.actors.get("${actor?.id}"); a?.items?.get("${item.id}")?.sheet?.render(true)` + } + if (command) { + Macro.create({ + name: item.name, + type: "script", + img: item.img, + command, + scope: "actor", + }).then(macro => bar.assignMacro(macro, slot)) + } return false } }) diff --git a/lang/fr.json b/lang/fr.json index 2bef2a0..91b64cd 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -640,7 +640,8 @@ "cancel": "Annuler", "roll": "Lancer l'épreuve", "rollCompetence": "Jet de compétence", - "skill": "Compétence" + "skill": "Compétence", + "drawCard": "Tirer une carte" }, "Tarot": { "FIELDS": { @@ -843,6 +844,16 @@ "Initiative": { "Title": "Initiative", "Value": "Valeur" - } + }, + "Wound": { + "Title": "Blessure incapacitante", + "Question": "Vous allez perdre 1 point de Résistance Épée. Voulez-vous plutôt subir une blessure incapacitante (membre cassé, -2 aux actions physiques) ?", + "Take": "Subir la blessure", + "Resist": "Perdre le point", + "Active": "Blessure incapacitante active", + "Remove": "Guérir la blessure", + "RemoveConfirm": "La blessure est-elle guérie ? Cela restaurera vos capacités physiques.", + "Healed": "Blessure guérie !" + }, } } \ No newline at end of file diff --git a/module/applications/sheets/personnage-sheet.mjs b/module/applications/sheets/personnage-sheet.mjs index ec9e035..c8418b2 100644 --- a/module/applications/sheets/personnage-sheet.mjs +++ b/module/applications/sheets/personnage-sheet.mjs @@ -20,6 +20,7 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet { createSortilege: HamalronPersonnageSheet.#onCreateSortilege, openRecovery: HamalronPersonnageSheet.#onOpenRecovery, modifyResistance: HamalronPersonnageSheet.#onModifyResistance, + removeWound: HamalronPersonnageSheet.#onRemoveWound, discardCard: HamalronPersonnageSheet.#onDiscardCard, rollCompetence: HamalronPersonnageSheet.#onRollCompetence, castSortilege: HamalronPersonnageSheet.#onCastSortilege, @@ -195,9 +196,46 @@ export default class HamalronPersonnageSheet extends HamalronActorSheet { } const newValue = Math.max(0, Math.min(resistance.max, resistance.value + delta)) + + // Blessure incapacitante pour Épée (règle p.159) + if (symbole === "epee" && delta < 0 && newValue < resistance.value && !this.document.system.blessureIncapacitante) { + const choice = await foundry.applications.api.DialogV2.wait({ + window: { title: game.i18n.localize("HAMALRON.Wound.Title") }, + content: `

${game.i18n.localize("HAMALRON.Wound.Question")}

`, + buttons: [ + { action: "wound", label: game.i18n.localize("HAMALRON.Wound.Take"), default: true, callback: () => "wound" }, + { action: "resist", label: game.i18n.localize("HAMALRON.Wound.Resist"), callback: () => "resist" }, + ], + rejectClose: false, + }) + if (choice === "wound") { + await this.document.update({ + "system.blessureIncapacitante": true, + "system.malusBlessure": -2, + }) + ui.notifications.info(game.i18n.localize("HAMALRON.Wound.Active")) + return + } + } + await this.document.update({ [`system.resistances.${symbole}.value`]: newValue }) } + static async #onRemoveWound(event, target) { + const confirmed = await foundry.applications.api.DialogV2.confirm({ + window: { title: game.i18n.localize("HAMALRON.Wound.Remove") }, + content: `

${game.i18n.localize("HAMALRON.Wound.RemoveConfirm")}

`, + rejectClose: false, + modal: true, + }) + if (!confirmed) return + await this.document.update({ + "system.blessureIncapacitante": false, + "system.malusBlessure": 0, + }) + ui.notifications.info(game.i18n.localize("HAMALRON.Wound.Healed")) + } + static async #onDiscardCard(event, target) { const itemId = $(event.target).data("item-id") const item = this.document.items.get(itemId) diff --git a/module/documents/tirage-tarot.mjs b/module/documents/tirage-tarot.mjs index b9e7d83..8df7fca 100644 --- a/module/documents/tirage-tarot.mjs +++ b/module/documents/tirage-tarot.mjs @@ -104,6 +104,9 @@ export default class HamalronTirageTarot extends Roll { // Récupérer le modificateur de compétence depuis NIVEAU_COMPETENCES const niveauData = SYSTEM.NIVEAU_COMPETENCES[options.rollItem.system.niveau] options.competenceModifier = niveauData ? niveauData.modificateur : 0 + if (actor.system.malusBlessure) { + options.competenceModifier += actor.system.malusBlessure + } // Marquer les cartes de succès if (options.tarotCards && actor.system.cartesSucces) { @@ -266,7 +269,6 @@ export default class HamalronTirageTarot extends Roll { const difficultyData = SYSTEM.DIFFICULTY_CHOICES[difficultyKey] if (difficultyData.standard === null) { - // Sous tension ou opposé - pas de score cible options.targetScore = null $("#target-score").text("-") } else { @@ -275,6 +277,29 @@ export default class HamalronTirageTarot extends Roll { } }) + // Tirage d'une carte pour la difficulté (épreuve sous tension) + $("#draw-difficulty-btn").click(async function () { + const deckManager = globalThis.HamalronTarotDeckManager?._instance + if (!deckManager || deckManager.deck.length === 0) { + ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.deckEmpty")) + return + } + const drawn = deckManager.drawCards(1) + if (drawn.length > 0) { + const card = drawn[0] + const valData = SYSTEM.TAROT_VALEURS[card.valeur] + const val = valData?.value ?? 0 + options.targetScore = val + options.selectedDifficulty = "soustension_oppose" + $(".difficulty-select").val("soustension_oppose") + $("#target-score").text(String(val)) + $("#drawn-card-name").text(`${card.name} (${val})`) + $("#drawn-card-info").show() + deckManager.addToDiscard(card) + await deckManager.saveDeckState() + } + }) + $(".tarot-card-select").click(function () { // Désélectionner toutes les cartes $(".tarot-card-select").removeClass("selected") diff --git a/module/models/personnage.mjs b/module/models/personnage.mjs index f9d9db1..f7905ca 100644 --- a/module/models/personnage.mjs +++ b/module/models/personnage.mjs @@ -34,8 +34,10 @@ export default class HamalronPersonnage extends foundry.abstract.TypeDataModel { schema.historial = new fields.HTMLField({ required: true, textSearch: true }) schema.progression = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) - schema.rangMagie = new fields.StringField({ required: true, initial: "initie", choices: Object.fromEntries(Object.entries(SYSTEM.RANG_MAGICIEN).map(([key, val]) => [key, val.label])) }) + schema.rangMagie = new fields.StringField({ required: true, initial: "initie", choices: Object.fromEntries(Object.entries(SYSTEM.RANG_MAGICIEN).map(([key, val]) => [key, val.name])) }) schema.resistanceRecovery = new fields.ObjectField({ required: false, initial: {} }) + schema.blessureIncapacitante = new fields.BooleanField({ required: true, initial: false }) + schema.malusBlessure = new fields.NumberField({ required: true, integer: true, initial: 0, min: -8, max: 0 }) schema.biodata = new fields.SchemaField({ age: new fields.StringField({ required: true, nullable: false, initial: "" }), diff --git a/templates/personnage-main.hbs b/templates/personnage-main.hbs index ea62c4f..8907bc5 100644 --- a/templates/personnage-main.hbs +++ b/templates/personnage-main.hbs @@ -191,6 +191,16 @@ {{/each}} + + {{#if (and system.blessureIncapacitante isPlayMode)}} +
+ + {{localize "HAMALRON.Wound.Active"}} ({{system.malusBlessure}}) + + + +
+ {{/if}} diff --git a/templates/roll-dialog.hbs b/templates/roll-dialog.hbs index 017d657..4f3e34d 100644 --- a/templates/roll-dialog.hbs +++ b/templates/roll-dialog.hbs @@ -63,13 +63,21 @@
{{localize "HAMALRON.Label.difficulty"}} - +
+ + +
+