MAnage spell/miracle spending points and favor/disfavor for shield rolls
This commit is contained in:
+1
-1
@@ -382,7 +382,7 @@
|
||||
"rollProgressionCount": "Roll progression count",
|
||||
"rollProgressionDice": "Roll progression/Lethargy dice",
|
||||
"earned": "Earned",
|
||||
"divinityPoints": "Divinity points",
|
||||
"divinityPoints": "Grace",
|
||||
"aetherPoints": "Aether points",
|
||||
"attacks": "Attacks",
|
||||
"attackMode": "Attack Mode",
|
||||
|
||||
@@ -828,6 +828,73 @@ Hooks.on("createChatMessage", async (message) => {
|
||||
}
|
||||
})
|
||||
|
||||
// Hook: deduct aether when a spell-attack or spell-power roll is posted to chat
|
||||
Hooks.on("createChatMessage", async (message) => {
|
||||
if (!["spell-attack", "spell-power"].includes(message.rolls[0]?.options?.rollType)) return
|
||||
|
||||
const actorId = message.rolls[0]?.options?.actorId
|
||||
if (!actorId) return
|
||||
const actor = game.actors.get(actorId)
|
||||
if (!actor) return
|
||||
|
||||
// Only the primary controller (player owner or GM) handles this
|
||||
const activePlayerOwners = game.users.filter(u => u.active && !u.isGM && actor.testUserPermission(u, "OWNER"))
|
||||
const isPrimary = activePlayerOwners.length > 0
|
||||
? activePlayerOwners[0].id === game.user.id
|
||||
: game.user.isGM
|
||||
if (!isPrimary) return
|
||||
|
||||
const rollTarget = message.rolls[0]?.options?.rollTarget
|
||||
const spellId = rollTarget?.id || rollTarget?._id
|
||||
const spell = spellId ? actor.items.get(spellId) : null
|
||||
if (!spell || spell.type !== "spell") return
|
||||
|
||||
const cost = Number(spell.system?.cost) || 0
|
||||
if (cost <= 0) return
|
||||
|
||||
const currentAether = Number(actor.system.aetherPoints?.value) || 0
|
||||
const newAether = Math.max(0, currentAether - cost)
|
||||
await actor.update({ "system.aetherPoints.value": newAether })
|
||||
|
||||
await ChatMessage.create({
|
||||
content: `<p>🔮 <strong>${actor.name}</strong> casts <em>${spell.name}</em> — spends <strong>${cost}</strong> Aether <span style="color:#888;">(${currentAether} → ${newAether})</span>.</p>`,
|
||||
speaker: ChatMessage.getSpeaker({ actor })
|
||||
})
|
||||
})
|
||||
|
||||
// Hook: deduct grace when a miracle-attack or miracle-power roll is posted to chat
|
||||
Hooks.on("createChatMessage", async (message) => {
|
||||
if (!["miracle-attack", "miracle-power"].includes(message.rolls[0]?.options?.rollType)) return
|
||||
|
||||
const actorId = message.rolls[0]?.options?.actorId
|
||||
if (!actorId) return
|
||||
const actor = game.actors.get(actorId)
|
||||
if (!actor) return
|
||||
|
||||
const activePlayerOwners = game.users.filter(u => u.active && !u.isGM && actor.testUserPermission(u, "OWNER"))
|
||||
const isPrimary = activePlayerOwners.length > 0
|
||||
? activePlayerOwners[0].id === game.user.id
|
||||
: game.user.isGM
|
||||
if (!isPrimary) return
|
||||
|
||||
const rollTarget = message.rolls[0]?.options?.rollTarget
|
||||
const miracleId = rollTarget?.id || rollTarget?._id
|
||||
const miracle = miracleId ? actor.items.get(miracleId) : null
|
||||
if (!miracle || miracle.type !== "miracle") return
|
||||
|
||||
const cost = Number(miracle.system?.level) || 0
|
||||
if (cost <= 0) return
|
||||
|
||||
const currentGrace = Number(actor.system.divinityPoints?.value) || 0
|
||||
const newGrace = Math.max(0, currentGrace - cost)
|
||||
await actor.update({ "system.divinityPoints.value": newGrace })
|
||||
|
||||
await ChatMessage.create({
|
||||
content: `<p>✨ <strong>${actor.name}</strong> invokes <em>${miracle.name}</em> — spends <strong>${cost}</strong> Grace <span style="color:#888;">(${currentGrace} → ${newGrace})</span>.</p>`,
|
||||
speaker: ChatMessage.getSpeaker({ actor })
|
||||
})
|
||||
})
|
||||
|
||||
// Hook pour appliquer automatiquement les dégâts si une cible est définie
|
||||
Hooks.on("createChatMessage", async (message) => {
|
||||
// Vérifier si c'est un message de dégâts avec un defenderId
|
||||
|
||||
@@ -198,6 +198,22 @@ export default class LethalFantasyActor extends Actor {
|
||||
case "miracle-power":
|
||||
rollTarget = this.items.find((i) => (i.type === "miracle" || i.type == "spell") && i.id === rollKey)
|
||||
rollTarget.rollKey = rollKey
|
||||
if (rollType === "spell-attack" || rollType === "spell-power") {
|
||||
const cost = Number(rollTarget.system?.cost) || 0
|
||||
const currentAether = Number(this.system.aetherPoints?.value) || 0
|
||||
if (cost > currentAether) {
|
||||
ui.notifications.warn(`${this.name} cannot cast ${rollTarget.name}: insufficient Aether (needs ${cost}, has ${currentAether}).`)
|
||||
return
|
||||
}
|
||||
}
|
||||
if (rollType === "miracle-attack" || rollType === "miracle-power") {
|
||||
const cost = Number(rollTarget.system?.level) || 0
|
||||
const currentGrace = Number(this.system.divinityPoints?.value) || 0
|
||||
if (cost > currentGrace) {
|
||||
ui.notifications.warn(`${this.name} cannot invoke ${rollTarget.name}: insufficient Grace (needs ${cost}, has ${currentGrace}).`)
|
||||
return
|
||||
}
|
||||
}
|
||||
break
|
||||
case "shield-roll": {
|
||||
rollTarget = this.items.find((i) => i.type === "shield" && i.id === rollKey)
|
||||
|
||||
@@ -272,6 +272,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
hasChangeDice = false
|
||||
hasMaxValue = false
|
||||
hasExplode = false
|
||||
hasFavor = true
|
||||
options.rollTarget.value = 0
|
||||
|
||||
} else if (options.rollType.includes("weapon-damage")) {
|
||||
|
||||
Reference in New Issue
Block a user