Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 54421e4a83 | |||
| ac44419b7a |
@@ -60,4 +60,4 @@ jobs:
|
|||||||
manifest: "https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json"
|
manifest: "https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json"
|
||||||
notes: "https://www.uberwald.me/gitea/public/fvtt-lethal-fantasy/raw/branch/main/changelog.md"
|
notes: "https://www.uberwald.me/gitea/public/fvtt-lethal-fantasy/raw/branch/main/changelog.md"
|
||||||
compatibility-minimum: "13"
|
compatibility-minimum: "13"
|
||||||
compatibility-verified: "13"
|
compatibility-verified: "14"
|
||||||
|
|||||||
+1
-1
@@ -382,7 +382,7 @@
|
|||||||
"rollProgressionCount": "Roll progression count",
|
"rollProgressionCount": "Roll progression count",
|
||||||
"rollProgressionDice": "Roll progression/Lethargy dice",
|
"rollProgressionDice": "Roll progression/Lethargy dice",
|
||||||
"earned": "Earned",
|
"earned": "Earned",
|
||||||
"divinityPoints": "Divinity points",
|
"divinityPoints": "Grace",
|
||||||
"aetherPoints": "Aether points",
|
"aetherPoints": "Aether points",
|
||||||
"attacks": "Attacks",
|
"attacks": "Attacks",
|
||||||
"attackMode": "Attack Mode",
|
"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
|
// Hook pour appliquer automatiquement les dégâts si une cible est définie
|
||||||
Hooks.on("createChatMessage", async (message) => {
|
Hooks.on("createChatMessage", async (message) => {
|
||||||
// Vérifier si c'est un message de dégâts avec un defenderId
|
// 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":
|
case "miracle-power":
|
||||||
rollTarget = this.items.find((i) => (i.type === "miracle" || i.type == "spell") && i.id === rollKey)
|
rollTarget = this.items.find((i) => (i.type === "miracle" || i.type == "spell") && i.id === rollKey)
|
||||||
rollTarget.rollKey = 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
|
break
|
||||||
case "shield-roll": {
|
case "shield-roll": {
|
||||||
rollTarget = this.items.find((i) => i.type === "shield" && i.id === rollKey)
|
rollTarget = this.items.find((i) => i.type === "shield" && i.id === rollKey)
|
||||||
|
|||||||
@@ -272,6 +272,7 @@ export default class LethalFantasyRoll extends Roll {
|
|||||||
hasChangeDice = false
|
hasChangeDice = false
|
||||||
hasMaxValue = false
|
hasMaxValue = false
|
||||||
hasExplode = false
|
hasExplode = false
|
||||||
|
hasFavor = true
|
||||||
options.rollTarget.value = 0
|
options.rollTarget.value = 0
|
||||||
|
|
||||||
} else if (options.rollType.includes("weapon-damage")) {
|
} else if (options.rollType.includes("weapon-damage")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user