Esprit de la Loi + Automaton

This commit is contained in:
2026-05-02 23:16:10 +02:00
parent d6b5891519
commit 0df4a5a9fb
280 changed files with 10668 additions and 419 deletions
+97 -3
View File
@@ -2,6 +2,9 @@
import { MournbladeUtility } from "./mournblade-utility.js";
import { MournbladeRollDialog } from "./applications/mournblade-roll-dialog.mjs";
import MournbladeInvocationDialog from "./applications/mournblade-invocation-dialog.mjs";
import MournbladeInvocationDemonDialog from "./applications/mournblade-invocation-demon-dialog.mjs";
import MournbladeInvocationEspritDialog from "./applications/mournblade-invocation-esprit-dialog.mjs";
import MournbladeEnchantementDialog from "./applications/mournblade-enchantement-dialog.mjs";
/* -------------------------------------------- */
const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10]
@@ -91,6 +94,8 @@ export class MournbladeActor extends Actor {
prepareArme(arme) {
arme = foundry.utils.duplicate(arme)
let combat = this.getCombatValues()
const enchBonus = (arme.system.enchantementLoi?.actif && arme.system.enchantementLoi?.bonus > 0)
? arme.system.enchantementLoi.bonus : 0
if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") {
arme.system.isMelee = true
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")
@@ -98,7 +103,7 @@ export class MournbladeActor extends Actor {
arme.system.competence = foundry.utils.duplicate(competence)
arme.system.attrKey = "pui"
arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal
arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + combat.attaqueModifier
arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + combat.attaqueModifier + enchBonus
if (arme.system.isdefense) {
arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.bonusmaniementdef
}
@@ -115,7 +120,7 @@ export class MournbladeActor extends Actor {
if (competence) {
arme.system.competence = foundry.utils.duplicate(competence)
arme.system.attrKey = "adr"
arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + combat.attaqueModifier
arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + combat.attaqueModifier + enchBonus
arme.system.totalDegats = arme.system.degats
if (arme.system.isdefense) {
arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.bonusmaniementdef
@@ -133,12 +138,14 @@ export class MournbladeActor extends Actor {
prepareBouclier(bouclier) {
bouclier = foundry.utils.duplicate(bouclier)
let combat = this.getCombatValues()
const enchBonus = (bouclier.system.enchantementLoi?.actif && bouclier.system.enchantementLoi?.bonus > 0)
? bouclier.system.enchantementLoi.bonus : 0
let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")
if (competence) {
bouclier.system.competence = foundry.utils.duplicate(competence)
bouclier.system.attrKey = "pui"
bouclier.system.totalDegats = bouclier.system.degats + "+" + combat.bonusDegatsTotal
bouclier.system.totalOffensif = this.system.attributs.pui.value + bouclier.system.competence.system.niveau
bouclier.system.totalOffensif = this.system.attributs.pui.value + bouclier.system.competence.system.niveau + enchBonus
bouclier.system.isdefense = true
bouclier.system.bonusmaniementoff = 0
bouclier.system.totalDefensif = combat.defenseTotal + bouclier.system.competence.system.niveau + bouclier.system.bonusdefense
@@ -213,6 +220,9 @@ export class MournbladeActor extends Actor {
getMonnaies() {
return this.getItemSorted(["monnaie"])
}
getPotions() {
return this.getItemSorted(["potion"])
}
getArmors() {
return this.getItemSorted(["protection"])
}
@@ -739,6 +749,90 @@ export class MournbladeActor extends Actor {
ui.notifications.info(`L'Élémentaire ${invoc.actorName} a été banni. ${invoc.soulCost} points d'Âme libérés.`)
}
/* -------------------------------------------- */
async invoquerDemon() {
const normalize = str => str.toLowerCase()
.replace(/œ/g, "oe").replace(/æ/g, "ae")
.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]+/g, " ").trim()
const hasKeywords = (item, ...words) => {
const n = normalize(item.name)
return words.every(w => n.includes(normalize(w)))
}
const coercitionComp = this.items.find(c => c.type === "competence" && hasKeywords(c, "coercition"))
if (!coercitionComp) {
ui.notifications.warn("La compétence Coercition est requise pour invoquer un Démon.")
return
}
const isChaotique = this.system.balance.chaos > this.system.balance.loi
const hasOeilSorcier = this.items.some(c => (c.type === "capacite" || c.type === "don") && hasKeywords(c, "oeil", "sorcier"))
const hasRuneChaos = this.items.some(i => i.type === "rune" && hasKeywords(i, "chaos"))
if (!isChaotique || !hasOeilSorcier || !hasRuneChaos) {
const missing = []
if (!isChaotique) missing.push("alignement chaotique (Chaos > Loi)")
if (!hasOeilSorcier) missing.push("Capacité/Don Œil du Sorcier")
if (!hasRuneChaos) missing.push("Rune du Chaos")
ui.notifications.warn(`Prérequis manquants pour l'invocation démoniaque : ${missing.join(", ")}.`)
}
let rollData = this.getCommonRollData("tre", coercitionComp._id)
rollData.isInvocationDemon = true
rollData.mainDice = "1d10"
await MournbladeInvocationDemonDialog.create(this, rollData)
}
/* -------------------------------------------- */
async libererDemon(invocIndex) {
const invocations = foundry.utils.duplicate(this.system.invocationsDemons || [])
const invoc = invocations[invocIndex]
if (!invoc) return
invocations.splice(invocIndex, 1)
await this.update({ "system.invocationsDemons": invocations })
ui.notifications.info(`Le Démon ${invoc.demonName ?? "invoqué"} a été libéré.`)
}
/* -------------------------------------------- */
async invoquerEspritLoi() {
const normalize = str => str.toLowerCase()
.replace(/œ/g, "oe").replace(/æ/g, "ae")
.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]+/g, " ").trim()
const hasKeywords = (item, ...words) => {
const n = normalize(item.name)
return words.every(w => n.includes(normalize(w)))
}
const persuasionComp = this.items.find(c => c.type === "competence" && hasKeywords(c, "persuasion"))
const isLoyal = this.system.balance.loi > this.system.balance.chaos
const hasRuneLoi = this.items.some(i => i.type === "rune" && hasKeywords(i, "loi"))
if (!isLoyal || !hasRuneLoi) {
const missing = []
if (!isLoyal) missing.push("alignement loyal (Loi > Chaos)")
if (!hasRuneLoi) missing.push("Rune de la Loi")
ui.notifications.warn(`Prérequis manquants : ${missing.join(", ")}.`)
}
const rollData = this.getCommonRollData("tre", persuasionComp?._id ?? null)
rollData.isInvocationEsprit = true
rollData.mainDice = "1d10"
await MournbladeInvocationEspritDialog.create(this, rollData)
}
/* -------------------------------------------- */
async enchanter(itemId) {
const item = this.items.get(itemId)
if (!item) return
if (!["arme", "equipement", "protection", "bouclier"].includes(item.type)) {
ui.notifications.warn("Seules les armes, équipements, protections et boucliers peuvent être enchantés.")
return
}
await MournbladeEnchantementDialog.create(this, item)
}
/* -------------------------------------------- */
async rollArmeOffensif(armeId) {
let arme = this.items.get(armeId)