3 Commits

Author SHA1 Message Date
61ed1597e7 Add damage management and DR for monsters also
All checks were successful
Release Creation / build (release) Successful in 1m48s
2025-12-19 15:41:27 +01:00
96062c6fd9 Roll damages and so on
All checks were successful
Release Creation / build (release) Successful in 56s
2025-12-14 21:18:00 +01:00
f6b35536de Manage DR and damage roll 2025-12-14 20:48:33 +01:00
41 changed files with 1283 additions and 322 deletions

View File

@@ -917,9 +917,10 @@ i.lethalfantasy {
flex: 1;
}
.lethalfantasy .monster-main .monster-skills .monster-skill {
display: flex;
display: grid;
grid-template-columns: repeat(3, auto 2.5rem);
gap: 0.5rem;
align-items: center;
margin-right: 0.5rem;
}
.lethalfantasy .monster-main .monster-skills .monster-skill .rollable:hover,
.lethalfantasy .monster-main .monster-skills .monster-skill .rollable:focus {
@@ -931,12 +932,9 @@ i.lethalfantasy {
max-width: 2.5rem;
}
.lethalfantasy .monster-main .monster-skills .monster-skill .name {
flex: 1;
min-width: 3.2rem;
margin-left: 4px;
}
.lethalfantasy .monster-main .monster-skills .monster-skill .form-group {
flex: 1;
padding-left: 4px;
}
.lethalfantasy .monster-main .monster-skills .monster-skill .form-group .form-fields {
@@ -951,8 +949,8 @@ i.lethalfantasy {
}
.lethalfantasy .monster-main .monster-movements .monster-movement {
display: flex;
align-items: center;
margin-right: 0.5rem;
flex-direction: column;
gap: 4px;
}
.lethalfantasy .monster-main .monster-movements .monster-movement .rollable:hover,
.lethalfantasy .monster-main .monster-movements .monster-movement .rollable:focus {
@@ -2218,6 +2216,54 @@ i.lethalfantasy {
border-color: var(--color-dark-6);
color: var(--color-dark-2);
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content {
padding: 6px;
font-size: calc(var(--font-size-standard) * 1);
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content .header {
text-align: center;
padding: 4px;
margin-bottom: 6px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content .damage-summary {
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px 6px;
margin-bottom: 6px;
background-color: rgba(139, 0, 0, 0.1);
border-radius: 3px;
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content .damage-summary .damage-value {
color: var(--color-level-error);
font-size: calc(var(--font-size-standard) * 1.2);
font-weight: bold;
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content .dr-summary {
display: flex;
justify-content: space-around;
gap: 4px;
padding: 3px;
margin-bottom: 6px;
font-size: calc(var(--font-size-standard) * 0.85);
background-color: rgba(0, 0, 0, 0.05);
border-radius: 3px;
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content .damage-options .option-line {
display: flex;
justify-content: space-between;
align-items: center;
padding: 3px 6px;
margin: 2px 0;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 3px;
}
.application.dialog.lethalfantasy .apply-damage-dialog .dialog-content .damage-options .option-line strong {
color: var(--color-dark-1);
font-size: calc(var(--font-size-standard) * 1.05);
}
.lethalfantasy-roll-dialog fieldset {
padding: 4px;
}
@@ -2261,9 +2307,16 @@ i.lethalfantasy {
min-width: 5rem;
max-width: 5em;
}
.dialog-form .form-footer {
padding: 4px;
gap: 4px;
}
.dialog-form .form-footer button {
min-width: 14rem;
min-height: 3.2rem;
min-width: 8rem;
min-height: 2rem;
padding: 2px 6px;
margin: 0;
font-size: calc(var(--font-size-standard) * 0.9);
}
.dialog-modifier {
display: flex;
@@ -2356,6 +2409,115 @@ i.lethalfantasy {
font-size: calc(var(--font-size-standard) * 1);
text-shadow: 0 0 10px var(--color-shadow-primary);
}
.dice-roll .damage-buttons {
width: 100%;
padding: 8px;
margin-top: 8px;
}
.dice-roll .damage-buttons .damage-buttons-title {
font-weight: bold;
margin-bottom: 8px;
font-size: calc(var(--font-size-standard) * 0.95);
text-align: center;
}
.dice-roll .damage-buttons .damage-buttons-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
padding: 8px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
.dice-roll .damage-buttons .damage-buttons-grid.monster-damage {
grid-template-columns: 1fr;
justify-items: center;
}
.dice-roll .damage-buttons .damage-buttons-grid .damage-roll-btn {
padding: 6px 10px;
background: linear-gradient(to bottom, #8b4513 0%, #6b3410 100%);
border: 1px solid #4b2408;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
color: #f0f0e0;
cursor: pointer;
border-radius: 4px;
font-size: calc(var(--font-size-standard) * 0.85);
font-weight: 500;
text-align: center;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
}
.dice-roll .damage-buttons .damage-buttons-grid .damage-roll-btn i {
font-size: calc(var(--font-size-standard) * 1);
}
.dice-roll .damage-buttons .damage-buttons-grid .damage-roll-btn:hover {
background: linear-gradient(to bottom, #9b5523 0%, #7b4420 100%);
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4);
transform: translateY(-1px);
border-color: #5b3418;
}
.dice-roll .damage-buttons .damage-buttons-grid .damage-roll-btn:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.dice-roll .damage-result {
width: 100%;
padding: 8px;
}
.dice-roll .damage-result ul {
padding: 0;
margin: 0;
}
.dice-roll .damage-result .li-apply-wounds {
list-style: none;
margin-top: 10px;
padding: 0;
display: none;
}
.dice-roll .damage-result .li-apply-wounds > div:first-child {
font-weight: bold;
margin-bottom: 8px;
font-size: calc(var(--font-size-standard) * 0.95);
text-align: center;
}
.dice-roll .damage-result .li-apply-wounds .combatants-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
margin-top: 5px;
padding: 8px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
.dice-roll .damage-result .li-apply-wounds .combatants-grid .apply-wounds-btn {
padding: 6px 10px;
background: linear-gradient(to bottom, #5a5850 0%, #4b4a44 100%);
border: 1px solid #2b2a24;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
color: #f0f0e0;
cursor: pointer;
border-radius: 4px;
font-size: calc(var(--font-size-standard) * 0.85);
font-weight: 500;
text-align: center;
transition: all 0.2s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.dice-roll .damage-result .li-apply-wounds .combatants-grid .apply-wounds-btn:hover {
background: linear-gradient(to bottom, #6a6860 0%, #5a5850 100%);
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4);
transform: translateY(-1px);
border-color: #3b3a34;
}
.dice-roll .damage-result .li-apply-wounds .combatants-grid .apply-wounds-btn:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
#token-hud .hp-loss-wrap {
position: absolute;
left: 75px;

View File

@@ -282,6 +282,8 @@
},
"Label": {
"agility": "Dexterity",
"applyDamage": "Apply damage to:",
"rollDamage": "Roll Damage",
"gotoToken": "Go to token",
"combatAction": "Combat action",
"currentAction": "Current ongoing action",
@@ -304,8 +306,10 @@
"grantedAttackDice": "Granted attack",
"grantedDamageDice": "Granted damage",
"grantedDefenseDice": "Granted defense",
"damageResistance": "Damage resistance",
"damageResistance": "DR",
"damageResistanceShort": "DR",
"shieldDamageReduction": "Shield DR",
"shieldDefenseDice": "Shield dice",
"stealth": "Stealth",
"progressionDice": "Progression/Lethargy dice",
"rollProgressionCount": "Roll progression count",
@@ -421,7 +425,9 @@
"monster-damage": "Monster damage",
"monster-defense": "Monster defense",
"weapons": "Weapons",
"wis": "WIS"
"wis": "WIS",
"weapon-damage-medium": "Weapon damage medium",
"weapon-damage-small": "Weapon damage small"
},
"Miracle": {
"FIELDS": {
@@ -553,7 +559,7 @@
"label": "Min"
}
},
"damagereduction": {
"damageReduction": {
"label": "Damage reduction"
},
"defense": {
@@ -856,6 +862,20 @@
"melee": "Melee",
"ranged": "Ranged"
}
},
"Dialog": {
"applyDamageTo": "Apply damage to",
"weapon": "Weapon",
"totalDamage": "Total Damage",
"damageReduction": "Damage Reduction",
"armorDR": "Armor DR",
"shieldDR": "Shield DR",
"totalDR": "Total DR",
"selectOption": "Select damage application option",
"noDR": "No DR",
"withArmor": "With Armor DR only",
"withAll": "With Armor + Shield DR",
"damage": "damage"
}
},
"TYPES": {

View File

@@ -152,6 +152,73 @@ Hooks.on(hookName, (message, html, data) => {
})
}
}
// Gestion du survol et du clic sur les boutons de dégâts pour les GMs
if (game.user.isGM) {
// Show damage buttons only for GM
$(html).find(".li-apply-wounds").each((i, btn) => {
btn.style.display = "block"
})
$(html).find(".apply-wounds-btn").hover(
function (event) {
// Mouse enter - select the token and pan to it
let combatantId = $(this).data("combatant-id")
if (combatantId && game.combat) {
let combatant = game.combat.combatants.get(combatantId)
if (combatant?.token) {
let token = canvas.tokens.get(combatant.token.id)
if (token) {
token.control({ releaseOthers: true })
canvas.animatePan(token.center)
}
}
}
},
function (event) {
// Mouse leave - release selection
canvas.tokens.releaseAll()
}
)
$(html).find(".apply-wounds-btn").click((event) => {
LethalFantasyUtils.applyDamage(message, event)
})
}
// Gestionnaire pour les boutons de jet de dégâts
$(html).find(".damage-roll-btn").click(async (event) => {
const button = $(event.currentTarget)
const weaponId = button.data("weapon-id")
const damageType = button.data("damage-type")
const damageFormula = button.data("damage-formula")
const damageModifier = button.data("damage-modifier")
const isMonster = button.data("is-monster")
// Récupérer l'acteur qui a fait le jet initial
const actor = game.actors.get(message.rolls[0]?.actorId)
if (!actor) {
ui.notifications.error("Actor not found")
return
}
// Pour les monstres, utiliser prepareMonsterRoll
if (isMonster || actor.type === "monster") {
await actor.system.prepareMonsterRoll("monster-damage", weaponId, undefined, undefined, damageModifier)
return
}
// Pour les personnages, récupérer l'arme
const weapon = actor.items.get(weaponId)
if (!weapon) {
ui.notifications.error("Weapon not found")
return
}
// Lancer les dégâts avec la bonne méthode
const rollType = damageType === "small" ? "weapon-damage-small" : "weapon-damage-medium"
await actor.prepareRoll(rollType, weaponId)
})
})
Hooks.on("getCombatTrackerEntryContext", (html, options) => {

View File

@@ -162,9 +162,11 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
async _onRoll(event, target) {
if (this.isEditMode) return
const rollType = event.target.dataset.rollType
let rollKey = event.target.dataset.rollKey
let rollDice = event.target.dataset?.rollDice || "0"
const rollable = event.target.closest('.rollable')
if (!rollable) return
const rollType = rollable.dataset.rollType
let rollKey = rollable.dataset.rollKey
let rollDice = rollable.dataset?.rollDice || "0"
this.actor.system.prepareMonsterRoll(rollType, rollKey, rollDice)
}
}

View File

@@ -65,7 +65,7 @@ export default class LethalFantasyActor extends Actor {
}
}
}
goodSkill.weaponSkillModifier = maxValue * multiplier
goodSkill.weaponSkillModifier = Math.ceil(maxValue * multiplier)
return goodSkill
}
@@ -80,14 +80,26 @@ export default class LethalFantasyActor extends Actor {
/* *************************************************/
computeDamageReduction() {
let naturalDR = Number(this.system.biodata.naturalDR) || 0
let magicDR = Number(this.system.biodata.magicDR) || 0
// Pour les monstres, utiliser hp.damageResistance et combat.damageReduction
if (this.type === "monster") {
let hpDR = Number(this.system.hp?.damageResistance) || 0
let combatDR = Number(this.system.combat?.damageReduction) || 0
return hpDR + combatDR
}
// Pour les personnages, utiliser biodata et items
let naturalDR = Number(this.system.biodata?.naturalDR) || 0
let magicDR = Number(this.system.biodata?.magicDR) || 0
let armorDR = this.getArmorDR()
return naturalDR + magicDR + armorDR
}
/* *************************************************/
getShieldDR() {
// Pour les monstres, utiliser combat.shieldDamageReduction
if (this.type === "monster") {
return Number(this.system.combat?.shieldDamageReduction) || 0
}
// Pour les personnages, utiliser les items de type shield
let dr = 0
for (let item of this.items) {
if (item.type === "shield" && item.system.equipped) {
@@ -119,6 +131,27 @@ export default class LethalFantasyActor extends Actor {
return defenseValue
}
/* *************************************************/
fuzzyNameSearchWeaponSkills(weaponName, weaponClass = null) {
// Get all weapon skills without the " skill" suffix
let skills = this.items.filter((i) => i.type === "skill" && i.system.weaponClass === weaponClass && i.system.category === "weapon")
// Remove parenthesis in the weapon name for better matching
weaponName = weaponName.replace(/\(.*?\)/g, "").trim()
// Now search if we find all the words of the weapon name in the skill name
skills = skills.filter((s) => {
let skillName = s.name.toLowerCase().replace(" skill", "").trim()
let wName = weaponName.toLowerCase().trim()
let wWords = wName.split(" ")
for (let w of wWords) {
if (!skillName.includes(w)) {
return false
}
}
return true
})
return skills
}
/* *************************************************/
async prepareRoll(rollType, rollKey, rollDice) {
console.log("Preparing roll", rollType, rollKey, rollDice)
@@ -179,19 +212,19 @@ export default class LethalFantasyActor extends Actor {
case "weapon-defense": {
let weapon = this.items.find((i) => i.type === "weapon" && i.id === rollKey)
let skill
let skills = this.items.filter((i) => i.type === "skill" && i.name.toLowerCase() === weapon.name.toLowerCase())
let skills = this.items.filter((i) => i.type === "skill" && i.system.category === "weapon" && i.name.toLowerCase() === weapon.name.toLowerCase())
if (skills.length > 0) {
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
} else {
skills = this.items.filter((i) => i.type === "skill" && i.name.toLowerCase().replace(" skill", "") === weapon.name.toLowerCase())
skills = this.fuzzyNameSearchWeaponSkills(weapon.name, weapon.system.weaponClass)
if (skills.length > 0) {
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
} else {
skills = this.items.filter((i) => i.type === "skill" && i.system.weaponClass === weapon.system.weaponClass)
skills = this.items.filter((i) => i.type === "skill" && i.system.category === "weapon" && i.system.weaponClass === weapon.system.weaponClass)
if (skills.length > 0) {
skill = this.getBestWeaponClassSkill(skills, rollType, 0.5)
} else {
skills = this.items.filter((i) => i.type === "skill" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
skills = this.items.filter((i) => i.type === "skill" && i.system.category === "weapon" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
if (skills.length > 0) {
skill = this.getBestWeaponClassSkill(skills, rollType, 0.25)
} else {
@@ -206,11 +239,14 @@ export default class LethalFantasyActor extends Actor {
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
return
}
rollTarget = skill
rollTarget.weapon = weapon
rollTarget.weaponSkillModifier = skill.weaponSkillModifier
rollTarget.rollKey = rollKey
rollTarget.combat = foundry.utils.duplicate(this.system.combat)
// Créer un objet plain au lieu de modifier directement le skill
rollTarget = {
...skill,
weapon: weapon,
weaponSkillModifier: skill.weaponSkillModifier,
rollKey: rollKey,
combat: foundry.utils.duplicate(this.system.combat)
}
if (rollType === "weapon-damage-small" || rollType === "weapon-damage-medium") {
rollTarget.grantedDice = this.system.granted.damageDice
}

View File

@@ -260,14 +260,17 @@ export default class LethalFantasyRoll extends Roll {
} else if (options.rollType.includes("weapon-damage")) {
options.rollName = options.rollTarget.name
options.isDamage = true
hasModifier = true
hasChangeDice = false
let damageBonus = (options.rollTarget.weapon.system.applyStrengthDamageBonus) ? options.rollTarget.combat.damageModifier : 0
options.rollTarget.value = damageBonus + options.rollTarget.weaponSkillModifier + options.rollTarget.weapon.system.bonuses.damageBonus
options.rollTarget.charModifier = damageBonus
if (options.rollType.includes("small")) {
options.damageSmall = true
dice = options.rollTarget.weapon.system.damage.damageS
} else {
options.damageMedium = true
dice = options.rollTarget.weapon.system.damage.damageM
}
dice = dice.replace("E", "")
@@ -275,6 +278,7 @@ export default class LethalFantasyRoll extends Roll {
} else if (options.rollType.includes("monster-damage")) {
options.rollName = options.rollTarget.name
options.isDamage = true
hasModifier = true
hasChangeDice = false
options.rollTarget.value = options.rollTarget.damageModifier
@@ -474,6 +478,9 @@ export default class LethalFantasyRoll extends Roll {
actorImage: options.actorImage,
rollMode: rollContext.visibility,
hasTarget: options.hasTarget,
isDamage: options.isDamage,
damageSmall: options.damageSmall,
damageMedium: options.damageMedium,
pointBlank,
beyondSkill,
letItFly,
@@ -1123,6 +1130,39 @@ export default class LethalFantasyRoll extends Roll {
* Generates the data required for rendering a roll chat card.
*/
async _getChatCardData(isPrivate) {
// Générer la liste des combatants de la scène
let combatants = []
if (game?.combat?.combatants && this.rollData?.isDamage) {
for (let c of game.combat.combatants) {
if (c.actorId !== this.actorId) {
combatants.push({ id: c.id, name: c.name })
}
}
}
// Récupérer les informations de l'arme pour les attaques réussies
let weaponDamageOptions = null
console.log("Roll type:", this.type, "rollTarget:", this.rollTarget, "Has weapon:", !!this.rollTarget?.weapon)
if (this.type === "weapon-attack" && this.rollTarget?.weapon) {
const weapon = this.rollTarget.weapon
weaponDamageOptions = {
weaponId: weapon._id || weapon.id,
weaponName: weapon.name,
damageS: weapon.system?.damage?.damageS,
damageM: weapon.system?.damage?.damageM
}
console.log("Weapon damage options:", weaponDamageOptions)
} else if (this.type === "monster-attack" && this.rollTarget) {
weaponDamageOptions = {
weaponId: this.rollTarget.rollKey,
weaponName: this.rollTarget.name,
damageFormula: this.rollTarget.damageDice,
damageModifier: this.rollTarget.damageModifier,
isMonster: true
}
console.log("Monster damage options:", weaponDamageOptions)
}
const cardData = {
css: [SYSTEM.id, "dice-roll"],
data: this.data,
@@ -1146,7 +1186,9 @@ export default class LethalFantasyRoll extends Roll {
D30result: this.D30result,
badResult: this.badResult,
rollData: this.rollData,
isPrivate: isPrivate
isPrivate: isPrivate,
combatants: combatants,
weaponDamageOptions: weaponDamageOptions
}
cardData.cssClass = cardData.css.join(" ")
cardData.tooltip = isPrivate ? "" : await this.getTooltip()

View File

@@ -118,6 +118,9 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
defenseModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
damageModifier: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
armorHitPoints: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
damageReduction: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
shieldDamageReduction: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
shieldDefenseDice: new fields.StringField({ required: true, nullable: false, initial: "d4" })
})
@@ -150,7 +153,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
await roll.toMessage({}, { rollMode: roll.options.rollMode })
}
async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined) {
async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined, damageModifier = undefined) {
let rollTarget
switch (rollType) {
case "monster-attack":
@@ -158,6 +161,10 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
case "monster-damage":
rollTarget = foundry.utils.duplicate(this.attacks[rollKey])
rollTarget.rollKey = rollKey
// Si damageModifier est fourni (depuis le chat), l'utiliser au lieu de celui de la fiche
if (damageModifier !== undefined && rollType === "monster-damage") {
rollTarget.damageModifier = damageModifier
}
break
case "monster-skill":
rollTarget = foundry.utils.duplicate(this.resists[rollKey])
@@ -168,6 +175,19 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
rollTarget.rollKey = rollKey
rollTarget.rollDice = rollDice
break
case "shield-defense": {
// Lance directement le dé de défense du bouclier
const formula = rollDice || this.combat.shieldDefenseDice
const roll = new Roll(formula)
await roll.evaluate()
const flavor = game.i18n.localize("LETHALFANTASY.Label.shieldDefenseDice")
await roll.toMessage({
flavor,
speaker: ChatMessage.getSpeaker({ actor: this.parent })
})
return
}
case "weapon-damage-small":
case "weapon-damage-medium":
case "weapon-attack":
@@ -210,13 +230,15 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
break
default:
ui.notifications.error(game.i18n.localize("LETHALFANTASY.Notifications.rollTypeNotFound") + String(rollType))
break
return
}
// In all cases
rollTarget.tokenId = tokenId
console.log(rollTarget)
await this.roll(rollType, rollTarget)
if (rollTarget) {
rollTarget.tokenId = tokenId
console.log(rollTarget)
await this.roll(rollType, rollTarget)
}
}
async rollInitiative(combatId = undefined, combatantId = undefined) {

View File

@@ -22,43 +22,43 @@ export default class LethalFantasyUtils {
static setHookListeners() {
Hooks.on('renderTokenHUD', async (hud, html, token) => {
const lossHPButton = await foundry.applications.handlebars.renderTemplate('systems/fvtt-lethal-fantasy/templates/loss-hp-hud.hbs', {} )
const lossHPButton = await foundry.applications.handlebars.renderTemplate('systems/fvtt-lethal-fantasy/templates/loss-hp-hud.hbs', {})
$(html).find('div.left').append(lossHPButton);
$(html).find('img.lethal-hp-loss-hud').click((event) => {
event.preventDefault();
let hpMenu = $(html).find('.hp-loss-wrap')[0]
if (hpMenu.classList.contains("hp-loss-hud-disabled")) {
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-disabled');
} else {
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
}
})
$(html).find('.loss-hp-hud-click').click((event) => {
event.preventDefault();
let hpLoss = event.currentTarget.dataset.hpValue;
if (token) {
let tokenFull = canvas.tokens.placeables.find( t => t.id === token._id);
console.log(tokenFull, token)
let actor = tokenFull.actor;
actor.applyDamage(Number(hpLoss));
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
}
})
$(html).find('img.lethal-hp-loss-hud').click((event) => {
event.preventDefault();
let hpMenu = $(html).find('.hp-loss-wrap')[0]
if (hpMenu.classList.contains("hp-loss-hud-disabled")) {
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-disabled');
} else {
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
}
})
$(html).find('.loss-hp-hud-click').click((event) => {
event.preventDefault();
let hpLoss = event.currentTarget.dataset.hpValue;
if (token) {
let tokenFull = canvas.tokens.placeables.find(t => t.id === token._id);
console.log(tokenFull, token)
let actor = tokenFull.actor;
actor.applyDamage(Number(hpLoss));
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
}
})
})
}
@@ -246,4 +246,100 @@ export default class LethalFantasyUtils {
}
}
/* -------------------------------------------- */
static async applyDamage(message, event) {
// Récupérer les données du message
let combatantId = event.currentTarget.dataset.combatantId
if (!combatantId || !game.combat) {
ui.notifications.error("No combatant selected")
return
}
let combatant = game.combat.combatants.get(combatantId)
if (!combatant) {
ui.notifications.error("Combatant not found")
return
}
let targetActor = combatant.token?.actor || game.actors.get(combatant.actorId)
if (!targetActor) {
ui.notifications.error("Target actor not found")
return
}
// Récupérer les données de dégâts du message
let damageTotal = message.rolls[0]?.total || 0
let weaponName = message.rolls[0]?.options?.rollName || "Unknown Weapon"
// Calculer les DR
let armorDR = targetActor.computeDamageReduction() || 0
let shieldDR = targetActor.getShieldDR() || 0
let totalDR = armorDR + shieldDR
// Créer le dialogue
const content = await foundry.applications.handlebars.renderTemplate(
"systems/fvtt-lethal-fantasy/templates/apply-damage-dialog.hbs",
{
targetName: targetActor.name,
weaponName: weaponName,
damageTotal: damageTotal,
armorDR: armorDR,
shieldDR: shieldDR,
totalDR: totalDR,
damageNoDR: damageTotal,
damageWithArmor: Math.max(0, damageTotal - armorDR),
damageWithAll: Math.max(0, damageTotal - totalDR)
}
)
const result = await foundry.applications.api.DialogV2.wait({
window: { title: "Apply Damage" },
classes: ["lethalfantasy"],
position: { width: 280 },
content,
buttons: [
{
action: "noDR",
label: "No DR",
callback: () => ({ drType: "none", damage: damageTotal })
},
{
action: "armorDR",
label: "With Armor DR",
callback: () => ({ drType: "armor", damage: Math.max(0, damageTotal - armorDR) })
},
{
action: "allDR",
label: "With Armor + Shield DR",
callback: () => ({ drType: "all", damage: Math.max(0, damageTotal - totalDR) })
},
{
action: "cancel",
label: "Cancel",
callback: () => null
}
],
rejectClose: false
})
if (result && result.damage !== undefined) {
await targetActor.applyDamage(-result.damage)
// Message de confirmation
let drText = ""
if (result.drType === "armor") {
drText = ` (Armor DR: ${armorDR})`
} else if (result.drType === "all") {
drText = ` (Total DR: ${totalDR})`
}
ChatMessage.create({
user: game.user.id,
speaker: { alias: targetActor.name },
rollMode: "gmroll",
content: `${targetActor.name} takes ${result.damage} damage${drText} from ${weaponName}`
})
}
}
}

View File

@@ -1 +1 @@
MANIFEST-000456
MANIFEST-000477

View File

@@ -1,8 +1,8 @@
2025/12/06-15:17:13.631288 7f19dd7fa6c0 Recovering log #454
2025/12/06-15:17:13.737044 7f19dd7fa6c0 Delete type=3 #452
2025/12/06-15:17:13.737119 7f19dd7fa6c0 Delete type=0 #454
2025/12/06-16:41:02.244527 7f19dbff76c0 Level-0 table #459: started
2025/12/06-16:41:02.244570 7f19dbff76c0 Level-0 table #459: 0 bytes OK
2025/12/06-16:41:02.281825 7f19dbff76c0 Delete type=0 #457
2025/12/06-16:41:02.281990 7f19dbff76c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/12/06-16:41:02.282024 7f19dbff76c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/12/19-14:37:50.298740 7f24377fe6c0 Recovering log #475
2025/12/19-14:37:50.308335 7f24377fe6c0 Delete type=3 #473
2025/12/19-14:37:50.308381 7f24377fe6c0 Delete type=0 #475
2025/12/19-15:40:35.866244 7f2436ffd6c0 Level-0 table #480: started
2025/12/19-15:40:35.866281 7f2436ffd6c0 Level-0 table #480: 0 bytes OK
2025/12/19-15:40:35.872420 7f2436ffd6c0 Delete type=0 #478
2025/12/19-15:40:35.879555 7f2436ffd6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/12/19-15:40:35.879588 7f2436ffd6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2025/11/07-07:57:26.850226 7f14baffd6c0 Recovering log #450
2025/11/07-07:57:26.860132 7f14baffd6c0 Delete type=3 #448
2025/11/07-07:57:26.860209 7f14baffd6c0 Delete type=0 #450
2025/11/07-07:58:43.705140 7f14b8ff96c0 Level-0 table #455: started
2025/11/07-07:58:43.705171 7f14b8ff96c0 Level-0 table #455: 0 bytes OK
2025/11/07-07:58:43.711108 7f14b8ff96c0 Delete type=0 #453
2025/11/07-07:58:43.724495 7f14b8ff96c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/11/07-07:58:43.724532 7f14b8ff96c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/12/15-21:20:57.107042 7f17053ff6c0 Recovering log #471
2025/12/15-21:20:57.117492 7f17053ff6c0 Delete type=3 #469
2025/12/15-21:20:57.117544 7f17053ff6c0 Delete type=0 #471
2025/12/15-22:37:50.650614 7f16eeffd6c0 Level-0 table #476: started
2025/12/15-22:37:50.650646 7f16eeffd6c0 Level-0 table #476: 0 bytes OK
2025/12/15-22:37:50.656552 7f16eeffd6c0 Delete type=0 #474
2025/12/15-22:37:50.669781 7f16eeffd6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
2025/12/15-22:37:50.669815 7f16eeffd6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000456
MANIFEST-000476

View File

@@ -1,8 +1,8 @@
2025/12/06-15:17:13.747297 7f19dc7f86c0 Recovering log #454
2025/12/06-15:17:13.857630 7f19dc7f86c0 Delete type=3 #452
2025/12/06-15:17:13.857707 7f19dc7f86c0 Delete type=0 #454
2025/12/06-16:41:02.159042 7f19dbff76c0 Level-0 table #459: started
2025/12/06-16:41:02.159069 7f19dbff76c0 Level-0 table #459: 0 bytes OK
2025/12/06-16:41:02.201619 7f19dbff76c0 Delete type=0 #457
2025/12/06-16:41:02.281970 7f19dbff76c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
2025/12/06-16:41:02.282008 7f19dbff76c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
2025/12/19-14:37:50.313071 7f2437fff6c0 Recovering log #474
2025/12/19-14:37:50.323320 7f2437fff6c0 Delete type=3 #472
2025/12/19-14:37:50.323373 7f2437fff6c0 Delete type=0 #474
2025/12/19-15:40:35.872568 7f2436ffd6c0 Level-0 table #479: started
2025/12/19-15:40:35.872597 7f2436ffd6c0 Level-0 table #479: 0 bytes OK
2025/12/19-15:40:35.879415 7f2436ffd6c0 Delete type=0 #477
2025/12/19-15:40:35.879563 7f2436ffd6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
2025/12/19-15:40:35.879582 7f2436ffd6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2025/11/07-07:57:26.863923 7f14b9ffb6c0 Recovering log #450
2025/11/07-07:57:26.873909 7f14b9ffb6c0 Delete type=3 #448
2025/11/07-07:57:26.873962 7f14b9ffb6c0 Delete type=0 #450
2025/11/07-07:58:43.711204 7f14b8ff96c0 Level-0 table #455: started
2025/11/07-07:58:43.711230 7f14b8ff96c0 Level-0 table #455: 0 bytes OK
2025/11/07-07:58:43.718265 7f14b8ff96c0 Delete type=0 #453
2025/11/07-07:58:43.724502 7f14b8ff96c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
2025/11/07-07:58:43.724539 7f14b8ff96c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
2025/12/15-21:20:57.122365 7f16effff6c0 Recovering log #470
2025/12/15-21:20:57.134320 7f16effff6c0 Delete type=3 #468
2025/12/15-21:20:57.134393 7f16effff6c0 Delete type=0 #470
2025/12/15-22:37:50.644221 7f16eeffd6c0 Level-0 table #475: started
2025/12/15-22:37:50.644288 7f16eeffd6c0 Level-0 table #475: 0 bytes OK
2025/12/15-22:37:50.650497 7f16eeffd6c0 Delete type=0 #473
2025/12/15-22:37:50.669770 7f16eeffd6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
2025/12/15-22:37:50.669829 7f16eeffd6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-000458
MANIFEST-000478

View File

@@ -1,8 +1,8 @@
2025/12/06-15:17:13.504137 7f19ddffb6c0 Recovering log #456
2025/12/06-15:17:13.609897 7f19ddffb6c0 Delete type=3 #454
2025/12/06-15:17:13.609952 7f19ddffb6c0 Delete type=0 #456
2025/12/06-16:41:02.201733 7f19dbff76c0 Level-0 table #461: started
2025/12/06-16:41:02.201761 7f19dbff76c0 Level-0 table #461: 0 bytes OK
2025/12/06-16:41:02.244399 7f19dbff76c0 Delete type=0 #459
2025/12/06-16:41:02.281980 7f19dbff76c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/12/06-16:41:02.282016 7f19dbff76c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/12/19-14:37:50.285216 7f244c9fe6c0 Recovering log #476
2025/12/19-14:37:50.295747 7f244c9fe6c0 Delete type=3 #474
2025/12/19-14:37:50.295805 7f244c9fe6c0 Delete type=0 #476
2025/12/19-15:40:35.852984 7f2436ffd6c0 Level-0 table #481: started
2025/12/19-15:40:35.853042 7f2436ffd6c0 Level-0 table #481: 0 bytes OK
2025/12/19-15:40:35.859968 7f2436ffd6c0 Delete type=0 #479
2025/12/19-15:40:35.879535 7f2436ffd6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/12/19-15:40:35.879576 7f2436ffd6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2025/11/07-07:57:26.836688 7f14b97fa6c0 Recovering log #451
2025/11/07-07:57:26.847365 7f14b97fa6c0 Delete type=3 #449
2025/11/07-07:57:26.847456 7f14b97fa6c0 Delete type=0 #451
2025/11/07-07:58:43.699007 7f14b8ff96c0 Level-0 table #457: started
2025/11/07-07:58:43.699056 7f14b8ff96c0 Level-0 table #457: 0 bytes OK
2025/11/07-07:58:43.705029 7f14b8ff96c0 Delete type=0 #455
2025/11/07-07:58:43.724484 7f14b8ff96c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/11/07-07:58:43.724525 7f14b8ff96c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/12/15-21:20:57.092288 7f16ef7fe6c0 Recovering log #472
2025/12/15-21:20:57.103016 7f16ef7fe6c0 Delete type=3 #470
2025/12/15-21:20:57.103072 7f16ef7fe6c0 Delete type=0 #472
2025/12/15-22:37:50.663349 7f16eeffd6c0 Level-0 table #477: started
2025/12/15-22:37:50.663375 7f16eeffd6c0 Level-0 table #477: 0 bytes OK
2025/12/15-22:37:50.669678 7f16eeffd6c0 Delete type=0 #475
2025/12/15-22:37:50.669808 7f16eeffd6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
2025/12/15-22:37:50.669842 7f16eeffd6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-000156
MANIFEST-000176

View File

@@ -1,8 +1,8 @@
2025/12/06-15:17:13.990000 7f19dcff96c0 Recovering log #154
2025/12/06-15:17:14.078163 7f19dcff96c0 Delete type=3 #152
2025/12/06-15:17:14.078227 7f19dcff96c0 Delete type=0 #154
2025/12/06-16:41:02.444766 7f19dbff76c0 Level-0 table #159: started
2025/12/06-16:41:02.444810 7f19dbff76c0 Level-0 table #159: 0 bytes OK
2025/12/06-16:41:02.474131 7f19dbff76c0 Delete type=0 #157
2025/12/06-16:41:02.619626 7f19dbff76c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/12/06-16:41:02.668537 7f19dbff76c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/12/19-14:37:50.338179 7f244d1ff6c0 Recovering log #174
2025/12/19-14:37:50.348596 7f244d1ff6c0 Delete type=3 #172
2025/12/19-14:37:50.348672 7f244d1ff6c0 Delete type=0 #174
2025/12/19-15:40:35.860117 7f2436ffd6c0 Level-0 table #179: started
2025/12/19-15:40:35.860149 7f2436ffd6c0 Level-0 table #179: 0 bytes OK
2025/12/19-15:40:35.866102 7f2436ffd6c0 Delete type=0 #177
2025/12/19-15:40:35.879546 7f2436ffd6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/12/19-15:40:35.879569 7f2436ffd6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2025/11/07-07:57:26.889185 7f14ba7fc6c0 Recovering log #150
2025/11/07-07:57:26.898546 7f14ba7fc6c0 Delete type=3 #148
2025/11/07-07:57:26.898639 7f14ba7fc6c0 Delete type=0 #150
2025/11/07-07:58:43.718395 7f14b8ff96c0 Level-0 table #155: started
2025/11/07-07:58:43.718429 7f14b8ff96c0 Level-0 table #155: 0 bytes OK
2025/11/07-07:58:43.724414 7f14b8ff96c0 Delete type=0 #153
2025/11/07-07:58:43.724518 7f14b8ff96c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/11/07-07:58:43.724544 7f14b8ff96c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/12/15-21:20:57.154335 7f1704bfe6c0 Recovering log #170
2025/12/15-21:20:57.164315 7f1704bfe6c0 Delete type=3 #168
2025/12/15-21:20:57.164371 7f1704bfe6c0 Delete type=0 #170
2025/12/15-22:37:50.692660 7f16eeffd6c0 Level-0 table #175: started
2025/12/15-22:37:50.692695 7f16eeffd6c0 Level-0 table #175: 0 bytes OK
2025/12/15-22:37:50.698767 7f16eeffd6c0 Delete type=0 #173
2025/12/15-22:37:50.710785 7f16eeffd6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
2025/12/15-22:37:50.710818 7f16eeffd6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-000455
MANIFEST-000475

View File

@@ -1,8 +1,8 @@
2025/12/06-15:17:13.870724 7f19ddffb6c0 Recovering log #453
2025/12/06-15:17:13.958289 7f19ddffb6c0 Delete type=3 #451
2025/12/06-15:17:13.958388 7f19ddffb6c0 Delete type=0 #453
2025/12/06-16:41:02.118716 7f19dbff76c0 Level-0 table #458: started
2025/12/06-16:41:02.121944 7f19dbff76c0 Level-0 table #458: 0 bytes OK
2025/12/06-16:41:02.158936 7f19dbff76c0 Delete type=0 #456
2025/12/06-16:41:02.281954 7f19dbff76c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/12/06-16:41:02.282000 7f19dbff76c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/12/19-14:37:50.326173 7f244c9fe6c0 Recovering log #473
2025/12/19-14:37:50.335692 7f244c9fe6c0 Delete type=3 #471
2025/12/19-14:37:50.335763 7f244c9fe6c0 Delete type=0 #473
2025/12/19-15:40:35.879641 7f2436ffd6c0 Level-0 table #478: started
2025/12/19-15:40:35.879661 7f2436ffd6c0 Level-0 table #478: 0 bytes OK
2025/12/19-15:40:35.886005 7f2436ffd6c0 Delete type=0 #476
2025/12/19-15:40:35.909027 7f2436ffd6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/12/19-15:40:35.927361 7f2436ffd6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2025/11/07-07:57:26.876181 7f14b97fa6c0 Recovering log #449
2025/11/07-07:57:26.886933 7f14b97fa6c0 Delete type=3 #447
2025/11/07-07:57:26.887010 7f14b97fa6c0 Delete type=0 #449
2025/11/07-07:58:43.747501 7f14b8ff96c0 Level-0 table #454: started
2025/11/07-07:58:43.747545 7f14b8ff96c0 Level-0 table #454: 0 bytes OK
2025/11/07-07:58:43.754307 7f14b8ff96c0 Delete type=0 #452
2025/11/07-07:58:43.772388 7f14b8ff96c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/11/07-07:58:43.785957 7f14b8ff96c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/12/15-21:20:57.138258 7f16ef7fe6c0 Recovering log #469
2025/12/15-21:20:57.151734 7f16ef7fe6c0 Delete type=3 #467
2025/12/15-21:20:57.151800 7f16ef7fe6c0 Delete type=0 #469
2025/12/15-22:37:50.656644 7f16eeffd6c0 Level-0 table #474: started
2025/12/15-22:37:50.656668 7f16eeffd6c0 Level-0 table #474: 0 bytes OK
2025/12/15-22:37:50.663254 7f16eeffd6c0 Delete type=0 #472
2025/12/15-22:37:50.669789 7f16eeffd6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
2025/12/15-22:37:50.669836 7f16eeffd6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)

View File

@@ -1,33 +1,34 @@
&.fortune {
img {
border: 0px;
}
.intro-chat {
border-radius: 20px;
display: flex;
flex-direction: row;
.intro-img {
padding: 5px;
width: 80px;
align-self: center;
}
.intro-right {
display: flex;
flex-direction: column;
.introText {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2);
width: 210px;
text-align: center;
}
}
}
.button.control, .fortune-accepted {
display: flex;
justify-content: center;
align-items: center;
font-size: calc(var(--font-size-standard) * 1.3);
img {
border: 0px;
}
.intro-chat {
border-radius: 20px;
display: flex;
flex-direction: row;
.intro-img {
padding: 5px;
width: 80px;
align-self: center;
}
.intro-right {
display: flex;
flex-direction: column;
.introText {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2);
width: 210px;
text-align: center;
}
}
}
.button.control,
.fortune-accepted {
display: flex;
justify-content: center;
align-items: center;
font-size: calc(var(--font-size-standard) * 1.3);
}
}
&.ask-roll {
@@ -37,4 +38,4 @@
justify-content: center;
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2);
}
}

View File

@@ -25,7 +25,6 @@
gap: 10px;
flex: 1;
.monster-hp {
display: flex;
gap: 4px;
@@ -46,7 +45,7 @@
min-width: 2.2rem;
max-width: 2.2rem;
margin-left: 4px;
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
}
.character-hp-max {
clear: both;
@@ -58,7 +57,7 @@
input {
width: 3.2rem;
text-align: center;
font-size: calc(var(--font-size-standard) * 1.0);
font-size: calc(var(--font-size-standard) * 1);
}
}
}
@@ -121,9 +120,11 @@
flex: 1;
.monster-skill {
display: flex;
display: grid;
grid-template-columns: repeat(3, auto 2.5rem);
gap: 0.5rem;
align-items: center;
margin-right: 0.5rem;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
@@ -134,12 +135,9 @@
max-width: 2.5rem;
}
.name {
flex: 1;
min-width: 3.2rem;
margin-left: 4px;
}
.form-group {
flex: 1;
padding-left: 4px;
.form-fields {
flex: none;
@@ -157,8 +155,9 @@
.monster-movement {
display: flex;
align-items: center;
margin-right: 0.5rem;
flex-direction: column;
gap: 4px;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
@@ -252,7 +251,7 @@
}
}
.tab.monster-skills .main-div{
.tab.monster-skills .main-div {
display: grid;
grid-template-columns: 1fr;
legend {

View File

@@ -7,6 +7,65 @@
border-color: var(--color-dark-6);
color: var(--color-dark-2);
}
.apply-damage-dialog {
.dialog-content {
padding: 6px;
font-size: calc(var(--font-size-standard) * 1);
.header {
text-align: center;
padding: 4px;
margin-bottom: 6px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.damage-summary {
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px 6px;
margin-bottom: 6px;
background-color: rgba(139, 0, 0, 0.1);
border-radius: 3px;
.damage-value {
color: var(--color-level-error);
font-size: calc(var(--font-size-standard) * 1.2);
font-weight: bold;
}
}
.dr-summary {
display: flex;
justify-content: space-around;
gap: 4px;
padding: 3px;
margin-bottom: 6px;
font-size: calc(var(--font-size-standard) * 0.85);
background-color: rgba(0, 0, 0, 0.05);
border-radius: 3px;
}
.damage-options {
.option-line {
display: flex;
justify-content: space-between;
align-items: center;
padding: 3px 6px;
margin: 2px 0;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 3px;
strong {
color: var(--color-dark-1);
font-size: calc(var(--font-size-standard) * 1.05);
}
}
}
}
}
}
.lethalfantasy-roll-dialog {
@@ -59,9 +118,14 @@
.dialog-form {
.form-footer {
padding: 4px;
gap: 4px;
button {
min-width: 14rem;
min-height: 3.2rem;
min-width: 8rem;
min-height: 2rem;
padding: 2px 6px;
margin: 0;
font-size: calc(var(--font-size-standard) * 0.9);
}
}
}
@@ -156,4 +220,129 @@
font-size: calc(var(--font-size-standard) * 1);
text-shadow: 0 0 10px var(--color-shadow-primary);
}
.damage-buttons {
width: 100%;
padding: 8px;
margin-top: 8px;
.damage-buttons-title {
font-weight: bold;
margin-bottom: 8px;
font-size: calc(var(--font-size-standard) * 0.95);
text-align: center;
}
.damage-buttons-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
padding: 8px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 5px;
&.monster-damage {
grid-template-columns: 1fr;
justify-items: center;
}
.damage-roll-btn {
padding: 6px 10px;
background: linear-gradient(to bottom, #8b4513 0%, #6b3410 100%);
border: 1px solid #4b2408;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
color: #f0f0e0;
cursor: pointer;
border-radius: 4px;
font-size: calc(var(--font-size-standard) * 0.85);
font-weight: 500;
text-align: center;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
i {
font-size: calc(var(--font-size-standard) * 1);
}
&:hover {
background: linear-gradient(to bottom, #9b5523 0%, #7b4420 100%);
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4);
transform: translateY(-1px);
border-color: #5b3418;
}
&:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
}
}
}
.damage-result {
width: 100%;
padding: 8px;
ul {
padding: 0;
margin: 0;
}
.li-apply-wounds {
list-style: none;
margin-top: 10px;
padding: 0;
display: none;
> div:first-child {
font-weight: bold;
margin-bottom: 8px;
font-size: calc(var(--font-size-standard) * 0.95);
text-align: center;
}
.combatants-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
margin-top: 5px;
padding: 8px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 5px;
.apply-wounds-btn {
padding: 6px 10px;
background: linear-gradient(to bottom, #5a5850 0%, #4b4a44 100%);
border: 1px solid #2b2a24;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
color: #f0f0e0;
cursor: pointer;
border-radius: 4px;
font-size: calc(var(--font-size-standard) * 0.85);
font-weight: 500;
text-align: center;
transition: all 0.2s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
&:hover {
background: linear-gradient(to bottom, #6a6860 0%, #5a5850 100%);
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4);
transform: translateY(-1px);
border-color: #3b3a34;
}
&:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
}
}
}
}
}

View File

@@ -0,0 +1,37 @@
<div class="apply-damage-dialog">
<div class="dialog-content">
<div class="header">
<strong>{{targetName}}</strong>
-
{{weaponName}}
</div>
<div class="damage-summary">
<span class="label">{{localize
"LETHALFANTASY.Dialog.totalDamage"
}}:</span>
<span class="damage-value">{{damageTotal}}</span>
</div>
<div class="dr-summary">
<span>{{localize "LETHALFANTASY.Dialog.armorDR"}}: {{armorDR}}</span>
<span>{{localize "LETHALFANTASY.Dialog.shieldDR"}}: {{shieldDR}}</span>
<span class="total">DR: <strong>{{totalDR}}</strong></span>
</div>
<div class="damage-options">
<div class="option-line">
<span>{{localize "LETHALFANTASY.Dialog.noDR"}}</span>
<strong>{{damageNoDR}}</strong>
</div>
<div class="option-line">
<span>{{localize "LETHALFANTASY.Dialog.withArmor"}}</span>
<strong>{{damageWithArmor}}</strong>
</div>
<div class="option-line">
<span>{{localize "LETHALFANTASY.Dialog.withAll"}}</span>
<strong>{{damageWithAll}}</strong>
</div>
</div>
</div>
</div>

View File

@@ -1,4 +1,5 @@
{{!log 'chat-message' this}}
{{!log 'weaponDamageOptions' weaponDamageOptions}}
<div class="{{cssClass}}">
<div class="intro-chat">
<div class="intro-img">
@@ -9,80 +10,184 @@
<span><STRONG>{{actingCharName}} - {{upperFirst rollName}}</STRONG></span>
{{#if (match rollType "attack")}}
<span>Attack roll !</span>
<span>Attack roll !</span>
{{/if}}
{{#if (match rollType "defense")}}
<span>Defense roll !</span>
<span>Defense roll !</span>
{{/if}}
{{#if (eq rollData.favor "favor")}}
<span><strong>Favor roll</strong></span>
<span><strong>Favor roll</strong></span>
{{/if}}
{{#if (eq rollData.favor "disfavor")}}
<span><strong>Disfavor roll</strong></span>
<span><strong>Disfavor roll</strong></span>
{{/if}}
{{#if badResult}}
<span><strong>{{localize "LETHALFANTASY.Label.otherResult"}}</strong> : {{badResult}}</span>
<span><strong>{{localize "LETHALFANTASY.Label.otherResult"}}</strong>
:
{{badResult}}</span>
{{/if}}
{{#if rollTarget.weapon}}
<span>{{rollTarget.weapon.name}}</span>
<span>{{rollTarget.weapon.name}}</span>
{{/if}}
{{#if rollData.isDamage}}
<span><strong>Damage Roll</strong></span>
{{/if}}
{{#if rollData.damageSmall}}
<span><strong>{{localize
"LETHALFANTASY.Label.weapon-damage-small"
}}</strong></span>
{{/if}}
{{#if rollData.damageMedium}}
<span><strong>{{localize
"LETHALFANTASY.Label.weapon-damage-medium"
}}</strong></span>
{{/if}}
{{#if rollData.letItFly}}
<span>Let It Fly attack ! </span>
<span>Let It Fly attack ! </span>
{{/if}}
{{#if rollData.pointBlank}}
<span>Point Blank Range Attack !</span>
<span>Point Blank Range Attack !</span>
{{/if}}
{{#if rollData.beyondSkill}}
<span>Beyond Skill Range Attack !</span>
<span>Beyond Skill Range Attack !</span>
{{/if}}
<span><strong>Formula</strong> : {{titleFormula}}</span>
{{#each diceResults as |result|}}
<span>{{result.dice}} : {{result.value}}</span>
<span>{{result.dice}} : {{result.value}}</span>
{{/each}}
</div>
</div>
{{#if isSave}}
<div class="result">
{{#if (eq resultType "success")}}
{{#if isPrivate}}?{{else}}{{localize "LETHALFANTASY.Roll.success"}}{{/if}}
{{else}}
{{#if isPrivate}}?{{else}}{{localize "LETHALFANTASY.Roll.failure"}}{{/if}}
{{/if}}
</div>
<div class="result">
{{#if (eq resultType "success")}}
{{#if isPrivate}}?{{else}}{{localize
"LETHALFANTASY.Roll.success"
}}{{/if}}
{{else}}
{{#if isPrivate}}?{{else}}{{localize
"LETHALFANTASY.Roll.failure"
}}{{/if}}
{{/if}}
</div>
{{/if}}
{{#if isResource}}
<div class="result">
{{#if (eq resultType "success")}}
{{#if isPrivate}}?{{else}}{{localize "LETHALFANTASY.Roll.success"}}{{/if}}
{{else}}
{{#if isPrivate}}?{{else}}{{localize "LETHALFANTASY.Roll.failure"}}{{#if isFailure}} ({{localize
"LETHALFANTASY.Roll.resourceLost"}}){{/if}}{{/if}}
{{/if}}
</div>
<div class="result">
{{#if (eq resultType "success")}}
{{#if isPrivate}}?{{else}}{{localize
"LETHALFANTASY.Roll.success"
}}{{/if}}
{{else}}
{{#if isPrivate}}?{{else}}{{localize "LETHALFANTASY.Roll.failure"}}{{#if
isFailure
}} ({{localize "LETHALFANTASY.Roll.resourceLost"}}){{/if}}{{/if}}
{{/if}}
</div>
{{/if}}
{{#if isDamage}}
<div>
{{#if (and isGM hasTarget)}}
{{{localize "LETHALFANTASY.Roll.displayArmor" targetName=targetName targetArmor=targetArmor realDamage=realDamage}}}
{{/if}}
</div>
<div>
{{#if (and isGM hasTarget)}}
{{{localize
"LETHALFANTASY.Roll.displayArmor"
targetName=targetName
targetArmor=targetArmor
realDamage=realDamage
}}}
{{/if}}
</div>
{{/if}}
{{#unless isPrivate}}
<div class="dice-result">
<h4 class="dice-total">{{total}}</h4>
</div>
{{#if D30result}}
<div class="dice-result">
<h4 class="dice-total">D30 result: {{D30result}}</h4>
</div>
{{/if}}
<div class="dice-result">
<h4 class="dice-total">{{total}}</h4>
</div>
{{#if D30result}}
<div class="dice-result">
<h4 class="dice-total">D30 result: {{D30result}}</h4>
</div>
{{/if}}
{{/unless}}
{{#if weaponDamageOptions}}
<div class="damage-buttons">
<div class="damage-buttons-title">{{localize
"LETHALFANTASY.Label.rollDamage"
}}</div>
<div class="damage-buttons-grid {{#if weaponDamageOptions.isMonster}}monster-damage{{/if}}">
{{#if weaponDamageOptions.isMonster}}
<button
class="damage-roll-btn"
data-weapon-id="{{weaponDamageOptions.weaponId}}"
data-damage-type="monster"
data-damage-formula="{{weaponDamageOptions.damageFormula}}"
data-damage-modifier="{{weaponDamageOptions.damageModifier}}"
data-is-monster="true"
title="{{weaponDamageOptions.weaponName}}"
>
<i class="fa-solid fa-dice"></i>
Damage:
{{weaponDamageOptions.damageFormula}}{{#if
weaponDamageOptions.damageModifier
}}+{{weaponDamageOptions.damageModifier}}{{/if}}
</button>
{{else}}
{{#if weaponDamageOptions.damageS}}
<button
class="damage-roll-btn"
data-weapon-id="{{weaponDamageOptions.weaponId}}"
data-damage-type="small"
data-damage-formula="{{weaponDamageOptions.damageS}}"
data-is-monster="false"
title="{{localize 'LETHALFANTASY.Label.weapon-damage-small'}}"
>
<i class="fa-solid fa-dice-d6"></i>
{{localize "LETHALFANTASY.Label.weapon-damage-small"}}
</button>
{{/if}}
{{#if weaponDamageOptions.damageM}}
<button
class="damage-roll-btn"
data-weapon-id="{{weaponDamageOptions.weaponId}}"
data-damage-type="medium"
data-damage-formula="{{weaponDamageOptions.damageM}}"
data-is-monster="false"
title="{{localize 'LETHALFANTASY.Label.weapon-damage-medium'}}"
>
<i class="fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.weapon-damage-medium"}}
</button>
{{/if}}
{{/if}}
</div>
</div>
{{/if}}
{{#if rollData.isDamage}}
<div class="damage-result">
<ul>
<li class="li-apply-wounds">
<div>{{localize "LETHALFANTASY.Label.applyDamage"}}</div>
<div class="combatants-grid">
{{#each combatants}}
<button
class="apply-wounds-btn"
data-combatant-id="{{this.id}}"
title="{{this.name}}"
>
{{this.name}}
</button>
{{/each}}
</div>
</li>
</ul>
</div>
{{/if}}
</div>

View File

@@ -6,80 +6,175 @@
<div class="monster-pc monster-pc-{{ifThen isPlayMode 'play' 'edit'}}">
<div class="monster-left">
<div class="monster-left-image">
<img class="monster-img" src="{{actor.img}}" data-edit="img" data-action="editImage"
data-tooltip="{{actor.name}}" />
<img
class="monster-img"
src="{{actor.img}}"
data-edit="img"
data-action="editImage"
data-tooltip="{{actor.name}}"
/>
</div>
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<fieldset
class="monster-characteristics monster-characteristics-{{ifThen
isPlayMode
'play'
'edit'
}}"
>
<div class="flexrow monster-hp">
<span class="name">{{localize "LETHALFANTASY.Label.HP"}}</span>
{{formInput systemFields.hp.fields.value value=system.hp.value disabled=isPlayMode
classes="monster-hp-value"}}
{{formInput
systemFields.hp.fields.value
value=system.hp.value
disabled=isPlayMode
classes="monster-hp-value"
}}
&nbsp;/&nbsp;
{{formInput systemFields.hp.fields.max value=system.hp.max disabled=isPlayMode classes="monster-hp-value"}}
{{formInput
systemFields.hp.fields.max
value=system.hp.max
disabled=isPlayMode
classes="monster-hp-value"
}}
</div>
<div class="flexrow monster-hp">
<span class="damage-resistance">{{localize "LETHALFANTASY.Label.damageResistance"}}</span>
{{formInput systemFields.hp.fields.damageResistance value=system.hp.damageResistance disabled=isPlayMode
classes="monster-hp-value"}}
<span class="name">{{localize
"LETHALFANTASY.Label.damageResistance"
}}</span>
{{formInput
systemFields.hp.fields.damageResistance
value=system.hp.damageResistance
disabled=isPlayMode
classes="monster-hp-value"
}}
<span class="name">{{localize
"LETHALFANTASY.Label.shieldDamageReduction"
}}</span>
{{formInput
systemFields.combat.fields.shieldDamageReduction
value=system.combat.shieldDamageReduction
disabled=isPlayMode
classes="monster-hp-value"
}}
</div>
<div class="flexrow monster-hp">
<span class="name"><a
class="rollable"
data-roll-type="shield-defense"
data-roll-dice={{system.combat.shieldDefenseDice}}
><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.shieldDefenseDice"
}}</a></span>
{{formInput
systemFields.combat.fields.shieldDefenseDice
value=system.combat.shieldDefenseDice
disabled=isPlayMode
classes="monster-hp-value"
}}
</div>
</fieldset>
</div>
<div class="monster-right">
<div class="monster-name">
{{formInput fields.name value=source.name rootId=partId disabled=isPlayMode}}
<a class="control" data-action="toggleSheet" data-tooltip="LETHALFANTASY.ToggleSheet"
data-tooltip-direction="UP">
{{formInput
fields.name
value=source.name
rootId=partId
disabled=isPlayMode
}}
<a
class="control"
data-action="toggleSheet"
data-tooltip="LETHALFANTASY.ToggleSheet"
data-tooltip-direction="UP"
>
<i class="fa-solid fa-user-{{ifThen isPlayMode 'lock' 'pen'}}"></i>
</a>
</div>
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<fieldset
class="monster-characteristics monster-characteristics-{{ifThen
isPlayMode
'play'
'edit'
}}"
>
<legend>{{localize "LETHALFANTASY.Label.Saves"}}</legend>
<div class="monster-saves">
<div class="monster-save">
<span class="name"><a class="rollable" data-roll-type="save" data-roll-key="will"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
<span class="name"><a
class="rollable"
data-roll-type="save"
data-roll-key="will"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.will"}}
</a></span>
{{formField systemFields.saves.fields.will.fields.value value=system.saves.will.value disabled=isPlayMode
{{formField
systemFields.saves.fields.will.fields.value
value=system.saves.will.value
disabled=isPlayMode
}}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="dodge"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
<a
class="rollable"
data-roll-type="save"
data-roll-key="dodge"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.dodge"}}
</a>
</span>
{{formField systemFields.saves.fields.dodge.fields.value value=system.saves.dodge.value
disabled=isPlayMode}}
{{formField
systemFields.saves.fields.dodge.fields.value
value=system.saves.dodge.value
disabled=isPlayMode
}}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="toughness"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
<a
class="rollable"
data-roll-type="save"
data-roll-key="toughness"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.toughness"}}
</a>
</span>
{{formField systemFields.saves.fields.toughness.fields.value value=system.saves.toughness.value
disabled=isPlayMode}}
{{formField
systemFields.saves.fields.toughness.fields.value
value=system.saves.toughness.value
disabled=isPlayMode
}}
</div>
<div class="monster-save">
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="contagion"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
<a
class="rollable"
data-roll-type="save"
data-roll-key="contagion"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.contagion"}}
</a>
</span>
{{formField systemFields.saves.fields.contagion.fields.value value=system.saves.contagion.value
disabled=isPlayMode}}
{{formField
systemFields.saves.fields.contagion.fields.value
value=system.saves.contagion.value
disabled=isPlayMode
}}
<span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="poison"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>
<a
class="rollable"
data-roll-type="save"
data-roll-key="poison"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>
{{localize "LETHALFANTASY.Label.saves.poison"}}
</a>
</span>
{{formField systemFields.saves.fields.poison.fields.value value=system.saves.poison.value
disabled=isPlayMode }}
{{formField
systemFields.saves.fields.poison.fields.value
value=system.saves.poison.value
disabled=isPlayMode
}}
<!-- <span class="name">
<a class="rollable" data-roll-type="save" data-roll-key="paincourage" data-roll-dice="D20" data-tooltip="Pain/Courage check on wound of..."><i
@@ -98,61 +193,81 @@
</div>
</fieldset>
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<fieldset
class="monster-characteristics monster-characteristics-{{ifThen
isPlayMode
'play'
'edit'
}}"
>
<legend>{{localize "LETHALFANTASY.Label.skills"}}</legend>
<div class="monster-skills">
<div class="monster-skill">
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="resistTorture"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistTorture"}}</a></span>
{{formField systemFields.resists.fields.resistTorture.fields.value
value=system.resists.resistTorture.value
disabled=isPlayMode
<span class="name"><a
class="rollable"
data-roll-type="monster-skill"
data-roll-key="resistTorture"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistTorture"
}}</a></span>
{{formField
systemFields.resists.fields.resistTorture.fields.value
value=system.resists.resistTorture.value
disabled=isPlayMode
}}
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="resistPerformance"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistPerformance"}}</a></span>
{{formField systemFields.resists.fields.resistPerformance.fields.value
value=system.resists.resistPerformance.value
disabled=isPlayMode
<span class="name"><a
class="rollable"
data-roll-type="monster-skill"
data-roll-key="resistPerformance"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistPerformance"
}}</a></span>
{{formField
systemFields.resists.fields.resistPerformance.fields.value
value=system.resists.resistPerformance.value
disabled=isPlayMode
}}
<span class="name"><a
class="rollable"
data-roll-type="monster-skill"
data-roll-key="resistIntimidation"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistIntimidation"
}}</a></span>
{{formField
systemFields.resists.fields.resistIntimidation.fields.value
value=system.resists.resistIntimidation.value
disabled=isPlayMode
}}
<span class="name"><a class="rollable" data-roll-type="monster-skill"
data-roll-key="resistIntimidation"><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.resistIntimidation"}}</a></span>
{{formField systemFields.resists.fields.resistIntimidation.fields.value
value=system.resists.resistIntimidation.value
disabled=isPlayMode }}
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="perception"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.perception"}}</a></span>
{{formField systemFields.resists.fields.perception.fields.value value=system.resists.perception.value
disabled=isPlayMode }}
<span class="name"><a class="rollable" data-roll-type="monster-skill" data-roll-key="stealth"><i
class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.stealth"}}</a></span>
{{formField systemFields.resists.fields.stealth.fields.value value=system.resists.stealth.value
disabled=isPlayMode }}
</div>
</div>
</fieldset>
<div class="monster-skill">
<span class="name"><a
class="rollable"
data-roll-type="monster-skill"
data-roll-key="perception"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.perception"
}}</a></span>
{{formField
systemFields.resists.fields.perception.fields.value
value=system.resists.perception.value
disabled=isPlayMode
}}
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<legend>{{localize "LETHALFANTASY.Label.Movement"}}</legend>
<div class="monster-movements">
<div class="monster-movement">
<span class="name">{{localize "LETHALFANTASY.Label.movement.walk"}}</span>
{{formField systemFields.movement.fields.walk value=system.movement.walk disabled=isPlayMode}}
<span class="name">{{localize "LETHALFANTASY.Label.movement.jog"}}</span>
{{formField systemFields.movement.fields.jog value=system.movement.jog disabled=isPlayMode}}
<span class="name">{{localize "LETHALFANTASY.Label.movement.run"}}</span>
{{formField systemFields.movement.fields.run value=system.movement.run disabled=isPlayMode}}
<span class="name">{{localize "LETHALFANTASY.Label.movement.sprint"}}</span>
{{formField systemFields.movement.fields.sprint value=system.movement.sprint disabled=isPlayMode}}
<span class="name"><a
class="rollable"
data-roll-type="monster-skill"
data-roll-key="stealth"
><i class="lf-roll-small fa-solid fa-dice-d20"></i>{{localize
"LETHALFANTASY.Label.stealth"
}}</a></span>
{{formField
systemFields.resists.fields.stealth.fields.value
value=system.resists.stealth.value
disabled=isPlayMode
}}
</div>
</div>
</fieldset>
@@ -160,23 +275,91 @@
</div>
</fieldset>
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
<fieldset
class="monster-characteristics monster-characteristics-{{ifThen
isPlayMode
'play'
'edit'
}}"
>
<legend>{{localize "LETHALFANTASY.Label.characteristics"}}</legend>
<div class="monster-characteristic">
<span>{{localize "LETHALFANTASY.Label.int"}}</span>
{{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value
disabled=isPlayMode data-char-id="int" }}
{{formField
systemFields.characteristics.fields.int.fields.value
value=system.characteristics.int.value
disabled=isPlayMode
data-char-id="int"
}}
{{formField systemFields.characteristics.fields.int.fields.percent value=system.characteristics.int.percent
disabled=isPlayMode type="number" }}
{{formField
systemFields.characteristics.fields.int.fields.percent
value=system.characteristics.int.percent
disabled=isPlayMode
type="number"
}}
</div>
<div class="monster-characteristic">
<span>{{localize "LETHALFANTASY.Label.dex"}}</span>
{{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value
disabled=isPlayMode data-char-id="wis" }}
{{formField
systemFields.characteristics.fields.dex.fields.value
value=system.characteristics.dex.value
disabled=isPlayMode
data-char-id="wis"
}}
{{formField systemFields.characteristics.fields.dex.fields.percent value=system.characteristics.dex.percent
disabled=isPlayMode type="number" }}
{{formField
systemFields.characteristics.fields.dex.fields.percent
value=system.characteristics.dex.percent
disabled=isPlayMode
type="number"
}}
</div>
<legend>{{localize "LETHALFANTASY.Label.Movement"}}</legend>
<div class="monster-movements">
<div class="monster-movement">
<div class="flexrow monster-hp">
<span class="name">{{localize
"LETHALFANTASY.Label.movement.walk"
}}</span>
{{formField
systemFields.movement.fields.walk
value=system.movement.walk
disabled=isPlayMode
}}
</div>
<div class="flexrow monster-hp">
<span class="name">{{localize
"LETHALFANTASY.Label.movement.jog"
}}</span>
{{formField
systemFields.movement.fields.jog
value=system.movement.jog
disabled=isPlayMode
}}
</div>
<div class="flexrow monster-hp">
<span class="name">{{localize
"LETHALFANTASY.Label.movement.run"
}}</span>
{{formField
systemFields.movement.fields.run
value=system.movement.run
disabled=isPlayMode
}}
</div>
<div class="flexrow monster-hp">
<span class="name">{{localize
"LETHALFANTASY.Label.movement.sprint"
}}</span>
{{formField
systemFields.movement.fields.sprint
value=system.movement.sprint
disabled=isPlayMode
}}
</div>
</div>
</div>
</fieldset>