2 Commits

Author SHA1 Message Date
uberwald 552731bc3b Divers petits fixs
Release Creation / build (release) Successful in 3m58s
2026-05-04 20:39:43 +02:00
uberwald 0187daa1e5 - ajoute les visuels système (bannière, pause, tokens)
Release Creation / build (release) Successful in 1m57s
- active le drag & drop inverse des objets depuis les fiches d’acteur
 - corrige le calcul des PV des créatures selon la taille
 - ajoute les options d’armes de créature manquantes
 - met à jour les styles et les packs générés
2026-05-04 13:17:07 +02:00
66 changed files with 356 additions and 153 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

+37
View File
@@ -87,6 +87,43 @@
--lo-control-height: 1.95rem; --lo-control-height: 1.95rem;
--lo-number-width: 4.75rem; --lo-number-width: 4.75rem;
} }
body.system-fvtt-les-oublies #pause {
font-size: 2rem;
}
body.system-fvtt-les-oublies #pause.paused {
gap: 0.5rem;
}
body.system-fvtt-les-oublies #pause > figcaption {
color: #d9d4ca;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.22);
}
body.system-fvtt-les-oublies #pause > img {
opacity: 0;
width: 0;
height: 0;
}
body.system-fvtt-les-oublies #pause::before {
content: "";
display: block;
width: 200px;
height: 200px;
margin-bottom: 0.75rem;
background: url("../assets/ui/pause_oublie.webp") center / contain no-repeat;
animation: lo-pause-logo 4.2s ease-in-out infinite;
transform-origin: 50% 50%;
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.35));
}
@keyframes lo-pause-logo {
0%,
100% {
transform: scale(0.98) translateY(0);
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.3));
}
50% {
transform: scale(1.03) translateY(-6px);
filter: drop-shadow(0 16px 26px rgba(0, 0, 0, 0.45));
}
}
.fvtt-les-oublies.sheet { .fvtt-les-oublies.sheet {
color: var(--lo-ink); color: var(--lo-ink);
font-family: "Cormorant Garamond", Georgia, serif; font-family: "Cormorant Garamond", Georgia, serif;
File diff suppressed because one or more lines are too long
+44
View File
@@ -34,6 +34,50 @@
--lo-number-width: 4.75rem; --lo-number-width: 4.75rem;
} }
body.system-fvtt-les-oublies #pause {
font-size: 2rem;
}
body.system-fvtt-les-oublies #pause.paused {
gap: 0.5rem;
}
body.system-fvtt-les-oublies #pause > figcaption {
color: #d9d4ca;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.22);
}
body.system-fvtt-les-oublies #pause > img {
opacity: 0;
width: 0;
height: 0;
}
body.system-fvtt-les-oublies #pause::before {
content: "";
display: block;
width: 200px;
height: 200px;
margin-bottom: 0.75rem;
background: url("../assets/ui/pause_oublie.webp") center/contain no-repeat;
animation: lo-pause-logo 4.2s ease-in-out infinite;
transform-origin: 50% 50%;
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.35));
}
@keyframes lo-pause-logo {
0%,
100% {
transform: scale(0.98) translateY(0);
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.3));
}
50% {
transform: scale(1.03) translateY(-6px);
filter: drop-shadow(0 16px 26px rgba(0, 0, 0, 0.45));
}
}
.fvtt-les-oublies.sheet { .fvtt-les-oublies.sheet {
color: var(--lo-ink); color: var(--lo-ink);
font-family: "Cormorant Garamond", Georgia, serif; font-family: "Cormorant Garamond", Georgia, serif;
@@ -77,10 +77,27 @@ 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)
} }
_onDragStart(event) {
const itemElement = event.currentTarget?.closest?.("[data-item-id]") ?? event.target?.closest?.("[data-item-id]")
const itemId = itemElement?.dataset?.itemId
const item = itemId ? this.document.items.get(itemId) : null
if (!item || !event.dataTransfer) return
event.dataTransfer.setData("text/plain", JSON.stringify(item.toDragData()))
}
_canDragStart() { _canDragStart() {
return this.isEditable return this.isEditable
} }
@@ -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")
+3 -2
View File
@@ -41,8 +41,9 @@ export class LesOubliesActor extends Actor {
if (this.type !== "creature") return if (this.type !== "creature") return
const system = this.system const system = this.system
const hpValue = Math.max(Number(system.hp?.value ?? 0), 0) const sizeValue = Math.clamp(Number(system.size?.value ?? 1), 1, 8)
const hpMax = Math.max(Number(system.hp?.max ?? hpValue), hpValue, 0) const hpMax = Math.max(sizeValue * 4, 0)
const hpValue = Math.max(Number(system.hp?.value ?? hpMax), 0)
system.hp.max = hpMax system.hp.max = hpMax
system.hp.value = Math.min(hpValue, hpMax) system.hp.value = Math.min(hpValue, hpMax)
const songesPoints = Math.max(Number(system.songes?.points ?? 0), 0) const songesPoints = Math.max(Number(system.songes?.points ?? 0), 0)
+2
View File
@@ -60,12 +60,14 @@ export const SIZE_LABELS = {
} }
export const WEAPON_CATEGORY_LABELS = { export const WEAPON_CATEGORY_LABELS = {
corpsacorps: "Corps à corps",
melee: "Mêlée", melee: "Mêlée",
tir: "Tir", tir: "Tir",
jet: "Jet", jet: "Jet",
} }
export const WEAPON_ORIGIN_LABELS = { export const WEAPON_ORIGIN_LABELS = {
animaux: "Animaux",
geant: "Géant", geant: "Géant",
petitPeuple: "Petit Peuple", petitPeuple: "Petit Peuple",
} }
+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-09:46:56.090569 7fe6b57ed6c0 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-09:46:56.106804 7fe6b4fec6c0 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-09:46:56.152550 7fe6b57ed6c0 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-09:46:56.122237 7fe6b67ef6c0 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-09:46:56.198341 7fe6b5fee6c0 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-09:46:56.137148 7fe6b5fee6c0 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-09:46:56.166829 7fe6b4fec6c0 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-09:46:56.214242 7fe6b57ed6c0 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-09:46:56.182767 7fe6b67ef6c0 Delete type=3 #1 2026/05/04-20:19:32.499232 7f037e7ef6c0 Delete type=3 #1
Binary file not shown.
+2 -1
View File
@@ -5,7 +5,8 @@
"manifest": "https://www.uberwald.me/gitea/public/fvtt-les-oublies/raw/branch/main/system.json", "manifest": "https://www.uberwald.me/gitea/public/fvtt-les-oublies/raw/branch/main/system.json",
"download": "#{DOWNLOAD}#", "download": "#{DOWNLOAD}#",
"url": "https://www.uberwald.me/gitea/public/fvtt-les-oublies", "url": "https://www.uberwald.me/gitea/public/fvtt-les-oublies",
"version": "0.1.0", "background": "systems/fvtt-les-oublies/assets/ui/banniere_les_oublies.webp",
"version": "14.0.0",
"authors": [ "authors": [
{ {
"name": "Copilot", "name": "Copilot",
+1 -1
View File
@@ -61,7 +61,7 @@
</div> </div>
<div class="item-list"> <div class="item-list">
{{#each powers as |item|}} {{#each powers as |item|}}
<article class="item-card"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{item.system.activationCondition}}</div></div> <div><strong>{{item.name}}</strong><div>{{item.system.activationCondition}}</div></div>
<div class="item-controls"><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="editItem" data-item-id="{{item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button></div>
</article> </article>
+6 -6
View File
@@ -70,7 +70,7 @@
<h3>{{group.label}}</h3> <h3>{{group.label}}</h3>
<div class="item-list"> <div class="item-list">
{{#each group.items as |entry|}} {{#each group.items as |entry|}}
<article class="item-card"> <article class="item-card" data-item-id="{{entry.item.id}}" draggable="true">
<div><strong>{{entry.item.name}}</strong><div>{{localize "LESOUBLIES.labels.valeurFinale"}} {{entry.finalValue}}</div></div> <div><strong>{{entry.item.name}}</strong><div>{{localize "LESOUBLIES.labels.valeurFinale"}} {{entry.finalValue}}</div></div>
<div class="item-controls"><button type="button" data-action="rollSkill" data-item-id="{{entry.item.id}}">{{localize "LESOUBLIES.ui.roll"}}</button><button type="button" data-action="editItem" data-item-id="{{entry.item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{entry.item.id}}">Delete</button></div> <div class="item-controls"><button type="button" data-action="rollSkill" data-item-id="{{entry.item.id}}">{{localize "LESOUBLIES.ui.roll"}}</button><button type="button" data-action="editItem" data-item-id="{{entry.item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{entry.item.id}}">Delete</button></div>
</article> </article>
@@ -117,25 +117,25 @@
</div> </div>
<div class="item-list"> <div class="item-list">
{{#each weapons as |item|}} {{#each weapons as |item|}}
<article class="item-card"> <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}}
{{#each armors as |item|}} {{#each armors as |item|}}
<article class="item-card"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>Prot {{item.system.protection}}</div></div> <div><strong>{{item.name}}</strong><div>Prot {{item.system.protection}}</div></div>
<div class="item-controls"><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="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}}
{{#each equipment as |item|}} {{#each equipment as |item|}}
<article class="item-card"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.equipement"}} - {{item.system.category}}</div></div> <div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.equipement"}} - {{item.system.category}}</div></div>
<div class="item-controls"><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="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}}
{{#each spells as |item|}} {{#each spells as |item|}}
<article class="item-card"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{item.system.tradition}} / {{item.system.polarity}}</div></div> <div><strong>{{item.name}}</strong><div>{{item.system.tradition}} / {{item.system.polarity}}</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> <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> </article>
+29 -30
View File
@@ -148,7 +148,7 @@
</div> </div>
<div class="item-list skills-item-list"> <div class="item-list skills-item-list">
{{#each group.items as |entry|}} {{#each group.items as |entry|}}
<article class="item-card skill-card"> <article class="item-card skill-card" data-item-id="{{entry.item.id}}" draggable="true">
<div class="skill-card-main"> <div class="skill-card-main">
<strong>{{entry.item.name}}</strong> <strong>{{entry.item.name}}</strong>
<span class="skill-summary">Base {{entry.item.system.base}} · {{group.label}} {{group.profileValue}} · {{localize "LESOUBLIES.labels.valeurFinale"}} {{entry.finalValue}}</span> <span class="skill-summary">Base {{entry.item.system.base}} · {{group.label}} {{group.profileValue}} · {{localize "LESOUBLIES.labels.valeurFinale"}} {{entry.finalValue}}</span>
@@ -187,8 +187,8 @@
<div class="item-list"> <div class="item-list">
{{#if equippedWeapons.length}} {{#if equippedWeapons.length}}
{{#each equippedWeapons as |item|}} {{#each equippedWeapons as |item|}}
<article class="item-card"> <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,29 +198,6 @@
</div> </div>
</section> </section>
<div class="sheet-grid sheet-grid-2">
<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">
<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"> <section class="sheet-card ledger-card reserve-card">
<div class="section-title-row"> <div class="section-title-row">
<h2>{{localize "LESOUBLIES.labels.threadReserves"}}</h2> <h2>{{localize "LESOUBLIES.labels.threadReserves"}}</h2>
@@ -292,7 +269,29 @@
</div> </div>
<p class="help-text">Les dépenses en fils rendent automatiquement autant de globes vides à la réserve utilisée.</p> <p class="help-text">Les dépenses en fils rendent automatiquement autant de globes vides à la réserve utilisée.</p>
</section> </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>
<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">
@@ -307,19 +306,19 @@
</div> </div>
<div class="item-list"> <div class="item-list">
{{#each weapons as |item|}} {{#each weapons as |item|}}
<article class="item-card"> <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}}
{{#each armors as |item|}} {{#each armors as |item|}}
<article class="item-card"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.armure"}} - Prot {{item.system.protection}}</div></div> <div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.armure"}} - Prot {{item.system.protection}}</div></div>
<div class="item-controls"><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="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}}
{{#each equipment as |item|}} {{#each equipment as |item|}}
<article class="item-card"> <article class="item-card" data-item-id="{{item.id}}" draggable="true">
<div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.equipement"}} - {{item.system.category}}</div></div> <div><strong>{{item.name}}</strong><div>{{localize "TYPES.Item.equipement"}} - {{item.system.category}}</div></div>
<div class="item-controls"><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="editItem" data-item-id="{{item.id}}">Edit</button><button type="button" data-action="deleteItem" data-item-id="{{item.id}}">Delete</button></div>
</article> </article>
+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>