feat: capacités de créature, blessures séquentielles et refonte fiche Groupe

- Nouvel item Capacité de créature (creaturecapacity) : DataModel, fiche
  AppV2, chat card, types Base/Survie/Cauchemar/Apocalypse, liste sur
  l'onglet Informations de la créature avec drag&drop et post au chat.
- Blessures : coches séquentielles respectant la gravité (onClickWound),
  malus de blessure -1D/-2D/-3D appliqué aux jets (Règles p.42),
  montée en gravité automatique si les cercles sont pleins.
- Fiche Groupe : objectifs majeurs/mineurs éditables, liste de membres
  simplifiée, notes de voyage (roadNotes), totem qui remplit
  instinct/interdits, refonte visuelle des onglets.
- Créature : Réaction lançable, seuils/cercles de blessures corrigés
  (Taille cumulée, Groupe sans seuil), libellés Taille/Meute.
- Corrections : icône de carte de chat plafonnée à 64px, slash orphelin
  d'entrave à 0, notes de matériel du Groupe éditable (formInput),
  bonus de Réaction non double-compté.
- Divers : suppression des captures de débogage, licence README.
This commit is contained in:
2026-08-05 09:38:36 +02:00
parent cf905cdcfb
commit d0373fab5a
59 changed files with 984 additions and 1211 deletions
+10 -5
View File
@@ -260,8 +260,9 @@ export default class CombatDialog extends HandlebarsApplicationMixin(foundry.app
const toolsChecked = this.#el.querySelector("input[name='usingTools']:checked");
const tooling = toolsChecked && toolsChecked.value !== "0" ? 1 : 0;
const group = parseInt(this.#el.querySelector("#group")?.value, 10) || 0;
const total = this.basePool + selfControl + pools + specialty + help + tooling + group;
return { ability, skill, selfControl, pools, specialty, help, tooling, group, total };
const malus = VermineExchange.woundMalus(this.actor);
const total = Math.max(0, this.basePool + selfControl + pools + specialty + help + tooling + group - malus);
return { ability, skill, selfControl, pools, specialty, help, tooling, group, malus, total };
}
getDicePool() {
@@ -297,7 +298,7 @@ export default class CombatDialog extends HandlebarsApplicationMixin(foundry.app
const b = this.getPoolBreakdown();
const bonusEl = this.#el.querySelector("#total-bonus");
if (bonusEl) bonusEl.textContent = b.selfControl + b.pools + b.specialty + b.help + b.tooling + b.group;
if (bonusEl) bonusEl.textContent = b.selfControl + b.pools + b.specialty + b.help + b.tooling + b.group - b.malus;
const handSel = this.#el.querySelector("#handicap");
const handEl = this.#el.querySelector("#current-handicap");
@@ -367,7 +368,7 @@ export default class CombatDialog extends HandlebarsApplicationMixin(foundry.app
: null
};
await VermineUtils.roll({
const rollParams = {
actor: this.actor,
NoD: this.getDicePool(),
Reroll: this.getReroll(),
@@ -387,9 +388,13 @@ export default class CombatDialog extends HandlebarsApplicationMixin(foundry.app
targets: targets.map(t => t.name),
attack,
messageFlags: { "vermine-exchange": attack }
});
};
// Fermeture immédiate du dialogue : le jet (et l'animation 3D) continue
// en arrière-plan sans bloquer la fermeture.
this.close();
await VermineUtils.roll(rollParams);
}
#getRangeKey() {
+10 -4
View File
@@ -1,4 +1,5 @@
import { VermineUtils } from "../roll.mjs"
import { VermineExchange } from "../exchange.mjs"
const { HandlebarsApplicationMixin } = foundry.applications.api
@@ -161,7 +162,8 @@ export default class NpcRollDialog extends HandlebarsApplicationMixin(foundry.ap
getPoolBreakdown() {
const help = this.#getHelped()
const group = this.#getGroup()
return { pool: this.pool, help, group, total: this.pool + help + group }
const malus = VermineExchange.woundMalus(this.#actor)
return { pool: this.pool, help, group, malus, total: Math.max(0, this.pool + help + group - malus) }
}
#updateUI() {
@@ -169,7 +171,7 @@ export default class NpcRollDialog extends HandlebarsApplicationMixin(foundry.ap
const totalEl = this.#el.querySelector("#dice-pool-total")
if (totalEl) totalEl.textContent = `${b.total}D`
const bonusEl = this.#el.querySelector("#total-bonus")
if (bonusEl) bonusEl.textContent = b.help + b.group
if (bonusEl) bonusEl.textContent = b.help + b.group - b.malus
const freeEl = this.#el.querySelector("#free-successes")
if (freeEl) freeEl.textContent = String(this.freeSuccesses)
}
@@ -191,7 +193,7 @@ export default class NpcRollDialog extends HandlebarsApplicationMixin(foundry.ap
: game.i18n.localize("VERMINE.defense_esquive"))
: this.label
await VermineUtils.roll({
const rollParams = {
actor: this.#actor,
NoD: this.getPoolBreakdown().total,
Reroll: this.rerolls,
@@ -201,8 +203,12 @@ export default class NpcRollDialog extends HandlebarsApplicationMixin(foundry.ap
bonusSuccesses: this.freeSuccesses,
poolBreakdown: this.getPoolBreakdown(),
messageFlags: this.defense ? { "vermine-defense": this.defense } : null
})
}
// Fermeture immédiate du dialogue : le jet (et l'animation 3D) continue
// en arrière-plan sans bloquer la fermeture.
this.close()
await VermineUtils.roll(rollParams)
}
}
+11 -5
View File
@@ -1,4 +1,5 @@
import { VermineUtils } from "../roll.mjs";
import { VermineExchange } from "../exchange.mjs";
const { HandlebarsApplicationMixin } = foundry.applications.api;
@@ -164,8 +165,9 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
const specialty = specChecked ? 1 : 0;
const help = helped ? 1 : 0;
const tooling = tools ? 1 : 0;
const total = ability + skillPool + selfControl + specialty + help + tooling + group + experience;
return { ability, skill: skillPool, selfControl, specialty, help, tooling, group, experience, total };
const malus = VermineExchange.woundMalus(this.#actor);
const total = Math.max(0, ability + skillPool + selfControl + specialty + help + tooling + group + experience - malus);
return { ability, skill: skillPool, selfControl, specialty, help, tooling, group, experience, malus, total };
}
getDicePool() {
@@ -293,7 +295,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
#calculateBonusCount() {
const b = this.getPoolBreakdown();
return b.specialty + b.help + b.tooling + b.group + b.selfControl + b.experience;
return b.specialty + b.help + b.tooling + b.group + b.selfControl + b.experience - b.malus;
}
#refreshExperienceUI() {
@@ -448,7 +450,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
await group.update({ "system.experience.dice": groupPool - pulled });
}
await VermineUtils.roll({
const rollParams = {
actor: this.#actor,
NoD: this.getDicePool(),
Reroll: this.getReroll(),
@@ -467,9 +469,13 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
weapon: this.weapon?.toObject() ?? null,
targets: [...game.user.targets].map(t => t.name),
messageFlags: this.defense ? { "vermine-defense": this.defense } : null
});
};
// Fermeture immédiate du dialogue : le jet (et l'animation 3D) continue
// en arrière-plan sans bloquer la fermeture.
this.close();
await VermineUtils.roll(rollParams);
}
}