From 97e97273da2be891c4c2830d4aeb9c3871568ccb Mon Sep 17 00:00:00 2001 From: LeRatierBretonnier Date: Fri, 6 Mar 2026 14:49:32 +0100 Subject: [PATCH] Nouvelles corrections sur la fiche --- lang/en.json | 3 ++ .../applications/sheets/character-sheet.mjs | 10 +++++- module/documents/actor.mjs | 32 +++++++++++++++++++ module/documents/roll.mjs | 24 ++++++++++++++ templates/character-equipment.hbs | 1 + templates/chat-message.hbs | 15 +++++++++ 6 files changed, 84 insertions(+), 1 deletion(-) diff --git a/lang/en.json b/lang/en.json index 7d0d68a..d253834 100644 --- a/lang/en.json +++ b/lang/en.json @@ -105,6 +105,9 @@ "AWEMMY.Weapon.Damage": "Damage", "AWEMMY.Weapon.DamageType": "Damage Type", "AWEMMY.Weapon.AttackAttribute": "Attack Attribute", + "AWEMMY.Weapon.AttackRoll": "Attack Roll", + "AWEMMY.Weapon.Hit": "Hit", + "AWEMMY.Weapon.CriticalHit": "Critical Hit!", "AWEMMY.Field.KeyAttribute": "Key Attribute", "AWEMMY.Field.KeyAttribute2": "Secondary Key Attribute", "AWEMMY.Field.Specializations": "Specializations", diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index 911fec3..5c393ad 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -19,7 +19,8 @@ export default class AwECharacterSheet extends AwEActorSheet { createEquipment: AwECharacterSheet.#onCreateEquipment, flowPointsPlus: AwECharacterSheet.#onFlowPointsPlus, flowPointsMinus: AwECharacterSheet.#onFlowPointsMinus, - rollField: AwECharacterSheet.#onRollField + rollField: AwECharacterSheet.#onRollField, + rollWeapon: AwECharacterSheet.#onRollWeapon } } @@ -240,6 +241,13 @@ export default class AwECharacterSheet extends AwEActorSheet { }) } + static async #onRollWeapon(event, target) { + const itemId = target.closest("[data-item-id]")?.dataset.itemId + const item = this.document.items.get(itemId) + if (!item) return + await this.document.rollWeapon(item) + } + /** Slugify a string for loose name matching (lowercase, trim, spaces→dash, strip non-alphanum). */ static #slugify(str) { return (str ?? "").toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "") diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index a68f205..13a5123 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -32,6 +32,38 @@ export default class AwEActor extends Actor { if (actorData.type !== "creature") return } + /** + * Roll a weapon attack: attack roll + damage if hit. + * @param {Item} weaponItem - The weapon item being used. + * @param {object} options - Additional roll options. + * @returns {Promise} The evaluated roll, or null if cancelled. + */ + async rollWeapon(weaponItem, options = {}) { + const attrId = weaponItem.system.attackAttribute + const attribute = this.system.attributes[attrId] + if (!attribute) return null + + const knowledgeBonuses = this.itemTypes.field?.map(f => ({ + label: f.name, + bonus: f.system.knowledgeBonus ?? "" + })).filter(f => f.bonus !== "") ?? [] + + return AwERoll.prompt({ + attributeKey: attrId, + modifier: attribute.mod ?? 0, + attributeBonus: attribute.bonus ?? 0, + knowledgeBonuses, + actorId: this.id, + actorName: this.name, + actorImage: this.img, + sourceItemName: weaponItem.name, + sourceItemImg: weaponItem.img, + damageFormula: weaponItem.system.damageFormula, + damageType: weaponItem.system.damageType, + ...options + }) + } + /** * Roll an attribute check. * @param {string} attributeId - The attribute to roll. diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index 5aee37a..6d6a320 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -19,6 +19,10 @@ export default class AwERoll extends Roll { get actorImage() { return this.options.actorImage } get sourceItemName() { return this.options.sourceItemName } get sourceItemImg() { return this.options.sourceItemImg } + get damageFormula() { return this.options.damageFormula } + get damageType() { return this.options.damageType } + get damageResult() { return this.options.damageResult } + get damageCritical() { return this.options.damageCritical ?? false } // --- Outcome calculation --- @@ -170,6 +174,23 @@ export default class AwERoll extends Roll { roll.options.outcome = AwERoll.computeOutcome(roll.total, dc, d20Value) } + // If this is a weapon attack and it hit, roll damage + if (options.damageFormula && roll.options.outcome) { + const isHit = roll.options.outcome === "success" || roll.options.outcome === "criticalSuccess" + const isCrit = roll.options.outcome === "criticalSuccess" + if (isHit) { + // Double the dice count on critical success + const formula = isCrit + ? options.damageFormula.replace(/(\d+)d(\d+)/gi, (_, n, d) => `${Number(n) * 2}d${d}`) + : options.damageFormula + const dmgRoll = new Roll(formula) + await dmgRoll.evaluate() + roll.options.damageResult = dmgRoll.total + roll.options.damageCritical = isCrit + roll.options.damageType = options.damageType + } + } + await roll.toMessage({ speaker: ChatMessage.getSpeaker({ actor: game.actors.get(options.actorId) }), flavor: attrLabel, @@ -197,6 +218,9 @@ export default class AwERoll extends Roll { actorImage: this.actorImage, sourceItemName: this.sourceItemName, sourceItemImg: this.sourceItemImg, + damageResult: isPrivate ? null : this.damageResult, + damageCritical: this.damageCritical, + damageType: this.damageType, isPrivate } ) diff --git a/templates/character-equipment.hbs b/templates/character-equipment.hbs index 6113766..e6001c2 100644 --- a/templates/character-equipment.hbs +++ b/templates/character-equipment.hbs @@ -36,6 +36,7 @@
{{item.system.damageFormula}} ({{item.system.damageType}})
{{localize "AWEMMY.Weapon.Range"}}: {{item.system.range}}
+ {{#if ../isEditMode}} diff --git a/templates/chat-message.hbs b/templates/chat-message.hbs index 897dd57..54d5510 100644 --- a/templates/chat-message.hbs +++ b/templates/chat-message.hbs @@ -65,6 +65,21 @@
{{/if}} + {{!-- Weapon damage (only on a successful attack with a DC) --}} + {{#if damageResult}} +
+ + {{#if damageCritical}} + {{localize "AWEMMY.Weapon.CriticalHit"}} + {{else}} + {{localize "AWEMMY.Weapon.Hit"}} + {{/if}} + + {{damageResult}} + {{#if damageType}}({{damageType}}){{/if}} +
+ {{/if}} + {{else}}
{{localize "AWEMMY.Roll.Private"}}