feat: jets d'attaque depuis les armes (combat en opposition)
- Bouton ⚔ Attaquer sur chaque arme (onglet Équipement, mode Jeu) - rollAttack(itemId) dans character.mjs : jet Échauffourée vs Corps PNJ - Dialog combat : input numérique 'Corps du PNJ' à la place du sélect difficulté - computeResult() : margin===0 → résultat 'tie' (égalité) en combat - Mêlée échec → blessure joueur auto-cochée (comme résistance) - Distance échec → simple raté, pas de blessure joueur - Chat message : infos arme, bandeau égalité, desc succès/échec combat - CSS : bandeau 'tie' (brun doré), zone arme dans dialog - i18n : CELESTOPOL.Combat.* (attack, corpsPnj, tie, successHit, etc.) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
11
lang/fr.json
11
lang/fr.json
@@ -108,6 +108,17 @@
|
|||||||
"grave": "Grave",
|
"grave": "Grave",
|
||||||
"dramatique": "Dramatique (hors combat)"
|
"dramatique": "Dramatique (hors combat)"
|
||||||
},
|
},
|
||||||
|
"Combat": {
|
||||||
|
"attack": "Attaquer",
|
||||||
|
"corpsPnj": "Corps du PNJ",
|
||||||
|
"tie": "ÉGALITÉ",
|
||||||
|
"tieDesc": "Personne n'est blessé",
|
||||||
|
"successHit": "PNJ touché — 1 blessure",
|
||||||
|
"failureHit": "Joueur touché — 1 blessure (mêlée)",
|
||||||
|
"distanceNoWound": "Raté — pas de riposte",
|
||||||
|
"weaponDamage": "dégâts supplémentaires",
|
||||||
|
"playerWounded": "Blessure infligée au joueur (mêlée)"
|
||||||
|
},
|
||||||
"Tab": {
|
"Tab": {
|
||||||
"main": "Principal",
|
"main": "Principal",
|
||||||
"competences": "Domaines",
|
"competences": "Domaines",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export default class CelestopolActorSheet extends HandlebarsApplicationMixin(fou
|
|||||||
toggleSheet: CelestopolActorSheet.#onToggleSheet,
|
toggleSheet: CelestopolActorSheet.#onToggleSheet,
|
||||||
edit: CelestopolActorSheet.#onItemEdit,
|
edit: CelestopolActorSheet.#onItemEdit,
|
||||||
delete: CelestopolActorSheet.#onItemDelete,
|
delete: CelestopolActorSheet.#onItemDelete,
|
||||||
|
attack: CelestopolActorSheet.#onAttack,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +152,12 @@ export default class CelestopolActorSheet extends HandlebarsApplicationMixin(fou
|
|||||||
await item?.deleteDialog()
|
await item?.deleteDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async #onAttack(_event, target) {
|
||||||
|
const itemId = target.getAttribute("data-item-id")
|
||||||
|
if (!itemId) return
|
||||||
|
await this.document.system.rollAttack(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup sequential checkbox logic for wound/destin/spleen tracks
|
* Setup sequential checkbox logic for wound/destin/spleen tracks
|
||||||
* Only allows checking the next checkbox in sequence
|
* Only allows checking the next checkbox in sequence
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export class CelestopolRoll extends Roll {
|
|||||||
get resultType() { return this.options.resultType }
|
get resultType() { return this.options.resultType }
|
||||||
get isSuccess() { return this.resultType === "success" || this.resultType === "critical-success" }
|
get isSuccess() { return this.resultType === "success" || this.resultType === "critical-success" }
|
||||||
get isFailure() { return this.resultType === "failure" || this.resultType === "critical-failure" }
|
get isFailure() { return this.resultType === "failure" || this.resultType === "critical-failure" }
|
||||||
|
get isTie() { return this.resultType === "tie" }
|
||||||
get isCriticalSuccess(){ return this.resultType === "critical-success" }
|
get isCriticalSuccess(){ return this.resultType === "critical-success" }
|
||||||
get isCriticalFailure(){ return this.resultType === "critical-failure" }
|
get isCriticalFailure(){ return this.resultType === "critical-failure" }
|
||||||
get actorId() { return this.options.actorId }
|
get actorId() { return this.options.actorId }
|
||||||
@@ -40,6 +41,10 @@ export class CelestopolRoll extends Roll {
|
|||||||
const destGaugeFull = options.destGaugeFull ?? false
|
const destGaugeFull = options.destGaugeFull ?? false
|
||||||
const fortuneValue = options.fortuneValue ?? 0
|
const fortuneValue = options.fortuneValue ?? 0
|
||||||
const isResistance = options.isResistance ?? false
|
const isResistance = options.isResistance ?? false
|
||||||
|
const isCombat = options.isCombat ?? false
|
||||||
|
const weaponType = options.weaponType ?? "melee"
|
||||||
|
const weaponName = options.weaponName ?? null
|
||||||
|
const weaponDegats = options.weaponDegats ?? "0"
|
||||||
const woundLabel = woundLevelId > 0
|
const woundLabel = woundLevelId > 0
|
||||||
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
|
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
|
||||||
: null
|
: null
|
||||||
@@ -66,6 +71,10 @@ export class CelestopolRoll extends Roll {
|
|||||||
destGaugeFull,
|
destGaugeFull,
|
||||||
defaultRollMoonDie: options.rollMoonDie ?? false,
|
defaultRollMoonDie: options.rollMoonDie ?? false,
|
||||||
isResistance,
|
isResistance,
|
||||||
|
isCombat,
|
||||||
|
weaponType,
|
||||||
|
weaponName,
|
||||||
|
weaponDegats,
|
||||||
modifierChoices,
|
modifierChoices,
|
||||||
aspectChoices,
|
aspectChoices,
|
||||||
fortuneValue,
|
fortuneValue,
|
||||||
@@ -135,7 +144,7 @@ export class CelestopolRoll extends Roll {
|
|||||||
if (previewEl) previewEl.textContent = formula
|
if (previewEl) previewEl.textContent = formula
|
||||||
}
|
}
|
||||||
|
|
||||||
wrap.querySelectorAll('#modifier, #aspectModifier, #useDestin, #useFortune, #puiserRessources')
|
wrap.querySelectorAll('#modifier, #aspectModifier, #useDestin, #useFortune, #puiserRessources, #corpsPnj')
|
||||||
.forEach(el => {
|
.forEach(el => {
|
||||||
el.addEventListener('change', update)
|
el.addEventListener('change', update)
|
||||||
el.addEventListener('input', update)
|
el.addEventListener('input', update)
|
||||||
@@ -161,8 +170,12 @@ export class CelestopolRoll extends Roll {
|
|||||||
|
|
||||||
if (!rollContext) return null
|
if (!rollContext) return null
|
||||||
|
|
||||||
const difficulty = rollContext.difficulty ?? "normal"
|
// En combat : Corps PNJ = seuil direct (pas le sélect difficulté)
|
||||||
const diffConfig = SYSTEM.DIFFICULTY_CHOICES[difficulty] ?? SYSTEM.DIFFICULTY_CHOICES.normal
|
const corpsPnj = isCombat ? (parseInt(rollContext.corpsPnj ?? 7) || 7) : null
|
||||||
|
const difficulty = isCombat ? "combat" : (rollContext.difficulty ?? "normal")
|
||||||
|
const diffConfig = isCombat
|
||||||
|
? { value: corpsPnj, label: "CELESTOPOL.Combat.corpsPnj" }
|
||||||
|
: (SYSTEM.DIFFICULTY_CHOICES[difficulty] ?? SYSTEM.DIFFICULTY_CHOICES.normal)
|
||||||
const autoSuccess = rollContext.modifier === "auto"
|
const autoSuccess = rollContext.modifier === "auto"
|
||||||
const modifier = autoSuccess ? 0 : (parseInt(rollContext.modifier ?? 0) || 0)
|
const modifier = autoSuccess ? 0 : (parseInt(rollContext.modifier ?? 0) || 0)
|
||||||
const aspectMod = parseInt(rollContext.aspectModifier ?? 0) || 0
|
const aspectMod = parseInt(rollContext.aspectModifier ?? 0) || 0
|
||||||
@@ -207,6 +220,10 @@ export class CelestopolRoll extends Roll {
|
|||||||
woundMalus: effectiveWoundMalus,
|
woundMalus: effectiveWoundMalus,
|
||||||
autoSuccess,
|
autoSuccess,
|
||||||
isResistance,
|
isResistance,
|
||||||
|
isCombat,
|
||||||
|
weaponType,
|
||||||
|
weaponName,
|
||||||
|
weaponDegats,
|
||||||
useDestin: !isResistance && useDestin,
|
useDestin: !isResistance && useDestin,
|
||||||
useFortune: !isResistance && useFortune,
|
useFortune: !isResistance && useFortune,
|
||||||
puiserRessources: effectivePuiser,
|
puiserRessources: effectivePuiser,
|
||||||
@@ -234,6 +251,16 @@ export class CelestopolRoll extends Roll {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Combat mêlée échoué → joueur prend une blessure
|
||||||
|
if (isCombat && weaponType === "melee" && actor && roll.options.resultType === "failure") {
|
||||||
|
const wounds = actor.system.blessures
|
||||||
|
const nextIdx = [1,2,3,4,5,6,7,8].find(i => !wounds[`b${i}`]?.checked)
|
||||||
|
if (nextIdx) {
|
||||||
|
await actor.update({ [`system.blessures.b${nextIdx}.checked`]: true })
|
||||||
|
roll.options.woundTaken = nextIdx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await roll.toMessage({}, { rollMode: rollData.rollMode })
|
await roll.toMessage({}, { rollMode: rollData.rollMode })
|
||||||
|
|
||||||
// Destin utilisé → vider la jauge (reset à 0)
|
// Destin utilisé → vider la jauge (reset à 0)
|
||||||
@@ -284,7 +311,8 @@ export class CelestopolRoll extends Roll {
|
|||||||
/**
|
/**
|
||||||
* Détermine succès/échec selon la marge (total − seuil).
|
* Détermine succès/échec selon la marge (total − seuil).
|
||||||
* - Marge ≥ 5 → succès critique
|
* - Marge ≥ 5 → succès critique
|
||||||
* - Marge ≥ 0 → succès
|
* - Marge > 0 → succès
|
||||||
|
* - Marge = 0 → succès (ou égalité en combat)
|
||||||
* - Marge ≤ −5 → échec critique
|
* - Marge ≤ −5 → échec critique
|
||||||
* - Marge < 0 → échec
|
* - Marge < 0 → échec
|
||||||
*/
|
*/
|
||||||
@@ -294,7 +322,9 @@ export class CelestopolRoll extends Roll {
|
|||||||
this.options.margin = null
|
this.options.margin = null
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0
|
const threshold = this.options.isCombat
|
||||||
|
? (this.options.difficultyValue ?? 0)
|
||||||
|
: (SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0)
|
||||||
if (threshold === 0) {
|
if (threshold === 0) {
|
||||||
this.options.resultType = "unknown"
|
this.options.resultType = "unknown"
|
||||||
this.options.margin = null
|
this.options.margin = null
|
||||||
@@ -302,7 +332,9 @@ export class CelestopolRoll extends Roll {
|
|||||||
}
|
}
|
||||||
const margin = this.total - threshold
|
const margin = this.total - threshold
|
||||||
this.options.margin = margin
|
this.options.margin = margin
|
||||||
if (margin >= 5) this.options.resultType = "critical-success"
|
if (this.options.isCombat && margin === 0) {
|
||||||
|
this.options.resultType = "tie"
|
||||||
|
} else if (margin >= 5) this.options.resultType = "critical-success"
|
||||||
else if (margin >= 0) this.options.resultType = "success"
|
else if (margin >= 0) this.options.resultType = "success"
|
||||||
else if (margin <= -5) this.options.resultType = "critical-failure"
|
else if (margin <= -5) this.options.resultType = "critical-failure"
|
||||||
else this.options.resultType = "failure"
|
else this.options.resultType = "failure"
|
||||||
@@ -320,7 +352,9 @@ export class CelestopolRoll extends Roll {
|
|||||||
const resultType = this.resultType
|
const resultType = this.resultType
|
||||||
const diceResults = this.dice[0]?.results?.map(r => r.result) ?? []
|
const diceResults = this.dice[0]?.results?.map(r => r.result) ?? []
|
||||||
const diceSum = diceResults.reduce((a, b) => a + b, 0)
|
const diceSum = diceResults.reduce((a, b) => a + b, 0)
|
||||||
const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0
|
const threshold = this.options.isCombat
|
||||||
|
? (this.options.difficultyValue ?? 0)
|
||||||
|
: (SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0)
|
||||||
const margin = this.options.margin
|
const margin = this.options.margin
|
||||||
const woundMalus = this.options.woundMalus ?? 0
|
const woundMalus = this.options.woundMalus ?? 0
|
||||||
const skillValue = this.options.skillValue ?? 0
|
const skillValue = this.options.skillValue ?? 0
|
||||||
@@ -337,11 +371,17 @@ export class CelestopolRoll extends Roll {
|
|||||||
const resultClassMap = {
|
const resultClassMap = {
|
||||||
"critical-success": "critical-success",
|
"critical-success": "critical-success",
|
||||||
"success": "success",
|
"success": "success",
|
||||||
|
"tie": "tie",
|
||||||
"failure": "failure",
|
"failure": "failure",
|
||||||
"critical-failure": "critical-failure",
|
"critical-failure": "critical-failure",
|
||||||
"unknown": "",
|
"unknown": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Libellé de difficulté : en combat, afficher "Corps PNJ : N"
|
||||||
|
const difficultyLabel = this.options.isCombat
|
||||||
|
? `${game.i18n.localize("CELESTOPOL.Combat.corpsPnj")} : ${threshold}`
|
||||||
|
: game.i18n.localize(SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.label ?? "")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cssClass: [SYSTEM.id, "dice-roll"].join(" "),
|
cssClass: [SYSTEM.id, "dice-roll"].join(" "),
|
||||||
actorId: this.actorId,
|
actorId: this.actorId,
|
||||||
@@ -357,10 +397,11 @@ export class CelestopolRoll extends Roll {
|
|||||||
resultClass: resultClassMap[resultType] ?? "",
|
resultClass: resultClassMap[resultType] ?? "",
|
||||||
isSuccess: this.isSuccess,
|
isSuccess: this.isSuccess,
|
||||||
isFailure: this.isFailure,
|
isFailure: this.isFailure,
|
||||||
|
isTie: this.isTie,
|
||||||
isCriticalSuccess: this.isCriticalSuccess,
|
isCriticalSuccess: this.isCriticalSuccess,
|
||||||
isCriticalFailure: this.isCriticalFailure,
|
isCriticalFailure: this.isCriticalFailure,
|
||||||
difficulty: this.options.difficulty,
|
difficulty: this.options.difficulty,
|
||||||
difficultyLabel: game.i18n.localize(SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.label ?? ""),
|
difficultyLabel,
|
||||||
difficultyValue: threshold,
|
difficultyValue: threshold,
|
||||||
margin,
|
margin,
|
||||||
marginAbs: margin !== null ? Math.abs(margin) : null,
|
marginAbs: margin !== null ? Math.abs(margin) : null,
|
||||||
@@ -376,6 +417,10 @@ export class CelestopolRoll extends Roll {
|
|||||||
woundMalus,
|
woundMalus,
|
||||||
woundLabel,
|
woundLabel,
|
||||||
isResistance: this.options.isResistance ?? false,
|
isResistance: this.options.isResistance ?? false,
|
||||||
|
isCombat: this.options.isCombat ?? false,
|
||||||
|
weaponName: this.options.weaponName ?? null,
|
||||||
|
weaponDegats: this.options.weaponDegats ?? null,
|
||||||
|
weaponType: this.options.weaponType ?? null,
|
||||||
woundTaken: this.options.woundTaken ?? null,
|
woundTaken: this.options.woundTaken ?? null,
|
||||||
// Dé de lune
|
// Dé de lune
|
||||||
hasMoonDie: moonDieResult !== null,
|
hasMoonDie: moonDieResult !== null,
|
||||||
|
|||||||
@@ -239,18 +239,39 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
|
|||||||
const statData = this.stats[statId]
|
const statData = this.stats[statId]
|
||||||
if (!statData) return null
|
if (!statData) return null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lance une attaque avec une arme (test Échauffourée vs Corps PNJ).
|
||||||
|
* Mêlée : échec → blessure joueur auto-cochée.
|
||||||
|
* Distance : échec → simple raté, pas de blessure joueur.
|
||||||
|
* Égalité (marge=0) → personne n'est blessé.
|
||||||
|
* @param {string} itemId - Id de l'item arme
|
||||||
|
*/
|
||||||
|
async rollAttack(itemId) {
|
||||||
|
const { CelestopolRoll } = await import("../documents/roll.mjs")
|
||||||
|
const item = this.parent.items.get(itemId)
|
||||||
|
if (!item || item.type !== "weapon") return null
|
||||||
|
|
||||||
|
const echauffouree = this.stats.corps.echauffouree
|
||||||
|
if (!echauffouree) return null
|
||||||
|
|
||||||
return CelestopolRoll.prompt({
|
return CelestopolRoll.prompt({
|
||||||
actorId: this.parent.id,
|
actorId: this.parent.id,
|
||||||
actorName: this.parent.name,
|
actorName: this.parent.name,
|
||||||
actorImage: this.parent.img,
|
actorImage: this.parent.img,
|
||||||
statId,
|
statId: "corps",
|
||||||
statLabel: SYSTEM.STATS[statId]?.label,
|
skillId: "echauffouree",
|
||||||
skillLabel: "CELESTOPOL.Roll.resistanceTest",
|
statLabel: SYSTEM.STATS.corps.label,
|
||||||
skillValue: statData.res ?? 0,
|
skillLabel: SYSTEM.SKILLS.corps.echauffouree.label,
|
||||||
woundMalus: this.getWoundMalus(),
|
skillValue: echauffouree.value,
|
||||||
woundLevel: this.blessures.lvl,
|
woundMalus: this.getWoundMalus(),
|
||||||
difficulty: this.prefs.difficulty,
|
woundLevel: this.blessures.lvl,
|
||||||
isResistance: true,
|
rollMoonDie: this.prefs.rollMoonDie ?? false,
|
||||||
|
destGaugeFull: this.destin.lvl > 0,
|
||||||
|
fortuneValue: this.attributs.fortune.value,
|
||||||
|
isCombat: true,
|
||||||
|
weaponType: item.system.type,
|
||||||
|
weaponName: item.name,
|
||||||
|
weaponDegats: item.system.degats,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -800,3 +800,61 @@
|
|||||||
.wound-icon { font-size: 1em; }
|
.wound-icon { font-size: 1em; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bandeau "Égalité" en combat
|
||||||
|
.celestopol.chat-roll {
|
||||||
|
.roll-result-banner.tie {
|
||||||
|
background: #3a2e1a;
|
||||||
|
color: #d4b870;
|
||||||
|
border-top: 2px solid #7a6230;
|
||||||
|
border-bottom: 2px solid #7a6230;
|
||||||
|
text-shadow: 0 1px 2px rgba(0,0,0,0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-info-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3em;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
font-size: 0.85em;
|
||||||
|
color: var(--cel-orange, #e07b00);
|
||||||
|
.weapon-icon-small { font-size: 0.9em; }
|
||||||
|
.weapon-degats-small {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #f0c060;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone arme dans le dialog (combat)
|
||||||
|
.fvtt-celestopol.roll-dialog {
|
||||||
|
.roll-weapon-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4em;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: var(--cel-orange, #e07b00);
|
||||||
|
.weapon-icon { font-size: 1em; }
|
||||||
|
.weapon-degats {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #f0c060;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-corps-pnj {
|
||||||
|
.corps-pnj-input {
|
||||||
|
width: 70px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
font-family: var(--cel-font-title, "CopaseticNF", serif);
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
color: var(--cel-orange, #e07b00);
|
||||||
|
border: 1px solid var(--cel-orange, #e07b00);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
<span class="item-tag type">{{#if (eq item.system.type "melee")}}{{localize "CELESTOPOL.Weapon.typeMelee"}}{{else}}{{localize "CELESTOPOL.Weapon.typeDistance"}}{{/if}}</span>
|
<span class="item-tag type">{{#if (eq item.system.type "melee")}}{{localize "CELESTOPOL.Weapon.typeMelee"}}{{else}}{{localize "CELESTOPOL.Weapon.typeDistance"}}{{/if}}</span>
|
||||||
<span class="item-tag dmg">{{localize "CELESTOPOL.Weapon.degats"}} {{item.system.degats}}</span>
|
<span class="item-tag dmg">{{localize "CELESTOPOL.Weapon.degats"}} {{item.system.degats}}</span>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
|
{{#unless ../isEditMode}}
|
||||||
|
<a data-action="attack" data-item-id="{{item.id}}" title="{{localize 'CELESTOPOL.Combat.attack'}}"><i class="fas fa-khanda"></i></a>
|
||||||
|
{{/unless}}
|
||||||
<a data-action="edit" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
<a data-action="edit" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
{{#if ../isEditMode}}<a data-action="delete" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>{{/if}}
|
{{#if ../isEditMode}}<a data-action="delete" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="roll-info">
|
<div class="roll-info">
|
||||||
<span class="actor-name">{{actorName}}</span>
|
<span class="actor-name">{{actorName}}</span>
|
||||||
|
{{!-- Arme (mode combat) --}}
|
||||||
|
{{#if isCombat}}
|
||||||
|
<span class="weapon-info-header">
|
||||||
|
<span class="weapon-icon-small">⚔</span>
|
||||||
|
<span class="weapon-name-small">{{weaponName}}</span>
|
||||||
|
{{#if (gt weaponDegats "0")}}<span class="weapon-degats-small">+{{weaponDegats}}</span>{{/if}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
<span class="skill-info">
|
<span class="skill-info">
|
||||||
{{#if statLabel}}<span class="stat-lbl">{{statLabel}}</span><span class="sep"> › </span>{{/if}}
|
{{#if statLabel}}<span class="stat-lbl">{{statLabel}}</span><span class="sep"> › </span>{{/if}}
|
||||||
<span class="skill-lbl">{{skillLabel}}</span>
|
<span class="skill-lbl">{{skillLabel}}</span>
|
||||||
@@ -64,7 +72,7 @@
|
|||||||
<span class="vs-wrap">
|
<span class="vs-wrap">
|
||||||
<span class="vs-label">vs</span>
|
<span class="vs-label">vs</span>
|
||||||
<span class="diff-label">{{difficultyLabel}}</span>
|
<span class="diff-label">{{difficultyLabel}}</span>
|
||||||
<span class="diff-val">({{difficultyValue}})</span>
|
{{#unless isCombat}}<span class="diff-val">({{difficultyValue}})</span>{{/unless}}
|
||||||
</span>
|
</span>
|
||||||
{{#if margin}}
|
{{#if margin}}
|
||||||
<span class="margin-badge {{#if marginAbove}}above{{else}}below{{/if}}">
|
<span class="margin-badge {{#if marginAbove}}above{{else}}below{{/if}}">
|
||||||
@@ -107,27 +115,46 @@
|
|||||||
{{#if autoSuccess}}
|
{{#if autoSuccess}}
|
||||||
<span class="result-icon">★</span>
|
<span class="result-icon">★</span>
|
||||||
<span class="result-label">{{localize "CELESTOPOL.Roll.autoSuccess"}}</span>
|
<span class="result-label">{{localize "CELESTOPOL.Roll.autoSuccess"}}</span>
|
||||||
|
{{else if isTie}}
|
||||||
|
<span class="result-icon">⚖</span>
|
||||||
|
<span class="result-label">{{localize "CELESTOPOL.Combat.tie"}}</span>
|
||||||
|
<span class="result-desc">{{localize "CELESTOPOL.Combat.tieDesc"}}</span>
|
||||||
{{else if isCriticalSuccess}}
|
{{else if isCriticalSuccess}}
|
||||||
<span class="result-icon">✦✦</span>
|
<span class="result-icon">✦✦</span>
|
||||||
<span class="result-label">{{localize "CELESTOPOL.Roll.criticalSuccess"}}</span>
|
<span class="result-label">{{localize "CELESTOPOL.Roll.criticalSuccess"}}</span>
|
||||||
|
{{#if isCombat}}
|
||||||
|
<span class="result-desc">{{localize "CELESTOPOL.Combat.successHit"}}{{#if (gt weaponDegats "0")}} +{{weaponDegats}} {{localize "CELESTOPOL.Combat.weaponDamage"}}{{/if}}</span>
|
||||||
|
{{else}}
|
||||||
<span class="result-desc">{{localize "CELESTOPOL.Roll.criticalSuccessDesc"}}</span>
|
<span class="result-desc">{{localize "CELESTOPOL.Roll.criticalSuccessDesc"}}</span>
|
||||||
|
{{/if}}
|
||||||
{{else if isSuccess}}
|
{{else if isSuccess}}
|
||||||
<span class="result-icon">✦</span>
|
<span class="result-icon">✦</span>
|
||||||
<span class="result-label">{{localize "CELESTOPOL.Roll.success"}}</span>
|
<span class="result-label">{{localize "CELESTOPOL.Roll.success"}}</span>
|
||||||
|
{{#if isCombat}}
|
||||||
|
<span class="result-desc">{{localize "CELESTOPOL.Combat.successHit"}}{{#if (gt weaponDegats "0")}} +{{weaponDegats}} {{localize "CELESTOPOL.Combat.weaponDamage"}}{{/if}}</span>
|
||||||
|
{{/if}}
|
||||||
{{else if isCriticalFailure}}
|
{{else if isCriticalFailure}}
|
||||||
<span class="result-icon">✖✖</span>
|
<span class="result-icon">✖✖</span>
|
||||||
<span class="result-label">{{localize "CELESTOPOL.Roll.criticalFailure"}}</span>
|
<span class="result-label">{{localize "CELESTOPOL.Roll.criticalFailure"}}</span>
|
||||||
|
{{#if isCombat}}
|
||||||
|
<span class="result-desc">{{#if (eq weaponType "melee")}}{{localize "CELESTOPOL.Combat.failureHit"}}{{else}}{{localize "CELESTOPOL.Combat.distanceNoWound"}}{{/if}}</span>
|
||||||
|
{{else}}
|
||||||
<span class="result-desc">{{localize "CELESTOPOL.Roll.criticalFailureDesc"}}</span>
|
<span class="result-desc">{{localize "CELESTOPOL.Roll.criticalFailureDesc"}}</span>
|
||||||
|
{{/if}}
|
||||||
{{else if isFailure}}
|
{{else if isFailure}}
|
||||||
<span class="result-icon">✖</span>
|
<span class="result-icon">✖</span>
|
||||||
<span class="result-label">{{localize "CELESTOPOL.Roll.failure"}}</span>
|
<span class="result-label">{{localize "CELESTOPOL.Roll.failure"}}</span>
|
||||||
|
{{#if isCombat}}
|
||||||
|
<span class="result-desc">{{#if (eq weaponType "melee")}}{{localize "CELESTOPOL.Combat.failureHit"}}{{else}}{{localize "CELESTOPOL.Combat.distanceNoWound"}}{{/if}}</span>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{!-- Blessure auto-cochée (test de résistance raté) --}}
|
|
||||||
|
{{!-- Blessure auto-cochée (résistance ratée ou combat mêlée raté) --}}
|
||||||
{{#if woundTaken}}
|
{{#if woundTaken}}
|
||||||
<div class="resistance-wound-notice">
|
<div class="resistance-wound-notice">
|
||||||
<span class="wound-icon">🩹</span>
|
<span class="wound-icon">🩹</span>
|
||||||
<span>{{localize "CELESTOPOL.Roll.woundTaken"}}</span>
|
<span>{{#if isCombat}}{{localize "CELESTOPOL.Combat.playerWounded"}}{{else}}{{localize "CELESTOPOL.Roll.woundTaken"}}{{/if}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
{{!-- En-tête : acteur + domaine + formule de base --}}
|
{{!-- En-tête : acteur + domaine + formule de base --}}
|
||||||
<div class="roll-info-block">
|
<div class="roll-info-block">
|
||||||
<div class="roll-actor">{{actorName}}</div>
|
<div class="roll-actor">{{actorName}}</div>
|
||||||
|
{{!-- Arme (mode combat) --}}
|
||||||
|
{{#if isCombat}}
|
||||||
|
<div class="roll-weapon-line">
|
||||||
|
<span class="weapon-icon">⚔</span>
|
||||||
|
<span class="weapon-name">{{weaponName}}</span>
|
||||||
|
<span class="weapon-degats">+{{weaponDegats}}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
<div class="roll-skill-line">
|
<div class="roll-skill-line">
|
||||||
{{#if statLabel}}<span class="stat-label">{{localize statLabel}}</span><span class="sep"> › </span>{{/if}}
|
{{#if statLabel}}<span class="stat-label">{{localize statLabel}}</span><span class="sep"> › </span>{{/if}}
|
||||||
<span class="skill-label">{{localize skillLabel}}</span>
|
<span class="skill-label">{{localize skillLabel}}</span>
|
||||||
@@ -24,7 +32,13 @@
|
|||||||
|
|
||||||
<div class="roll-form-rows">
|
<div class="roll-form-rows">
|
||||||
|
|
||||||
{{!-- Difficulté --}}
|
{{!-- Difficulté : sélect standard OU input Corps PNJ en combat --}}
|
||||||
|
{{#if isCombat}}
|
||||||
|
<div class="form-row-line form-corps-pnj">
|
||||||
|
<label for="corpsPnj">{{localize "CELESTOPOL.Combat.corpsPnj"}}</label>
|
||||||
|
<input type="number" id="corpsPnj" name="corpsPnj" value="7" min="1" max="30" class="corps-pnj-input">
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
<div class="form-row-line">
|
<div class="form-row-line">
|
||||||
<label for="difficulty">{{localize "CELESTOPOL.Roll.difficulty"}}</label>
|
<label for="difficulty">{{localize "CELESTOPOL.Roll.difficulty"}}</label>
|
||||||
<select id="difficulty" name="difficulty">
|
<select id="difficulty" name="difficulty">
|
||||||
@@ -35,6 +49,7 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{!-- Options non disponibles en test de résistance --}}
|
{{!-- Options non disponibles en test de résistance --}}
|
||||||
{{#unless isResistance}}
|
{{#unless isResistance}}
|
||||||
|
|||||||
Reference in New Issue
Block a user