Nouvelles corrections sur la fiche

This commit is contained in:
2026-03-06 14:49:32 +01:00
parent a527bd494f
commit 97e97273da
6 changed files with 84 additions and 1 deletions
+3
View File
@@ -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",
@@ -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, "")
+32
View File
@@ -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<AwERoll|null>} 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.
+24
View File
@@ -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
}
)
+1
View File
@@ -36,6 +36,7 @@
<div class="item-damage">{{item.system.damageFormula}} ({{item.system.damageType}})</div>
<div class="item-range">{{localize "AWEMMY.Weapon.Range"}}: {{item.system.range}}</div>
<div class="item-controls">
<a data-action="rollWeapon" data-item-id="{{item.id}}" data-tooltip="{{localize "AWEMMY.Weapon.AttackRoll"}}"><i class="fas fa-dice-d20"></i></a>
<a data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
{{#if ../isEditMode}}
<a data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
+15
View File
@@ -65,6 +65,21 @@
</div>
{{/if}}
{{!-- Weapon damage (only on a successful attack with a DC) --}}
{{#if damageResult}}
<div class="chat-damage {{#if damageCritical}}critical{{/if}}">
<span class="damage-label">
{{#if damageCritical}}
<i class="fa-solid fa-explosion"></i> {{localize "AWEMMY.Weapon.CriticalHit"}}
{{else}}
<i class="fa-solid fa-burst"></i> {{localize "AWEMMY.Weapon.Hit"}}
{{/if}}
</span>
<span class="damage-value">{{damageResult}}</span>
{{#if damageType}}<span class="damage-type">({{damageType}})</span>{{/if}}
</div>
{{/if}}
{{else}}
<div class="private-result">
<i class="fa-solid fa-eye-slash"></i> {{localize "AWEMMY.Roll.Private"}}