feat: message d'initiative stylisé avec carte de tarot

Les messages d'initiative affichent désormais :
- Avatar et nom du protagoniste
- Badge avec le score d'initiative (éclair)
- Image de la carte de tarot tirée
- Nom et valeur de la carte
- Pied de page avec la mention 'Initiative'

Correction d'une syntax error (extra }) qui cassait le hook
This commit is contained in:
2026-07-10 21:26:11 +02:00
parent 206abb3947
commit ef9b57d6b9
3 changed files with 67 additions and 1 deletions
+40 -1
View File
@@ -44,6 +44,7 @@ Hooks.once("init", function () {
Combatant.prototype.getInitiativeRoll = function (formula) {
const data = this.actor?.getRollData() ?? {}
const roll = new Roll("1d6", data)
const combatantName = this.name
const origEvaluate = roll.evaluate.bind(roll)
roll.evaluate = async function (options = {}) {
const deckManager = globalThis.HamalronTarotDeckManager?._instance
@@ -55,6 +56,13 @@ Hooks.once("init", function () {
this._total = val
this._evaluated = true
this._formula = `${card.name} (${val})`
this.options.cardDraw = {
name: card.name,
img: card.img,
valeur: card.valeur,
value: val,
}
if (combatantName) globalThis._initiativeCardMap.set(combatantName, this.options.cardDraw)
deckManager.addToDiscard(card)
await deckManager.saveDeckState()
return this
@@ -190,7 +198,38 @@ Hooks.on("getSceneControlButtons", (controls) => {
}
})
Hooks.on("renderChatMessageHTML", (message, html, data) => {
// Store card info from initiative rolls for the chat hook
globalThis._initiativeCardMap = new Map()
Hooks.on("createChatMessage", async (message, options, userId) => {
const speakerName = message.speaker?.alias
if (!speakerName) return
const card = globalThis._initiativeCardMap.get(speakerName)
if (!card) return
globalThis._initiativeCardMap.delete(speakerName)
await new Promise(r => setTimeout(r, 50))
const actor = game.actors.getName(speakerName)
const actorImg = actor?.img || "icons/svg/mystery-man.svg"
const total = message.rolls?.[0]?.total ?? ""
const content = `
<div class="fvtt-hamalron initiative-roll">
<div class="initiative-header">
<div class="initiative-actor">
<img src="${actorImg}" class="initiative-avatar" />
<span class="initiative-name">${speakerName}</span>
</div>
<div class="initiative-badge"><i class="fas fa-bolt"></i> ${total}</div>
</div>
<div class="initiative-card">
<img src="${card.img}" alt="${card.name}" class="initiative-card-img" />
<div class="initiative-card-info">
<span class="card-name">${card.name}</span>
<span class="card-value">${game.i18n.localize("HAMALRON.Initiative.Value")} : ${card.value}</span>
</div>
</div>
<div class="initiative-footer"><i class="fas fa-cards"></i> ${game.i18n.localize("HAMALRON.Initiative.Title")}</div>
</div>`
await message.update({ content })
})
+4
View File
@@ -839,6 +839,10 @@
"Last": "Dernière récup",
"Success": "Récupération réussie ! +1 en {label}",
"Failure": "Échec de la récupération en {label}. Réessayez demain."
},
"Initiative": {
"Title": "Initiative",
"Value": "Valeur"
}
}
}
+23
View File
@@ -0,0 +1,23 @@
<div class="fvtt-hamalron initiative-roll">
<div class="initiative-header">
<div class="initiative-actor">
<img src="{{actorImg}}" class="initiative-avatar" data-tooltip="{{actorName}}" />
<span class="initiative-name">{{actorName}}</span>
</div>
<div class="initiative-badge">
<i class="fas fa-bolt"></i> {{total}}
</div>
</div>
{{#if card}}
<div class="initiative-card">
<img src="{{card.img}}" alt="{{card.name}}" class="initiative-card-img" />
<div class="initiative-card-info">
<span class="card-name">{{card.name}}</span>
<span class="card-value">{{localize "HAMALRON.Initiative.Value"}} : {{cardValue}}</span>
</div>
</div>
{{/if}}
<div class="initiative-footer">
<i class="fas fa-cards"></i> {{localize "HAMALRON.Initiative.Title"}}
</div>
</div>