Divers petits fixs
Release Creation / build (release) Successful in 3m58s

This commit is contained in:
2026-05-04 20:39:43 +02:00
parent 0187daa1e5
commit 552731bc3b
55 changed files with 247 additions and 138 deletions
@@ -77,6 +77,14 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
} }
} }
_prepareWeaponEntries(items = []) {
return items.map((item) => ({
...item.toObject(),
id: item.id,
displayDamage: LesOubliesUtility.formatWeaponDamage(this.document, item),
}))
}
_onRender(context, options) { _onRender(context, options) {
super._onRender(context, options) super._onRender(context, options)
} }
@@ -105,6 +105,9 @@ export default class LesOubliesItemSheet extends HandlebarsApplicationMixin(foun
choiceSets, choiceSets,
enriched, enriched,
enrichedDescription: foundry.utils.getProperty(enriched, "description") ?? "", enrichedDescription: foundry.utils.getProperty(enriched, "description") ?? "",
weaponDamagePreview: this.document.type === "arme"
? LesOubliesUtility.formatWeaponDamage(this.document.parent instanceof Actor ? this.document.parent : null, this.document)
: "",
} }
} }
@@ -44,7 +44,7 @@ export default class LesOubliesCreatureSheet extends LesOubliesActorSheet {
context.derived = this.document.getDerivedOverview() context.derived = this.document.getDerivedOverview()
context.skillGroups = this.document.getGroupedCompetences() context.skillGroups = this.document.getGroupedCompetences()
context.spells = this.document.getEmbeddedItems("sortilege") context.spells = this.document.getEmbeddedItems("sortilege")
context.weapons = this.document.getEmbeddedItems("arme") context.weapons = this._prepareWeaponEntries(this.document.getEmbeddedItems("arme"))
context.armors = this.document.getEmbeddedItems("armure") context.armors = this.document.getEmbeddedItems("armure")
context.equipment = this.document.getEmbeddedItems("equipement") context.equipment = this.document.getEmbeddedItems("equipement")
return context return context
@@ -64,7 +64,7 @@ export default class LesOubliesPersonnageSheet extends LesOubliesActorSheet {
context.skillGroups.slice(splitIndex), context.skillGroups.slice(splitIndex),
] ]
context.spells = this.document.getEmbeddedItems("sortilege") context.spells = this.document.getEmbeddedItems("sortilege")
context.weapons = this.document.getEmbeddedItems("arme") context.weapons = this._prepareWeaponEntries(this.document.getEmbeddedItems("arme"))
context.equippedWeapons = context.weapons.filter((item) => item.system.equipped) context.equippedWeapons = context.weapons.filter((item) => item.system.equipped)
context.armors = this.document.getEmbeddedItems("armure") context.armors = this.document.getEmbeddedItems("armure")
context.equipment = this.document.getEmbeddedItems("equipement") context.equipment = this.document.getEmbeddedItems("equipement")
+22
View File
@@ -6,6 +6,8 @@ import { LesOubliesRolls } from "./les-oublies-rolls.js"
import * as models from "./models/index.mjs" import * as models from "./models/index.mjs"
import * as sheets from "./applications/sheets/_module.mjs" import * as sheets from "./applications/sheets/_module.mjs"
const DEFAULT_PERSONNAGE_TOKEN_TEXTURE = "systems/fvtt-les-oublies/assets/tokens/border_token_oublies.webp"
function ensureSystemStyles() { function ensureSystemStyles() {
const href = `systems/${game.system.id}/css/les-oublies.css` const href = `systems/${game.system.id}/css/les-oublies.css`
const existingLink = document.querySelector(`link[href$="${href}"]`) const existingLink = document.querySelector(`link[href$="${href}"]`)
@@ -19,6 +21,13 @@ function ensureSystemStyles() {
document.head.append(link) document.head.append(link)
} }
function usesFoundryDefaultTokenTexture(actor, data) {
const tokenTexture = foundry.utils.getProperty(data, "prototypeToken.texture.src")
?? foundry.utils.getProperty(actor, "prototypeToken.texture.src")
?? ""
return !tokenTexture || tokenTexture === CONST.DEFAULT_TOKEN || tokenTexture === "icons/svg/mystery-man.svg"
}
Hooks.once("init", function () { Hooks.once("init", function () {
console.info("Les Oubliés | Initialisation du système") console.info("Les Oubliés | Initialisation du système")
ensureSystemStyles() ensureSystemStyles()
@@ -67,3 +76,16 @@ Hooks.once("init", function () {
LesOubliesUtility.registerHandlebarsHelpers() LesOubliesUtility.registerHandlebarsHelpers()
}) })
Hooks.on("preCreateActor", function (actor, data) {
if (actor.type !== "personnage") return
if (!usesFoundryDefaultTokenTexture(actor, data)) return
actor.updateSource({
prototypeToken: {
texture: {
src: DEFAULT_PERSONNAGE_TOKEN_TEXTURE,
},
},
})
})
+92 -44
View File
@@ -289,10 +289,13 @@ export class LesOubliesRolls {
const result = await this.resolveTest(actor, data) const result = await this.resolveTest(actor, data)
if (!result) return null if (!result) return null
const initiativeScore = Math.min(Math.max(Math.ceil(result.final / 2), 0), 12)
await this.#syncInitiativeToCombat(actor, initiativeScore)
return this.#createChatMessage(actor, { return this.#createChatMessage(actor, {
...result, ...result,
mode: "initiative", mode: "initiative",
initiativeScore: Math.min(Math.max(Math.ceil(result.final / 2), 0), 12), initiativeScore,
successLabel: null, successLabel: null,
}) })
} }
@@ -716,14 +719,7 @@ export class LesOubliesRolls {
} }
const pool = this.#buildPool(options.rollMode, options.extraDie) const pool = this.#buildPool(options.rollMode, options.extraDie)
const dice = [] const dice = await this.#rollExplodingPool(pool)
for (let index = 0; index < pool.length; index += 1) {
const spec = pool[index]
dice.push(await this.#rollExplodingDie({
...spec,
index,
}))
}
const selectedIndex = this.#needsSelection(dice) const selectedIndex = this.#needsSelection(dice)
? await this.#promptDieSelection(actor, options.label, dice) ? await this.#promptDieSelection(actor, options.label, dice)
@@ -792,6 +788,23 @@ export class LesOubliesRolls {
}) })
} }
static async #syncInitiativeToCombat(actor, initiativeScore) {
if (!game.combat || !actor?.id) return false
const combatants = game.combat.combatants.filter((combatant) => combatant.actorId === actor.id)
if (!combatants.length) {
ui.notifications.warn(`${actor.name} n'est pas présent dans le combat actif.`)
return false
}
await game.combat.updateEmbeddedDocuments("Combatant", combatants.map((combatant) => ({
_id: combatant.id,
initiative: initiativeScore,
})))
return true
}
static async #createConfrontationMessage(actor, data, actionData = null) { static async #createConfrontationMessage(actor, data, actionData = null) {
const attacker = await this.resolveTest(actor, { const attacker = await this.resolveTest(actor, {
label: data.attackerLabel, label: data.attackerLabel,
@@ -1507,38 +1520,82 @@ export class LesOubliesRolls {
return dice return dice
} }
static async #rollExplodingDie({ type, index, source = "base" }) { static async #rollExplodingPool(pool) {
const faces = [] const dice = pool.map(({ type, source = "base" }, index) => ({
const rolls = []
let total = 0
let lastFace = 12
while (lastFace === 12) {
const roll = await this.#evaluateDisplayedRoll("1d12")
lastFace = Number(roll.total ?? 0)
rolls.push(roll)
faces.push(lastFace)
total += lastFace
}
const typeLabel = game.i18n.localize(`LESOUBLIES.rolls.dice.${type}`)
return {
index, index,
type, type,
typeLabel, typeLabel: game.i18n.localize(`LESOUBLIES.rolls.dice.${type}`),
source, source,
sourceLabel: source === "extra" ? game.i18n.localize("LESOUBLIES.rolls.extraDie") : null, sourceLabel: source === "extra" ? game.i18n.localize("LESOUBLIES.rolls.extraDie") : null,
faces, faces: [],
rolls, rolls: [],
firstFace: faces[0] ?? 0, total: 0,
total, }))
exploded: faces.length > 1,
breakdown: faces.join(" + "), let pendingDice = [...dice]
while (pendingDice.length) {
const roll = await this.#evaluateDisplayedRoll(
Array.from({ length: pendingDice.length }, () => "1d12").join(" + "),
(pendingRoll) => this.#applyDieAppearances(pendingRoll, pendingDice),
)
const dieTerms = roll.terms.filter((term) => Number(term.faces ?? 0) === 12)
const nextPendingDice = []
pendingDice.forEach((die, index) => {
const face = Number(dieTerms[index]?.results?.[0]?.result ?? 0)
die.rolls.push(roll)
die.faces.push(face)
die.total += face
if (face === 12) nextPendingDice.push(die)
})
pendingDice = nextPendingDice
}
return dice.map((die) => ({
...die,
firstFace: die.faces[0] ?? 0,
exploded: die.faces.length > 1,
breakdown: die.faces.join(" + "),
}))
}
static #applyDieAppearances(roll, dice) {
const dieTerms = roll.terms.filter((term) => Number(term.faces ?? 0) === 12)
dieTerms.forEach((term, index) => {
term.options ??= {}
term.options.appearance = this.#getDieAppearance(dice[index]?.type)
})
}
static #getDieAppearance(type) {
switch (type) {
case "songes":
return {
foreground: "#111111",
background: "#f3efe4",
outline: "#b8aa87",
}
case "cauchemar":
return {
foreground: "#f4f0e8",
background: "#111111",
outline: "#5d5d5d",
}
default:
return {
foreground: "#201813",
background: "#ddd0b0",
outline: "#8d5c3b",
}
} }
} }
static async #evaluateDisplayedRoll(formula) { static async #evaluateDisplayedRoll(formula, configureRoll = null) {
const roll = await (new Roll(formula)).evaluate() const roll = typeof formula === "string" ? new Roll(formula) : formula
if (configureRoll) configureRoll(roll)
await roll.evaluate()
await this.#showDiceSoNice(roll) await this.#showDiceSoNice(roll)
return roll return roll
} }
@@ -2059,16 +2116,7 @@ export class LesOubliesRolls {
} }
static #getWeaponBaseDamage(actor, weapon) { static #getWeaponBaseDamage(actor, weapon) {
const damageText = String(weapon?.system?.damage || "") return LesOubliesUtility.getWeaponBaseDamage(actor, weapon)
const parsed = this.#extractFirstInteger(damageText)
if (parsed !== null) return parsed
const explicitValue = Number(weapon?.system?.sizeValue ?? 0)
if (explicitValue > 0) return explicitValue
const actorSize = Number(actor?.system?.size?.value ?? 0)
const sizeModifier = Number(weapon?.system?.sizeModifier ?? 0)
return Math.max(actorSize + sizeModifier, 0)
} }
static #extractFirstInteger(text) { static #extractFirstInteger(text) {
+26
View File
@@ -97,6 +97,32 @@ export class LesOubliesUtility {
return [...documents].sort((left, right) => left.name.localeCompare(right.name, "fr")) return [...documents].sort((left, right) => left.name.localeCompare(right.name, "fr"))
} }
static getWeaponBaseDamage(actor, weapon) {
const sizeMode = String(weapon?.system?.sizeMode || "").toLowerCase()
if (sizeMode === "variable") {
const actorSize = Number(actor?.system?.size?.value ?? 0)
const sizeModifier = Number(weapon?.system?.sizeModifier ?? 0)
return Math.max(actorSize + sizeModifier, 0)
}
const explicitValue = Number(weapon?.system?.sizeValue ?? 0)
if (explicitValue > 0) return explicitValue
const damageText = String(weapon?.system?.damage || "")
const match = damageText.match(/-?\d+/)
return match ? Number(match[0]) : 0
}
static formatWeaponDamage(actor, weapon) {
const baseLabel = String(weapon?.system?.damage || "").trim()
const baseDamage = this.getWeaponBaseDamage(actor, weapon)
const sizeMode = String(weapon?.system?.sizeMode || "").toLowerCase()
if (sizeMode === "variable" || /taille/i.test(baseLabel)) {
return baseLabel ? `${baseLabel} (${baseDamage})` : String(baseDamage)
}
return baseLabel || String(baseDamage)
}
static uniqueStrings(values = []) { static uniqueStrings(values = []) {
return [...new Set((Array.isArray(values) ? values : []) return [...new Set((Array.isArray(values) ? values : [])
.map((value) => String(value ?? "").trim()) .map((value) => String(value ?? "").trim())
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.098074 7f9b5cbfd6c0 Delete type=3 #1 2026/05/04-20:19:31.964617 7f037d7ed6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.164577 7f9b4ffff6c0 Delete type=3 #1 2026/05/04-20:19:32.040110 7f037cfec6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.395797 7f9b5cbfd6c0 Delete type=3 #1 2026/05/04-20:19:32.300821 7f037d7ed6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.240415 7f9b5dbff6c0 Delete type=3 #1 2026/05/04-20:19:32.128147 7f037e7ef6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.609281 7f9b5d3fe6c0 Delete type=3 #1 2026/05/04-20:19:32.576403 7f037dfee6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.319307 7f9b5d3fe6c0 Delete type=3 #1 2026/05/04-20:19:32.214437 7f037dfee6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.459120 7f9b4ffff6c0 Delete type=3 #1 2026/05/04-20:19:32.413325 7f037cfec6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.677244 7f9b5cbfd6c0 Delete type=3 #1 2026/05/04-20:19:32.651585 7f037d7ed6c0 Delete type=3 #1
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
2026/05/04-10:50:49.540176 7f9b5dbff6c0 Delete type=3 #1 2026/05/04-20:19:32.499232 7f037e7ef6c0 Delete type=3 #1
Binary file not shown.
+1 -1
View File
@@ -118,7 +118,7 @@
<div class="item-list"> <div class="item-list">
{{#each weapons as |item|}} {{#each weapons as |item|}}
<article class="item-card" data-item-id="{{item.id}}" draggable="true"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{item.system.damage}}</div></div> <div><strong>{{item.name}}</strong><div>{{item.displayDamage}}</div></div>
<div class="item-controls"><button type="button" data-action="useWeapon" data-item-id="{{item.id}}">Attaque</button><button type="button" data-action="resolveWeaponDamage" data-item-id="{{item.id}}">Dégâts</button><button type="button" data-action="editItem" data-item-id="{{item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button></div> <div class="item-controls"><button type="button" data-action="useWeapon" data-item-id="{{item.id}}">Attaque</button><button type="button" data-action="resolveWeaponDamage" data-item-id="{{item.id}}">Dégâts</button><button type="button" data-action="editItem" data-item-id="{{item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button></div>
</article> </article>
{{/each}} {{/each}}
+81 -82
View File
@@ -188,7 +188,7 @@
{{#if equippedWeapons.length}} {{#if equippedWeapons.length}}
{{#each equippedWeapons as |item|}} {{#each equippedWeapons as |item|}}
<article class="item-card" data-item-id="{{item.id}}" draggable="true"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.arme"}} - {{item.system.damage}}</div></div> <div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.arme"}} - {{item.displayDamage}}</div></div>
<div class="item-controls"><button type="button" data-action="useWeapon" data-item-id="{{item.id}}">Attaque</button><button type="button" data-action="resolveWeaponDamage" data-item-id="{{item.id}}">Dégâts</button><button type="button" data-action="toggleEquipped" data-item-id="{{item.id}}">Retirer</button></div> <div class="item-controls"><button type="button" data-action="useWeapon" data-item-id="{{item.id}}">Attaque</button><button type="button" data-action="resolveWeaponDamage" data-item-id="{{item.id}}">Dégâts</button><button type="button" data-action="toggleEquipped" data-item-id="{{item.id}}">Retirer</button></div>
</article> </article>
{{/each}} {{/each}}
@@ -198,101 +198,100 @@
</div> </div>
</section> </section>
<div class="sheet-grid sheet-grid-2"> <section class="sheet-card ledger-card reserve-card">
<section class="sheet-card ledger-card"> <div class="section-title-row">
<div class="section-title-row"> <h2>{{localize "LESOUBLIES.labels.threadReserves"}}</h2>
<h2>{{localize "LESOUBLIES.ui.magie"}}</h2> <button type="button" data-action="openThreadHarvest">Récolte de fils</button>
<button type="button" data-action="createItem" data-type="sortilege">+ {{localize "TYPES.Item.sortilege"}}</button> </div>
<div class="reserve-grid">
<div class="reserve-panel">
<h3>{{localize "LESOUBLIES.labels.personalReserve"}}</h3>
<div class="field-row">
<label>{{localize "LESOUBLIES.labels.threadSonges"}}</label>
<input name="system.reserves.songesThreads" type="number" value="{{system.reserves.songesThreads}}" {{#if isPlayMode}}disabled{{/if}} />
</div>
<div class="field-row">
<label>{{localize "LESOUBLIES.labels.threadCauchemar"}}</label>
<input name="system.reserves.cauchemarThreads" type="number" value="{{system.reserves.cauchemarThreads}}" {{#if isPlayMode}}disabled{{/if}} />
</div>
<div class="field-row">
<label>{{localize "LESOUBLIES.labels.emptyGlobes"}}</label>
<input name="system.reserves.emptyGlobes" type="number" value="{{system.reserves.emptyGlobes}}" {{#if isPlayMode}}disabled{{/if}} />
</div>
</div> </div>
<div class="item-list">
{{#each spells as |item|}}
<article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div>
<strong>{{item.name}}</strong>
<div>{{item.system.tradition}} / {{item.system.polarity}} / coût {{item.system.cost}}</div>
</div>
<div class="item-controls">
<button type="button" data-action="useSpell" data-item-id="{{item.id}}">Activer</button>
<button type="button" data-action="editItem" data-item-id="{{item.id}}">Edit</button>
<button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button>
</div>
</article>
{{/each}}
</div>
</section>
<section class="sheet-card ledger-card reserve-card"> <div class="reserve-panel reserve-panel--company">
<div class="section-title-row"> <h3>{{localize "LESOUBLIES.labels.companyReserve"}}</h3>
<h2>{{localize "LESOUBLIES.labels.threadReserves"}}</h2> {{#if derived.compagnie}}
<button type="button" data-action="openThreadHarvest">Récolte de fils</button>
</div>
<div class="reserve-grid">
<div class="reserve-panel">
<h3>{{localize "LESOUBLIES.labels.personalReserve"}}</h3>
<div class="field-row"> <div class="field-row">
<label>{{localize "LESOUBLIES.labels.threadSonges"}}</label> <label>{{localize "LESOUBLIES.labels.threadSonges"}}</label>
<input name="system.reserves.songesThreads" type="number" value="{{system.reserves.songesThreads}}" {{#if isPlayMode}}disabled{{/if}} /> <span>{{derived.companyReserves.songesThreads}}</span>
</div> </div>
<div class="field-row"> <div class="field-row">
<label>{{localize "LESOUBLIES.labels.threadCauchemar"}}</label> <label>{{localize "LESOUBLIES.labels.threadCauchemar"}}</label>
<input name="system.reserves.cauchemarThreads" type="number" value="{{system.reserves.cauchemarThreads}}" {{#if isPlayMode}}disabled{{/if}} /> <span>{{derived.companyReserves.cauchemarThreads}}</span>
</div> </div>
<div class="field-row"> <div class="field-row">
<label>{{localize "LESOUBLIES.labels.emptyGlobes"}}</label> <label>{{localize "LESOUBLIES.labels.emptyGlobes"}}</label>
<input name="system.reserves.emptyGlobes" type="number" value="{{system.reserves.emptyGlobes}}" {{#if isPlayMode}}disabled{{/if}} /> <span>{{derived.companyReserves.emptyGlobes}}</span>
</div> </div>
</div>
<div class="reserve-panel reserve-panel--company"> <div class="transfer-list">
<h3>{{localize "LESOUBLIES.labels.companyReserve"}}</h3> <div class="transfer-row" data-transfer-row>
{{#if derived.compagnie}} <strong>{{localize "LESOUBLIES.labels.threadSonges"}}</strong>
<div class="field-row"> <input type="number" min="1" value="1" data-transfer-amount />
<label>{{localize "LESOUBLIES.labels.threadSonges"}}</label> <div class="item-controls">
<span>{{derived.companyReserves.songesThreads}}</span> <button type="button" data-action="transferThread" data-direction="toCompany" data-resource-key="songesThreads">{{localize "LESOUBLIES.labels.toCompany"}}</button>
</div> <button type="button" data-action="transferThread" data-direction="toActor" data-resource-key="songesThreads">{{localize "LESOUBLIES.labels.toActor"}}</button>
<div class="field-row">
<label>{{localize "LESOUBLIES.labels.threadCauchemar"}}</label>
<span>{{derived.companyReserves.cauchemarThreads}}</span>
</div>
<div class="field-row">
<label>{{localize "LESOUBLIES.labels.emptyGlobes"}}</label>
<span>{{derived.companyReserves.emptyGlobes}}</span>
</div>
<div class="transfer-list">
<div class="transfer-row" data-transfer-row>
<strong>{{localize "LESOUBLIES.labels.threadSonges"}}</strong>
<input type="number" min="1" value="1" data-transfer-amount />
<div class="item-controls">
<button type="button" data-action="transferThread" data-direction="toCompany" data-resource-key="songesThreads">{{localize "LESOUBLIES.labels.toCompany"}}</button>
<button type="button" data-action="transferThread" data-direction="toActor" data-resource-key="songesThreads">{{localize "LESOUBLIES.labels.toActor"}}</button>
</div>
</div>
<div class="transfer-row" data-transfer-row>
<strong>{{localize "LESOUBLIES.labels.threadCauchemar"}}</strong>
<input type="number" min="1" value="1" data-transfer-amount />
<div class="item-controls">
<button type="button" data-action="transferThread" data-direction="toCompany" data-resource-key="cauchemarThreads">{{localize "LESOUBLIES.labels.toCompany"}}</button>
<button type="button" data-action="transferThread" data-direction="toActor" data-resource-key="cauchemarThreads">{{localize "LESOUBLIES.labels.toActor"}}</button>
</div>
</div>
<div class="transfer-row" data-transfer-row>
<strong>{{localize "LESOUBLIES.labels.emptyGlobes"}}</strong>
<input type="number" min="1" value="1" data-transfer-amount />
<div class="item-controls">
<button type="button" data-action="transferThread" data-direction="toCompany" data-resource-key="emptyGlobes">{{localize "LESOUBLIES.labels.toCompany"}}</button>
<button type="button" data-action="transferThread" data-direction="toActor" data-resource-key="emptyGlobes">{{localize "LESOUBLIES.labels.toActor"}}</button>
</div>
</div> </div>
</div> </div>
{{else}} <div class="transfer-row" data-transfer-row>
<p class="help-text">Liez une compagnie pour gérer une réserve commune de fils et de globes.</p> <strong>{{localize "LESOUBLIES.labels.threadCauchemar"}}</strong>
{{/if}} <input type="number" min="1" value="1" data-transfer-amount />
</div> <div class="item-controls">
<button type="button" data-action="transferThread" data-direction="toCompany" data-resource-key="cauchemarThreads">{{localize "LESOUBLIES.labels.toCompany"}}</button>
<button type="button" data-action="transferThread" data-direction="toActor" data-resource-key="cauchemarThreads">{{localize "LESOUBLIES.labels.toActor"}}</button>
</div>
</div>
<div class="transfer-row" data-transfer-row>
<strong>{{localize "LESOUBLIES.labels.emptyGlobes"}}</strong>
<input type="number" min="1" value="1" data-transfer-amount />
<div class="item-controls">
<button type="button" data-action="transferThread" data-direction="toCompany" data-resource-key="emptyGlobes">{{localize "LESOUBLIES.labels.toCompany"}}</button>
<button type="button" data-action="transferThread" data-direction="toActor" data-resource-key="emptyGlobes">{{localize "LESOUBLIES.labels.toActor"}}</button>
</div>
</div>
</div>
{{else}}
<p class="help-text">Liez une compagnie pour gérer une réserve commune de fils et de globes.</p>
{{/if}}
</div> </div>
<p class="help-text">Les dépenses en fils rendent automatiquement autant de globes vides à la réserve utilisée.</p> </div>
</section> <p class="help-text">Les dépenses en fils rendent automatiquement autant de globes vides à la réserve utilisée.</p>
</div> </section>
<section class="sheet-card ledger-card">
<div class="section-title-row">
<h2>{{localize "LESOUBLIES.ui.magie"}}</h2>
<button type="button" data-action="createItem" data-type="sortilege">+ {{localize "TYPES.Item.sortilege"}}</button>
</div>
<div class="item-list">
{{#each spells as |item|}}
<article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div>
<strong>{{item.name}}</strong>
<div>{{item.system.tradition}} / {{item.system.polarity}} / coût {{item.system.cost}}</div>
</div>
<div class="item-controls">
<button type="button" data-action="useSpell" data-item-id="{{item.id}}">Activer</button>
<button type="button" data-action="editItem" data-item-id="{{item.id}}">Edit</button>
<button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button>
</div>
</article>
{{/each}}
</div>
</section>
</section> </section>
<section class="sheet-tab {{tabs.equipment.cssClass}}" data-tab="equipment"> <section class="sheet-tab {{tabs.equipment.cssClass}}" data-tab="equipment">
@@ -308,7 +307,7 @@
<div class="item-list"> <div class="item-list">
{{#each weapons as |item|}} {{#each weapons as |item|}}
<article class="item-card" data-item-id="{{item.id}}" draggable="true"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.arme"}} - {{item.system.damage}}{{#if item.system.equipped}} - Équipée{{/if}}</div></div> <div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.arme"}} - {{item.displayDamage}}{{#if item.system.equipped}} - Équipée{{/if}}</div></div>
<div class="item-controls"><button type="button" data-action="toggleEquipped" data-item-id="{{item.id}}">{{#if item.system.equipped}}Retirer{{else}}Équiper{{/if}}</button><button type="button" data-action="editItem" data-item-id="{{item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button></div> <div class="item-controls"><button type="button" data-action="toggleEquipped" data-item-id="{{item.id}}">{{#if item.system.equipped}}Retirer{{else}}Équiper{{/if}}</button><button type="button" data-action="editItem" data-item-id="{{item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button></div>
</article> </article>
{{/each}} {{/each}}
+3
View File
@@ -16,6 +16,9 @@
<div class="field-row"><label>{{localize "LESOUBLIES.labels.quantite"}}</label><input name="system.quantity" type="number" value="{{system.quantity}}" {{#if isPlayMode}}disabled{{/if}} /></div> <div class="field-row"><label>{{localize "LESOUBLIES.labels.quantite"}}</label><input name="system.quantity" type="number" value="{{system.quantity}}" {{#if isPlayMode}}disabled{{/if}} /></div>
<div class="field-row"><label>Équipée</label><input name="system.equipped" type="checkbox" {{checked system.equipped}} {{#if isPlayMode}}disabled{{/if}} /></div> <div class="field-row"><label>Équipée</label><input name="system.equipped" type="checkbox" {{checked system.equipped}} {{#if isPlayMode}}disabled{{/if}} /></div>
<p><strong>Race restreinte :</strong> {{system.restrictedRace}}</p> <p><strong>Race restreinte :</strong> {{system.restrictedRace}}</p>
{{#if weaponDamagePreview}}
<p><strong>Dégâts calculés :</strong> {{weaponDamagePreview}}</p>
{{/if}}
</section> </section>
<section class="sheet-card notes-card"> <section class="sheet-card notes-card">
<h2>{{localize "LESOUBLIES.labels.description"}}</h2> <h2>{{localize "LESOUBLIES.labels.description"}}</h2>