diff --git a/lang/en.json b/lang/en.json index 39deed3..dae5123 100644 --- a/lang/en.json +++ b/lang/en.json @@ -988,6 +988,9 @@ "diceResult": "Dice result", "progressionCount": "Progression count:" }, + "Combat": { + "RollMonsters": "Roll Monsters" + }, "EquipmentCategories": { "ClassKit": "Class Kit", "Clothing": "Clothing", diff --git a/lethal-fantasy.mjs b/lethal-fantasy.mjs index bd0471b..40994bf 100644 --- a/lethal-fantasy.mjs +++ b/lethal-fantasy.mjs @@ -129,310 +129,284 @@ Hooks.once("ready", function () { } }) -// Test if version below 13 -let hookName = "renderChatMessage" -if (foundry.utils.isNewerVersion(game.version, "12.0",)) { - hookName = "renderChatMessageHTML" -} -Hooks.on(hookName, (message, html, data) => { +Hooks.on("renderChatMessageHTML", (message, html, data) => { const typeMessage = data.message.flags.lethalFantasy?.typeMessage // Message de demande de jet de dés if (typeMessage === "askRoll") { // Affichage des boutons de jet de dés uniquement pour les joueurs if (game.user.isGM) { - html.find(".ask-roll-dice").each((i, btn) => { + for (const btn of html.querySelectorAll(".ask-roll-dice")) { btn.style.display = "none" - }) + } } else { - html.find(".ask-roll-dice").click((event) => { - const btn = $(event.currentTarget) - const type = btn.data("type") - const value = btn.data("value") - const avantage = btn.data("avantage") ?? "=" - const character = game.user.character - if (type === SYSTEM.ROLL_TYPE.RESOURCE) character.rollResource(value) - else if (type === SYSTEM.ROLL_TYPE.SAVE) character.rollSave(value, avantage) - }) + for (const btn of html.querySelectorAll(".ask-roll-dice")) { + btn.addEventListener("click", () => { + const type = btn.dataset.type + const value = btn.dataset.value + const avantage = btn.dataset.avantage ?? "=" + const character = game.user.character + if (type === SYSTEM.ROLL_TYPE.RESOURCE) character.rollResource(value) + else if (type === SYSTEM.ROLL_TYPE.SAVE) character.rollSave(value, avantage) + }) + } } } // 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) => { + for (const btn of html.querySelectorAll(".li-apply-wounds")) { 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") + for (const btn of html.querySelectorAll(".apply-wounds-btn")) { + btn.addEventListener("mouseenter", () => { + const combatantId = btn.dataset.combatantId if (combatantId && game.combat) { - let combatant = game.combat.combatants.get(combatantId) + const combatant = game.combat.combatants.get(combatantId) if (combatant?.token) { - let token = canvas.tokens.get(combatant.token.id) + const 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) - }) + }) + btn.addEventListener("mouseleave", () => canvas.tokens.releaseAll()) + btn.addEventListener("click", event => LethalFantasyUtils.applyDamage(message, event)) + } } // Gestion du survol et du clic sur les boutons de défense - $(html).find(".request-defense-btn").hover( - function (event) { - // Mouse enter - select the token and pan to it - let tokenId = $(this).data("token-id") + for (const btn of html.querySelectorAll(".request-defense-btn")) { + btn.addEventListener("mouseenter", () => { + const tokenId = btn.dataset.tokenId if (tokenId) { - let token = canvas.tokens.get(tokenId) + const token = canvas.tokens.get(tokenId) if (token) { token.control({ releaseOthers: true }) canvas.animatePan(token.center) } } - }, - function (event) { - // Mouse leave - release selection - canvas.tokens.releaseAll() - } - ) + }) + btn.addEventListener("mouseleave", () => canvas.tokens.releaseAll()) - // Gestionnaire pour les boutons de demande de défense - $(html).find(".request-defense-btn").off("click").on("click", (event) => { - event.preventDefault() - event.stopPropagation() + // Gestionnaire pour les boutons de demande de défense + btn.addEventListener("click", event => { + event.preventDefault() + event.stopPropagation() - const button = $(event.currentTarget) - const combatantId = button.data("combatant-id") - const tokenId = button.data("token-id") + const combatantId = btn.dataset.combatantId + const tokenId = btn.dataset.tokenId - // Récupérer le combattant soit du combat, soit directement du token - let combatant = null - let token = null + // Récupérer le combattant soit du combat, soit directement du token + let combatant = null + let token = null - if (game.combat && combatantId) { - combatant = game.combat.combatants.get(combatantId) - } + if (game.combat && combatantId) { + combatant = game.combat.combatants.get(combatantId) + } - // Si pas de combattant trouvé, chercher le token directement - if (!combatant && tokenId) { - token = canvas.tokens.get(tokenId) - if (token) { - // Créer un pseudo-combattant avec les infos du token - combatant = { - actor: token.actor, - name: token.name, - token: token, - actorId: token.actorId + // Si pas de combattant trouvé, chercher le token directement + if (!combatant && tokenId) { + token = canvas.tokens.get(tokenId) + if (token) { + // Créer un pseudo-combattant avec les infos du token + combatant = { + actor: token.actor, + name: token.name, + token: token, + actorId: token.actorId + } } } - } - if (!combatant) return + if (!combatant) return - // Récupérer les informations de l'attaquant depuis le message - const attackerName = message.rolls[0]?.actorName || "Unknown" - const attackerId = message.rolls[0]?.actorId - const weaponName = message.rolls[0]?.rollName || "weapon" - const attackRoll = message.rolls[0]?.rollTotal || 0 - const defenderName = combatant.name - const attackWeaponId = message.rolls[0]?.rollTarget?.weapon?.id || message.rolls[0]?.rollTarget?.weapon?._id - const attackRollType = message.rolls[0]?.type - const attackRollKey = message.rolls[0]?.rollTarget?.rollKey - console.log(`[LF] request-defense-btn | attackRollType=${attackRollType} defender=${defenderName} defenderType=${combatant.actor?.type}`) - const attackD30result = message.rolls[0]?.options?.D30result || null - const attackD30message = message.rolls[0]?.options?.D30message || null - const attackRerollContext = { - rollType: message.rolls[0]?.options?.rollType, - rollTarget: foundry.utils.duplicate(message.rolls[0]?.options?.rollTarget ?? {}), - actorId: message.rolls[0]?.options?.actorId, - actorName: message.rolls[0]?.options?.actorName, - actorImage: message.rolls[0]?.options?.actorImage, - defenderId: combatant.actor?.id || null, - defenderTokenId: tokenId || combatant.token?.id || null, - rollContext: foundry.utils.duplicate(message.rolls[0]?.options?.rollData ?? {}) - } + // Récupérer les informations de l'attaquant depuis le message + const attackerName = message.rolls[0]?.actorName || "Unknown" + const attackerId = message.rolls[0]?.actorId + const weaponName = message.rolls[0]?.rollName || "weapon" + const attackRoll = message.rolls[0]?.rollTotal || 0 + const defenderName = combatant.name + const attackWeaponId = message.rolls[0]?.rollTarget?.weapon?.id || message.rolls[0]?.rollTarget?.weapon?._id + const attackRollType = message.rolls[0]?.type + const attackRollKey = message.rolls[0]?.rollTarget?.rollKey + console.log(`[LF] request-defense-btn | attackRollType=${attackRollType} defender=${defenderName} defenderType=${combatant.actor?.type}`) + const attackD30result = message.rolls[0]?.options?.D30result || null + const attackD30message = message.rolls[0]?.options?.D30message || null + const attackRerollContext = { + rollType: message.rolls[0]?.options?.rollType, + rollTarget: foundry.utils.duplicate(message.rolls[0]?.options?.rollTarget ?? {}), + actorId: message.rolls[0]?.options?.actorId, + actorName: message.rolls[0]?.options?.actorName, + actorImage: message.rolls[0]?.options?.actorImage, + defenderId: combatant.actor?.id || null, + defenderTokenId: tokenId || combatant.token?.id || null, + rollContext: foundry.utils.duplicate(message.rolls[0]?.options?.rollData ?? {}) + } - // Préparer le message de demande de défense - // isRanged: true si le monstre était en mode ranged (via rollTarget.attackMode stocké dans le roll) - // OU si l'attaquant utilisait une arme ranged (weapon-attack avec weaponType === "ranged") - const attacker = game.actors.get(attackerId) - const rollTargetOptions = message.rolls[0]?.options?.rollTarget - const attackerWeapon = rollTargetOptions?.weapon - const isRangedAttack = (rollTargetOptions?.attackMode === "ranged") - || (attacker?.type === "monster" && attacker.system.attackMode === "ranged") - || (attackerWeapon?.system?.weaponType === "ranged") + // Préparer le message de demande de défense + // isRanged: true si le monstre était en mode ranged (via rollTarget.attackMode stocké dans le roll) + // OU si l'attaquant utilisait une arme ranged (weapon-attack avec weaponType === "ranged") + const attacker = game.actors.get(attackerId) + const rollTargetOptions = message.rolls[0]?.options?.rollTarget + const attackerWeapon = rollTargetOptions?.weapon + const isRangedAttack = (rollTargetOptions?.attackMode === "ranged") + || (attacker?.type === "monster" && attacker.system.attackMode === "ranged") + || (attackerWeapon?.system?.weaponType === "ranged") - const defenseMsg = { - type: "requestDefense", - attackerName: attackerName, - attackerId: attackerId, - defenderName: defenderName, - weaponName: weaponName, - attackRoll: attackRoll, - attackWeaponId: attackWeaponId, - attackRollType: attackRollType, - attackRollKey: attackRollKey, - attackD30result: attackD30result, - attackD30message: attackD30message, - attackRerollContext: attackRerollContext, - combatantId: combatantId, - tokenId: tokenId, - isRanged: isRangedAttack - } + const defenseMsg = { + type: "requestDefense", + attackerName, + attackerId, + defenderName, + weaponName, + attackRoll, + attackWeaponId, + attackRollType, + attackRollKey, + attackD30result, + attackD30message, + attackRerollContext, + combatantId, + tokenId, + isRanged: isRangedAttack + } - // Envoyer le message socket à l'utilisateur contrôlant le combatant - // Only consider active (online) users; fall back to any active GM for unowned/GM monsters. - let owners = game.users.filter(u => - u.active && combatant.actor.testUserPermission(u, "OWNER") - ) - if (owners.length === 0) { - owners = game.users.filter(u => u.active && u.isGM) - } + // Envoyer le message socket à l'utilisateur contrôlant le combatant + // Only consider active (online) users; fall back to any active GM for unowned/GM monsters. + let owners = game.users.filter(u => u.active && combatant.actor.testUserPermission(u, "OWNER")) + if (owners.length === 0) { + owners = game.users.filter(u => u.active && u.isGM) + } - // Récupérer l'acteur attaquant pour vérifier qui l'a lancé - const attackerOwners = attacker ? game.users.filter(u => attacker.testUserPermission(u, "OWNER")).map(u => u.id) : [] + // Récupérer l'acteur attaquant pour vérifier qui l'a lancé + const attackerOwners = attacker ? game.users.filter(u => attacker.testUserPermission(u, "OWNER")).map(u => u.id) : [] - // Monsters always need their owner (usually the GM) to roll a save/defense, - // even if that owner also controls the attacker. Only skip for same-player PC-vs-PC. - const defenderIsMonster = combatant.actor?.type === "monster" + // Monsters always need their owner (usually the GM) to roll a save/defense, + // even if that owner also controls the attacker. Only skip for same-player PC-vs-PC. + const defenderIsMonster = combatant.actor?.type === "monster" - let messageSent = false - owners.forEach(owner => { - // Don't let a player be both attacker and defender for their own PC, unless defending a monster. - if (attackerOwners.includes(owner.id) && owner.id === game.user.id && !defenderIsMonster) { - // Ne rien faire - on ne veut pas que l'attaquant se défende contre lui-même + let messageSent = false + owners.forEach(owner => { + // Don't let a player be both attacker and defender for their own PC, unless defending a monster. + if (attackerOwners.includes(owner.id) && owner.id === game.user.id && !defenderIsMonster) { + // Ne rien faire - on ne veut pas que l'attaquant se défende contre lui-même + return + } + + if (owner.id === game.user.id) { + // Si l'utilisateur actuel est le propriétaire du défenseur (mais pas l'attaquant), appeler directement + LethalFantasyUtils.showDefenseRequest({ ...defenseMsg, userId: owner.id }) + messageSent = true + } else { + // Sinon, envoyer via socket + game.socket.emit(`system.${SYSTEM.id}`, { ...defenseMsg, userId: owner.id }) + messageSent = true + } + }) + + // Notification pour l'attaquant + if (messageSent) { + ui.notifications.info(`Defense request sent to ${defenderName}'s controller`) + } + }) + } + + // Gestionnaire pour les boutons de jet de dégâts (armes et résultats de combat) + for (const btn of html.querySelectorAll(".damage-roll-btn, .roll-damage-btn")) { + btn.addEventListener("click", async event => { + event.preventDefault() + event.stopPropagation() + + const weaponId = btn.dataset.weaponId + const attackKey = btn.dataset.attackKey + const attackerId = btn.dataset.attackerId + const defenderId = btn.dataset.defenderId + const defenderTokenId = btn.dataset.defenderTokenId || null + const extraShieldDr = Number(btn.dataset.extraShieldDr || 0) + const damageType = btn.dataset.damageType + const damageFormula = btn.dataset.damageFormula + const damageModifier = btn.dataset.damageModifier + const isMonster = btn.dataset.isMonster + + // Récupérer l'acteur (soit depuis le message, soit depuis attackerId) + const actor = attackerId ? game.actors.get(attackerId) : game.actors.get(message.rolls[0]?.actorId) + if (!actor) { + ui.notifications.error("Actor not found") return } - if (owner.id === game.user.id) { - // Si l'utilisateur actuel est le propriétaire du défenseur (mais pas l'attaquant), appeler directement - LethalFantasyUtils.showDefenseRequest({ ...defenseMsg, userId: owner.id }) - messageSent = true - } else { - // Sinon, envoyer via socket - game.socket.emit(`system.${SYSTEM.id}`, { - ...defenseMsg, - userId: owner.id + // Pour les sorts, rouler les dés de dégâts avec option bypass DR + if (damageType === "spell" && damageFormula) { + const bypassArmor = await foundry.applications.api.DialogV2.confirm({ + window: { title: "Spell Damage" }, + classes: ["lethalfantasy"], + content: "
Does this spell's damage bypass armor DR?
", + yes: { label: "Yes (ignore armor)", icon: "fa-solid fa-wand-magic-sparkles" }, + no: { label: "No (apply armor DR)", icon: "fa-solid fa-shield" } }) - messageSent = true + const rollOpts = { + type: "spell-damage", + rollType: "spell-damage", + rollName: damageFormula, + isDamage: true, + rollData: { isDamage: true }, + bypassArmor: bypassArmor ?? false, + defenderId, + defenderTokenId, + actorId: actor.id, + actorName: actor.name, + actorImage: actor.img + } + const roll = new LethalFantasyRoll(damageFormula, {}, rollOpts) + await roll.evaluate() + roll.options.rollTotal = roll.total + if (game?.dice3d) await game.dice3d.showForRoll(roll, game.user, true) + await roll.toMessage() + return } + + // Pour les boutons de résultat de combat (monster damage) + if (damageType === "monster" && attackKey) { + await actor.system.prepareMonsterRoll("monster-damage", attackKey, undefined, undefined, undefined, defenderId, defenderTokenId, extraShieldDr) + 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, undefined, defenderId, defenderTokenId, extraShieldDr) }) - - // Notification pour l'attaquant - if (messageSent) { - ui.notifications.info(`Defense request sent to ${defenderName}'s controller`) - } - }) - - // Gestionnaire pour les boutons de jet de dégâts (armes et résultats de combat) - $(html).find(".damage-roll-btn, .roll-damage-btn").off("click").on("click", async (event) => { - event.preventDefault() - event.stopPropagation() - - const button = $(event.currentTarget) - const weaponId = button.data("weapon-id") - const attackKey = button.data("attack-key") - let attackerId = button.data("attacker-id") - const defenderId = button.data("defender-id") - const defenderTokenId = button.data("defender-token-id") || null - const extraShieldDr = Number(button.data("extra-shield-dr") || 0) - 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 (soit depuis le message, soit depuis attackerId) - let actor = attackerId ? game.actors.get(attackerId) : game.actors.get(message.rolls[0]?.actorId) - if (!actor) { - ui.notifications.error("Actor not found") - return - } - - // Pour les sorts, rouler les dés de dégâts avec option bypass DR - if (damageType === "spell" && damageFormula) { - const bypassArmor = await foundry.applications.api.DialogV2.confirm({ - window: { title: "Spell Damage" }, - classes: ["lethalfantasy"], - content: "Does this spell's damage bypass armor DR?
", - yes: { label: "Yes (ignore armor)", icon: "fa-solid fa-wand-magic-sparkles" }, - no: { label: "No (apply armor DR)", icon: "fa-solid fa-shield" } - }) - const rollOpts = { - type: "spell-damage", - rollType: "spell-damage", - rollName: damageFormula, - isDamage: true, - rollData: { isDamage: true }, - bypassArmor: bypassArmor ?? false, - defenderId, - defenderTokenId, - actorId: actor.id, - actorName: actor.name, - actorImage: actor.img - } - const roll = new LethalFantasyRoll(damageFormula, {}, rollOpts) - await roll.evaluate() - roll.options.rollTotal = roll.total - if (game?.dice3d) await game.dice3d.showForRoll(roll, game.user, true) - await roll.toMessage() - return - } - - // Pour les boutons de résultat de combat (monster damage) - if (damageType === "monster" && attackKey) { - await actor.system.prepareMonsterRoll("monster-damage", attackKey, undefined, undefined, undefined, defenderId, defenderTokenId, extraShieldDr) - 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, undefined, defenderId, defenderTokenId, extraShieldDr) - }) + } // Masquer les boutons de dommages dans les messages de résultat de combat si l'utilisateur n'est pas l'attaquant - $(html).find(".roll-damage-btn").each(function() { - const button = $(this) - const attackerId = button.data("attacker-id") - + for (const btn of html.querySelectorAll(".roll-damage-btn")) { + const attackerId = btn.dataset.attackerId if (attackerId) { const attacker = game.actors.get(attackerId) // Masquer le bouton si l'utilisateur n'est pas GM et ne possède pas l'attaquant if (!game.user.isGM && !attacker?.testUserPermission(game.user, "OWNER")) { - button.hide() + btn.style.display = "none" } } - }) + } }) -Hooks.on("getCombatTrackerEntryContext", (html, options) => { - LethalFantasyUtils.pushCombatOptions(html, options); -}); - // Hook pour ajouter les données d'attaque au message de défense Hooks.on("preCreateChatMessage", (message) => { const rollType = message.rolls[0]?.options?.rollType diff --git a/module/applications/combat.mjs b/module/applications/combat.mjs index cb7ec5e..2cf681c 100644 --- a/module/applications/combat.mjs +++ b/module/applications/combat.mjs @@ -18,6 +18,7 @@ export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tab actions: { initiativePlus: LethalFantasyCombatTracker.#initiativePlus, initiativeMinus: LethalFantasyCombatTracker.#initiativeMinus, + rollMonsterProgression: LethalFantasyCombatTracker.#rollMonsterProgression, }, }); @@ -49,6 +50,15 @@ export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tab c.update({ 'initiative': newInit }); } + /** + * Roll progression dice for all monster combatants that are eligible this round. + * @param {Event} ev Click event. + */ + static async #rollMonsterProgression(ev) { + ev.preventDefault(); + await game.combat.rollMonsterProgression(); + } + activateListeners(html) { super.activateListeners(html); // Display Combat settings @@ -130,6 +140,17 @@ export class LethalFantasyCombat extends Combat { return this; } + /** Roll progression dice for all eligible monster combatants this round. Called manually by the GM. */ + async rollMonsterProgression() { + const currentRound = this.round; + for (let c of this.combatants) { + if (c.actor.type !== "monster") continue; + if (c.initiative !== null && currentRound >= c.initiative) { + await c.actor.system.rollProgressionDice(this.id, c.id); + } + } + } + resetProgression(cId) { let c = this.combatants.get(cId); c.update({ 'system.progressionCount': 0 }); @@ -203,6 +224,7 @@ export class LethalFantasyCombat extends Combat { for (let c of this.combatants) { if (nextRound >= c.initiative) { + if (c.actor.type === "monster") continue; // Monsters roll manually via the "Roll Monsters" button const playerOwner = game.users.find(u => u.active && !u.isGM && u.character?.id === c.actor.id); if (game.user.isGM && playerOwner) { game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", userId: playerOwner.id, progressionCount: c.system.progressionCount + 1, actorId: c.actor.id, combatId: this.id, combatantId: c.id }); diff --git a/module/applications/free-roll.mjs b/module/applications/free-roll.mjs index de667a6..85466a9 100644 --- a/module/applications/free-roll.mjs +++ b/module/applications/free-roll.mjs @@ -147,6 +147,6 @@ export async function rollFreeDie(dieType, count = 1, explode = false) { content, sound: CONFIG.sounds.dice, } - ChatMessage.applyRollMode(msgData, rollMode) + ChatMessage.applyMode(msgData, rollMode) await ChatMessage.create(msgData) } diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index 470bfd4..d800d06 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -172,7 +172,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet }) if (!roll) return null - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } static async #onRollInitiative(event, target) { diff --git a/module/applications/sheets/monster-sheet.mjs b/module/applications/sheets/monster-sheet.mjs index deb1d32..67a3649 100644 --- a/module/applications/sheets/monster-sheet.mjs +++ b/module/applications/sheets/monster-sheet.mjs @@ -111,7 +111,7 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet { }) if (!roll) return null - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } static async #onRollInitiative(event, target) { diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index 36f38cf..85e5f0c 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -320,7 +320,7 @@ export default class LethalFantasyRoll extends Roll { hasModifier = false } - const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)])) + const rollModes = foundry.utils.duplicate(CONFIG.ChatMessage.modes); console.log("Roll mode", rollModes) const fieldRollMode = new foundry.data.fields.StringField({ @@ -676,7 +676,7 @@ export default class LethalFantasyRoll extends Roll { /* ***********************************************************/ static async promptInitiative(options = {}) { - const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)])) + const rollModes = foundry.utils.duplicate(CONFIG.ChatMessage.modes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)])) const fieldRollMode = new foundry.data.fields.StringField({ choices: rollModes, blank: false, @@ -730,7 +730,7 @@ export default class LethalFantasyRoll extends Roll { let initRoll = new Roll(formula, options.data) await initRoll.evaluate() - let msg = await initRoll.toMessage({ flavor: `Initiative for ${options.actorName}` }, { rollMode: rollContext.visibility }) + let msg = await initRoll.toMessage({ flavor: `Initiative for ${options.actorName}` }, { messageMode: rollContext.visibility }) if (game?.dice3d && initRoll.dice?.length) { await game.dice3d.waitFor3DAnimationByMessageID(msg.id) } @@ -744,7 +744,7 @@ export default class LethalFantasyRoll extends Roll { /* ***********************************************************/ static async promptCombatAction(options = {}) { - const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)])) + const rollModes = foundry.utils.duplicate(CONFIG.ChatMessage.modes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)])) const fieldRollMode = new foundry.data.fields.StringField({ choices: rollModes, blank: false, @@ -1001,7 +1001,7 @@ export default class LethalFantasyRoll extends Roll { let max = roll.dice[0].faces - 1 max = Math.min(currentAction.progressionCount, max) - let msg = await roll.toMessage({ flavor: `Progression Roll for ${currentAction.name}, progression count : ${currentAction.progressionCount}/${max}` }, { rollMode: rollContext.visibility }) + let msg = await roll.toMessage({ flavor: `Progression Roll for ${currentAction.name}, progression count : ${currentAction.progressionCount}/${max}` }, { messageMode: rollContext.visibility }) if (game?.dice3d) { await game.dice3d.waitFor3DAnimationByMessageID(msg.id) } @@ -1043,7 +1043,7 @@ export default class LethalFantasyRoll extends Roll { /* ***********************************************************/ static async promptRangedDefense(options = {}) { - const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); + const rollModes = foundry.utils.duplicate(CONFIG.ChatMessage.modes); const fieldRollMode = new foundry.data.fields.StringField({ choices: rollModes, blank: false, @@ -1332,11 +1332,11 @@ export default class LethalFantasyRoll extends Roll { * * @param {Object} [messageData={}] Additional data to include in the message. * @param {Object} options Options for message creation. - * @param {string} options.rollMode The mode of the roll (e.g., public, private). + * @param {string} options.messageMode The mode of the roll (e.g., public, private). * @param {boolean} [options.create=true] Whether to create the message. * @returns {Promise} - A promise that resolves when the message is created. */ - async toMessage(messageData = {}, { rollMode, create = true } = {}) { + async toMessage(messageData = {}, { messageMode, create = true } = {}) { return await super.toMessage( { isSave: this.isSave, @@ -1354,7 +1354,7 @@ export default class LethalFantasyRoll extends Roll { rollData: this.rollData, ...messageData, }, - { rollMode, create }, + { messageMode, create }, ) } diff --git a/module/models/character.mjs b/module/models/character.mjs index d114d53..cb83f2d 100644 --- a/module/models/character.mjs +++ b/module/models/character.mjs @@ -297,7 +297,7 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod }) if (!roll) return null - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } async rollInitiative(combatId = undefined, combatantId = undefined) { @@ -318,7 +318,7 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod }) if (!roll) return null - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } async rollProgressionDice(combatId, combatantId, rollProgressionCount) { diff --git a/module/models/monster.mjs b/module/models/monster.mjs index c963606..738e580 100644 --- a/module/models/monster.mjs +++ b/module/models/monster.mjs @@ -180,7 +180,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel }) if (!roll) return null - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined, damageModifier = undefined, defenderId = undefined, defenderTokenId = undefined, extraShieldDr = 0) { @@ -305,7 +305,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel }) if (!roll) return null - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } async rollProgressionDice(combatId, combatantId) { @@ -317,7 +317,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel return } - const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes) + const rollModes = foundry.utils.duplicate(CONFIG.ChatMessage.modes) const fieldRollMode = new foundry.data.fields.StringField({ choices: rollModes, blank: false, diff --git a/module/utils.mjs b/module/utils.mjs index 8a2a204..ba5c65e 100644 --- a/module/utils.mjs +++ b/module/utils.mjs @@ -401,7 +401,7 @@ export default class LethalFantasyUtils { defenderTokenId, isRanged: true } - await roll.toMessage({}, { rollMode: roll.options.rollMode }) + await roll.toMessage({}, { messageMode: roll.options.rollMode }) } return } @@ -1092,25 +1092,32 @@ 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) { + if (!combatantId) { ui.notifications.error("No combatant selected") return } - let combatant = game.combat.combatants.get(combatantId) - if (!combatant) { - ui.notifications.error("Combatant not found") - return + // Try to find the target: first as a combat combatant, then as a scene token + let targetActor = null + if (game.combat) { + const combatant = game.combat.combatants.get(combatantId) + if (combatant) { + targetActor = combatant.token?.actor || game.actors.get(combatant.actorId) + } + } + if (!targetActor) { + // Fall back to scene token lookup (non-combat tokens use tokenId as their combatantId) + const token = canvas.tokens?.placeables?.find(t => t.id === combatantId) + targetActor = token?.actor } - - 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 + // Use options.rollTotal (includes weapon modifier bonus) rather than roll.total (dice formula only) + let damageTotal = message.rolls[0]?.options?.rollTotal ?? message.rolls[0]?.total ?? 0 let weaponName = message.rolls[0]?.options?.rollName || "Unknown Weapon" // Calculer les DR diff --git a/packs-system/lf-equipment/000589.log b/packs-system/lf-equipment/000593.log similarity index 100% rename from packs-system/lf-equipment/000589.log rename to packs-system/lf-equipment/000593.log diff --git a/packs-system/lf-equipment/CURRENT b/packs-system/lf-equipment/CURRENT index 474021a..df90b48 100644 --- a/packs-system/lf-equipment/CURRENT +++ b/packs-system/lf-equipment/CURRENT @@ -1 +1 @@ -MANIFEST-000587 +MANIFEST-000591 diff --git a/packs-system/lf-equipment/LOG b/packs-system/lf-equipment/LOG index f33db91..f9593fc 100644 --- a/packs-system/lf-equipment/LOG +++ b/packs-system/lf-equipment/LOG @@ -1,8 +1,8 @@ -2026/05/02-08:40:55.892385 7fd7557ee6c0 Recovering log #585 -2026/05/02-08:40:55.903385 7fd7557ee6c0 Delete type=3 #583 -2026/05/02-08:40:55.903442 7fd7557ee6c0 Delete type=0 #585 -2026/05/02-08:41:12.057856 7fd7477fe6c0 Level-0 table #590: started -2026/05/02-08:41:12.057882 7fd7477fe6c0 Level-0 table #590: 0 bytes OK -2026/05/02-08:41:12.121845 7fd7477fe6c0 Delete type=0 #588 -2026/05/02-08:41:12.122077 7fd7477fe6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) -2026/05/02-08:41:12.122121 7fd7477fe6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) +2026/05/17-11:57:50.231387 7f16423fc6c0 Recovering log #589 +2026/05/17-11:57:50.249229 7f16423fc6c0 Delete type=3 #587 +2026/05/17-11:57:50.249281 7f16423fc6c0 Delete type=0 #589 +2026/05/17-13:21:53.429711 7f1641bfb6c0 Level-0 table #594: started +2026/05/17-13:21:53.429759 7f1641bfb6c0 Level-0 table #594: 0 bytes OK +2026/05/17-13:21:53.437714 7f1641bfb6c0 Delete type=0 #592 +2026/05/17-13:21:53.449134 7f1641bfb6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) +2026/05/17-13:21:53.461721 7f1641bfb6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-equipment/LOG.old b/packs-system/lf-equipment/LOG.old index ae05e54..f33db91 100644 --- a/packs-system/lf-equipment/LOG.old +++ b/packs-system/lf-equipment/LOG.old @@ -1,8 +1,8 @@ -2026/05/01-23:33:08.433602 7f8fb27bf6c0 Recovering log #581 -2026/05/01-23:33:08.476792 7f8fb27bf6c0 Delete type=3 #579 -2026/05/01-23:33:08.476868 7f8fb27bf6c0 Delete type=0 #581 -2026/05/01-23:33:55.878970 7f8d1bfff6c0 Level-0 table #586: started -2026/05/01-23:33:55.881418 7f8d1bfff6c0 Level-0 table #586: 0 bytes OK -2026/05/01-23:33:55.924908 7f8d1bfff6c0 Delete type=0 #584 -2026/05/01-23:33:56.035970 7f8d1bfff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) -2026/05/01-23:33:56.036022 7f8d1bfff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) +2026/05/02-08:40:55.892385 7fd7557ee6c0 Recovering log #585 +2026/05/02-08:40:55.903385 7fd7557ee6c0 Delete type=3 #583 +2026/05/02-08:40:55.903442 7fd7557ee6c0 Delete type=0 #585 +2026/05/02-08:41:12.057856 7fd7477fe6c0 Level-0 table #590: started +2026/05/02-08:41:12.057882 7fd7477fe6c0 Level-0 table #590: 0 bytes OK +2026/05/02-08:41:12.121845 7fd7477fe6c0 Delete type=0 #588 +2026/05/02-08:41:12.122077 7fd7477fe6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) +2026/05/02-08:41:12.122121 7fd7477fe6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-equipment/MANIFEST-000587 b/packs-system/lf-equipment/MANIFEST-000591 similarity index 71% rename from packs-system/lf-equipment/MANIFEST-000587 rename to packs-system/lf-equipment/MANIFEST-000591 index eb9ea43..52effdb 100644 Binary files a/packs-system/lf-equipment/MANIFEST-000587 and b/packs-system/lf-equipment/MANIFEST-000591 differ diff --git a/packs-system/lf-gifts/000586.log b/packs-system/lf-gifts/000590.log similarity index 100% rename from packs-system/lf-gifts/000586.log rename to packs-system/lf-gifts/000590.log diff --git a/packs-system/lf-gifts/CURRENT b/packs-system/lf-gifts/CURRENT index f6d7c1b..1610e6f 100644 --- a/packs-system/lf-gifts/CURRENT +++ b/packs-system/lf-gifts/CURRENT @@ -1 +1 @@ -MANIFEST-000584 +MANIFEST-000588 diff --git a/packs-system/lf-gifts/LOG b/packs-system/lf-gifts/LOG index b81ef55..aa26a98 100644 --- a/packs-system/lf-gifts/LOG +++ b/packs-system/lf-gifts/LOG @@ -1,8 +1,8 @@ -2026/05/02-08:40:55.909564 7fd747fff6c0 Recovering log #582 -2026/05/02-08:40:55.919159 7fd747fff6c0 Delete type=3 #580 -2026/05/02-08:40:55.919214 7fd747fff6c0 Delete type=0 #582 -2026/05/02-08:41:11.999050 7fd7477fe6c0 Level-0 table #587: started -2026/05/02-08:41:11.999076 7fd7477fe6c0 Level-0 table #587: 0 bytes OK -2026/05/02-08:41:12.057672 7fd7477fe6c0 Delete type=0 #585 -2026/05/02-08:41:12.122063 7fd7477fe6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) -2026/05/02-08:41:12.122111 7fd7477fe6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) +2026/05/17-11:57:50.260046 7f16433fe6c0 Recovering log #586 +2026/05/17-11:57:50.276348 7f16433fe6c0 Delete type=3 #584 +2026/05/17-11:57:50.276460 7f16433fe6c0 Delete type=0 #586 +2026/05/17-13:21:53.474443 7f1641bfb6c0 Level-0 table #591: started +2026/05/17-13:21:53.474485 7f1641bfb6c0 Level-0 table #591: 0 bytes OK +2026/05/17-13:21:53.481502 7f1641bfb6c0 Delete type=0 #589 +2026/05/17-13:21:53.490389 7f1641bfb6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) +2026/05/17-13:21:53.512946 7f1641bfb6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-gifts/LOG.old b/packs-system/lf-gifts/LOG.old index f2cd8eb..b81ef55 100644 --- a/packs-system/lf-gifts/LOG.old +++ b/packs-system/lf-gifts/LOG.old @@ -1,8 +1,8 @@ -2026/05/01-23:33:08.486839 7f8fb17bd6c0 Recovering log #578 -2026/05/01-23:33:08.536613 7f8fb17bd6c0 Delete type=3 #576 -2026/05/01-23:33:08.536667 7f8fb17bd6c0 Delete type=0 #578 -2026/05/01-23:33:55.999594 7f8d1bfff6c0 Level-0 table #583: started -2026/05/01-23:33:55.999624 7f8d1bfff6c0 Level-0 table #583: 0 bytes OK -2026/05/01-23:33:56.035856 7f8d1bfff6c0 Delete type=0 #581 -2026/05/01-23:33:56.036000 7f8d1bfff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) -2026/05/01-23:33:56.036042 7f8d1bfff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) +2026/05/02-08:40:55.909564 7fd747fff6c0 Recovering log #582 +2026/05/02-08:40:55.919159 7fd747fff6c0 Delete type=3 #580 +2026/05/02-08:40:55.919214 7fd747fff6c0 Delete type=0 #582 +2026/05/02-08:41:11.999050 7fd7477fe6c0 Level-0 table #587: started +2026/05/02-08:41:11.999076 7fd7477fe6c0 Level-0 table #587: 0 bytes OK +2026/05/02-08:41:12.057672 7fd7477fe6c0 Delete type=0 #585 +2026/05/02-08:41:12.122063 7fd7477fe6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) +2026/05/02-08:41:12.122111 7fd7477fe6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-gifts/MANIFEST-000584 b/packs-system/lf-gifts/MANIFEST-000588 similarity index 77% rename from packs-system/lf-gifts/MANIFEST-000584 rename to packs-system/lf-gifts/MANIFEST-000588 index afbe028..e51b96e 100644 Binary files a/packs-system/lf-gifts/MANIFEST-000584 and b/packs-system/lf-gifts/MANIFEST-000588 differ diff --git a/packs-system/lf-skills/000591.log b/packs-system/lf-skills/000595.log similarity index 100% rename from packs-system/lf-skills/000591.log rename to packs-system/lf-skills/000595.log diff --git a/packs-system/lf-skills/CURRENT b/packs-system/lf-skills/CURRENT index 9c7b9ea..c4c83ef 100644 --- a/packs-system/lf-skills/CURRENT +++ b/packs-system/lf-skills/CURRENT @@ -1 +1 @@ -MANIFEST-000589 +MANIFEST-000593 diff --git a/packs-system/lf-skills/LOG b/packs-system/lf-skills/LOG index 75bc490..b950e04 100644 --- a/packs-system/lf-skills/LOG +++ b/packs-system/lf-skills/LOG @@ -1,8 +1,8 @@ -2026/05/02-08:40:55.873571 7fd747fff6c0 Recovering log #587 -2026/05/02-08:40:55.883892 7fd747fff6c0 Delete type=3 #585 -2026/05/02-08:40:55.883950 7fd747fff6c0 Delete type=0 #587 -2026/05/02-08:41:11.870087 7fd7477fe6c0 Level-0 table #592: started -2026/05/02-08:41:11.870140 7fd7477fe6c0 Level-0 table #592: 0 bytes OK -2026/05/02-08:41:11.937524 7fd7477fe6c0 Delete type=0 #590 -2026/05/02-08:41:12.122025 7fd7477fe6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) -2026/05/02-08:41:12.122087 7fd7477fe6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) +2026/05/17-11:57:50.206131 7f1643bff6c0 Recovering log #591 +2026/05/17-11:57:50.222037 7f1643bff6c0 Delete type=3 #589 +2026/05/17-11:57:50.222089 7f1643bff6c0 Delete type=0 #591 +2026/05/17-13:21:53.292176 7f1641bfb6c0 Level-0 table #596: started +2026/05/17-13:21:53.292219 7f1641bfb6c0 Level-0 table #596: 0 bytes OK +2026/05/17-13:21:53.299322 7f1641bfb6c0 Delete type=0 #594 +2026/05/17-13:21:53.306548 7f1641bfb6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) +2026/05/17-13:21:53.318889 7f1641bfb6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-skills/LOG.old b/packs-system/lf-skills/LOG.old index 14f8907..75bc490 100644 --- a/packs-system/lf-skills/LOG.old +++ b/packs-system/lf-skills/LOG.old @@ -1,8 +1,8 @@ -2026/05/01-23:33:08.376215 7f8fb0fbc6c0 Recovering log #583 -2026/05/01-23:33:08.417318 7f8fb0fbc6c0 Delete type=3 #581 -2026/05/01-23:33:08.417396 7f8fb0fbc6c0 Delete type=0 #583 -2026/05/01-23:33:55.962045 7f8d1bfff6c0 Level-0 table #588: started -2026/05/01-23:33:55.962068 7f8d1bfff6c0 Level-0 table #588: 0 bytes OK -2026/05/01-23:33:55.999439 7f8d1bfff6c0 Delete type=0 #586 -2026/05/01-23:33:56.035992 7f8d1bfff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) -2026/05/01-23:33:56.036035 7f8d1bfff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) +2026/05/02-08:40:55.873571 7fd747fff6c0 Recovering log #587 +2026/05/02-08:40:55.883892 7fd747fff6c0 Delete type=3 #585 +2026/05/02-08:40:55.883950 7fd747fff6c0 Delete type=0 #587 +2026/05/02-08:41:11.870087 7fd7477fe6c0 Level-0 table #592: started +2026/05/02-08:41:11.870140 7fd7477fe6c0 Level-0 table #592: 0 bytes OK +2026/05/02-08:41:11.937524 7fd7477fe6c0 Delete type=0 #590 +2026/05/02-08:41:12.122025 7fd7477fe6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) +2026/05/02-08:41:12.122087 7fd7477fe6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-skills/MANIFEST-000589 b/packs-system/lf-skills/MANIFEST-000593 similarity index 71% rename from packs-system/lf-skills/MANIFEST-000589 rename to packs-system/lf-skills/MANIFEST-000593 index f1ee75d..564f69e 100644 Binary files a/packs-system/lf-skills/MANIFEST-000589 and b/packs-system/lf-skills/MANIFEST-000593 differ diff --git a/packs-system/lf-spells-miracles/000286.log b/packs-system/lf-spells-miracles/000290.log similarity index 100% rename from packs-system/lf-spells-miracles/000286.log rename to packs-system/lf-spells-miracles/000290.log diff --git a/packs-system/lf-spells-miracles/CURRENT b/packs-system/lf-spells-miracles/CURRENT index 0041f5d..2c3afb9 100644 --- a/packs-system/lf-spells-miracles/CURRENT +++ b/packs-system/lf-spells-miracles/CURRENT @@ -1 +1 @@ -MANIFEST-000284 +MANIFEST-000288 diff --git a/packs-system/lf-spells-miracles/LOG b/packs-system/lf-spells-miracles/LOG index 778dcda..458f5c6 100644 --- a/packs-system/lf-spells-miracles/LOG +++ b/packs-system/lf-spells-miracles/LOG @@ -1,8 +1,8 @@ -2026/05/02-08:40:55.939668 7fd754fed6c0 Recovering log #282 -2026/05/02-08:40:55.949715 7fd754fed6c0 Delete type=3 #280 -2026/05/02-08:40:55.949784 7fd754fed6c0 Delete type=0 #282 -2026/05/02-08:41:12.184448 7fd7477fe6c0 Level-0 table #287: started -2026/05/02-08:41:12.184496 7fd7477fe6c0 Level-0 table #287: 0 bytes OK -2026/05/02-08:41:12.252892 7fd7477fe6c0 Delete type=0 #285 -2026/05/02-08:41:12.365481 7fd7477fe6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) -2026/05/02-08:41:12.365509 7fd7477fe6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) +2026/05/17-11:57:50.303535 7f16433fe6c0 Recovering log #286 +2026/05/17-11:57:50.318955 7f16433fe6c0 Delete type=3 #284 +2026/05/17-11:57:50.319061 7f16433fe6c0 Delete type=0 #286 +2026/05/17-13:21:53.481662 7f1641bfb6c0 Level-0 table #291: started +2026/05/17-13:21:53.481693 7f1641bfb6c0 Level-0 table #291: 0 bytes OK +2026/05/17-13:21:53.490187 7f1641bfb6c0 Delete type=0 #289 +2026/05/17-13:21:53.502325 7f1641bfb6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) +2026/05/17-13:21:53.512979 7f1641bfb6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-spells-miracles/LOG.old b/packs-system/lf-spells-miracles/LOG.old index fb78b9d..778dcda 100644 --- a/packs-system/lf-spells-miracles/LOG.old +++ b/packs-system/lf-spells-miracles/LOG.old @@ -1,8 +1,8 @@ -2026/05/01-23:33:08.590994 7f8fb1fbe6c0 Recovering log #278 -2026/05/01-23:33:08.636941 7f8fb1fbe6c0 Delete type=3 #276 -2026/05/01-23:33:08.636992 7f8fb1fbe6c0 Delete type=0 #278 -2026/05/01-23:33:56.204694 7f8d1bfff6c0 Level-0 table #283: started -2026/05/01-23:33:56.204728 7f8d1bfff6c0 Level-0 table #283: 0 bytes OK -2026/05/01-23:33:56.238272 7f8d1bfff6c0 Delete type=0 #281 -2026/05/01-23:33:56.371888 7f8d1bfff6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) -2026/05/01-23:33:56.426259 7f8d1bfff6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) +2026/05/02-08:40:55.939668 7fd754fed6c0 Recovering log #282 +2026/05/02-08:40:55.949715 7fd754fed6c0 Delete type=3 #280 +2026/05/02-08:40:55.949784 7fd754fed6c0 Delete type=0 #282 +2026/05/02-08:41:12.184448 7fd7477fe6c0 Level-0 table #287: started +2026/05/02-08:41:12.184496 7fd7477fe6c0 Level-0 table #287: 0 bytes OK +2026/05/02-08:41:12.252892 7fd7477fe6c0 Delete type=0 #285 +2026/05/02-08:41:12.365481 7fd7477fe6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) +2026/05/02-08:41:12.365509 7fd7477fe6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-spells-miracles/MANIFEST-000284 b/packs-system/lf-spells-miracles/MANIFEST-000288 similarity index 72% rename from packs-system/lf-spells-miracles/MANIFEST-000284 rename to packs-system/lf-spells-miracles/MANIFEST-000288 index a733f45..550f20b 100644 Binary files a/packs-system/lf-spells-miracles/MANIFEST-000284 and b/packs-system/lf-spells-miracles/MANIFEST-000288 differ diff --git a/packs-system/lf-vulnerabilities/000585.log b/packs-system/lf-vulnerabilities/000589.log similarity index 100% rename from packs-system/lf-vulnerabilities/000585.log rename to packs-system/lf-vulnerabilities/000589.log diff --git a/packs-system/lf-vulnerabilities/CURRENT b/packs-system/lf-vulnerabilities/CURRENT index e29f5f5..474021a 100644 --- a/packs-system/lf-vulnerabilities/CURRENT +++ b/packs-system/lf-vulnerabilities/CURRENT @@ -1 +1 @@ -MANIFEST-000583 +MANIFEST-000587 diff --git a/packs-system/lf-vulnerabilities/LOG b/packs-system/lf-vulnerabilities/LOG index 2bf5a0a..23422a2 100644 --- a/packs-system/lf-vulnerabilities/LOG +++ b/packs-system/lf-vulnerabilities/LOG @@ -1,8 +1,8 @@ -2026/05/02-08:40:55.925402 7fd755fef6c0 Recovering log #581 -2026/05/02-08:40:55.935869 7fd755fef6c0 Delete type=3 #579 -2026/05/02-08:40:55.935924 7fd755fef6c0 Delete type=0 #581 -2026/05/02-08:41:11.937698 7fd7477fe6c0 Level-0 table #586: started -2026/05/02-08:41:11.937727 7fd7477fe6c0 Level-0 table #586: 0 bytes OK -2026/05/02-08:41:11.998871 7fd7477fe6c0 Delete type=0 #584 -2026/05/02-08:41:12.122041 7fd7477fe6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) -2026/05/02-08:41:12.122099 7fd7477fe6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) +2026/05/17-11:57:50.282340 7f16423fc6c0 Recovering log #585 +2026/05/17-11:57:50.297125 7f16423fc6c0 Delete type=3 #583 +2026/05/17-11:57:50.297189 7f16423fc6c0 Delete type=0 #585 +2026/05/17-13:21:53.299508 7f1641bfb6c0 Level-0 table #590: started +2026/05/17-13:21:53.299854 7f1641bfb6c0 Level-0 table #590: 0 bytes OK +2026/05/17-13:21:53.306309 7f1641bfb6c0 Delete type=0 #588 +2026/05/17-13:21:53.318877 7f1641bfb6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) +2026/05/17-13:21:53.325564 7f1641bfb6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-vulnerabilities/LOG.old b/packs-system/lf-vulnerabilities/LOG.old index 259d03e..2bf5a0a 100644 --- a/packs-system/lf-vulnerabilities/LOG.old +++ b/packs-system/lf-vulnerabilities/LOG.old @@ -1,8 +1,8 @@ -2026/05/01-23:33:08.543693 7f8fb0fbc6c0 Recovering log #577 -2026/05/01-23:33:08.586596 7f8fb0fbc6c0 Delete type=3 #575 -2026/05/01-23:33:08.586670 7f8fb0fbc6c0 Delete type=0 #577 -2026/05/01-23:33:55.925044 7f8d1bfff6c0 Level-0 table #582: started -2026/05/01-23:33:55.925074 7f8d1bfff6c0 Level-0 table #582: 0 bytes OK -2026/05/01-23:33:55.961939 7f8d1bfff6c0 Delete type=0 #580 -2026/05/01-23:33:56.035982 7f8d1bfff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) -2026/05/01-23:33:56.036029 7f8d1bfff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) +2026/05/02-08:40:55.925402 7fd755fef6c0 Recovering log #581 +2026/05/02-08:40:55.935869 7fd755fef6c0 Delete type=3 #579 +2026/05/02-08:40:55.935924 7fd755fef6c0 Delete type=0 #581 +2026/05/02-08:41:11.937698 7fd7477fe6c0 Level-0 table #586: started +2026/05/02-08:41:11.937727 7fd7477fe6c0 Level-0 table #586: 0 bytes OK +2026/05/02-08:41:11.998871 7fd7477fe6c0 Delete type=0 #584 +2026/05/02-08:41:12.122041 7fd7477fe6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) +2026/05/02-08:41:12.122099 7fd7477fe6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end) diff --git a/packs-system/lf-vulnerabilities/MANIFEST-000583 b/packs-system/lf-vulnerabilities/MANIFEST-000587 similarity index 72% rename from packs-system/lf-vulnerabilities/MANIFEST-000583 rename to packs-system/lf-vulnerabilities/MANIFEST-000587 index 960fbf8..36368e1 100644 Binary files a/packs-system/lf-vulnerabilities/MANIFEST-000583 and b/packs-system/lf-vulnerabilities/MANIFEST-000587 differ diff --git a/templates/combat-tracker-footer-v2.hbs b/templates/combat-tracker-footer-v2.hbs index 6eb221e..49fc727 100644 --- a/templates/combat-tracker-footer-v2.hbs +++ b/templates/combat-tracker-footer-v2.hbs @@ -13,6 +13,14 @@ {{ localize "COMBAT.End" }} + {{#if combat.round}} + + {{/if}} +