Nouvelles corrections sur la fiche
This commit is contained in:
@@ -105,6 +105,9 @@
|
|||||||
"AWEMMY.Weapon.Damage": "Damage",
|
"AWEMMY.Weapon.Damage": "Damage",
|
||||||
"AWEMMY.Weapon.DamageType": "Damage Type",
|
"AWEMMY.Weapon.DamageType": "Damage Type",
|
||||||
"AWEMMY.Weapon.AttackAttribute": "Attack Attribute",
|
"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.KeyAttribute": "Key Attribute",
|
||||||
"AWEMMY.Field.KeyAttribute2": "Secondary Key Attribute",
|
"AWEMMY.Field.KeyAttribute2": "Secondary Key Attribute",
|
||||||
"AWEMMY.Field.Specializations": "Specializations",
|
"AWEMMY.Field.Specializations": "Specializations",
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ export default class AwECharacterSheet extends AwEActorSheet {
|
|||||||
createEquipment: AwECharacterSheet.#onCreateEquipment,
|
createEquipment: AwECharacterSheet.#onCreateEquipment,
|
||||||
flowPointsPlus: AwECharacterSheet.#onFlowPointsPlus,
|
flowPointsPlus: AwECharacterSheet.#onFlowPointsPlus,
|
||||||
flowPointsMinus: AwECharacterSheet.#onFlowPointsMinus,
|
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). */
|
/** Slugify a string for loose name matching (lowercase, trim, spaces→dash, strip non-alphanum). */
|
||||||
static #slugify(str) {
|
static #slugify(str) {
|
||||||
return (str ?? "").toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "")
|
return (str ?? "").toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "")
|
||||||
|
|||||||
@@ -32,6 +32,38 @@ export default class AwEActor extends Actor {
|
|||||||
if (actorData.type !== "creature") return
|
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.
|
* Roll an attribute check.
|
||||||
* @param {string} attributeId - The attribute to roll.
|
* @param {string} attributeId - The attribute to roll.
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ export default class AwERoll extends Roll {
|
|||||||
get actorImage() { return this.options.actorImage }
|
get actorImage() { return this.options.actorImage }
|
||||||
get sourceItemName() { return this.options.sourceItemName }
|
get sourceItemName() { return this.options.sourceItemName }
|
||||||
get sourceItemImg() { return this.options.sourceItemImg }
|
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 ---
|
// --- Outcome calculation ---
|
||||||
|
|
||||||
@@ -170,6 +174,23 @@ export default class AwERoll extends Roll {
|
|||||||
roll.options.outcome = AwERoll.computeOutcome(roll.total, dc, d20Value)
|
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({
|
await roll.toMessage({
|
||||||
speaker: ChatMessage.getSpeaker({ actor: game.actors.get(options.actorId) }),
|
speaker: ChatMessage.getSpeaker({ actor: game.actors.get(options.actorId) }),
|
||||||
flavor: attrLabel,
|
flavor: attrLabel,
|
||||||
@@ -197,6 +218,9 @@ export default class AwERoll extends Roll {
|
|||||||
actorImage: this.actorImage,
|
actorImage: this.actorImage,
|
||||||
sourceItemName: this.sourceItemName,
|
sourceItemName: this.sourceItemName,
|
||||||
sourceItemImg: this.sourceItemImg,
|
sourceItemImg: this.sourceItemImg,
|
||||||
|
damageResult: isPrivate ? null : this.damageResult,
|
||||||
|
damageCritical: this.damageCritical,
|
||||||
|
damageType: this.damageType,
|
||||||
isPrivate
|
isPrivate
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
<div class="item-damage">{{item.system.damageFormula}} ({{item.system.damageType}})</div>
|
<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-range">{{localize "AWEMMY.Weapon.Range"}}: {{item.system.range}}</div>
|
||||||
<div class="item-controls">
|
<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>
|
<a data-action="edit" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
{{#if ../isEditMode}}
|
{{#if ../isEditMode}}
|
||||||
<a data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
<a data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
||||||
|
|||||||
@@ -65,6 +65,21 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/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}}
|
{{else}}
|
||||||
<div class="private-result">
|
<div class="private-result">
|
||||||
<i class="fa-solid fa-eye-slash"></i> {{localize "AWEMMY.Roll.Private"}}
|
<i class="fa-solid fa-eye-slash"></i> {{localize "AWEMMY.Roll.Private"}}
|
||||||
|
|||||||
Reference in New Issue
Block a user