New combat management and various improvments
All checks were successful
Release Creation / build (release) Successful in 48s

This commit is contained in:
2026-01-19 23:22:32 +01:00
parent a06dfa0ae9
commit 52877e3a68
46 changed files with 4655 additions and 475 deletions

View File

@@ -1,5 +1,6 @@
import { SYSTEM } from "../config/system.mjs"
import LethalFantasyUtils from "../utils.mjs"
import D30Roll from "./d30-roll.mjs"
export default class LethalFantasyRoll extends Roll {
/**
@@ -92,6 +93,10 @@ export default class LethalFantasyRoll extends Roll {
return this.options.D30result
}
get D30message() {
return this.options.D30message
}
get badResult() {
return this.options.badResult
}
@@ -100,6 +105,10 @@ export default class LethalFantasyRoll extends Roll {
return this.options.rollData
}
get defenderId() {
return this.options.defenderId
}
/**
* Prompt the user with a dialog to configure and execute a roll.
*
@@ -544,6 +553,14 @@ export default class LethalFantasyRoll extends Roll {
game.dice3d.showForRoll(rollD30, game.user, true)
}
options.D30result = rollD30.total
// Récupérer le message D30 correspondant
const d30Message = D30Roll.getResult(
rollD30.total,
options.rollType,
options.rollTarget?.weapon
)
options.D30message = d30Message
}
let rollTotal = 0
@@ -599,8 +616,10 @@ export default class LethalFantasyRoll extends Roll {
rollBase.options.rollTarget = options.rollTarget
rollBase.options.titleFormula = titleFormula
rollBase.options.D30result = options.D30result
rollBase.options.D30message = options.D30message
rollBase.options.badResult = badResult
rollBase.options.rollData = foundry.utils.duplicate(rollData)
rollBase.options.defenderId = options.defenderId
/**
* A hook event that fires after the roll has been made.
@@ -862,8 +881,17 @@ export default class LethalFantasyRoll extends Roll {
let toCompare = Math.min(currentAction.progressionCount, max)
if (roll.total <= toCompare) {
// Notify that the player can act now with a chat message
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyOK", { name: combatant.actor.name, spellName: currentAction.name, roll: roll.total })
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
const messageContent = await foundry.applications.handlebars.renderTemplate(
"systems/fvtt-lethal-fantasy/templates/progression-message.hbs",
{
success: true,
actorName: combatant.actor.name,
weaponName: currentAction.name,
rollResult: roll.total,
isLethargy: true
}
)
ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
// Update the combatant progression count
await combatant.setFlag(SYSTEM.id, "currentAction", "")
// Display the action selection window again
@@ -872,8 +900,18 @@ export default class LethalFantasyRoll extends Roll {
// Notify that the player cannot act now with a chat message
currentAction.progressionCount += 1
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyKO", { name: combatant.actor.name, spellName: currentAction.name, roll: roll.total })
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
const messageContent = await foundry.applications.handlebars.renderTemplate(
"systems/fvtt-lethal-fantasy/templates/progression-message.hbs",
{
success: false,
actorName: combatant.actor.name,
weaponName: currentAction.name,
rollResult: roll.total,
progressionCount: currentAction.progressionCount,
isLethargy: true
}
)
ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
}
}
}
@@ -919,16 +957,33 @@ export default class LethalFantasyRoll extends Roll {
if (roll.total <= max) {
// Notify that the player can act now with a chat message
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionOK", { isMonster, name: combatant.actor.name, weapon: currentAction.name, roll: roll.total })
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
const messageContent = await foundry.applications.handlebars.renderTemplate(
"systems/fvtt-lethal-fantasy/templates/progression-message.hbs",
{
success: true,
actorName: combatant.actor.name,
weaponName: currentAction.name,
rollResult: roll.total
}
)
ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
await combatant.setFlag(SYSTEM.id, "currentAction", "")
combatant.actor.prepareRoll(currentAction.type === "weapon" ? "weapon-attack" : "spell-attack", currentAction._id)
} else {
// Notify that the player cannot act now with a chat message
currentAction.progressionCount += 1
combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionKO", { isMonster, name: combatant.actor.name, weapon: currentAction.name, roll: roll.total })
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
const messageContent = await foundry.applications.handlebars.renderTemplate(
"systems/fvtt-lethal-fantasy/templates/progression-message.hbs",
{
success: false,
actorName: combatant.actor.name,
weaponName: currentAction.name,
rollResult: roll.total,
progressionCount: currentAction.progressionCount
}
)
ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
}
}
}
@@ -1132,10 +1187,28 @@ export default class LethalFantasyRoll extends Roll {
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 })
let isAttack = this.type === "weapon-attack" || this.type === "monster-attack" || this.type === "spell-attack" || this.type === "miracle-attack"
if (this.rollData?.isDamage || isAttack) {
// D'abord, ajouter les combattants du combat actif
if (game?.combat?.combatants) {
for (let c of game.combat.combatants) {
if (c.actorId !== this.actorId) {
combatants.push({ id: c.id, name: c.name, tokenId: c.token.id })
}
}
}
// Ensuite, ajouter tous les tokens de la scène active qui ne sont pas déjà dans la liste
if (canvas?.scene?.tokens) {
const existingTokenIds = new Set(combatants.map(c => c.tokenId))
for (let token of canvas.scene.tokens) {
if (token.actorId !== this.actorId && !existingTokenIds.has(token.id)) {
combatants.push({
id: token.id,
name: token.name,
tokenId: token.id
})
}
}
}
}
@@ -1184,11 +1257,16 @@ export default class LethalFantasyRoll extends Roll {
targetName: this.targetName,
targetArmor: this.targetArmor,
D30result: this.D30result,
D30message: this.D30message,
badResult: this.badResult,
rollData: this.rollData,
isPrivate: isPrivate,
combatants: combatants,
weaponDamageOptions: weaponDamageOptions
weaponDamageOptions: weaponDamageOptions,
isAttack: isAttack,
defenderId: this.defenderId,
// Vérifier si l'utilisateur peut sélectionner une cible (est GM ou possède l'acteur)
canSelectTarget: game.user.isGM || game.actors.get(this.actorId)?.testUserPermission(game.user, "OWNER")
}
cardData.cssClass = cardData.css.join(" ")
cardData.tooltip = isPrivate ? "" : await this.getTooltip()