Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31f2f4530c |
+25
-2
@@ -241,6 +241,28 @@
|
||||
"success_count": "Success Count",
|
||||
"success_required": "Success Required",
|
||||
"test_of": "Test of",
|
||||
"roll_success": "Success",
|
||||
"roll_failure": "Failure",
|
||||
"roll_context": "Roll context",
|
||||
"roll_pool": "Dice pool",
|
||||
"roll_dice": "Dice detail",
|
||||
"pool_ability": "Ability",
|
||||
"pool_skill": "Skill",
|
||||
"pool_specialty": "Specialty",
|
||||
"pool_help": "Help",
|
||||
"pool_tooling": "Equipment",
|
||||
"pool_group": "Group",
|
||||
"pool_selfControl": "Self-Control",
|
||||
"pool_total": "Total",
|
||||
"totem_used": "Totem",
|
||||
"totem_keep": "kept",
|
||||
"domain_bonus": "Domain bonus",
|
||||
"domain_penalty": "Domain penalty",
|
||||
"used": "used",
|
||||
"die_regular": "dice",
|
||||
"die_human": "human",
|
||||
"die_adapted": "adapted",
|
||||
"die_successes": "successes",
|
||||
"total": "Total",
|
||||
"totem_dice": "Totem Dice",
|
||||
"totem_hint": "Totem Hint",
|
||||
@@ -574,7 +596,7 @@
|
||||
"name": "Repulsion"
|
||||
},
|
||||
"tracks": {
|
||||
"name": "Tracks"
|
||||
"name": "Tracking"
|
||||
},
|
||||
"crafting": {
|
||||
"name": "Crafting"
|
||||
@@ -604,7 +626,7 @@
|
||||
"name": "Melee"
|
||||
},
|
||||
"archery": {
|
||||
"name": "Ranged"
|
||||
"name": "Ranged Weapons"
|
||||
},
|
||||
"throwing": {
|
||||
"name": "Throwing"
|
||||
@@ -656,6 +678,7 @@
|
||||
"Round": "Round"
|
||||
},
|
||||
"SIZE_LEVELS": {
|
||||
"tiny": "Insect",
|
||||
"small": "Small",
|
||||
"medium": "Medium",
|
||||
"large": "Large"
|
||||
|
||||
+26
-3
@@ -93,7 +93,7 @@
|
||||
"AGE_TYPES": {
|
||||
"young": "Jeune",
|
||||
"adult": "Adulte",
|
||||
"old": "Vieux"
|
||||
"old": "Ancien"
|
||||
},
|
||||
"IDENTITY": {
|
||||
"biography": "Biographie",
|
||||
@@ -188,6 +188,28 @@
|
||||
"grant_reroll": "accorder des relances",
|
||||
"success_count": "nombre de succès",
|
||||
"success_required": "succès requis",
|
||||
"roll_success": "Réussite",
|
||||
"roll_failure": "Échec",
|
||||
"roll_context": "Contexte du jet",
|
||||
"roll_pool": "Composition du jet",
|
||||
"roll_dice": "Détail des dés",
|
||||
"pool_ability": "Caractéristique",
|
||||
"pool_skill": "Compétence",
|
||||
"pool_specialty": "Spécialité",
|
||||
"pool_help": "Entraide",
|
||||
"pool_tooling": "Équipement",
|
||||
"pool_group": "Groupe",
|
||||
"pool_selfControl": "Sang-Froid",
|
||||
"pool_total": "Total",
|
||||
"totem_used": "Totem",
|
||||
"totem_keep": "gardé",
|
||||
"domain_bonus": "Bonus de domaine",
|
||||
"domain_penalty": "Malus de domaine",
|
||||
"used": "utilisé",
|
||||
"die_regular": "dés",
|
||||
"die_human": "humains",
|
||||
"die_adapted": "adaptés",
|
||||
"die_successes": "succès",
|
||||
"error_no_actor_selected": "Vous n'avez pas de personnage attitré ou de token sélectionné",
|
||||
"error_cannot_reroll": "Vous ne pouvez pas relancer un dés sur ce jet",
|
||||
"error_no_rerolls_left": "Plus de relances possibles",
|
||||
@@ -433,6 +455,7 @@
|
||||
"major": "Majeur"
|
||||
},
|
||||
"SIZE_LEVELS": {
|
||||
"tiny": "Insecte",
|
||||
"small": "Petit",
|
||||
"medium": "Moyen",
|
||||
"large": "Grand"
|
||||
@@ -596,7 +619,7 @@
|
||||
"name": "Répulsion"
|
||||
},
|
||||
"tracks": {
|
||||
"name": "Pistage"
|
||||
"name": "Traces"
|
||||
},
|
||||
"crafting": {
|
||||
"name": "Artisanat"
|
||||
@@ -617,7 +640,7 @@
|
||||
"name": "Armes à feu"
|
||||
},
|
||||
"archery": {
|
||||
"name": "Tir à l'arc"
|
||||
"name": "Armes de Tir"
|
||||
},
|
||||
"armory": {
|
||||
"name": "Armurerie"
|
||||
|
||||
+158
-1
@@ -44,6 +44,24 @@ body.system-vermine2047.theme-dark {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
// Core sheets the system doesn't restyle (RollTable, Journal, …) inherit the
|
||||
// gray text overrides above, which are unreadable on their dark backgrounds.
|
||||
// Restore Foundry's default light-on-dark text colors for those apps (dark theme only).
|
||||
body.system-vermine2047.theme-dark {
|
||||
.roll-table-sheet,
|
||||
.journal-sheet,
|
||||
.document-sheet,
|
||||
.settings-sheet {
|
||||
--color-text-primary: var(--color-light-2);
|
||||
--color-text-emphatic: var(--color-light-1);
|
||||
--color-text-secondary: var(--color-light-3);
|
||||
--color-text-subtle: var(--color-light-5);
|
||||
--color-text-light-highlight: #f0f0e0;
|
||||
--color-text-light-heading: #c9c7b8;
|
||||
--color-text-light-primary: #b5b3a4;
|
||||
}
|
||||
}
|
||||
|
||||
body.system-vermine2047.theme-dark .form-group > label {
|
||||
color: #777777;
|
||||
}
|
||||
@@ -97,6 +115,21 @@ ul.unstyled {
|
||||
}
|
||||
}
|
||||
|
||||
// Les fenêtres de choix (totem, acteur) peuvent dépasser la hauteur fixe :
|
||||
// on autorise le défilement pour accéder à la totalité du contenu.
|
||||
.application#TOTEM_PICKER .window-content,
|
||||
.application#ACTOR_PICKER .window-content,
|
||||
.application#TRAIT_SELECTOR .window-content {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
// La fiche de groupe contient beaucoup de zones (membres, objectifs, totem…) :
|
||||
// dès que le contenu dépasse la hauteur de la fenêtre, on autorise le défilement
|
||||
// pour ne pas perdre l'accès aux zones du bas.
|
||||
.application.sheet.vermine2047.group .window-content {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.window-content .row {
|
||||
&.smb { margin-bottom: 0.25rem; }
|
||||
&.mdb { margin-bottom: 0.5rem; }
|
||||
@@ -113,6 +146,29 @@ ul.unstyled {
|
||||
|
||||
.rollable {
|
||||
.transition();
|
||||
|
||||
// Affordance légère au repos : la zone est cliquable.
|
||||
i.fa-dice-d10,
|
||||
i.fa-dice {
|
||||
font-size: 0.8em;
|
||||
color: @color-acid-green;
|
||||
}
|
||||
}
|
||||
|
||||
// Sur la fiche créature, les valeurs lançables (Attaque…) sont fortement
|
||||
// matérialisées : pastille de dé + bordure pointillée.
|
||||
.application.sheet.vermine2047.creature {
|
||||
.rollable {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
color: @theme-color-light;
|
||||
border: 1px dashed fade(@color-acid-green, 45%);
|
||||
background: fade(@color-acid-green, 8%);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
img.profile-img {
|
||||
@@ -420,7 +476,7 @@ body.system-vermine2047 img#logo {
|
||||
}
|
||||
|
||||
.item-name {
|
||||
padding-left: 5px;
|
||||
padding: 0 2px 0 5px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@@ -674,6 +730,107 @@ ol.chat-log {
|
||||
color: @color-amber;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Verdict ───────────────────────────────────────────────────────
|
||||
.roll-verdict {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin: 6px 0;
|
||||
padding: 6px 12px;
|
||||
border-radius: 3px;
|
||||
font-family: "DistressBlack";
|
||||
text-transform: uppercase;
|
||||
font-size: @font-size-16;
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
&.success {
|
||||
color: @color-acid-green;
|
||||
background: fade(@color-acid-green, 15%);
|
||||
border: 1px solid @color-acid-green;
|
||||
}
|
||||
|
||||
&.failure {
|
||||
color: @color-hemolymph;
|
||||
background: fade(@color-hemolymph, 15%);
|
||||
border: 1px solid @color-hemolymph;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Contexte du jet ───────────────────────────────────────────────
|
||||
div.roll-context {
|
||||
gap: 6px 12px;
|
||||
margin: 4px 0 6px;
|
||||
padding: 6px 8px;
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
|
||||
.context-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
|
||||
.context-label {
|
||||
font-family: "DistressBlack";
|
||||
text-transform: uppercase;
|
||||
font-size: @font-size-11;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.context-value {
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: @font-size-12;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.totem-human .context-value { color: @totem-human-color; }
|
||||
&.totem-adapted .context-value { color: @totem-adapted-color; }
|
||||
}
|
||||
}
|
||||
|
||||
// ── Composition du jet ────────────────────────────────────────────
|
||||
div.roll-pool {
|
||||
margin: 4px 0;
|
||||
|
||||
h4 {
|
||||
font-family: "DistressBlack";
|
||||
text-transform: uppercase;
|
||||
font-size: @font-size-11;
|
||||
margin: 4px 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.pool-breakdown {
|
||||
gap: 4px 10px;
|
||||
|
||||
.pool-item {
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: @font-size-11;
|
||||
|
||||
&.pool-total {
|
||||
font-weight: 700;
|
||||
color: @theme-color-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Résumé des dés ────────────────────────────────────────────────
|
||||
div.roll-dice-summary {
|
||||
gap: 6px 12px;
|
||||
justify-content: center;
|
||||
margin: 4px 0 2px;
|
||||
padding: 4px 8px;
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
|
||||
.die-summary {
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: @font-size-11;
|
||||
|
||||
&.human { color: @totem-human-color; }
|
||||
&.adapted { color: @totem-adapted-color; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.item-card header img {
|
||||
|
||||
@@ -51,6 +51,7 @@ export default class VermineCharacterSheetV2 extends VermineBaseActorSheet {
|
||||
case "main": break
|
||||
case "abilities":
|
||||
context.tab = context.tabs.abilities
|
||||
context.specialties = doc.itemTypes.specialty
|
||||
break
|
||||
case "totem":
|
||||
context.tab = context.tabs.totem
|
||||
|
||||
@@ -2,6 +2,10 @@ import VermineBaseActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class VermineCreatureSheetV2 extends VermineBaseActorSheet {
|
||||
|
||||
// La fiche créature s'ouvre en mode édition : Gabarit, Taille, Rôle et Meute
|
||||
// se règlent dès l'ouverture (le mode jeu reste accessible via le toggle).
|
||||
_sheetMode = this.constructor.SHEET_MODES.EDIT
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["creature"],
|
||||
position: { width: 700, height: 650 },
|
||||
@@ -61,10 +65,22 @@ export default class VermineCreatureSheetV2 extends VermineBaseActorSheet {
|
||||
break
|
||||
case "stats":
|
||||
context.tab = context.tabs.stats
|
||||
context.patternLabel = doc.system.pattern?.value ? CONFIG.VERMINE.creaturePatternLevels[doc.system.pattern.value]?.label : ""
|
||||
context.sizeLabel = doc.system.size?.value || ""
|
||||
context.roleLabel = doc.system.role?.value ? CONFIG.VERMINE.creatureRoleLevels[doc.system.role.value]?.label : ""
|
||||
context.patternLabel = doc.system.pattern?.value ? game.i18n.localize(CONFIG.VERMINE.creaturePatternLevels[doc.system.pattern.value]?.label ?? "") : ""
|
||||
context.sizeLabel = doc.system.size?.value !== undefined ? game.i18n.localize(CONFIG.VERMINE.creatureSizeLevels[doc.system.size.value]?.label ?? "") : ""
|
||||
context.roleLabel = doc.system.role?.value ? game.i18n.localize(CONFIG.VERMINE.creatureRoleLevels[doc.system.role.value]?.label ?? "") : ""
|
||||
context.packLabel = doc.system.pack?.value || game.i18n.localize("VERMINE.none")
|
||||
// Contribution cumulée de la Taille (les modificateurs se cumulent : Taille N = somme 1..N)
|
||||
const sizeLevels = CONFIG.VERMINE.creatureSizeLevels || {}
|
||||
const sizeLevel = doc.system.size?.value ?? 0
|
||||
context.sizeCumulative = { attack: 0, vigor: 0, minorWound: 0, majorWound: 0, deadlyWound: 0 }
|
||||
for (let i = 1; i <= sizeLevel; i++) {
|
||||
const cfg = sizeLevels[i] || {}
|
||||
context.sizeCumulative.attack += cfg.attack || 0
|
||||
context.sizeCumulative.vigor += cfg.vigor || 0
|
||||
context.sizeCumulative.minorWound += cfg.minorWound || 0
|
||||
context.sizeCumulative.majorWound += cfg.majorWound || 0
|
||||
context.sizeCumulative.deadlyWound += cfg.deadlyWound || 0
|
||||
}
|
||||
break
|
||||
case "combat":
|
||||
context.tab = context.tabs.combat
|
||||
@@ -77,4 +93,25 @@ export default class VermineCreatureSheetV2 extends VermineBaseActorSheet {
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override - Les créatures n'ont pas de caractéristiques/compétences : on lance directement le pool d'attaque. */
|
||||
async _onRoll(event) {
|
||||
event.preventDefault()
|
||||
const el = event.currentTarget
|
||||
const type = el.dataset.type
|
||||
if (type !== "creature-attack") return super._onRoll(event)
|
||||
const pool = this.document.system.computed?.attack ?? 0
|
||||
if (!pool) {
|
||||
ui.notifications.warn(game.i18n.localize("VERMINE.error_select_ability"))
|
||||
return
|
||||
}
|
||||
const difficulty = this.document.system.combatStatus?.difficulty ?? 7
|
||||
const { VermineUtils } = await import("../../system/roll.mjs")
|
||||
await VermineUtils.roll({
|
||||
actor: this.document,
|
||||
NoD: pool,
|
||||
difficulty: parseInt(difficulty, 10),
|
||||
rollLabel: game.i18n.localize("ADVERSITY.attack")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ import VermineBaseActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
|
||||
|
||||
// La fiche PNJ s'ouvre en mode édition : caractéristiques, compétences et
|
||||
// niveaux se règlent dès l'ouverture (le mode jeu reste accessible via le toggle).
|
||||
_sheetMode = this.constructor.SHEET_MODES.EDIT
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["npc"],
|
||||
position: { width: 750, height: 680 },
|
||||
|
||||
@@ -219,7 +219,7 @@ const reqInt = { required: true, nullable: false, integer: true }
|
||||
export function raritySchema() {
|
||||
const fields = foundry.data.fields
|
||||
return new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...reqInt, initial: 3, min: 1, max: 5 }),
|
||||
value: new fields.NumberField({ ...reqInt, initial: 3, min: 1, max: 10 }),
|
||||
handicap: new fields.NumberField({ ...reqInt, initial: 0, min: 0 })
|
||||
})
|
||||
}
|
||||
|
||||
+32
-11
@@ -48,7 +48,7 @@ export default class VermineCreatureData extends foundry.abstract.TypeDataModel
|
||||
|
||||
// Niveaux de créature (patron, taille, rôle, meute)
|
||||
pattern: attributeSchema(1, 1, 4),
|
||||
size: attributeSchema(1, 1, 3),
|
||||
size: attributeSchema(0, 0, 3),
|
||||
role: attributeSchema(1, 1, 4),
|
||||
pack: attributeSchema(0, 0, 3),
|
||||
|
||||
@@ -97,28 +97,38 @@ export default class VermineCreatureData extends foundry.abstract.TypeDataModel
|
||||
*/
|
||||
_calculateCreatureComputedValues() {
|
||||
const patternLevel = this.pattern?.value || 1
|
||||
const sizeLevel = this.size?.value || 1
|
||||
const sizeLevel = this.size?.value || 0
|
||||
const roleLevel = this.role?.value || 1
|
||||
const packLevel = this.pack?.value || 0
|
||||
|
||||
const patternConfig = CONFIG.VERMINE.creaturePatternLevels[patternLevel] || {}
|
||||
const sizeConfig = CONFIG.VERMINE.creatureSizeLevels[sizeLevel] || {}
|
||||
const roleConfig = CONFIG.VERMINE.creatureRoleLevels[roleLevel] || {}
|
||||
const packConfig = CONFIG.VERMINE.creaturePackLevels[packLevel] || {}
|
||||
|
||||
// Les modificateurs de Taille se cumulent : une créature de Taille N applique
|
||||
// les modificateurs de chaque Taille de 1 à N (Taille 0 = insecte, aucun).
|
||||
const sizeLevels = CONFIG.VERMINE.creatureSizeLevels || {}
|
||||
let sizeAttack = 0
|
||||
let sizeVigor = 0
|
||||
for (let i = 1; i <= sizeLevel; i++) {
|
||||
const cfg = sizeLevels[i] || {}
|
||||
sizeAttack += cfg.attack || 0
|
||||
sizeVigor += cfg.vigor || 0
|
||||
}
|
||||
|
||||
// Attaque : patron + taille + meute + réaction du rôle
|
||||
this.computed.attack = (patternConfig.attack || 0)
|
||||
+ (sizeConfig.attack || 0)
|
||||
+ sizeAttack
|
||||
+ (packConfig.attack || 0)
|
||||
+ (roleConfig.reaction || 0)
|
||||
|
||||
// Dégâts : patron + vigueur de taille + meute
|
||||
this.computed.damage = (patternConfig.damage || 0)
|
||||
+ (sizeConfig.vigor || 0)
|
||||
+ sizeVigor
|
||||
+ (packConfig.damage || 0)
|
||||
|
||||
// Vigueur : taille + meute
|
||||
this.computed.vigor = (sizeConfig.vigor || 0) + (packConfig.damage || 0)
|
||||
this.computed.vigor = sizeVigor + (packConfig.damage || 0)
|
||||
|
||||
// Réaction : rôle
|
||||
this.computed.reaction = (roleConfig.reaction || 0) + (roleConfig.reaction_bonus || 0)
|
||||
@@ -141,21 +151,32 @@ export default class VermineCreatureData extends foundry.abstract.TypeDataModel
|
||||
*/
|
||||
_calculateCreatureWoundThresholds() {
|
||||
const patternLevel = this.pattern?.value || 1
|
||||
const sizeLevel = this.size?.value || 1
|
||||
const sizeLevel = this.size?.value || 0
|
||||
const packLevel = this.pack?.value || 0
|
||||
|
||||
const patternConfig = CONFIG.VERMINE.creaturePatternLevels[patternLevel] || {}
|
||||
const sizeConfig = CONFIG.VERMINE.creatureSizeLevels[sizeLevel] || {}
|
||||
const packConfig = CONFIG.VERMINE.creaturePackLevels[packLevel] || {}
|
||||
|
||||
// Les modificateurs de Taille se cumulent (Taille N = somme des tailles 1..N).
|
||||
const sizeLevels = CONFIG.VERMINE.creatureSizeLevels || {}
|
||||
let sizeMinor = 0
|
||||
let sizeMajor = 0
|
||||
let sizeDeadly = 0
|
||||
for (let i = 1; i <= sizeLevel; i++) {
|
||||
const cfg = sizeLevels[i] || {}
|
||||
sizeMinor += cfg.minorWound || 0
|
||||
sizeMajor += cfg.majorWound || 0
|
||||
sizeDeadly += cfg.deadlyWound || 0
|
||||
}
|
||||
|
||||
this.minorWound.threshold = (patternConfig.minorWound || 0)
|
||||
+ (sizeConfig.minorWound || 0)
|
||||
+ sizeMinor
|
||||
+ (packConfig.minorWound || 0)
|
||||
this.majorWound.threshold = (patternConfig.majorWound || 0)
|
||||
+ (sizeConfig.majorWound || 0)
|
||||
+ sizeMajor
|
||||
+ (packConfig.majorWound || 0)
|
||||
this.deadlyWound.threshold = (patternConfig.deadlyWound || 0)
|
||||
+ (sizeConfig.deadlyWound || 0)
|
||||
+ sizeDeadly
|
||||
+ (packConfig.deadlyWound || 0)
|
||||
|
||||
// Max de blessures
|
||||
|
||||
@@ -10,9 +10,11 @@ export default class VermineSpecialtyData extends foundry.abstract.TypeDataModel
|
||||
/** @override */
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const reqInt = { required: true, nullable: false, integer: true }
|
||||
return {
|
||||
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
skill: new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
skill: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
level: new fields.NumberField({ ...reqInt, initial: 1, min: 0, max: 5 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,9 +139,10 @@ VERMINE.creaturePatternLevels = {
|
||||
* Creature Size Levels configuration
|
||||
*/
|
||||
VERMINE.creatureSizeLevels = {
|
||||
1: { "label": "SIZE_LEVELS.small", "attack": 2, "vigor": 1, "minorWound": 0, "majorWound": 0, "deadlyWound": 1 },
|
||||
2: { "label": "SIZE_LEVELS.medium", "attack": 3, "vigor": 2, "minorWound": 0, "majorWound": 1, "deadlyWound": 1 },
|
||||
3: { "label": "SIZE_LEVELS.large", "attack": 4, "vigor": 3, "minorWound": 1, "majorWound": 1, "deadlyWound": 1 }
|
||||
0: { "label": "SIZE_LEVELS.tiny", "attack": 0, "vigor": 0, "minorWound": 0, "majorWound": 0, "deadlyWound": 0 },
|
||||
1: { "label": "SIZE_LEVELS.small", "attack": 1, "vigor": 1, "minorWound": 0, "majorWound": 1, "deadlyWound": 1 },
|
||||
2: { "label": "SIZE_LEVELS.medium", "attack": 2, "vigor": 2, "minorWound": 2, "majorWound": 2, "deadlyWound": 2 },
|
||||
3: { "label": "SIZE_LEVELS.large", "attack": 3, "vigor": 3, "minorWound": 3, "majorWound": 3, "deadlyWound": 3 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -112,18 +112,32 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
|
||||
#getHandicap() { return this.#el.querySelector("#handicap"); }
|
||||
#getSelfCtrl() { return this.#el.querySelector("#self_control"); }
|
||||
|
||||
getDicePool() {
|
||||
/** Décomposition du pool de dés pour affichage dans le message. */
|
||||
getPoolBreakdown() {
|
||||
const abil = this.#getAbility();
|
||||
const abilVal = parseInt(abil?.options[abil?.selectedIndex]?.value, 10) || 0;
|
||||
const ability = parseInt(abil?.options[abil?.selectedIndex]?.value, 10) || 0;
|
||||
const skill = this.#getSkill();
|
||||
const skillPool = parseInt(skill?.options[skill?.selectedIndex]?.dataset?.pool, 10) || 0;
|
||||
const sc = parseInt(this.#getSelfCtrl()?.value, 10) || 0;
|
||||
const specChecked = this.#el.querySelector("#usingSpecialization")?.checked;
|
||||
const selfControl = parseInt(this.#getSelfCtrl()?.value, 10) || 0;
|
||||
const specChecked = this.hasSpecialtySelected();
|
||||
const helped = this.#el.querySelector("#helped")?.checked;
|
||||
const tools = this.#el.querySelector("input[name='usingTools']:checked")?.value !== "0";
|
||||
const toolsChecked = this.#el.querySelector("input[name='usingTools']:checked");
|
||||
const tools = toolsChecked && toolsChecked.value !== "0";
|
||||
const group = parseInt(this.#el.querySelector("#group")?.value, 10) || 0;
|
||||
const bonuses = (specChecked ? 1 : 0) + (helped ? 1 : 0) + (tools ? 1 : 0) + group;
|
||||
return (abilVal + sc + skillPool + bonuses) || 0;
|
||||
const specialty = specChecked ? 1 : 0;
|
||||
const help = helped ? 1 : 0;
|
||||
const tooling = tools ? 1 : 0;
|
||||
const total = ability + skillPool + selfControl + specialty + help + tooling + group;
|
||||
return { ability, skill: skillPool, selfControl, specialty, help, tooling, group, total };
|
||||
}
|
||||
|
||||
getDicePool() {
|
||||
return this.getPoolBreakdown().total;
|
||||
}
|
||||
|
||||
getSpecialtyName() {
|
||||
const checked = this.#el.querySelector("input[name='usingSpecialization']:checked");
|
||||
return checked && checked.value !== "aucune" ? checked.value : null;
|
||||
}
|
||||
|
||||
getDifficultySelect() {
|
||||
@@ -207,14 +221,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
|
||||
}
|
||||
|
||||
#calculateBonusCount() {
|
||||
let b = 0;
|
||||
if (this.#el.querySelector("#helped")?.checked) b += 1;
|
||||
b += parseInt(this.#el.querySelector("#group")?.value, 10) || 0;
|
||||
b += parseInt(this.#getSelfCtrl()?.value, 10) || 0;
|
||||
const tools = this.#el.querySelector("input[name='usingTools']:checked");
|
||||
if (tools && tools.value !== "0") b += 1;
|
||||
if (this.hasSpecialtySelected()) b += 1;
|
||||
return b;
|
||||
const b = this.getPoolBreakdown();
|
||||
return b.specialty + b.help + b.tooling + b.group + b.selfControl;
|
||||
}
|
||||
|
||||
#updateUI() {
|
||||
@@ -315,7 +323,9 @@ export default class RollDialog extends HandlebarsApplicationMixin(foundry.appli
|
||||
keepTotem: this.getKeepTotem(),
|
||||
skillCategory: this.getSkillCategory(),
|
||||
skillLevel: this.getSkillLevel(),
|
||||
hasSpecialty: this.hasSpecialtySelected()
|
||||
hasSpecialty: this.hasSpecialtySelected(),
|
||||
poolBreakdown: this.getPoolBreakdown(),
|
||||
specialtyName: this.getSpecialtyName()
|
||||
});
|
||||
|
||||
this.close();
|
||||
|
||||
@@ -32,6 +32,7 @@ export const preloadHandlebarsTemplates = async function () {
|
||||
// npc partials
|
||||
"systems/vermine2047/templates/actor/npc/npc-combat.hbs",
|
||||
"systems/vermine2047/templates/actor/parts/npc-skill-category.hbs",
|
||||
"systems/vermine2047/templates/actor/parts/npc-skill-item.hbs",
|
||||
|
||||
// creature partials
|
||||
"systems/vermine2047/templates/actor/creature/creature-combat.hbs",
|
||||
@@ -100,6 +101,21 @@ export const registerHandlebarsHelpers = function () {
|
||||
return game.i18n.localize(arrayLabel + "." + objectLabel + ".name");
|
||||
});
|
||||
|
||||
// Return an object of skills ordered alphabetically by their localized
|
||||
// display name (easier to find a skill quickly). Use with `{{#each}}`.
|
||||
Handlebars.registerHelper('sortedSkills', function (skills) {
|
||||
if (!skills || typeof skills !== 'object') return skills;
|
||||
const sorted = {};
|
||||
Object.keys(skills)
|
||||
.sort((a, b) => {
|
||||
const na = game.i18n.localize(`SKILLS.${a}.name`).toLocaleLowerCase();
|
||||
const nb = game.i18n.localize(`SKILLS.${b}.name`).toLocaleLowerCase();
|
||||
return na.localeCompare(nb, game.i18n.lang);
|
||||
})
|
||||
.forEach(k => { sorted[k] = skills[k]; });
|
||||
return sorted;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('smarttlk', function (arrayLabel, objectLabel, key) {
|
||||
return game.i18n.localize(arrayLabel + "." + objectLabel + "." + key);
|
||||
});
|
||||
@@ -347,6 +363,9 @@ export const registerHandlebarsHelpers = function () {
|
||||
Handlebars.registerHelper('ifincludes', function (arg1, arg2, options) {
|
||||
return (arg1.includes(arg2)) ? options.fn(this) : options.inverse(this);
|
||||
});
|
||||
Handlebars.registerHelper('ifStartsWith', function (arg1, arg2, options) {
|
||||
return (typeof arg1 === 'string' && arg1.startsWith(arg2)) ? options.fn(this) : options.inverse(this);
|
||||
});
|
||||
|
||||
|
||||
//math operations
|
||||
|
||||
+114
-28
@@ -29,7 +29,9 @@ export class VermineUtils {
|
||||
keepTotem = null,
|
||||
skillLevel = null,
|
||||
hasSpecialty = false,
|
||||
handicap = 0
|
||||
handicap = 0,
|
||||
poolBreakdown = null,
|
||||
specialtyName = null
|
||||
}) {
|
||||
// Validate inputs
|
||||
if (!actor) {
|
||||
@@ -105,6 +107,27 @@ export class VermineUtils {
|
||||
// Build final formula
|
||||
formula = modFormula !== null ? `${baseFormula}+${modFormula}` : baseFormula;
|
||||
|
||||
// Reconcile the breakdown displayed in chat with the dice actually rolled.
|
||||
// Domain bonuses/malus are only applied when the corresponding totem die
|
||||
// is used, and totem dice replace (not add to) base-pool dice.
|
||||
if (poolBreakdown) {
|
||||
// Count totem dice present in the final modifier formula.
|
||||
let totemDice = 0;
|
||||
if (modFormula) {
|
||||
if (modFormula.includes("human_")) totemDice += 1;
|
||||
if (modFormula.includes("adapted_")) totemDice += 1;
|
||||
}
|
||||
// Only count the domain bonus of totems actually activated in the roll.
|
||||
const domainBonus = (totems.human ? totemBonus.human : 0)
|
||||
+ (totems.adapted ? totemBonus.adapted : 0);
|
||||
const basePool = poolBreakdown.total;
|
||||
poolBreakdown.totemDice = totemDice;
|
||||
poolBreakdown.domainBonus = domainBonus;
|
||||
// Total = nombre réel de dés lancés (NoD réguliers + dés de totem).
|
||||
// Équivaut à basePool + domainBonus sauf si le pool régulier clampe à 0.
|
||||
poolBreakdown.total = NoD + totemDice;
|
||||
}
|
||||
|
||||
// Create the roll
|
||||
const roll = new Roll(formula, actor.getRollData());
|
||||
|
||||
@@ -143,7 +166,9 @@ export class VermineUtils {
|
||||
keepTotem,
|
||||
skillLevel,
|
||||
hasSpecialty,
|
||||
handicap
|
||||
handicap,
|
||||
poolBreakdown,
|
||||
specialtyName
|
||||
});
|
||||
|
||||
return roll;
|
||||
@@ -199,10 +224,10 @@ export class VermineUtils {
|
||||
/**
|
||||
* Handles reroll events on dice in chat messages.
|
||||
* @param {Object} message - The chat message containing the reroll event
|
||||
* @param {Object} ev - The reroll event
|
||||
* @param {HTMLElement} target - The clicked die element
|
||||
* @returns {Promise<boolean>} Whether the reroll was successful
|
||||
*/
|
||||
static async onReroll(message, ev) {
|
||||
static async onReroll(message, target) {
|
||||
// Verify user permissions
|
||||
const msgUserId = message.user?.id ?? message.user;
|
||||
if (msgUserId !== game.user?.id && !game.user?.isGM) {
|
||||
@@ -211,7 +236,7 @@ export class VermineUtils {
|
||||
}
|
||||
|
||||
// Get reroll count
|
||||
const rollMessage = ev.currentTarget.closest('div.vermine-roll-message');
|
||||
const rollMessage = target.closest('div.vermine-roll-message');
|
||||
if (!rollMessage) {
|
||||
return false;
|
||||
}
|
||||
@@ -221,22 +246,22 @@ export class VermineUtils {
|
||||
// Check if rerolls are available
|
||||
if (!rerollCount || parseInt(rerollCount, 10) < 1) {
|
||||
ui.notifications.warn(game.i18n.localize('VERMINE.error_no_rerolls_left'));
|
||||
const rerollables = ev.currentTarget.closest('ul')?.querySelectorAll('.rerollable');
|
||||
const rerollables = target.closest('ul')?.querySelectorAll('.rerollable');
|
||||
if (rerollables) {
|
||||
rerollables.forEach(el => el.classList.remove('rerollable'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ev.currentTarget.classList.add('rerolled');
|
||||
target.classList.add('rerolled');
|
||||
|
||||
// Set reroll flag
|
||||
await message.setFlag("world", "reroll", true);
|
||||
|
||||
// Get difficulty and dice type
|
||||
const ulElement = ev.currentTarget.closest('ul');
|
||||
const ulElement = target.closest('ul');
|
||||
const difficulty = ulElement?.dataset.difficulty ?? 7;
|
||||
let diceType = ev.currentTarget.dataset.diceType;
|
||||
let diceType = target.dataset.diceType;
|
||||
|
||||
// Sanitize user name
|
||||
const safeUserName = (game.user?.name ?? "user").replace(/[^a-zA-Z0-9_]/g, '_');
|
||||
@@ -265,30 +290,68 @@ export class VermineUtils {
|
||||
|
||||
// Update die display
|
||||
const result = reroll.dice[0]?.results[0]?.result ?? 0;
|
||||
const dieSpan = ev.currentTarget.querySelector('span');
|
||||
const dieSpan = target.querySelector('span');
|
||||
if (dieSpan) {
|
||||
dieSpan.innerText = result;
|
||||
}
|
||||
// Update the face used for the CSS background image.
|
||||
target.dataset.result = result;
|
||||
|
||||
// Update total if successful
|
||||
// Set/clear the success class from the rerolled die (a previous success
|
||||
// must be removed if the new result fails).
|
||||
const success = reroll.dice[0]?.results[0]?.success;
|
||||
if (success) {
|
||||
ev.currentTarget.classList.add('success');
|
||||
const totalElement = rollMessage.querySelector('#total');
|
||||
if (totalElement) {
|
||||
const currentTotal = parseInt(totalElement.innerText, 10) || 0;
|
||||
totalElement.innerText = currentTotal + reroll.total;
|
||||
}
|
||||
target.classList.toggle('success', !!success);
|
||||
target.classList.remove("rerollable");
|
||||
|
||||
// Recompute the total from the live dice in the DOM. This avoids the
|
||||
// cumulative-increment drift of the old logic (which never removed a
|
||||
// removed success from #total). Totem dice (human/adapted) count double.
|
||||
const totalEl = rollMessage.querySelector('#total');
|
||||
if (totalEl) {
|
||||
let total = 0;
|
||||
rollMessage.querySelectorAll('li.die.success').forEach(die => {
|
||||
const isTotem = die.classList.contains('human') || die.classList.contains('adapted');
|
||||
total += isTotem ? 2 : 1;
|
||||
});
|
||||
totalEl.innerText = total;
|
||||
}
|
||||
|
||||
// Update message content
|
||||
ev.currentTarget.classList.remove("rerollable");
|
||||
|
||||
const messageContent = ev.currentTarget.closest('div.message-content');
|
||||
const messageContent = target.closest('div.message-content');
|
||||
if (messageContent) {
|
||||
const newRerollCount = parseInt(rerollCount, 10) - 1;
|
||||
rollMessage.querySelector('#allowed_reroll').innerText = newRerollCount;
|
||||
|
||||
|
||||
// Recompute the verdict banner from the recomputed total.
|
||||
const verdictEl = rollMessage.querySelector('.roll-verdict');
|
||||
const requiredEl = rollMessage.querySelector('#required');
|
||||
if (verdictEl && totalEl && requiredEl) {
|
||||
const total = parseInt(totalEl.innerText, 10) || 0;
|
||||
const required = parseInt(requiredEl.innerText, 10) || 1;
|
||||
const won = total >= required;
|
||||
verdictEl.classList.toggle('success', won);
|
||||
verdictEl.classList.toggle('failure', !won);
|
||||
const label = won
|
||||
? game.i18n.localize('VERMINE.roll_success')
|
||||
: game.i18n.localize('VERMINE.roll_failure');
|
||||
verdictEl.innerHTML = `${won ? '<i class="fas fa-check-circle"></i>' : '<i class="fas fa-times-circle"></i>'}<span>${label}</span>`;
|
||||
}
|
||||
|
||||
// Recompute the dice summary from the current die list.
|
||||
const summaryEl = rollMessage.querySelector('.roll-dice-summary');
|
||||
if (summaryEl) {
|
||||
const stats = { regular: { count: 0, success: 0 }, human: { count: 0, success: 0 }, adapted: { count: 0, success: 0 } };
|
||||
rollMessage.querySelectorAll('li.die').forEach(die => {
|
||||
const type = die.classList.contains('human') ? 'human' : die.classList.contains('adapted') ? 'adapted' : 'regular';
|
||||
stats[type].count += 1;
|
||||
if (die.classList.contains('success')) stats[type].success += 1;
|
||||
});
|
||||
const mk = (key, count, s) => count ? `<span class="die-summary ${key}">${count} ${game.i18n.localize(`VERMINE.die_${key}`)} · ${s} ${game.i18n.localize('VERMINE.die_successes')}</span>` : '';
|
||||
summaryEl.innerHTML = mk('regular', stats.regular.count, stats.regular.success)
|
||||
+ mk('human', stats.human.count, stats.human.success)
|
||||
+ mk('adapted', stats.adapted.count, stats.adapted.success);
|
||||
}
|
||||
|
||||
await message.update({
|
||||
content: messageContent.outerHTML
|
||||
});
|
||||
@@ -314,10 +377,11 @@ export class VermineUtils {
|
||||
html.querySelectorAll('.rerollable').forEach(el => {
|
||||
el.addEventListener('click', async (ev) => {
|
||||
ev.preventDefault();
|
||||
const msgId = ev.currentTarget.closest("li.message")?.dataset?.messageId;
|
||||
const dieEl = ev.currentTarget;
|
||||
const msgId = dieEl.closest("li.message")?.dataset?.messageId;
|
||||
if (msgId) {
|
||||
const message = await game.messages.get(msgId);
|
||||
await VermineUtils.onReroll(message, ev);
|
||||
await VermineUtils.onReroll(message, dieEl);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -336,6 +400,7 @@ export class VermineUtils {
|
||||
// Add click event for granting rerolls
|
||||
html.querySelectorAll("button.grant-reroll").forEach(el => {
|
||||
el.addEventListener('click', async (ev) => {
|
||||
const btn = ev.currentTarget;
|
||||
const grantedRerollElement = html.querySelector('#granted-reroll');
|
||||
const allowedRerollElement = html.querySelector("#allowed_reroll");
|
||||
|
||||
@@ -343,13 +408,13 @@ export class VermineUtils {
|
||||
allowedRerollElement.innerText = grantedRerollElement.innerText;
|
||||
}
|
||||
|
||||
const mesEl = ev.currentTarget.closest('[data-message-id]');
|
||||
const mesEl = btn.closest('[data-message-id]');
|
||||
const messageId = mesEl?.dataset?.messageId;
|
||||
|
||||
if (messageId) {
|
||||
ev.currentTarget.closest('.reroll-from-effort').style.display = "none";
|
||||
btn.closest('.reroll-from-effort').style.display = "none";
|
||||
|
||||
const rollMessage = ev.currentTarget.closest(".vermine-roll-message");
|
||||
const rollMessage = btn.closest(".vermine-roll-message");
|
||||
if (rollMessage) {
|
||||
const content = rollMessage.outerHTML;
|
||||
const message = await game.messages.get(messageId);
|
||||
@@ -401,7 +466,28 @@ export class VermineUtils {
|
||||
* @returns {Promise<ChatMessage>} The created chat message
|
||||
*/
|
||||
static async diplayChatRoll(roll, param) {
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/vermine2047/templates/roll-message.hbs", { roll, param });
|
||||
// Aggregate dice stats per type (regular / human / adapted)
|
||||
const diceStats = { regular: { count: 0, success: 0 }, human: { count: 0, success: 0 }, adapted: { count: 0, success: 0 } };
|
||||
for (const die of roll.dice ?? []) {
|
||||
// Flavors look like "<type>_<user>"; classify from the leading token.
|
||||
const flavor = die.options?.flavor ?? "";
|
||||
const prefix = flavor.split("_")[0];
|
||||
const type = prefix === "human" ? "human" : prefix === "adapted" ? "adapted" : "regular";
|
||||
for (const r of die.results ?? []) {
|
||||
diceStats[type].count += 1;
|
||||
if (r.success) diceStats[type].success += 1;
|
||||
}
|
||||
}
|
||||
// Verdict
|
||||
const required = 1 + (param.handicap ?? 0);
|
||||
const total = roll._total ?? 0;
|
||||
const verdict = {
|
||||
success: total >= required,
|
||||
total,
|
||||
required
|
||||
};
|
||||
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/vermine2047/templates/roll-message.hbs", { roll, param, diceStats, verdict });
|
||||
const chatData = {
|
||||
user: game.user?._id,
|
||||
speaker: ChatMessage.getSpeaker(),
|
||||
|
||||
@@ -221,6 +221,7 @@
|
||||
{{> "systems/vermine2047/templates/actor/parts/npc-skill-category.hbs"
|
||||
categoryKey=key
|
||||
categoryLabel=(concat "VERMINE.skill_category." key)
|
||||
skills=@root.system.skills
|
||||
}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
>
|
||||
{{/if}}
|
||||
</h4>
|
||||
{{#each @root.system.skills as |skill skey|}}
|
||||
{{#each (sortedSkills @root.system.skills) as |skill skey|}}
|
||||
|
||||
{{#if (eq skill.category sckey) }}
|
||||
<div class="ability flexrow ">
|
||||
@@ -79,12 +79,10 @@
|
||||
data-action="addSpecialty"
|
||||
></i>
|
||||
{{/ifgt}}
|
||||
{{#each skill.specialties as |spe ind|}}
|
||||
{{#each @root.specialties as |spe|}}
|
||||
{{#ife spe.system.skill skey}}
|
||||
<i
|
||||
class="specialty"
|
||||
data-tooltip="spécialité utilisable"
|
||||
>{{spe.name}}</i>
|
||||
<span class="specialty" data-tooltip="spécialité utilisable"
|
||||
>{{spe.name}}<sup>{{spe.system.level}}</sup></span>
|
||||
{{/ife}}
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
@@ -1,90 +1,4 @@
|
||||
<div class="tab equipment sheet-part" data-group="sheet" data-tab="equipment">
|
||||
<div class="grid grid-2col">
|
||||
<div>
|
||||
<ol class="items-list">
|
||||
<li class="item flexrow items-header">
|
||||
<div
|
||||
class="item-name"
|
||||
style="flex:4;"
|
||||
>{{ localize
|
||||
'IDENTITY.name'}}</div>
|
||||
<div class="item-quantity">{{ localize 'VERMINE.qty'}}</div>
|
||||
<div class="item-weight">{{ localize 'VERMINE.weight'}}</div>
|
||||
<div class="item-controls">
|
||||
{{#if isEditMode}}
|
||||
<a
|
||||
class="item-control item-create"
|
||||
title="Create item"
|
||||
data-action="create"
|
||||
data-type="item"
|
||||
><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{#each gear as |item id|}}
|
||||
<li
|
||||
class="item flexrow flex-group-center"
|
||||
data-item-id="{{item._id}}"
|
||||
>
|
||||
<div
|
||||
class="item-name"
|
||||
style="flex:4;"
|
||||
>
|
||||
<div class="item-image">
|
||||
<a
|
||||
class="item-control item-edit"
|
||||
data-action="edit"
|
||||
data-item-id="{{item._id}}"
|
||||
data-roll-type="item"
|
||||
><img
|
||||
src="{{item.img}}"
|
||||
title="{{item.name}}"
|
||||
width="24"
|
||||
height="24"
|
||||
/></a>
|
||||
</div>
|
||||
<a
|
||||
class="item-control item-edit"
|
||||
data-action="edit"
|
||||
data-item-id="{{item._id}}"
|
||||
data-tooltip="Edit Item"
|
||||
>{{item.name}} </a>
|
||||
|
||||
{{#if item.system.damages.value}}
|
||||
/
|
||||
<span data-tooltip="{{item.damagedLabel}}">{{{item.damagedIcon}}}</span>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">
|
||||
{{item.system.quantity}}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">
|
||||
{{item.system.weight}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if @root.isEditMode}}
|
||||
<a
|
||||
class="item-control item-delete"
|
||||
data-action="delete"
|
||||
data-item-id="{{item._id}}"
|
||||
title="Delete Item"
|
||||
><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ localize 'IDENTITY.notes'}}</h4>
|
||||
{{formInput systemFields.equipment.fields.description enriched=enrichedEquipmentNotes value=system.equipment.description name="system.equipment.description" toggled=true}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="weapons">
|
||||
<h4>{{localize 'ITEMS.weapons'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/parts/actor-weapons.hbs"}}
|
||||
@@ -93,4 +7,87 @@
|
||||
<h4>{{localize 'ITEMS.defenses'}}</h4>
|
||||
{{> "systems/vermine2047/templates/actor/parts/actor-defenses.hbs"}}
|
||||
</div>
|
||||
<div class="objects">
|
||||
<h4>{{localize 'ITEMS.items'}}</h4>
|
||||
<ol class="items-list">
|
||||
<li class="item flexrow items-header">
|
||||
<div
|
||||
class="item-name"
|
||||
style="flex:4;"
|
||||
>{{ localize
|
||||
'IDENTITY.name'}}</div>
|
||||
<div class="item-quantity">{{ localize 'VERMINE.qty'}}</div>
|
||||
<div class="item-weight">{{ localize 'VERMINE.weight'}}</div>
|
||||
<div class="item-controls">
|
||||
<a
|
||||
class="item-control item-create"
|
||||
title="Create item"
|
||||
data-action="create"
|
||||
data-type="item"
|
||||
><i class="fas fa-plus"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{#each gear as |item id|}}
|
||||
<li
|
||||
class="item flexrow flex-group-center"
|
||||
data-item-id="{{item._id}}"
|
||||
>
|
||||
<div
|
||||
class="item-name"
|
||||
style="flex:4;"
|
||||
>
|
||||
<div class="item-image">
|
||||
<a
|
||||
class="item-control item-edit"
|
||||
data-action="edit"
|
||||
data-item-id="{{item._id}}"
|
||||
data-roll-type="item"
|
||||
><img
|
||||
src="{{item.img}}"
|
||||
title="{{item.name}}"
|
||||
width="24"
|
||||
height="24"
|
||||
/></a>
|
||||
</div>
|
||||
<a
|
||||
class="item-control item-edit"
|
||||
data-action="edit"
|
||||
data-item-id="{{item._id}}"
|
||||
data-tooltip="Edit Item"
|
||||
>{{item.name}} </a>
|
||||
|
||||
{{#if item.system.damages.value}}
|
||||
/
|
||||
<span data-tooltip="{{item.damagedLabel}}">{{{item.damagedIcon}}}</span>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">
|
||||
{{item.system.quantity}}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="item-control item-edit" data-action="edit" data-item-id="{{item._id}}" title="Edit Item">
|
||||
{{item.system.weight}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if @root.isEditMode}}
|
||||
<a
|
||||
class="item-control item-delete"
|
||||
data-action="delete"
|
||||
data-item-id="{{item._id}}"
|
||||
title="Delete Item"
|
||||
><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="equipment-notes">
|
||||
<h4>{{ localize 'IDENTITY.notes'}}</h4>
|
||||
{{formInput systemFields.equipment.fields.description enriched=enrichedEquipmentNotes value=system.equipment.description name="system.equipment.description" toggled=true}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<div class="tab stats sheet-part" data-group="sheet" data-tab="stats">
|
||||
<h3>{{ localize 'VERMINE.base_values' }}</h3>
|
||||
|
||||
{{!-- Total attaque (lancable) --}}
|
||||
<div class="mdb align-center">
|
||||
<h4>{{ localize 'VERMINE.total_attack' }}</h4>
|
||||
<a class="rollable" data-type="creature-attack" data-label="attack" title="{{ localize 'VERMINE.roll' }}">{{ system.computed.attack }}<i class="fas fa-dice-d10"></i></a>
|
||||
</div>
|
||||
|
||||
<section class="grid grid-3col gap-md">
|
||||
<div class="mdb">
|
||||
<h4 class="align-center">{{ localize 'ADVERSITY.pattern' }}: {{ patternLabel }}</h4>
|
||||
@@ -16,12 +23,12 @@
|
||||
<div class="mdb">
|
||||
<h4 class="align-center">{{ localize 'ADVERSITY.size' }}: {{ sizeLabel }}</h4>
|
||||
<ul class="unstyled">
|
||||
<li>{{ localize 'ADVERSITY.attack' }}: {{ creatureSizeLevel "attack" system.size.value }}</li>
|
||||
<li>{{ localize 'ADVERSITY.vigor' }}: {{ creatureSizeLevel "vigor" system.size.value }}</li>
|
||||
<li>{{ localize 'ADVERSITY.attack' }}: {{ sizeCumulative.attack }}</li>
|
||||
<li>{{ localize 'ADVERSITY.vigor' }}: {{ sizeCumulative.vigor }}</li>
|
||||
<li>{{ localize 'ADVERSITY.wounds' }}:
|
||||
{{ creatureSizeLevel "minorWound" system.size.value }}/
|
||||
{{ creatureSizeLevel "majorWound" system.size.value }}/
|
||||
{{ creatureSizeLevel "deadlyWound" system.size.value }}
|
||||
{{ sizeCumulative.minorWound }}/
|
||||
{{ sizeCumulative.majorWound }}/
|
||||
{{ sizeCumulative.deadlyWound }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.physical' }}</h4>
|
||||
<div class="grid grid-2col">
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.vigor.value">{{ localize 'ABILITIES.vigor.name' }}</label>
|
||||
<label for="system.abilities.vigor.value" class="resource-label rollable" data-type="ability" data-label="vigor">{{ localize 'ABILITIES.vigor.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.vigor.value" value="{{system.abilities.vigor.value}}" min="{{system.abilities.vigor.min}}" max="{{system.abilities.vigor.max}}" data-dtype="Number"/>
|
||||
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.health.value">{{ localize 'ABILITIES.health.name' }}</label>
|
||||
<label for="system.abilities.health.value" class="resource-label rollable" data-type="ability" data-label="health">{{ localize 'ABILITIES.health.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.health.value" value="{{system.abilities.health.value}}" min="{{system.abilities.health.min}}" max="{{system.abilities.health.max}}" data-dtype="Number"/>
|
||||
@@ -31,7 +31,7 @@
|
||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.manual' }}</h4>
|
||||
<div class="grid grid-2col">
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.precision.value">{{ localize 'ABILITIES.precision.name' }}</label>
|
||||
<label for="system.abilities.precision.value" class="resource-label rollable" data-type="ability" data-label="precision">{{ localize 'ABILITIES.precision.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.precision.value" value="{{system.abilities.precision.value}}" min="{{system.abilities.precision.min}}" max="{{system.abilities.precision.max}}" data-dtype="Number"/>
|
||||
@@ -40,7 +40,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.reflexes.value">{{ localize 'ABILITIES.reflexes.name' }}</label>
|
||||
<label for="system.abilities.reflexes.value" class="resource-label rollable" data-type="ability" data-label="reflexes">{{ localize 'ABILITIES.reflexes.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.reflexes.value" value="{{system.abilities.reflexes.value}}" min="{{system.abilities.reflexes.min}}" max="{{system.abilities.reflexes.max}}" data-dtype="Number"/>
|
||||
@@ -56,7 +56,7 @@
|
||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.mental' }}</h4>
|
||||
<div class="grid grid-2col">
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.knowledge.value">{{ localize 'ABILITIES.knowledge.name' }}</label>
|
||||
<label for="system.abilities.knowledge.value" class="resource-label rollable" data-type="ability" data-label="knowledge">{{ localize 'ABILITIES.knowledge.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.knowledge.value" value="{{system.abilities.knowledge.value}}" min="{{system.abilities.knowledge.min}}" max="{{system.abilities.knowledge.max}}" data-dtype="Number"/>
|
||||
@@ -65,7 +65,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.perception.value">{{ localize 'ABILITIES.perception.name' }}</label>
|
||||
<label for="system.abilities.perception.value" class="resource-label rollable" data-type="ability" data-label="perception">{{ localize 'ABILITIES.perception.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.perception.value" value="{{system.abilities.perception.value}}" min="{{system.abilities.perception.min}}" max="{{system.abilities.perception.max}}" data-dtype="Number"/>
|
||||
@@ -81,7 +81,7 @@
|
||||
<h4 class="ability-category-header">{{ localize 'VERMINE.ability_category.social' }}</h4>
|
||||
<div class="grid grid-2col">
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.will.value">{{ localize 'ABILITIES.will.name' }}</label>
|
||||
<label for="system.abilities.will.value" class="resource-label rollable" data-type="ability" data-label="will">{{ localize 'ABILITIES.will.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.will.value" value="{{system.abilities.will.value}}" min="{{system.abilities.will.min}}" max="{{system.abilities.will.max}}" data-dtype="Number"/>
|
||||
@@ -90,7 +90,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-item">
|
||||
<label for="system.abilities.empathy.value">{{ localize 'ABILITIES.empathy.name' }}</label>
|
||||
<label for="system.abilities.empathy.value" class="resource-label rollable" data-type="ability" data-label="empathy">{{ localize 'ABILITIES.empathy.name' }}</label>
|
||||
<div class="ability-control">
|
||||
{{#if isEditMode}}
|
||||
<input type="range" name="system.abilities.empathy.value" value="{{system.abilities.empathy.value}}" min="{{system.abilities.empathy.min}}" max="{{system.abilities.empathy.max}}" data-dtype="Number"/>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
{{> "systems/vermine2047/templates/actor/parts/npc-skill-category.hbs"
|
||||
categoryKey=key
|
||||
categoryLabel=(concat "VERMINE.skill_category." key)
|
||||
skills=@root.system.skills
|
||||
}}
|
||||
{{/ife}}
|
||||
{{/each}}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
{{/ife}}
|
||||
>
|
||||
</h4>
|
||||
{{#each @root.system.skills as |skill skey|}}
|
||||
{{#each (sortedSkills @root.system.skills) as |skill skey|}}
|
||||
|
||||
{{#if (eq skill.category sckey) }}
|
||||
<div class="ability flexrow ">
|
||||
@@ -70,14 +70,16 @@
|
||||
data-tooltip="ajout de spécialité"
|
||||
></i>
|
||||
{{/ifgt}}
|
||||
{{#each skill.specialties as |spe ind|}}
|
||||
{{#if @root.specialties}}
|
||||
{{#each @root.specialties as |spe|}}
|
||||
{{#ife spe.system.skill skey}}
|
||||
<i
|
||||
<span
|
||||
class="specialty"
|
||||
data-tooltip="spécialité utilisable"
|
||||
>{{spe.name}}</i>
|
||||
>{{spe.name}}<sup>{{spe.system.level}}</sup></span>
|
||||
{{/ife}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<select
|
||||
name="system.skills.{{skey}}.value"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
data-type="defense"
|
||||
data-action="create"
|
||||
><i class="fas fa-plus"></i></a>
|
||||
<a style="visibility:hidden;" aria-hidden="true"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{#each defenses as |item id|}}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-create" title="Create item"
|
||||
data-type="weapon" data-action="create"><i class="fas fa-plus"></i></a>
|
||||
<a style="visibility:hidden;" aria-hidden="true"><i class="fas fa-trash"></i></a>
|
||||
<a style="visibility:hidden;" aria-hidden="true"><i class="fas fa-edit"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{#each weapons as |item id|}}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<div class="skill-category">
|
||||
<h4>{{ localize categoryLabel }}</h4>
|
||||
<div class="grid grid-2col">
|
||||
{{#each system.skills as |skill key|}}
|
||||
{{#ife skill.category categoryKey}}
|
||||
{{#each (sortedSkills skills) as |skill key|}}
|
||||
{{#ife skill.category ../categoryKey}}
|
||||
{{> "systems/vermine2047/templates/actor/parts/npc-skill-item.hbs" skill=skill key=key}}
|
||||
{{/ife}}
|
||||
{{/each}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="skill-item">
|
||||
<label for="system.skills.{{key}}.value" title="{{ localize (concat 'SKILLS.' key) }} - {{ localize (concat 'VERMINE.rarity_' skill.rarity) }}">
|
||||
{{ localize (concat 'SKILLS.' key) }}
|
||||
<label for="system.skills.{{key}}.value" class="resource-label rollable" data-type="skill" data-label="{{key}}" title="{{ smarttlk 'SKILLS' key 'name' }} - {{ localize (concat 'VERMINE.rarity_' skill.rarity) }}">
|
||||
{{ smarttlk 'SKILLS' key 'name' }}
|
||||
{{#if skill.rarity}}
|
||||
<span class="rarity-badge rarity-{{skill.rarity}}" title="{{ localize (concat 'VERMINE.rarity_' skill.rarity) }}">
|
||||
{{skill.rarity}}
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
{{#if (ne tk "adapted")}}
|
||||
|
||||
<div class="flexrow row mdb flex-group-center">
|
||||
<h4 style="flex:33%;">
|
||||
<h4 style="flex:30%;text-align:center;">
|
||||
<a class="totem" data-totem="{{ tk }}"
|
||||
title="{{ smarttlk "TOTEMS"
|
||||
tk "description"}}">
|
||||
<img
|
||||
src="/systems/vermine2047/assets/images/ui/totems/{{ tk }}.webp"
|
||||
alt="{{ localize totem }}" width="80" height="80" />
|
||||
<h2>{{ smarttlk "TOTEMS"
|
||||
alt="{{ localize totem }}" width="60" height="60" />
|
||||
<h2 style="font-size:1rem;">{{ smarttlk "TOTEMS"
|
||||
tk "name"}}</h2>
|
||||
</a>
|
||||
</h4>
|
||||
<p style="flex:66%;text-align:left;">
|
||||
<p style="flex:70%;text-align:left;margin:0;font-size:0.8rem;">
|
||||
<strong>Instincts</strong> : {{ smarttlk "TOTEMS" tk
|
||||
"instincts"}}<br>
|
||||
<strong>Interdits</strong> : {{ smarttlk "TOTEMS" tk
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
|
||||
{{!-- Specialty specific content --}}
|
||||
<div class="grid grid-2col">
|
||||
{{#if item.system.skill}}
|
||||
<div class="resource flexrow">
|
||||
<span class="resource-label">{{ localize 'VERMINE.skill_title' }}:</span>
|
||||
<span>{{ smarttlk 'SKILLS' item.system.skill 'name' }}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if item.system.skill}}
|
||||
<div class="resource flexrow">
|
||||
<span class="resource-label">{{ localize 'VERMINE.skill_title' }}:</span>
|
||||
<span>{{ smarttlk 'SKILLS' item.system.skill 'name' }}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if item.system.level}}
|
||||
<div class="resource flexrow">
|
||||
<span class="resource-label">{{ localize 'VERMINE.level' }}:</span>
|
||||
<span>{{ item.system.level }}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if item.system.description}}
|
||||
<div class="resource flexcol full-width">
|
||||
|
||||
@@ -13,25 +13,34 @@
|
||||
value="{{item.name}}"
|
||||
placeholder="Name"
|
||||
/></h1>
|
||||
<select
|
||||
name="system.skill"
|
||||
class="skill-select"
|
||||
>
|
||||
{{#each @root.config.skillCategories as |skillCategory sckey|}}
|
||||
<optgroup label="{{ smarttlk 'SKILLS_CATEGORIES' sckey 'name' }}">
|
||||
{{#each @root.config.skills as |skill key|}}
|
||||
{{#ife skill.category sckey}}
|
||||
<option
|
||||
value="{{key}}"
|
||||
{{#ife key @root.item.system.skill}}
|
||||
selected
|
||||
{{/ife}}
|
||||
>{{ smarttlk 'SKILLS' key 'name' }}</option>
|
||||
{{/ife}}
|
||||
{{/each}}
|
||||
</optgroup>
|
||||
{{/each}}
|
||||
</select>
|
||||
<div class="flexrow">
|
||||
<select
|
||||
name="system.skill"
|
||||
class="skill-select"
|
||||
>
|
||||
{{#each @root.config.skillCategories as |skillCategory sckey|}}
|
||||
<optgroup label="{{ smarttlk 'SKILLS_CATEGORIES' sckey 'name' }}">
|
||||
{{#each @root.config.skills as |skill key|}}
|
||||
{{#ife skill.category sckey}}
|
||||
<option
|
||||
value="{{key}}"
|
||||
{{#ife key @root.item.system.skill}}
|
||||
selected
|
||||
{{/ife}}
|
||||
>{{ smarttlk 'SKILLS' key 'name' }}</option>
|
||||
{{/ife}}
|
||||
{{/each}}
|
||||
</optgroup>
|
||||
{{/each}}
|
||||
</select>
|
||||
<select
|
||||
name="system.level"
|
||||
class="skill-select"
|
||||
title="{{ localize 'VERMINE.level' }}"
|
||||
>
|
||||
{{selectOptions @root.config.SkillLevels selected=item.system.level localize=true}}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
+116
-13
@@ -1,11 +1,99 @@
|
||||
<div class="vermine-roll-message">
|
||||
<h3>{{param.actor.name}} : {{localize "VERMINE.test_of"}} {{param.rollLabel}}</h3>
|
||||
|
||||
<div class="flexrow">
|
||||
<h4>{{localize "VERMINE.difficulty"}}:</h4>
|
||||
<span id="difficulty">{{param.difficulty}}</span>
|
||||
{{!-- Verdict --}}
|
||||
<div class="roll-verdict {{#if verdict.success}}success{{else}}failure{{/if}}">
|
||||
{{#if verdict.success}}
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<span>{{localize "VERMINE.roll_success"}}</span>
|
||||
{{else}}
|
||||
<i class="fas fa-times-circle"></i>
|
||||
<span>{{localize "VERMINE.roll_failure"}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<h3>{{param.actor.name}} : {{localize "VERMINE.test_of"}} {{param.rollLabel}}</h3>
|
||||
|
||||
{{!-- Context --}}
|
||||
<div class="roll-context flexrow flex-wrap">
|
||||
<div class="context-item">
|
||||
<span class="context-label">{{localize "VERMINE.difficulty"}}</span>
|
||||
<span class="context-value" id="difficulty">{{param.difficulty}}</span>
|
||||
</div>
|
||||
<div class="context-item">
|
||||
<span class="context-label">{{localize "VERMINE.success_required"}}</span>
|
||||
<span class="context-value">{{verdict.required}}</span>
|
||||
</div>
|
||||
{{#if param.handicap}}
|
||||
<div class="context-item">
|
||||
<span class="context-label">{{localize "VERMINE.handicap"}}</span>
|
||||
<span class="context-value">+{{param.handicap}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if param.specialtyName}}
|
||||
<div class="context-item">
|
||||
<span class="context-label">{{localize "VERMINE.specialty"}}</span>
|
||||
<span class="context-value">+1D {{param.specialtyName}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if param.self_control}}
|
||||
<div class="context-item">
|
||||
<span class="context-label">{{localize "VERMINE.self_control"}}</span>
|
||||
<span class="context-value">+{{param.self_control}}D</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if param.totems.human}}
|
||||
<div class="context-item totem-human">
|
||||
<span class="context-label">{{localize "VERMINE.totem_used"}}</span>
|
||||
<span class="context-value">{{localize "TOTEMS.human.name"}}{{#ife param.keepTotem "human"}} ({{localize "VERMINE.totem_keep"}}){{/ife}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if param.totems.adapted}}
|
||||
<div class="context-item totem-adapted">
|
||||
<span class="context-label">{{localize "VERMINE.totem_used"}}</span>
|
||||
<span class="context-value">{{localize "TOTEMS.adapted.name"}}{{#ife param.keepTotem "adapted"}} ({{localize "VERMINE.totem_keep"}}){{/ife}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if param.skillLevel}}
|
||||
<div class="context-item">
|
||||
<span class="context-label">{{localize "VERMINE.skill_mastery"}}</span>
|
||||
<span class="context-value">{{skillLevel "label" param.skillLevel}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{!-- Dice pool breakdown --}}
|
||||
{{#if param.poolBreakdown}}
|
||||
<div class="roll-pool">
|
||||
<h4>{{localize "VERMINE.roll_pool"}}</h4>
|
||||
<div class="flexrow flex-wrap pool-breakdown">
|
||||
{{#if param.poolBreakdown.ability}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_ability"}} {{param.poolBreakdown.ability}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.skill}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_skill"}} {{param.poolBreakdown.skill}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.specialty}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_specialty"}} +{{param.poolBreakdown.specialty}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.help}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_help"}} +{{param.poolBreakdown.help}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.tooling}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_tooling"}} +{{param.poolBreakdown.tooling}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.group}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_group"}} +{{param.poolBreakdown.group}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.selfControl}}
|
||||
<span class="pool-item">{{localize "VERMINE.pool_selfControl"}} +{{param.poolBreakdown.selfControl}}D</span>
|
||||
{{/if}}
|
||||
{{#if param.poolBreakdown.domainBonus}}
|
||||
<span class="pool-item">{{#ifgt param.poolBreakdown.domainBonus 0}}{{localize "VERMINE.domain_bonus"}}{{else}}{{localize "VERMINE.domain_penalty"}}{{/ifgt}} {{param.poolBreakdown.domainBonus}}D</span>
|
||||
{{/if}}
|
||||
<span class="pool-item pool-total">{{localize "VERMINE.pool_total"}} {{param.poolBreakdown.total}}D</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="reroll-fromroll">
|
||||
<h4>{{localize "VERMINE.rerolls_possible"}} : <span id="allowed_reroll">{{param.Reroll}}</span></h4>
|
||||
<div class="reroll flexrow">
|
||||
@@ -25,21 +113,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{!-- Dice results --}}
|
||||
<ul class="flexrow roll-results initial-roll" data-difficulty="{{param.difficulty}}">
|
||||
{{#each roll.dice as |dieType index|}}
|
||||
{{#each dieType.results as |die index|}}
|
||||
{{! Determine dice class and type based on flavor }}
|
||||
{{#ifincludes dieType.options.flavor "human"}}
|
||||
{{! Determine dice class and type based on flavor (leading token) }}
|
||||
{{#ifStartsWith dieType.options.flavor "human_"}}
|
||||
{{set diceClass="human"}}
|
||||
{{set diceTypeVal="human"}}
|
||||
{{else ifincludes dieType.options.flavor "adapted"}}
|
||||
{{else ifStartsWith dieType.options.flavor "adapted_"}}
|
||||
{{set diceClass="adapted"}}
|
||||
{{set diceTypeVal="adapted"}}
|
||||
{{else}}
|
||||
{{set diceClass="regular"}}
|
||||
{{set diceTypeVal="regular"}}
|
||||
{{/ifincludes}}
|
||||
{{/ifStartsWith}}
|
||||
<li class="roll die flexcol {{diceClass}} {{#if die.success}}success{{/if}}"
|
||||
data-dice-type="{{diceTypeVal}}"
|
||||
data-result="{{die.result}}">
|
||||
@@ -48,7 +137,21 @@
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
|
||||
{{!-- Dice summary --}}
|
||||
<div class="roll-dice-summary flexrow">
|
||||
{{#if diceStats.regular.count}}
|
||||
<span class="die-summary regular">{{diceStats.regular.count}} {{localize "VERMINE.die_regular"}} · {{diceStats.regular.success}} {{localize "VERMINE.die_successes"}}</span>
|
||||
{{/if}}
|
||||
{{#if diceStats.human.count}}
|
||||
<span class="die-summary human">{{diceStats.human.count}} {{localize "VERMINE.die_human"}} · {{diceStats.human.success}} {{localize "VERMINE.die_successes"}}</span>
|
||||
{{/if}}
|
||||
{{#if diceStats.adapted.count}}
|
||||
<span class="die-summary adapted">{{diceStats.adapted.count}} {{localize "VERMINE.die_adapted"}} · {{diceStats.adapted.success}} {{localize "VERMINE.die_successes"}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{!-- Total --}}
|
||||
<div class="roll-total flexrow">
|
||||
<div class="flexcol">
|
||||
<h4>{{localize "VERMINE.success_count"}}:</h4>
|
||||
@@ -56,7 +159,7 @@
|
||||
</div>
|
||||
<div class="flexcol">
|
||||
<h4>{{localize "VERMINE.success_required"}}:</h4>
|
||||
<span id="required">{{math_add 1 param.handicap}}</span>
|
||||
<span id="required">{{verdict.required}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user