Corrections sur factions, aspects, degats et fiches PNJs

This commit is contained in:
2026-04-11 15:02:46 +02:00
parent 36516c3b08
commit 3358dea306
44 changed files with 2308 additions and 148 deletions

View File

@@ -1,3 +1,16 @@
/**
* Célestopol 1922 — Système FoundryVTT
*
* Célestopol 1922 est un jeu de rôle édité par Antre-Monde Éditions.
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
* affilié à Antre-Monde Éditions,
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
*
* @author LeRatierBretonnien
* @copyright 20252026 LeRatierBretonnien
* @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
*/
export { default as CelestopolCharacter } from "./character.mjs"
export { default as CelestopolNPC } from "./npc.mjs"
export { CelestopolAnomaly, CelestopolAspect, CelestopolEquipment, CelestopolWeapon, CelestopolArmure } from "./items.mjs"

View File

@@ -1,3 +1,16 @@
/**
* Célestopol 1922 — Système FoundryVTT
*
* Célestopol 1922 est un jeu de rôle édité par Antre-Monde Éditions.
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
* affilié à Antre-Monde Éditions,
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
*
* @author LeRatierBretonnien
* @copyright 20252026 LeRatierBretonnien
* @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
*/
import { SYSTEM } from "../config/system.mjs"
export default class CelestopolCharacter extends foundry.abstract.TypeDataModel {
@@ -165,8 +178,21 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
getArmorMalus() {
if (!this.parent) return 0
return -(this.parent.itemTypes.armure
.filter(a => a.system.equipped && a.system.malus > 0)
.reduce((sum, a) => sum + a.system.malus, 0))
.filter(a => a.system.equipped && (a.system.protection ?? a.system.malus) > 0)
.reduce((sum, a) => sum + (a.system.protection ?? a.system.malus), 0))
}
/**
* Retourne le malus d'armure applicable pour un jet PJ.
* Règle : uniquement sur Mobilité et Effacement si l'armure est équipée.
* @param {string} statId
* @param {string|null} skillId
* @returns {number}
*/
getArmorMalusForRoll(statId, skillId = null) {
if (statId !== "corps") return 0
if (!["mobilite", "effacement"].includes(skillId)) return 0
return this.getArmorMalus()
}
/**
@@ -198,7 +224,7 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
skillLabel: skill.label,
skillValue: skill.value,
woundMalus: this.getWoundMalus(),
armorMalus: this.getArmorMalus(),
armorMalus: this.getArmorMalusForRoll(statId, skillId),
woundLevel: this.blessures.lvl,
difficulty: this.prefs.difficulty,
rollMoonDie: this.prefs.rollMoonDie ?? false,
@@ -229,7 +255,7 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
skillLabel: "CELESTOPOL.Roll.resistanceTest",
skillValue: statData.res,
woundMalus: this.getWoundMalus(),
armorMalus: this.getArmorMalus(),
armorMalus: 0,
woundLevel: this.blessures.lvl,
isResistance: true,
rollMoonDie: false,
@@ -240,8 +266,8 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
}
/**
* Collecte les tokens PNJs disponibles comme cibles de combat.
* Priorise le combat tracker, sinon les tokens ciblés par l'utilisateur.
* Collecte les cibles de combat sur la scène active.
* Pour un PJ attaquant, seules les cibles PNJ présentes sur la scène sont proposées.
* @returns {Array<{id:string, name:string, corps:number}>}
*/
_getCombatTargets() {
@@ -250,25 +276,13 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
name: actor.name,
corps: actor.system.stats?.corps?.res ?? 0,
})
// Priorité 1 : PNJs dans le combat actif
if (game.combat?.active) {
const list = game.combat.combatants
.filter(c => c.actor?.type === "npc" && c.actorId !== this.parent.id)
.map(c => toEntry(c.actor))
if (list.length) return list
}
// Priorité 2 : Tokens ciblés par le joueur
const targeted = [...(game.user?.targets ?? [])]
.filter(t => t.actor?.type === "npc")
.map(t => toEntry(t.actor))
if (targeted.length) return targeted
// Priorité 3 : Tous les tokens NPC de la scène active
if (canvas?.tokens?.placeables) {
return canvas.tokens.placeables
.filter(t => t.actor?.type === "npc" && t.actor.id !== this.parent.id)
.map(t => toEntry(t.actor))
}
return []
const sceneTokens = canvas?.scene?.isView ? (canvas.tokens?.placeables ?? []) : []
return [...new Map(sceneTokens
.filter(t => t.actor?.type === "npc" && t.actor.id !== this.parent.id)
.map(t => {
const actor = t.actor
return [actor.id, toEntry(actor)]
})).values()]
}
/**
@@ -296,7 +310,7 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
skillLabel: SYSTEM.SKILLS.corps.echauffouree.label,
skillValue: echauffouree.value,
woundMalus: this.getWoundMalus(),
armorMalus: this.getArmorMalus(),
armorMalus: this.getArmorMalusForRoll("corps", "echauffouree"),
woundLevel: this.blessures.lvl,
rollMoonDie: this.prefs.rollMoonDie ?? false,
destGaugeFull: this.destin.lvl > 0,
@@ -334,7 +348,7 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
skillLabel: SYSTEM.SKILLS.corps.mobilite.label,
skillValue: mobilite.value,
woundMalus: this.getWoundMalus(),
armorMalus: this.getArmorMalus(),
armorMalus: this.getArmorMalusForRoll("corps", "mobilite"),
woundLevel: this.blessures.lvl,
rollMoonDie: this.prefs.rollMoonDie ?? false,
destGaugeFull: this.destin.lvl > 0,

View File

@@ -1,3 +1,16 @@
/**
* Célestopol 1922 — Système FoundryVTT
*
* Célestopol 1922 est un jeu de rôle édité par Antre-Monde Éditions.
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
* affilié à Antre-Monde Éditions,
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
*
* @author LeRatierBretonnien
* @copyright 20252026 LeRatierBretonnien
* @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
*/
import { SYSTEM } from "../config/system.mjs"
/** Schéma partagé pour les bonus/malus par domaine (utilisé dans anomaly/aspect). */
@@ -83,9 +96,14 @@ export class CelestopolArmure extends foundry.abstract.TypeDataModel {
const reqInt = { required: true, nullable: false, integer: true }
return {
protection: new fields.NumberField({ ...reqInt, initial: 1, min: 1, max: 2 }),
malus: new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 2 }),
malus: new fields.NumberField({ ...reqInt, initial: 1, min: 0, max: 2 }),
equipped: new fields.BooleanField({ initial: false }),
description: new fields.HTMLField({ required: true, textSearch: true }),
}
}
prepareDerivedData() {
super.prepareDerivedData()
this.malus = this.protection
}
}

