296 lines
9.6 KiB
JavaScript
296 lines
9.6 KiB
JavaScript
/**
|
|
* Lethal Fantasy RPG System
|
|
* Author: LeRatierBretonnien/Uberwald
|
|
*/
|
|
|
|
import { SYSTEM } from "./module/config/system.mjs"
|
|
globalThis.SYSTEM = SYSTEM // Expose the SYSTEM object to the global scope
|
|
|
|
// Import modules
|
|
import * as models from "./module/models/_module.mjs"
|
|
import * as documents from "./module/documents/_module.mjs"
|
|
import * as applications from "./module/applications/_module.mjs"
|
|
|
|
import { handleSocketEvent } from "./module/socket.mjs"
|
|
import { configureDiceSoNice } from "./module/dice.mjs"
|
|
import { Macros } from "./module/macros.mjs"
|
|
import { initControlButtons } from "./module/control-buttons.mjs"
|
|
import { setupTextEnrichers } from "./module/enrichers.mjs"
|
|
|
|
Hooks.once("init", function () {
|
|
console.info("Lethal Fantasy RPG | Initializing System")
|
|
console.info(SYSTEM.ASCII)
|
|
|
|
globalThis.lethalFantasy = game.system
|
|
game.system.CONST = SYSTEM
|
|
|
|
// Expose the system API
|
|
game.system.api = {
|
|
applications,
|
|
models,
|
|
documents,
|
|
}
|
|
|
|
CONFIG.Actor.documentClass = documents.LethalFantasyActor
|
|
CONFIG.Actor.dataModels = {
|
|
character: models.LethalFantasyCharacter,
|
|
opponent: models.LethalFantasyOpponent,
|
|
}
|
|
|
|
CONFIG.Item.documentClass = documents.LethalFantasyItem
|
|
CONFIG.Item.dataModels = {
|
|
path: models.LethalFantasyPath,
|
|
talent: models.LethalFantasyTalent,
|
|
weapon: models.LethalFantasyWeapon,
|
|
armor: models.LethalFantasyArmor,
|
|
spell: models.LethalFantasySpell,
|
|
attack: models.LethalFantasyAttack,
|
|
}
|
|
|
|
// Register sheet application classes
|
|
Actors.unregisterSheet("core", ActorSheet)
|
|
Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true })
|
|
Actors.registerSheet("lethalFantasy", applications.LethalFantasyOpponentSheet, { types: ["opponent"], makeDefault: true })
|
|
|
|
Items.unregisterSheet("core", ItemSheet)
|
|
Items.registerSheet("lethalFantasy", applications.LethalFantasyTalentSheet, { types: ["talent"], makeDefault: true })
|
|
Items.registerSheet("lethalFantasy", applications.LethalFantasyPathSheet, { types: ["path"], makeDefault: true })
|
|
Items.registerSheet("lethalFantasy", applications.LethalFantasyWeaponSheet, { types: ["weapon"], makeDefault: true })
|
|
Items.registerSheet("lethalFantasy", applications.LethalFantasySpellSheet, { types: ["spell"], makeDefault: true })
|
|
Items.registerSheet("lethalFantasy", applications.LethalFantasyArmorSheet, { types: ["armor"], makeDefault: true })
|
|
Items.registerSheet("lethalFantasy", applications.LethalFantasyAttackSheet, { types: ["attack"], makeDefault: true })
|
|
|
|
// Other Document Configuration
|
|
CONFIG.ChatMessage.documentClass = documents.LethalFantasyChatMessage
|
|
|
|
// Dice system configuration
|
|
CONFIG.Dice.rolls.push(documents.LethalFantasyRoll)
|
|
|
|
// Register system settings
|
|
game.settings.register("lethalFantasy", "displayOpponentMalus", {
|
|
name: "TENEBRIS.Setting.displayOpponentMalus",
|
|
hint: "TENEBRIS.Setting.displayOpponentMalusHint",
|
|
scope: "world",
|
|
config: true,
|
|
type: Boolean,
|
|
default: true,
|
|
})
|
|
|
|
game.settings.register("lethalFantasy", "fortune", {
|
|
name: "TENEBRIS.Setting.fortune",
|
|
hint: "TENEBRIS.Setting.fortuneHint",
|
|
scope: "world",
|
|
config: true,
|
|
type: Number,
|
|
default: 0,
|
|
requiresReload: true,
|
|
})
|
|
|
|
game.settings.register("lethalFantasy", "worldKey", {
|
|
name: "Unique world key",
|
|
scope: "world",
|
|
config: false,
|
|
type: String,
|
|
default: "",
|
|
})
|
|
|
|
// Activate socket handler
|
|
game.socket.on(`system.${SYSTEM.id}`, handleSocketEvent)
|
|
|
|
// Pre-localize configuration objects
|
|
// TODO : encore d'actualité ?
|
|
// preLocalizeConfig()
|
|
|
|
initControlButtons()
|
|
|
|
setupTextEnrichers()
|
|
|
|
// Gestion des jets de dés depuis les journaux
|
|
document.addEventListener("click", (event) => {
|
|
const anchor = event.target.closest("a.ask-roll-journal")
|
|
if (!anchor) return
|
|
event.preventDefault()
|
|
event.stopPropagation()
|
|
const type = anchor.dataset.rollType
|
|
const target = anchor.dataset.rollTarget
|
|
const title = anchor.dataset.rollTitle
|
|
const avantage = anchor.dataset.rollAvantage
|
|
applications.LethalFantasyManager.askRollForAll(type, target, title, avantage)
|
|
})
|
|
|
|
console.info("CTHULHU TENEBRIS | System Initialized")
|
|
})
|
|
|
|
/**
|
|
* Perform one-time configuration of system configuration objects.
|
|
*/
|
|
function preLocalizeConfig() {
|
|
const localizeConfigObject = (obj, keys) => {
|
|
for (let o of Object.values(obj)) {
|
|
for (let k of keys) {
|
|
o[k] = game.i18n.localize(o[k])
|
|
}
|
|
}
|
|
}
|
|
|
|
// CONFIG.Dice.rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
|
|
|
// localizeConfigObject(SYSTEM.ACTION.TAG_CATEGORIES, ["label"])
|
|
// localizeConfigObject(CONFIG.Dice.rollModes, ["label"])
|
|
}
|
|
|
|
Hooks.once("ready", function () {
|
|
console.info("CTHULHU TENEBRIS | Ready")
|
|
game.system.applicationFortune = new applications.LethalFantasyFortune()
|
|
game.system.applicationFortune.render(true)
|
|
game.system.applicationManager = new applications.LethalFantasyManager()
|
|
if (game.user.isGM) {
|
|
game.system.applicationManager.render(true)
|
|
}
|
|
|
|
if (!SYSTEM.DEV_MODE) {
|
|
registerWorldCount("lethalFantasy")
|
|
}
|
|
_showUserGuide()
|
|
|
|
/**
|
|
*
|
|
*/
|
|
async function _showUserGuide() {
|
|
if (game.user.isGM) {
|
|
const newVer = game.system.version
|
|
const userGuideJournalName = "Guide du système"
|
|
const userGuideCompendiumLabel = "userguide"
|
|
|
|
let currentVer = "0"
|
|
let oldUserGuide = game.journal.getName(userGuideJournalName)
|
|
if (oldUserGuide !== undefined && oldUserGuide !== null && oldUserGuide.getFlag("lethalFantasy", "UserGuideVersion") !== undefined) {
|
|
currentVer = oldUserGuide.getFlag("lethalFantasy", "UserGuideVersion")
|
|
}
|
|
if (newVer === currentVer) {
|
|
// Up to date
|
|
return
|
|
}
|
|
|
|
let newReleasePack = game.packs.find((p) => p.metadata.name === userGuideCompendiumLabel)
|
|
if (newReleasePack === null || newReleasePack === undefined) {
|
|
console.info("CTHULHU TENEBRIS | No compendium found for the system guide")
|
|
return
|
|
}
|
|
await newReleasePack.getIndex()
|
|
|
|
let newUserGuide = newReleasePack.index.find((j) => j.name === userGuideJournalName)
|
|
if (newUserGuide === undefined || newUserGuide === null) {
|
|
console.info("CTHULHU TENEBRIS | No system guide found in the compendium")
|
|
return
|
|
}
|
|
|
|
// Don't delete until we have new release Pack
|
|
if (oldUserGuide !== null && oldUserGuide !== undefined) {
|
|
await oldUserGuide.delete()
|
|
}
|
|
|
|
await game.journal.importFromCompendium(newReleasePack, newUserGuide._id)
|
|
let newReleaseJournal = game.journal.getName(newUserGuide.name)
|
|
|
|
await newReleaseJournal.setFlag("lethalFantasy", "UserGuideVersion", newVer)
|
|
|
|
// Show journal
|
|
await newReleaseJournal.sheet.render(true, { sheetMode: "text" })
|
|
}
|
|
}
|
|
})
|
|
|
|
Hooks.on("renderChatMessage", (message, html, data) => {
|
|
const typeMessage = data.message.flags.lethalFantasy?.typeMessage
|
|
// Message de fortune
|
|
if (typeMessage === "fortune") {
|
|
if (game.user.isGM && !data.message.flags.lethalFantasy?.accepted) {
|
|
html.find(".button").click((event) => applications.LethalFantasyFortune.acceptRequest(event, html, data))
|
|
} else {
|
|
html.find(".button").each((i, btn) => {
|
|
btn.style.display = "none"
|
|
})
|
|
if (game.user.isGM) {
|
|
html.find(".fortune-accepted").each((i, btn) => (btn.style.display = "flex"))
|
|
}
|
|
}
|
|
}
|
|
// Message de demande de jet de dés
|
|
else if (typeMessage === "askRoll") {
|
|
// Affichage des boutons de jet de dés uniquement pour les joueurs
|
|
if (game.user.isGM) {
|
|
html.find(".ask-roll-dice").each((i, btn) => {
|
|
btn.style.display = "none"
|
|
})
|
|
} else {
|
|
html.find(".ask-roll-dice").click((event) => {
|
|
const btn = $(event.currentTarget)
|
|
const type = btn.data("type")
|
|
const value = btn.data("value")
|
|
const avantage = btn.data("avantage") ?? "="
|
|
const character = game.user.character
|
|
if (type === SYSTEM.ROLL_TYPE.RESOURCE) character.rollResource(value)
|
|
else if (type === SYSTEM.ROLL_TYPE.SAVE) character.rollSave(value, avantage)
|
|
})
|
|
}
|
|
}
|
|
})
|
|
|
|
Hooks.on("updateSetting", async (setting, update, options, id) => {
|
|
if (setting.key === "lethalFantasy.fortune") {
|
|
game.system.applicationFortune.render(true)
|
|
}
|
|
})
|
|
|
|
// Dice-so-nice Ready
|
|
Hooks.once("diceSoNiceReady", (dice3d) => {
|
|
configureDiceSoNice(dice3d)
|
|
})
|
|
|
|
/**
|
|
* Create a macro when dropping an entity on the hotbar
|
|
* Item - open roll dialog
|
|
* Actor - open actor sheet
|
|
* Journal - open journal sheet
|
|
*/
|
|
Hooks.on("hotbarDrop", (bar, data, slot) => {
|
|
if (["Actor", "Item", "JournalEntry", "roll", "rollDamage", "rollAttack"].includes(data.type)) {
|
|
Macros.createLethalFantasyMacro(data, slot)
|
|
return false
|
|
}
|
|
})
|
|
|
|
/**
|
|
* Register world usage statistics
|
|
* @param {string} registerKey
|
|
*/
|
|
function registerWorldCount(registerKey) {
|
|
if (game.user.isGM) {
|
|
let worldKey = game.settings.get(registerKey, "worldKey")
|
|
if (worldKey === undefined || worldKey === "") {
|
|
worldKey = foundry.utils.randomID(32)
|
|
game.settings.set(registerKey, "worldKey", worldKey)
|
|
}
|
|
|
|
// Simple API counter
|
|
const worldData = {
|
|
register_key: registerKey,
|
|
world_key: worldKey,
|
|
foundry_version: `${game.release.generation}.${game.release.build}`,
|
|
system_name: game.system.id,
|
|
system_version: game.system.version,
|
|
}
|
|
|
|
let apiURL = "https://worlds.qawstats.info/worlds-counter"
|
|
$.ajax({
|
|
url: apiURL,
|
|
type: "POST",
|
|
data: JSON.stringify(worldData),
|
|
contentType: "application/json; charset=utf-8",
|
|
dataType: "json",
|
|
async: false,
|
|
})
|
|
}
|
|
}
|