Rework des fiches creature/PJ et Tinji/Loksyu

This commit is contained in:
2026-03-30 16:36:38 +02:00
parent 0689fae792
commit cab77645b7
70 changed files with 1712 additions and 1075 deletions

View File

@@ -1,12 +1,10 @@
/**
* Singleton actor utilities for Loksyu and Tin Ji.
* Loksyu / TinJi settings-based helpers.
*
* Both are world-level shared trackers backed by a singleton Actor document
* of type "loksyu" / "tinji". GMs can create them via the Actors sidebar;
* the apps find the first one or offer to create it.
* Data is stored as world settings instead of singleton Actor documents.
*/
import { ACTOR_TYPES } from "../../config/constants.js"
const SYSTEM_ID = "fvtt-chroniques-de-l-etrange"
/** Wu Xing generating cycle — [successes, auspicious, noxious, loksyu, tinji] */
const WU_XING_CYCLE = {
@@ -17,7 +15,6 @@ const WU_XING_CYCLE = {
water: ["water", "wood", "metal", "fire", "earth"],
}
/** Die face pairs [yin, yang] per aspect (0 = face "10") */
const ASPECT_FACES = {
metal: [3, 8],
water: [1, 6],
@@ -26,39 +23,35 @@ const ASPECT_FACES = {
wood: [4, 9],
}
/**
* Find the first actor of the given type in the world, or create one if the
* current user is a GM and none exists.
*
* @param {"loksyu"|"tinji"} type
* @returns {Promise<Actor|null>}
*/
export async function getSingletonActor(type) {
const existing = game.actors.find((a) => a.type === type)
if (existing) return existing
if (!game.user.isGM) {
ui.notifications.warn(game.i18n.localize(type === ACTOR_TYPES.loksyu ? "CDE.LoksyuNotFound" : "CDE.TinjiNotFound"))
return null
/** Read the current loksyu data object from world settings */
export function getLoksyuData() {
return game.settings.get(SYSTEM_ID, "loksyuData") ?? {
wood: {yin:0,yang:0}, fire: {yin:0,yang:0}, earth: {yin:0,yang:0}, metal: {yin:0,yang:0}, water: {yin:0,yang:0},
}
}
// Auto-create the singleton when the GM opens the app for the first time.
const nameKey = type === ACTOR_TYPES.loksyu ? "CDE.UpperCaseLoksyu" : "CDE.UpperCaseTinJi"
const actor = await Actor.create({
name: game.i18n.localize(nameKey),
type,
img: type === ACTOR_TYPES.loksyu
? "systems/fvtt-chroniques-de-l-etrange/images/loksyu_long.webp"
: "systems/fvtt-chroniques-de-l-etrange/images/tinji.webp",
})
return actor ?? null
/** Write the loksyu data object to world settings */
export async function setLoksyuData(data) {
await game.settings.set(SYSTEM_ID, "loksyuData", data)
Hooks.callAll("cde:loksyuUpdated", data)
}
/** Read current TinJi value from world settings */
export function getTinjiValue() {
return game.settings.get(SYSTEM_ID, "tinjiData") ?? 0
}
/** Write TinJi value to world settings */
export async function setTinjiValue(value) {
await game.settings.set(SYSTEM_ID, "tinjiData", Math.max(0, value))
Hooks.callAll("cde:tinjiUpdated", Math.max(0, value))
}
/**
* After a WuXing roll, add the loksyu faces (yin + yang) of the relevant
* aspect to the singleton Loksyu actor.
* aspect to the loksyu settings data.
*
* @param {string} activeAspect - The aspect used for the roll (e.g. "fire")
* @param {string} activeAspect - e.g. "fire"
* @param {Object} faces - Die face counts { 0: n, 1: n, …, 9: n }
*/
export async function updateLoksyuFromRoll(activeAspect, faces) {
@@ -73,27 +66,22 @@ export async function updateLoksyuFromRoll(activeAspect, faces) {
const yangCount = faces[yangFace] ?? 0
if (yinCount === 0 && yangCount === 0) return
const actor = await getSingletonActor(ACTOR_TYPES.loksyu)
if (!actor) return
const current = actor.system[lokAspect] ?? { yin: { value: 0 }, yang: { value: 0 } }
await actor.update({
[`system.${lokAspect}.yin.value`]: (current.yin.value ?? 0) + yinCount,
[`system.${lokAspect}.yang.value`]: (current.yang.value ?? 0) + yangCount,
})
const data = getLoksyuData()
const current = data[lokAspect] ?? { yin: 0, yang: 0 }
data[lokAspect] = {
yin: (current.yin ?? 0) + yinCount,
yang: (current.yang ?? 0) + yangCount,
}
await setLoksyuData(data)
}
/**
* After a WuXing roll, add tinji faces to the singleton TinJi actor.
* After a WuXing roll, add tinji faces to the TinJi settings.
*
* @param {number} count - Number of tinji faces rolled
*/
export async function updateTinjiFromRoll(count) {
if (!count || count <= 0) return
const actor = await getSingletonActor(ACTOR_TYPES.tinji)
if (!actor) return
const current = actor.system.value ?? 0
await actor.update({ "system.value": current + count })
const current = getTinjiValue()
await setTinjiValue(current + count)
}