This commit is contained in:
@@ -289,10 +289,13 @@ export class LesOubliesRolls {
|
||||
|
||||
const result = await this.resolveTest(actor, data)
|
||||
if (!result) return null
|
||||
const initiativeScore = Math.min(Math.max(Math.ceil(result.final / 2), 0), 12)
|
||||
await this.#syncInitiativeToCombat(actor, initiativeScore)
|
||||
|
||||
return this.#createChatMessage(actor, {
|
||||
...result,
|
||||
mode: "initiative",
|
||||
initiativeScore: Math.min(Math.max(Math.ceil(result.final / 2), 0), 12),
|
||||
initiativeScore,
|
||||
successLabel: null,
|
||||
})
|
||||
}
|
||||
@@ -716,14 +719,7 @@ export class LesOubliesRolls {
|
||||
}
|
||||
|
||||
const pool = this.#buildPool(options.rollMode, options.extraDie)
|
||||
const dice = []
|
||||
for (let index = 0; index < pool.length; index += 1) {
|
||||
const spec = pool[index]
|
||||
dice.push(await this.#rollExplodingDie({
|
||||
...spec,
|
||||
index,
|
||||
}))
|
||||
}
|
||||
const dice = await this.#rollExplodingPool(pool)
|
||||
|
||||
const selectedIndex = this.#needsSelection(dice)
|
||||
? await this.#promptDieSelection(actor, options.label, dice)
|
||||
@@ -792,6 +788,23 @@ export class LesOubliesRolls {
|
||||
})
|
||||
}
|
||||
|
||||
static async #syncInitiativeToCombat(actor, initiativeScore) {
|
||||
if (!game.combat || !actor?.id) return false
|
||||
|
||||
const combatants = game.combat.combatants.filter((combatant) => combatant.actorId === actor.id)
|
||||
if (!combatants.length) {
|
||||
ui.notifications.warn(`${actor.name} n'est pas présent dans le combat actif.`)
|
||||
return false
|
||||
}
|
||||
|
||||
await game.combat.updateEmbeddedDocuments("Combatant", combatants.map((combatant) => ({
|
||||
_id: combatant.id,
|
||||
initiative: initiativeScore,
|
||||
})))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
static async #createConfrontationMessage(actor, data, actionData = null) {
|
||||
const attacker = await this.resolveTest(actor, {
|
||||
label: data.attackerLabel,
|
||||
@@ -1507,38 +1520,82 @@ export class LesOubliesRolls {
|
||||
return dice
|
||||
}
|
||||
|
||||
static async #rollExplodingDie({ type, index, source = "base" }) {
|
||||
const faces = []
|
||||
const rolls = []
|
||||
let total = 0
|
||||
let lastFace = 12
|
||||
|
||||
while (lastFace === 12) {
|
||||
const roll = await this.#evaluateDisplayedRoll("1d12")
|
||||
lastFace = Number(roll.total ?? 0)
|
||||
rolls.push(roll)
|
||||
faces.push(lastFace)
|
||||
total += lastFace
|
||||
}
|
||||
|
||||
const typeLabel = game.i18n.localize(`LESOUBLIES.rolls.dice.${type}`)
|
||||
return {
|
||||
static async #rollExplodingPool(pool) {
|
||||
const dice = pool.map(({ type, source = "base" }, index) => ({
|
||||
index,
|
||||
type,
|
||||
typeLabel,
|
||||
typeLabel: game.i18n.localize(`LESOUBLIES.rolls.dice.${type}`),
|
||||
source,
|
||||
sourceLabel: source === "extra" ? game.i18n.localize("LESOUBLIES.rolls.extraDie") : null,
|
||||
faces,
|
||||
rolls,
|
||||
firstFace: faces[0] ?? 0,
|
||||
total,
|
||||
exploded: faces.length > 1,
|
||||
breakdown: faces.join(" + "),
|
||||
faces: [],
|
||||
rolls: [],
|
||||
total: 0,
|
||||
}))
|
||||
|
||||
let pendingDice = [...dice]
|
||||
while (pendingDice.length) {
|
||||
const roll = await this.#evaluateDisplayedRoll(
|
||||
Array.from({ length: pendingDice.length }, () => "1d12").join(" + "),
|
||||
(pendingRoll) => this.#applyDieAppearances(pendingRoll, pendingDice),
|
||||
)
|
||||
|
||||
const dieTerms = roll.terms.filter((term) => Number(term.faces ?? 0) === 12)
|
||||
const nextPendingDice = []
|
||||
|
||||
pendingDice.forEach((die, index) => {
|
||||
const face = Number(dieTerms[index]?.results?.[0]?.result ?? 0)
|
||||
die.rolls.push(roll)
|
||||
die.faces.push(face)
|
||||
die.total += face
|
||||
if (face === 12) nextPendingDice.push(die)
|
||||
})
|
||||
|
||||
pendingDice = nextPendingDice
|
||||
}
|
||||
|
||||
return dice.map((die) => ({
|
||||
...die,
|
||||
firstFace: die.faces[0] ?? 0,
|
||||
exploded: die.faces.length > 1,
|
||||
breakdown: die.faces.join(" + "),
|
||||
}))
|
||||
}
|
||||
|
||||
static #applyDieAppearances(roll, dice) {
|
||||
const dieTerms = roll.terms.filter((term) => Number(term.faces ?? 0) === 12)
|
||||
dieTerms.forEach((term, index) => {
|
||||
term.options ??= {}
|
||||
term.options.appearance = this.#getDieAppearance(dice[index]?.type)
|
||||
})
|
||||
}
|
||||
|
||||
static #getDieAppearance(type) {
|
||||
switch (type) {
|
||||
case "songes":
|
||||
return {
|
||||
foreground: "#111111",
|
||||
background: "#f3efe4",
|
||||
outline: "#b8aa87",
|
||||
}
|
||||
case "cauchemar":
|
||||
return {
|
||||
foreground: "#f4f0e8",
|
||||
background: "#111111",
|
||||
outline: "#5d5d5d",
|
||||
}
|
||||
default:
|
||||
return {
|
||||
foreground: "#201813",
|
||||
background: "#ddd0b0",
|
||||
outline: "#8d5c3b",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async #evaluateDisplayedRoll(formula) {
|
||||
const roll = await (new Roll(formula)).evaluate()
|
||||
static async #evaluateDisplayedRoll(formula, configureRoll = null) {
|
||||
const roll = typeof formula === "string" ? new Roll(formula) : formula
|
||||
if (configureRoll) configureRoll(roll)
|
||||
await roll.evaluate()
|
||||
await this.#showDiceSoNice(roll)
|
||||
return roll
|
||||
}
|
||||
@@ -2059,16 +2116,7 @@ export class LesOubliesRolls {
|
||||
}
|
||||
|
||||
static #getWeaponBaseDamage(actor, weapon) {
|
||||
const damageText = String(weapon?.system?.damage || "")
|
||||
const parsed = this.#extractFirstInteger(damageText)
|
||||
if (parsed !== null) return parsed
|
||||
|
||||
const explicitValue = Number(weapon?.system?.sizeValue ?? 0)
|
||||
if (explicitValue > 0) return explicitValue
|
||||
|
||||
const actorSize = Number(actor?.system?.size?.value ?? 0)
|
||||
const sizeModifier = Number(weapon?.system?.sizeModifier ?? 0)
|
||||
return Math.max(actorSize + sizeModifier, 0)
|
||||
return LesOubliesUtility.getWeaponBaseDamage(actor, weapon)
|
||||
}
|
||||
|
||||
static #extractFirstInteger(text) {
|
||||
|
||||
Reference in New Issue
Block a user