View File

@@ -1,3 +1,16 @@
/**
* Célestopol 1922 — Système FoundryVTT
*
* Célestopol 1922 est un jeu de rôle édité par Antre-Monde Éditions.
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
* affilié à Antre-Monde Éditions,
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
*
* @author LeRatierBretonnien
* @copyright 20252026 LeRatierBretonnien
* @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
*/
import { SYSTEM } from "../config/system.mjs"
export default class CelestopolNPC extends foundry.abstract.TypeDataModel {
@@ -66,7 +79,20 @@ export default class CelestopolNPC extends foundry.abstract.TypeDataModel {
const armures = this.parent?.itemTypes?.armure ?? []
return armures
.filter(a => a.system.equipped)
.reduce((sum, a) => sum + (a.system.malus ? -Math.abs(a.system.malus) : 0), 0)
.reduce((sum, a) => {
const value = a.system.protection ?? a.system.malus
return sum + (value ? -Math.abs(value) : 0)
}, 0)
}
/**
* Retourne le malus d'armure applicable pour un jet PNJ.
* Règle : sur tous les jets de Corps uniquement.
* @param {string} statId
* @returns {number}
*/
getArmorMalusForRoll(statId) {
return statId === "corps" ? this.getArmorMalus() : 0
}
/**
@@ -91,7 +117,7 @@ export default class CelestopolNPC extends foundry.abstract.TypeDataModel {
skillLabel,
skillValue: statData.res,
woundMalus: this.getWoundMalus(),
armorMalus: this.getArmorMalus(),
armorMalus: this.getArmorMalusForRoll(statId),
woundLevel: this.blessures.lvl,
})
}