Files
fvtt-lethal-fantasy/module/documents/d30-roll.mjs
LeRatierBretonnien 52877e3a68
All checks were successful
Release Creation / build (release) Successful in 48s
New combat management and various improvments
2026-01-19 23:22:32 +01:00

216 lines
6.6 KiB
JavaScript

/**
* Classe pour gérer les résultats du D30 dans Lethal Fantasy
*/
export default class D30Roll {
/**
* Table des résultats D30 chargée depuis le fichier JSON
* @type {Object}
*/
static resultsTable = null
/**
* Définitions des conditions spéciales
* @type {Object}
*/
static definitions = null
/**
* Types de jets supportés
* @type {Object}
*/
static ROLL_TYPES = {
MELEE_ATTACK: "melee_attack",
RANGED_ATTACK: "ranged_attack",
MELEE_DEFENSE: "melee_defense",
ARCANE_SPELL_ATTACK: "arcane_spell_attack",
ARCANE_SPELL_DEFENSE: "arcane_spell_defense",
SKILL_ROLLS: "skill_rolls"
}
/**
* Initialise la classe en chargeant la table des résultats
* @returns {Promise<void>}
*/
static async initialize() {
try {
const response = await fetch("systems/fvtt-lethal-fantasy/module/config/d30_results_tables.json")
const data = await response.json()
this.resultsTable = data.d30_dice_results
this.definitions = data.definitions
console.log("D30Roll | D30 results table loaded successfully")
} catch (error) {
console.error("D30Roll | Error loading D30 table:", error)
ui.notifications.error("Unable to load D30 results table")
}
}
/**
* Récupère le résultat d'un jet de D30
* @param {number} diceValue La valeur du dé (1-30)
* @param {string} rollType Le type de jet externe (ex: "weapon-attack", "spell-attack", etc.)
* @param {Object} weapon L'arme ou l'objet utilisé (optionnel, nécessaire pour certains types)
* @returns {string|null} Le résultat correspondant ou null si vide/non trouvé
*/
static getResult(diceValue, rollType, weapon = null) {
if (!this.resultsTable) {
console.warn("D30Roll | Results table is not initialized. Call D30Roll.initialize() first.")
return null
}
// Validation des paramètres
if (diceValue < 1 || diceValue > 30) {
console.warn(`D30Roll | Invalid dice value: ${diceValue}. Must be between 1 and 30.`)
return null
}
// Convert external rollType to internal rollType
const internalType = this.convertToInternalType(rollType, weapon)
if (!internalType) {
console.warn(`D30Roll | Could not convert roll type: ${rollType}`)
return null
}
if (!Object.values(this.ROLL_TYPES).includes(internalType)) {
console.warn(`D30Roll | Invalid internal roll type: ${internalType}`)
return null
}
const resultEntry = this.resultsTable[diceValue]
if (!resultEntry) {
console.warn(`D30Roll | No entry found for value ${diceValue}`)
return null
}
const result = resultEntry[internalType]
// Retourne null si le résultat est "empty"
if (result === "empty" || !result) {
return null
}
return result
}
/**
* Convertit un rollType externe en rollType interne
* @param {string} externalType Le type de jet externe (ex: "weapon-attack")
* @param {Object} weapon L'arme ou l'objet utilisé (optionnel)
* @returns {string|null} Le type interne correspondant ou null
*/
static convertToInternalType(externalType, weapon = null) {
// Attack types - need weapon to determine if melee or ranged
if (externalType === "weapon-attack") {
if (!weapon) {
console.warn("D30Roll | Weapon object required for weapon-attack type")
return this.ROLL_TYPES.MELEE_ATTACK // Default to melee
}
return weapon.system?.weaponType === "ranged"
? this.ROLL_TYPES.RANGED_ATTACK
: this.ROLL_TYPES.MELEE_ATTACK
}
// Monster attacks - default to melee
if (externalType === "monster-attack") {
// Check if weapon object has range information
if (weapon?.system?.weaponType === "ranged") {
return this.ROLL_TYPES.RANGED_ATTACK
}
return this.ROLL_TYPES.MELEE_ATTACK
}
// Defense types
if (externalType === "weapon-defense" || externalType === "monster-defense") {
return this.ROLL_TYPES.MELEE_DEFENSE
}
// Spell types
if (externalType === "spell-attack" || externalType === "spell" || externalType === "spell-power") {
return this.ROLL_TYPES.ARCANE_SPELL_ATTACK
}
// Skill types
if (externalType === "skill" || externalType === "monster-skill" ||
externalType === "save" || externalType === "challenge") {
return this.ROLL_TYPES.SKILL_ROLLS
}
// If no match, return null
console.warn(`D30Roll | Unknown external roll type: ${externalType}`)
return null
}
/**
* Récupère toutes les informations pour une valeur de dé donnée
* @param {number} diceValue La valeur du dé (1-30)
* @returns {Object|null} Tous les résultats pour cette valeur ou null
*/
static getAllResultsForValue(diceValue) {
if (!this.resultsTable) {
console.warn("D30Roll | Results table is not initialized.")
return null
}
if (diceValue < 1 || diceValue > 30) {
console.warn(`D30Roll | Invalid dice value: ${diceValue}`)
return null
}
return this.resultsTable[diceValue]
}
/**
* Récupère la définition d'une condition spéciale
* @param {string} definitionKey La clé de la définition (ex: "flash_of_pain")
* @returns {string|null} La définition ou null
*/
static getDefinition(definitionKey) {
if (!this.definitions) {
console.warn("D30Roll | Definitions are not initialized.")
return null
}
return this.definitions[definitionKey] || null
}
/**
* Vérifie si un résultat est vide
* @param {string} result Le résultat à vérifier
* @returns {boolean} True si le résultat est vide
*/
static isEmptyResult(result) {
return !result || result === "empty"
}
/**
* Récupère un résultat formaté pour l'affichage
* @param {number} diceValue La valeur du dé (1-30)
* @param {string} rollType Le type de jet externe
* @param {Object} weapon L'arme ou l'objet utilisé (optionnel)
* @returns {Object} Un objet avec le résultat et des informations de formatage
*/
static getFormattedResult(diceValue, rollType, weapon = null) {
const result = this.getResult(diceValue, rollType, weapon)
const internalType = this.convertToInternalType(rollType, weapon)
return {
value: diceValue,
rollType: rollType,
internalType: internalType,
result: result,
isEmpty: this.isEmptyResult(result),
hasResult: !this.isEmptyResult(result)
}
}
/**
* Vérifie si la table est chargée
* @returns {boolean} True si la table est chargée
*/
static isInitialized() {
return this.resultsTable !== null && this.definitions !== null
}
}