Fix for ranged monsters attack
Release Creation / build (release) Successful in 1m2s

This commit is contained in:
2026-05-01 01:12:56 +02:00
parent 968d156d09
commit 841ed82277
9 changed files with 457 additions and 91 deletions
+2
View File
@@ -256,6 +256,8 @@ export default class LethalFantasyActor extends Actor {
if (rollType === "weapon-defense") {
rollTarget.armorDefense = this.getArmorDefenseValue()
rollTarget.grantedDice = this.system.granted.defenseDice
// Check if this is a ranged defense
rollTarget.isRangedDefense = game.lethalFantasy?.nextDefenseData?.isRanged ?? false
}
}
break
+13 -7
View File
@@ -22,6 +22,7 @@ export default class D30Roll {
MELEE_ATTACK: "melee_attack",
RANGED_ATTACK: "ranged_attack",
MELEE_DEFENSE: "melee_defense",
RANGED_DEFENSE: "ranged_defense",
ARCANE_SPELL_ATTACK: "arcane_spell_attack",
ARCANE_SPELL_DEFENSE: "arcane_spell_defense",
SKILL_ROLLS: "skill_rolls"
@@ -51,9 +52,11 @@ export default class D30Roll {
* @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)
* @param {Object} options Options supplémentaires (optionnel)
* @param {boolean} options.isRanged Si true, utilise ranged_defense au lieu de melee_defense
* @returns {Object|null} L'objet effet `{ type, description, ...fields }` ou null si aucun effet
*/
static getResult(diceValue, rollType, weapon = null) {
static getResult(diceValue, rollType, weapon = null, options = {}) {
if (!this.resultsTable) {
console.warn("D30Roll | Results table is not initialized. Call D30Roll.initialize() first.")
return null
@@ -64,7 +67,7 @@ export default class D30Roll {
return null
}
const internalType = this.convertToInternalType(rollType, weapon)
const internalType = this.convertToInternalType(rollType, weapon, options)
if (!internalType) {
console.warn(`D30Roll | Could not convert roll type: ${rollType}`)
@@ -99,9 +102,11 @@ export default class D30Roll {
* 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)
* @param {Object} options Options supplémentaires (optionnel)
* @param {boolean} options.isRanged Si true, utilise ranged_defense au lieu de melee_defense
* @returns {string|null} Le type interne correspondant ou null
*/
static convertToInternalType(externalType, weapon = null) {
static convertToInternalType(externalType, weapon = null, options = {}) {
// Attack types - need weapon to determine if melee or ranged
if (externalType === "weapon-attack") {
if (!weapon) {
@@ -124,7 +129,7 @@ export default class D30Roll {
// Defense types
if (externalType === "weapon-defense" || externalType === "monster-defense") {
return this.ROLL_TYPES.MELEE_DEFENSE
return options.isRanged ? this.ROLL_TYPES.RANGED_DEFENSE : this.ROLL_TYPES.MELEE_DEFENSE
}
// Spell types
@@ -190,11 +195,12 @@ export default class D30Roll {
* @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)
* @param {Object} options Options supplémentaires (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)
static getFormattedResult(diceValue, rollType, weapon = null, options = {}) {
const result = this.getResult(diceValue, rollType, weapon, options)
const internalType = this.convertToInternalType(rollType, weapon, options)
return {
value: diceValue,
+12 -4
View File
@@ -182,6 +182,7 @@ export default class LethalFantasyRoll extends Roll {
} else {
options.rollTarget.value = options.rollTarget.defenseModifier
options.rollTarget.charModifier = 0
options.isRangedDefense = options.rollTarget.isRangedDefense ?? false
}
} else if (options.rollType === "monster-skill") {
@@ -219,8 +220,14 @@ export default class LethalFantasyRoll extends Roll {
options.rollTarget.charModifier = options.rollTarget.combat.rangedAttackModifier
}
} else {
options.rollTarget.value = options.rollTarget.combat.defenseModifier + options.rollTarget.weaponSkillModifier + options.rollTarget.weapon.system.bonuses.defenseBonus + options.rollTarget.armorDefense
options.rollTarget.charModifier = options.rollTarget.combat.defenseModifier
// For defense, check if it's a ranged defense
const defenseModifier = options.rollTarget.isRangedDefense
? options.rollTarget.combat.rangedDefenseModifier
: options.rollTarget.combat.defenseModifier
options.rollTarget.value = defenseModifier + options.rollTarget.weaponSkillModifier + options.rollTarget.weapon.system.bonuses.defenseBonus + options.rollTarget.armorDefense
options.rollTarget.charModifier = defenseModifier
// Store isRanged flag for D30 lookup
options.isRangedDefense = options.rollTarget.isRangedDefense
}
} else if (options.rollType === "spell" || options.rollType === "spell-attack" || options.rollType === "spell-power") {
@@ -577,7 +584,8 @@ export default class LethalFantasyRoll extends Roll {
const d30Message = D30Roll.getResult(
rollD30.total,
options.rollType,
options.rollTarget?.weapon
options.rollTarget?.weapon,
{ isRanged: options.isRangedDefense }
)
options.D30message = d30Message
}
@@ -1113,7 +1121,7 @@ export default class LethalFantasyRoll extends Roll {
await rollBase.evaluate()
let rollD30 = await new Roll("1D30").evaluate()
options.D30result = rollD30.total
options.D30message = D30Roll.getResult(rollD30.total, options.rollType, options.rollTarget?.weapon)
options.D30message = D30Roll.getResult(rollD30.total, options.rollType, options.rollTarget?.weapon, { isRanged: true })
let badResult = 0
if (rollContext.movement.includes("kh")) {