Potions et élémentaires
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import { MournbladeUtility } from "../mournblade-utility.js"
|
||||
|
||||
export default class MournbladeInvocationDialog {
|
||||
|
||||
static async create(actor, rollData) {
|
||||
const ameDisponible = Math.max(0, (actor.system.ame.currentmax - actor.system.ame.value))
|
||||
const maxExtra = Math.max(0, ameDisponible - 15)
|
||||
|
||||
// Detect elemental pacte bonus — the bonus is always available,
|
||||
// but we display it dynamically based on chosen element.
|
||||
// We pass the pactes to let JS listeners detect the match.
|
||||
const pactes = actor.getPactes().map(p => ({
|
||||
name: p.name,
|
||||
allegeance: (p.system.allegeance || "").toLowerCase()
|
||||
}))
|
||||
|
||||
const hautParlerComp = actor.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : haut-parler")
|
||||
const seigneursElemComp = actor.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : seigneurs élémentaires")
|
||||
|
||||
const context = {
|
||||
...rollData,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
ameDisponible,
|
||||
ameExtraOptions: Array.from({ length: maxExtra + 1 }, (_, i) => i),
|
||||
modOptions: Array.from({ length: 21 }, (_, i) => i - 10),
|
||||
hautParlerNiveau: hautParlerComp ? hautParlerComp.system.niveau : null,
|
||||
seigneursElemNiveau: seigneursElemComp ? seigneursElemComp.system.niveau : null,
|
||||
bonusPacte: false,
|
||||
pactes,
|
||||
}
|
||||
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/fvtt-mournblade/templates/dialog-invocation-elementaire.hbs",
|
||||
context
|
||||
)
|
||||
|
||||
Hooks.once("renderDialogV2", (_app, html) => {
|
||||
const form = html.querySelector ? html : html[0]
|
||||
MournbladeInvocationDialog._attachListeners(form, pactes)
|
||||
})
|
||||
|
||||
return foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Invoquer un Élémentaire", icon: "fa-solid fa-wind" },
|
||||
classes: ["mournblade-roll-dialog"],
|
||||
position: { width: 480 },
|
||||
modal: false,
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
action: "invoquer",
|
||||
label: "Invoquer",
|
||||
icon: "fa-solid fa-wind",
|
||||
default: true,
|
||||
callback: (event, button, dialog) => {
|
||||
MournbladeInvocationDialog._updateRollData(rollData, button.form.elements, actor, pactes)
|
||||
MournbladeUtility.rollInvocationElementaire(rollData)
|
||||
}
|
||||
},
|
||||
],
|
||||
rejectClose: false,
|
||||
})
|
||||
}
|
||||
|
||||
static _elementKeywords = {
|
||||
air: ["air", "vent", "sylphe", "seigneur de l'air"],
|
||||
terre: ["terre", "gnome", "seigneur de la terre"],
|
||||
feu: ["feu", "flamme", "salamandre", "seigneur du feu"],
|
||||
eau: ["eau", "ondine", "seigneur de l'eau"],
|
||||
}
|
||||
|
||||
static _hasPacteBonus(element, pactes) {
|
||||
const keywords = MournbladeInvocationDialog._elementKeywords[element] || []
|
||||
return pactes.some(p => keywords.some(kw => p.allegeance.includes(kw)))
|
||||
}
|
||||
|
||||
static _attachListeners(html, pactes) {
|
||||
const tierSeuils = { mineur: 15, median: 20, majeur: 25 }
|
||||
const tierTemps = { mineur: "1 tour", median: "1 minute", majeur: "1 heure" }
|
||||
|
||||
const recalculate = () => {
|
||||
const element = html.querySelector('[name="element"]')?.value ?? "air"
|
||||
const tier = html.querySelector('[name="tier"]')?.value ?? "mineur"
|
||||
const ameExtra = parseInt(html.querySelector('[name="ameExtra"]')?.value ?? 0)
|
||||
|
||||
const seuilBase = tierSeuils[tier] ?? 15
|
||||
const seuil = seuilBase + ameExtra
|
||||
const hasPacte = MournbladeInvocationDialog._hasPacteBonus(element, pactes)
|
||||
|
||||
const seuilEl = html.querySelector('#invoc-seuil')
|
||||
const coutEl = html.querySelector('#invoc-cout')
|
||||
const tempsEl = html.querySelector('#invoc-temps')
|
||||
const pacteBanner = html.querySelector('.invoc-bonus-pacte')
|
||||
|
||||
if (seuilEl) seuilEl.textContent = seuil + (hasPacte ? " (-5 avec bonus Pacte)" : "")
|
||||
if (coutEl) coutEl.textContent = seuil
|
||||
if (tempsEl) tempsEl.textContent = tierTemps[tier] ?? "1 tour"
|
||||
if (pacteBanner) pacteBanner.style.display = hasPacte ? "" : "none"
|
||||
}
|
||||
|
||||
html.querySelectorAll('[name="element"], [name="tier"], [name="ameExtra"]').forEach(el => {
|
||||
el.addEventListener('change', recalculate)
|
||||
})
|
||||
recalculate()
|
||||
}
|
||||
|
||||
static _updateRollData(rollData, formElements, actor, pactes) {
|
||||
const element = formElements['element']?.value ?? "air"
|
||||
const tier = formElements['tier']?.value ?? "mineur"
|
||||
const ameExtra = parseInt(formElements['ameExtra']?.value ?? 0)
|
||||
const modificateur = parseInt(formElements['modificateur']?.value ?? 0)
|
||||
|
||||
const tierSeuils = { mineur: 15, median: 20, majeur: 25 }
|
||||
const seuilBase = tierSeuils[tier] ?? 15
|
||||
const seuil = seuilBase + ameExtra
|
||||
|
||||
rollData.invocationElement = element
|
||||
rollData.invocationTier = tier
|
||||
rollData.invocationSeuil = seuil
|
||||
rollData.invocationAmeExtra = ameExtra
|
||||
rollData.invocationSoulCost = seuil
|
||||
rollData.difficulte = seuil
|
||||
rollData.modificateur = modificateur
|
||||
rollData.bonusPacte = MournbladeInvocationDialog._hasPacteBonus(element, pactes) ? 5 : 0
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,248 @@ export class MournbladeRollDialog {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mettre à jour rollData avec les valeurs du formulaire
|
||||
* Create and display the sortilège (multi-rune spell) roll dialog
|
||||
* @param {MournbladeActor} actor
|
||||
* @param {Object} rollData
|
||||
*/
|
||||
static async createSortilege(actor, rollData) {
|
||||
const ameDisponible = Math.max(1, (actor.system.ame.currentmax - actor.system.ame.value))
|
||||
const context = {
|
||||
...rollData,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
config: game.system.mournblade.config,
|
||||
runes: actor.getRunes(),
|
||||
runemode: "prononcer",
|
||||
ameDisponible,
|
||||
ameOptions: Array.from({ length: ameDisponible }, (_, i) => i + 1),
|
||||
modOptions: Array.from({ length: 21 }, (_, i) => i - 10),
|
||||
}
|
||||
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/fvtt-mournblade/templates/dialog-sortilege.hbs",
|
||||
context
|
||||
)
|
||||
|
||||
// Attach dynamic recalculation after render
|
||||
Hooks.once("renderDialogV2", (_app, html) => {
|
||||
const form = html.querySelector ? html : html[0]
|
||||
MournbladeRollDialog._attachSortilegeListeners(form)
|
||||
})
|
||||
|
||||
return foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Lancer un Sortilège", icon: "fa-solid fa-star-of-david" },
|
||||
classes: ["mournblade-roll-dialog"],
|
||||
position: { width: 520 },
|
||||
modal: false,
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
action: "rolld10",
|
||||
label: "Lancer 1d10",
|
||||
icon: "fa-solid fa-dice-d10",
|
||||
default: true,
|
||||
callback: (event, button, dialog) => {
|
||||
this._updateSortilegeRollData(rollData, button.form.elements, actor)
|
||||
rollData.mainDice = "1d10"
|
||||
MournbladeUtility.rollSortilege(rollData)
|
||||
}
|
||||
},
|
||||
{
|
||||
action: "rolld20",
|
||||
label: "Lancer 1d20",
|
||||
icon: "fa-solid fa-dice-d20",
|
||||
callback: (event, button, dialog) => {
|
||||
this._updateSortilegeRollData(rollData, button.form.elements, actor)
|
||||
rollData.mainDice = "1d20"
|
||||
MournbladeUtility.rollSortilege(rollData)
|
||||
}
|
||||
},
|
||||
],
|
||||
rejectClose: false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the potion preparation dialog
|
||||
* @param {MournbladeActor} actor
|
||||
* @param {object} rollData
|
||||
*/
|
||||
static async createPotion(actor, rollData) {
|
||||
const ameDisponible = Math.max(1, (actor.system.ame.currentmax - actor.system.ame.value))
|
||||
const context = {
|
||||
...rollData,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
config: game.system.mournblade.config,
|
||||
runes: actor.getRunes(),
|
||||
ameDisponible,
|
||||
ameOptions: Array.from({ length: ameDisponible }, (_, i) => i + 1),
|
||||
modOptions: Array.from({ length: 21 }, (_, i) => i - 10),
|
||||
}
|
||||
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/fvtt-mournblade/templates/dialog-potion.hbs",
|
||||
context
|
||||
)
|
||||
|
||||
Hooks.once("renderDialogV2", (_app, html) => {
|
||||
const form = html.querySelector ? html : html[0]
|
||||
MournbladeRollDialog._attachPotionListeners(form)
|
||||
})
|
||||
|
||||
return foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Préparer une Potion", icon: "fa-solid fa-flask" },
|
||||
classes: ["mournblade-roll-dialog"],
|
||||
position: { width: 520 },
|
||||
modal: false,
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
action: "preparer",
|
||||
label: "Préparer",
|
||||
icon: "fa-solid fa-flask",
|
||||
default: true,
|
||||
callback: (event, button, dialog) => {
|
||||
MournbladeRollDialog._updatePotionRollData(rollData, button.form.elements, actor)
|
||||
MournbladeUtility.rollPotion(rollData)
|
||||
}
|
||||
},
|
||||
],
|
||||
rejectClose: false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach dynamic recalculation listeners to the potion dialog
|
||||
* @param {HTMLElement} html
|
||||
*/
|
||||
static _attachPotionListeners(html) {
|
||||
const recalculate = () => {
|
||||
const radioChecked = html.querySelector('.potion-rune-radio:checked')
|
||||
const runeRow = radioChecked?.closest('[data-seuil]')
|
||||
const seuil = parseInt(runeRow?.dataset.seuil ?? 0)
|
||||
const pa = parseInt(html.querySelector('[name="pointsAme"]')?.value ?? 1)
|
||||
const mod = parseInt(html.querySelector('[name="modificateur"]')?.value ?? 0)
|
||||
|
||||
const difficulteEl = html.querySelector('#potion-difficulte')
|
||||
if (difficulteEl) difficulteEl.textContent = (seuil + pa) + (mod !== 0 ? ` (mod ${mod > 0 ? '+' : ''}${mod})` : '')
|
||||
|
||||
const tempsEl = html.querySelector('#potion-temps')
|
||||
if (tempsEl) {
|
||||
const heures = Math.max(1, Math.ceil(pa / 3))
|
||||
tempsEl.textContent = heures === 1 ? '1 heure' : `${heures} heures`
|
||||
}
|
||||
}
|
||||
|
||||
html.querySelectorAll('.potion-rune-radio, [name="pointsAme"]').forEach(el => {
|
||||
el.addEventListener('change', recalculate)
|
||||
})
|
||||
recalculate()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update rollData from the potion dialog form elements
|
||||
* @param {object} rollData
|
||||
* @param {HTMLFormControlsCollection} formElements
|
||||
* @param {MournbladeActor} actor
|
||||
*/
|
||||
static _updatePotionRollData(rollData, formElements, actor) {
|
||||
const runeId = formElements['rune-selected']?.value
|
||||
if (runeId) {
|
||||
const rune = actor.getRunes().find(r => r._id === runeId)
|
||||
if (rune) {
|
||||
rollData.runeId = runeId
|
||||
rollData.runeName = rune.name
|
||||
rollData.runeImg = rune.img
|
||||
rollData.runeSeuil = rune.system.seuil ?? 0
|
||||
rollData.runeHautParler = rune.system.hautParler ?? ""
|
||||
}
|
||||
}
|
||||
rollData.pointsAme = parseInt(formElements['pointsAme']?.value ?? 1)
|
||||
rollData.forme = formElements['forme']?.value ?? "liquide"
|
||||
rollData.modificateur = parseInt(formElements['modificateur']?.value ?? 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach dynamic recalculation listeners to the sortilège dialog
|
||||
* @param {HTMLElement} html
|
||||
*/
|
||||
static _attachSortilegeListeners(html) {
|
||||
const recalculate = () => {
|
||||
const checkboxes = html.querySelectorAll('.sortilege-rune-checkbox:checked')
|
||||
const modeSelect = html.querySelector('[name="runemode"]')
|
||||
const mode = modeSelect?.value ?? "prononcer"
|
||||
|
||||
let maxSeuil = 0
|
||||
let totalAme = 0
|
||||
let totalActions = 0
|
||||
let count = 0
|
||||
|
||||
// Enable/disable points inputs based on checkbox state
|
||||
html.querySelectorAll('.sortilege-rune-checkbox').forEach(cb => {
|
||||
const row = cb.closest('.sortilege-rune-row')
|
||||
const pointsInput = row?.querySelector('.sortilege-rune-points')
|
||||
if (pointsInput) pointsInput.disabled = !cb.checked
|
||||
})
|
||||
|
||||
checkboxes.forEach(cb => {
|
||||
const row = cb.closest('.sortilege-rune-row')
|
||||
const seuil = Number(row?.dataset.seuil ?? 0)
|
||||
const pts = Number(row?.querySelector('.sortilege-rune-points')?.value ?? 1)
|
||||
if (seuil > maxSeuil) maxSeuil = seuil
|
||||
totalAme += pts
|
||||
totalActions += Math.ceil(pts / 3) * (mode === "inscrire" ? 2 : 1)
|
||||
count++
|
||||
})
|
||||
|
||||
const difficulte = count > 0 ? maxSeuil + (count - 1) : 0
|
||||
html.querySelector('#sortilege-difficulte').textContent = count > 0 ? difficulte : '—'
|
||||
html.querySelector('#sortilege-total-ame').textContent = totalAme
|
||||
html.querySelector('#sortilege-actions').textContent = totalActions
|
||||
}
|
||||
|
||||
html.querySelectorAll('.sortilege-rune-checkbox, .sortilege-rune-points, [name="runemode"]')
|
||||
.forEach(el => el.addEventListener('change', recalculate))
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract sortilège data from the form
|
||||
* @param {Object} rollData
|
||||
* @param {HTMLFormControlsCollection} formElements
|
||||
* @param {MournbladeActor} actor
|
||||
*/
|
||||
static _updateSortilegeRollData(rollData, formElements, actor) {
|
||||
rollData.runemode = formElements.runemode?.value ?? "prononcer"
|
||||
rollData.modificateur = Number(formElements.modificateur?.value ?? 0)
|
||||
rollData.runeautocible = formElements.runeautocible?.checked ?? false
|
||||
|
||||
// Collect selected runes with their soul points
|
||||
const runes = actor.getRunes()
|
||||
rollData.sortilegeRunes = []
|
||||
for (const rune of runes) {
|
||||
const checkbox = formElements[`rune-selected-${rune._id}`]
|
||||
if (checkbox?.checked) {
|
||||
const pts = Math.max(1, Number(formElements[`rune-points-${rune._id}`]?.value ?? 1))
|
||||
rollData.sortilegeRunes.push({
|
||||
id: rune._id,
|
||||
name: rune.name,
|
||||
img: rune.img,
|
||||
seuil: rune.system.seuil,
|
||||
formule: rune.system.formule,
|
||||
pts,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (rollData.sortilegeRunes.length === 0) return
|
||||
|
||||
const maxSeuil = Math.max(...rollData.sortilegeRunes.map(r => r.seuil))
|
||||
rollData.difficulte = maxSeuil + (rollData.sortilegeRunes.length - 1)
|
||||
rollData.runeame = rollData.sortilegeRunes.reduce((s, r) => s + r.pts, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} rollData - L'objet rollData à mettre à jour
|
||||
* @param {HTMLFormControlsCollection} formElements - Les éléments du formulaire
|
||||
* @param {MournbladeActor} actor - L'acteur pour récupérer les attributs
|
||||
@@ -98,6 +339,9 @@ export class MournbladeRollDialog {
|
||||
if (formElements.runeame) {
|
||||
rollData.runeame = Number(formElements.runeame.value)
|
||||
}
|
||||
if (formElements.runeautocible !== undefined) {
|
||||
rollData.runeautocible = formElements.runeautocible.checked
|
||||
}
|
||||
|
||||
// Combat mêlée
|
||||
if (formElements.typeAttaque) {
|
||||
|
||||
@@ -24,6 +24,7 @@ export { default as MournbladePacteSheet } from './mournblade-pacte-sheet.mjs';
|
||||
export { default as MournbladeProtectionSheet } from './mournblade-protection-sheet.mjs';
|
||||
export { default as MournbladeRuneSheet } from './mournblade-rune-sheet.mjs';
|
||||
export { default as MournbladeRuneEffectSheet } from './mournblade-runeeffect-sheet.mjs';
|
||||
export { default as MournbladePotionSheet } from './mournblade-potion-sheet.mjs';
|
||||
export { default as MournbladeTendanceSheet } from './mournblade-tendance-sheet.mjs';
|
||||
export { default as MournbladeTraitChaotiqueSheet } from './mournblade-traitchaotique-sheet.mjs';
|
||||
export { default as MournbladeTraitEspeceSheet } from './mournblade-traitespece-sheet.mjs';
|
||||
|
||||
@@ -45,6 +45,7 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
editItem: MournbladeActorSheet.#onEditItem,
|
||||
deleteItem: MournbladeActorSheet.#onDeleteItem,
|
||||
createItem: MournbladeActorSheet.#onCreateItem,
|
||||
postItem: MournbladeActorSheet.#onPostItem,
|
||||
equipItem: MournbladeActorSheet.#onEquipItem,
|
||||
modifyQuantity: MournbladeActorSheet.#onModifyQuantity,
|
||||
modifySante: MournbladeActorSheet.#onModifySante,
|
||||
@@ -52,6 +53,10 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
rollAttribut: MournbladeActorSheet.#onRollAttribut,
|
||||
rollCompetence: MournbladeActorSheet.#onRollCompetence,
|
||||
rollRune: MournbladeActorSheet.#onRollRune,
|
||||
rollSortilege: MournbladeActorSheet.#onRollSortilege,
|
||||
preparePotion: MournbladeActorSheet.#onPreparePotion,
|
||||
invoquerElementaire: MournbladeActorSheet.#onInvoquerElementaire,
|
||||
bannirElementaire: MournbladeActorSheet.#onBannirElementaire,
|
||||
rollArmeOffensif: MournbladeActorSheet.#onRollArmeOffensif,
|
||||
rollArmeSpecial: MournbladeActorSheet.#onRollArmeSpecial,
|
||||
rollArmeDegats: MournbladeActorSheet.#onRollArmeDegats,
|
||||
@@ -238,6 +243,16 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
await this.actor.createEmbeddedDocuments("Item", [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle posting an item to chat
|
||||
*/
|
||||
static async #onPostItem(event, target) {
|
||||
const li = target.closest(".item")
|
||||
const itemId = li?.dataset.itemId ?? target.dataset.itemId
|
||||
if (!itemId) return
|
||||
MournbladeUtility.postItemToChat(this.actor.id, itemId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle equipping an item
|
||||
* @param {Event} event - The triggering event
|
||||
@@ -335,6 +350,39 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
await actor.rollRune(runeId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle launching a sortilège (multi-rune spell)
|
||||
*/
|
||||
static async #onRollSortilege(event, target) {
|
||||
event.preventDefault()
|
||||
await this.document.rollSortilege()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle preparing a potion
|
||||
*/
|
||||
static async #onPreparePotion(event, target) {
|
||||
event.preventDefault()
|
||||
await this.document.preparePotion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle invoking an elemental
|
||||
*/
|
||||
static async #onInvoquerElementaire(event, target) {
|
||||
event.preventDefault()
|
||||
await this.document.invoquerElementaire()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle banishing an elemental invocation
|
||||
*/
|
||||
static async #onBannirElementaire(event, target) {
|
||||
event.preventDefault()
|
||||
const invocIndex = parseInt(target.dataset.invocIndex ?? "0")
|
||||
await this.document.bannirElementaire(invocIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle rolling an arme offensif
|
||||
* @param {Event} event - The triggering event
|
||||
|
||||
@@ -122,21 +122,37 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
|
||||
if (this.document.actor) {
|
||||
chatData.actor = { id: this.document.actor.id }
|
||||
}
|
||||
// Don't post any image for the item if the default image is used
|
||||
if (chatData.img.includes("/blank.png")) {
|
||||
if (chatData.img?.includes("/blank.png")) {
|
||||
chatData.img = null
|
||||
}
|
||||
// JSON object for easy creation
|
||||
chatData.jsondata = JSON.stringify({
|
||||
compendium: "postedItem",
|
||||
payload: chatData,
|
||||
})
|
||||
|
||||
const html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData)
|
||||
const chatOptions = {
|
||||
user: game.user.id,
|
||||
content: html,
|
||||
// Localized type label
|
||||
const typeLabels = {
|
||||
arme: "Arme", bouclier: "Bouclier", competence: "Compétence",
|
||||
rune: "Rune", runeeffect: "Rune Active", don: "Don", pacte: "Pacte",
|
||||
protection: "Protection", equipement: "Équipement", heritage: "Héritage",
|
||||
metier: "Métier", capacite: "Capacité", tendance: "Tendance",
|
||||
traitchaotique: "Trait Chaotique", traitespece: "Trait d'Espèce",
|
||||
origine: "Origine", modifier: "Modificateur", monnaie: "Monnaie"
|
||||
}
|
||||
ChatMessage.create(chatOptions)
|
||||
chatData.typeLabel = typeLabels[chatData.type] ?? chatData.type
|
||||
|
||||
// Type icon for the badge
|
||||
const typeIcons = {
|
||||
arme: "fa-sword", bouclier: "fa-shield-halved", competence: "fa-graduation-cap",
|
||||
rune: "fa-star-of-david", runeeffect: "fa-star-of-david", don: "fa-hand-sparkles",
|
||||
pacte: "fa-scroll", protection: "fa-shield", equipement: "fa-box",
|
||||
heritage: "fa-dna", metier: "fa-hammer", capacite: "fa-bolt",
|
||||
tendance: "fa-yin-yang", traitchaotique: "fa-skull", traitespece: "fa-paw",
|
||||
origine: "fa-compass", modifier: "fa-sliders", monnaie: "fa-coins"
|
||||
}
|
||||
chatData.typeIcon = typeIcons[chatData.type] ?? "fa-cube"
|
||||
|
||||
const html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData)
|
||||
ChatMessage.create({ user: game.user.id, content: html })
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ export default class MournbladeCreatureSheet extends MournbladeActorSheet {
|
||||
context.skills = actor.getSkills()
|
||||
context.armes = foundry.utils.duplicate(actor.getWeapons())
|
||||
context.protections = foundry.utils.duplicate(actor.getArmors())
|
||||
context.capacites = foundry.utils.duplicate(actor.getCapacites())
|
||||
context.runes = foundry.utils.duplicate(actor.getRunes())
|
||||
context.combat = actor.getCombatValues()
|
||||
context.equipements = foundry.utils.duplicate(actor.getEquipments())
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import MournbladeItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class MournbladePotionSheet extends MournbladeItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["potion"],
|
||||
position: {
|
||||
width: 640,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["potion-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-mournblade/templates/item-potion-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "details",
|
||||
}
|
||||
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
details: { id: "details", group: "primary", label: "Détails" },
|
||||
effets: { id: "effets", group: "primary", label: "Effets" },
|
||||
description: { id: "description", group: "primary", label: "Description" },
|
||||
}
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
v.cssClass = v.active ? "active" : ""
|
||||
}
|
||||
return tabs
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.tabs = this.#getTabs()
|
||||
context.config = game.system.mournblade.config
|
||||
return context
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user