fix: bouton Épreuve basé sur les cartes de tarot (pas de dés)
Remplace le jet de dés par un vrai dialogue d'épreuve Hamalron : - Sélection d'une carte dans la main du personnage - Choix de la difficulté (table standard) - Calcul réussi/échec basé sur la valeur de la carte - La carte est défaussée et remplacée depuis le deck
This commit is contained in:
@@ -90,6 +90,138 @@ export default class HamalronTirageTarot extends Roll {
|
||||
ui.notifications.info(`Le Mat ! Toutes vos cartes ont été défaussées et vous recevez 7 nouvelles cartes. Le deck a été mélangé.`)
|
||||
}
|
||||
|
||||
// Carte de symbole par défaut pour les épreuves sans compétence
|
||||
static async promptEpreuve(actor) {
|
||||
const tarotCards = actor.items.filter(i => i.type === "tarot")
|
||||
if (tarotCards.length === 0) {
|
||||
ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.noTarotCards"))
|
||||
return
|
||||
}
|
||||
|
||||
const cardData = tarotCards.map(c => ({
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
img: c.img,
|
||||
valeur: c.system.valeur,
|
||||
symbole: c.system.symbole,
|
||||
type: c.system.type,
|
||||
valeurNumerique: HamalronTirageTarot.#vNumerique(c.system.valeur),
|
||||
}))
|
||||
|
||||
const content = `
|
||||
<div class="fvtt-hamalron-roll-dialog">
|
||||
<fieldset>
|
||||
<legend>${game.i18n.localize("HAMALRON.Label.selectTarotCard")}</legend>
|
||||
<div class="tarot-hand">
|
||||
${cardData.map(c => `
|
||||
<div class="tarot-card-select" data-card-id="${c.id}" data-card-value="${c.valeurNumerique}">
|
||||
<img src="${c.img}" alt="${c.name}" />
|
||||
<span class="card-name">${c.name}</span>
|
||||
<span class="card-value-display">${c.valeurNumerique}</span>
|
||||
</div>
|
||||
`).join("")}
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>${game.i18n.localize("HAMALRON.Label.difficulty")}</legend>
|
||||
<div class="difficulty-row">
|
||||
<select class="difficulty-select-epreuve">
|
||||
${Object.entries(SYSTEM.DIFFICULTY_CHOICES).filter(([k]) => k !== "soustension_oppose").map(([k, v]) =>
|
||||
`<option value="${v.standard}">${v.label} (${v.standard})</option>`
|
||||
).join("")}
|
||||
</select>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="dialog-result">
|
||||
<legend>${game.i18n.localize("HAMALRON.Label.total")}</legend>
|
||||
<div class="total-display">
|
||||
<span id="card-value-display">+ 0</span>
|
||||
<span>=</span>
|
||||
<span id="total-value">0</span>
|
||||
</div>
|
||||
<div class="difficulty-info">
|
||||
<span>${game.i18n.localize("HAMALRON.Label.targetScore")}: <span id="target-score">3</span></span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>`
|
||||
|
||||
const result = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: game.i18n.localize("HAMALRON.Label.titleStandard") },
|
||||
classes: ["fvtt-hamalron"],
|
||||
position: { width: 420 },
|
||||
content,
|
||||
buttons: [{ action: "roll", label: game.i18n.localize("HAMALRON.Roll.roll"), default: true, callback: (e, btn) => {
|
||||
const selected = btn.form.querySelector('.tarot-card-select.selected')
|
||||
if (!selected) return null
|
||||
return {
|
||||
cardId: selected.dataset.cardId,
|
||||
cardValue: Number(selected.dataset.cardValue) || 0,
|
||||
difficulty: Number(btn.form.querySelector('.difficulty-select-epreuve')?.value || 3),
|
||||
}
|
||||
}}, { action: "cancel", label: game.i18n.localize("HAMALRON.Roll.cancel") }],
|
||||
rejectClose: false,
|
||||
render: () => {
|
||||
$(document).off(".epreuve")
|
||||
$(document).on("click.epreuve", ".tarot-card-select", function () {
|
||||
$(".tarot-card-select").removeClass("selected")
|
||||
$(this).addClass("selected")
|
||||
const val = Number($(this).data("cardValue")) || 0
|
||||
$("#card-value-display").text(`+ ${val}`)
|
||||
$("#total-value").text(String(val))
|
||||
})
|
||||
$(document).on("change.epreuve", ".difficulty-select-epreuve", function () {
|
||||
$("#target-score").text($(this).val())
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
if (!result) return
|
||||
|
||||
const cardItem = actor.items.get(result.cardId)
|
||||
const isSuccess = result.cardValue >= result.difficulty
|
||||
|
||||
// Card used: move to discard
|
||||
const deckModule = await import("../applications/tarot-deck-manager.mjs")
|
||||
const DM = deckModule.default
|
||||
if (DM._instance) {
|
||||
DM._instance.addToDiscard({
|
||||
id: cardItem.id, name: cardItem.name, img: cardItem.img,
|
||||
symbole: cardItem.system.symbole, valeur: cardItem.system.valeur,
|
||||
type: cardItem.system.type,
|
||||
})
|
||||
await DM._instance.saveDeckState()
|
||||
}
|
||||
if (cardItem) await actor.deleteEmbeddedDocuments("Item", [cardItem.id])
|
||||
|
||||
// Draw replacement
|
||||
if (DM._instance?.deck?.length > 0) {
|
||||
const drawn = DM._instance.drawCards(1)
|
||||
if (drawn.length > 0) {
|
||||
const orig = await HamalronUtils.findTarotItem(drawn[0])
|
||||
if (orig) await actor.createEmbeddedDocuments("Item", [orig.toObject()])
|
||||
}
|
||||
await DM._instance.saveDeckState()
|
||||
}
|
||||
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
speaker: ChatMessage.getSpeaker({ actor }),
|
||||
content: `<div class="fvtt-hamalron epreuve-result">
|
||||
<h3>${game.i18n.localize("HAMALRON.Label.titleStandard")}</h3>
|
||||
<p><strong>${cardItem?.name}</strong>: ${result.cardValue}</p>
|
||||
<p>${game.i18n.localize("HAMALRON.Label.difficulty")}: ${result.difficulty}</p>
|
||||
<p class="${isSuccess ? "result-success" : "result-failure"}">
|
||||
${isSuccess ? game.i18n.localize("HAMALRON.Label.success") : game.i18n.localize("HAMALRON.Label.failure")}
|
||||
</p>
|
||||
</div>`,
|
||||
style: CONST.CHAT_MESSAGE_STYLES.OTHER,
|
||||
})
|
||||
}
|
||||
|
||||
static #vNumerique(valeur) {
|
||||
return SYSTEM.TAROT_VALEURS[valeur]?.value ?? (Number.parseInt(valeur) || 0)
|
||||
}
|
||||
|
||||
static async prompt(options = {}) {
|
||||
let formula = `3D6 + 0D6KH - 0D6KH + ${options?.rollItem?.value}`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user