From 5ddd9db9b3ed280161af6e89be0fc3e2c421f7c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Guillois?= Date: Thu, 20 Apr 2023 15:12:05 +0200 Subject: [PATCH] first data modeling --- assets/images/totem-logo.jpg | Bin 0 -> 77706 bytes module/system/config.mjs | 66 ++++++ module/system/dialogs.mjs | 71 ++++++ module/system/effects.mjs | 63 ++++++ module/system/fight.mjs | 424 +++++++++++++++++++++++++++++++++++ module/system/functions.mjs | 109 +++++++++ module/system/helpers.mjs | 25 +++ module/system/hooks.mjs | 105 +++++++++ module/system/roll.js | 284 +++++++++++++++++++++++ module/system/settings.mjs | 29 +++ module/system/templates.mjs | 17 ++ template.json | 399 +++++++++++++++++++++++++++++--- 12 files changed, 1567 insertions(+), 25 deletions(-) create mode 100644 assets/images/totem-logo.jpg create mode 100644 module/system/config.mjs create mode 100644 module/system/dialogs.mjs create mode 100644 module/system/effects.mjs create mode 100644 module/system/fight.mjs create mode 100644 module/system/functions.mjs create mode 100644 module/system/helpers.mjs create mode 100644 module/system/hooks.mjs create mode 100644 module/system/roll.js create mode 100644 module/system/settings.mjs create mode 100644 module/system/templates.mjs diff --git a/assets/images/totem-logo.jpg b/assets/images/totem-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a57027534b69e28c44d40f1366cbdf300c2e66f3 GIT binary patch literal 77706 zcmc$_dpJ~W7%x1c=M zCC*t-&qC;c&{h^-A+_s@Ss)*h6ogGHxFBdmi>3&QifCVb7hh$KNkc8ZGoh z$lrJ1uBzfxuvgY?*syNi-T!sf1?+9g|NHs-|9L$QH#dm8gj4$e`)lqMPIn>h{k#jx zO3QHbbd{8KmF5IW_i;F-`TuKZ|9iAJrFqIK^B1TtR8!Z`!Oc@rR-UJ#Jb%6lW~ov< z_CK78?tHza>)jUU?>VBn?3BTVi<$QpT5f&TXt=inTyA&tbb^|?k?|rE(-kYNR;^xR z@8IaPag($AHjnL|JG}ncxBtLF-$Q=>!N)?5hlYhmoQaM(8%sZTKJijgGAkwZ^0ln% zH?nhX-nxCi;6dTTqT)x7pO;ruR#m@vS<}Q9G`FEO5%=G`V=>K7lE@sa>6%}O_)xY*A&5QkOtgg!ZrRx{yx$RLs za!P;MhKmagwr1XY)~IG_w-+=#db&g1Xt}+31@zaX|7p?xok0ozuPpjM2K^s<<_2(@ z%1YRRDeL0MI22uV|1$3X{!v#TjTOAN6mc49X=D?|HdUEw6D2u+6P))1XCcn<2JuPL zRHKN0gCq5pbS}qT`8Qp-v~f571L4vf4)i1R>q|o?`A~^$IY>$2N0R4Nk~Qhd%>=`k zDLuM7e-4L7+@bO2*_NV$PYf;iG>ze5R4))d$EVluoUzHhSc0sjd-QpQ&l&*4O+q!mwl>*B>)z#edtmE2&C7=Xr!yfFJt z1plC=lZ}t;V1z+4$#vd^^fG_RxBg|9KR>;^Fah8?U5W`uJj7JZ@fqjH@L1CysSn3y zOheu!PghJ$+B&-wgq>u)WmLr+++?|FzPs)g^C*KoTju|N_^@z+T%@gy)PyYh)zvpTua+A*COyI~S)s|t~C`TV(RCh{~pc~<6T^4CcDbIXgx3uuU0W;+{ z>eYNsB^fcIplW4uL&jl_h&<^b-!(!|W3Fiw^YHXH$of*4Ajz(Ka~Eb$az4#+Wv!P; z1UQTTYNySe3o*M#E8V01bq8|Wk;R4b07j7FJ|HUPEGC&Ve7p4n;6S+z{U_y;a3Rwo zY_?#uMmtBmJKv%Q@jSmm?{h`aT1X+a8D8FZZROQPrBT5t0r2rvtzBgBKVmDj-&-bt zz2q(oChQ@ekc{xpw)7x zykOA`|Md;dTPM;csQZa2^~MD<7jH3#YwYEK+wm%qgnnnBbq;5NZ2NiP*EEqehf_hV zg2L{;unen*Xe?y;v869;^`1YH+AOsC(Y_dH4CRULP_=gA!n-T-P)8sP zf9ZT19M|kbvW2P�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

uyDh;Y?hT3lEPOecs=Isg`^ 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

uPK){utOS{2Ybd@|+O@Y1 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 K@7IKX`~M4w<2&U5 literal 0 HcmV?d00001 diff --git a/module/system/config.mjs b/module/system/config.mjs new file mode 100644 index 0000000..5aebee7 --- /dev/null +++ b/module/system/config.mjs @@ -0,0 +1,66 @@ +export const TOTEM = {}; + +/** + * The set of Ability Scores used within the sytem. + * @type {Object} + */ +/* + + + +TOTEM.nations = { + "istanie1":{ + "label": "Istanie (îles du couchant)", + "cities": ["tanger", "argan", "ar'kobah", "ishandra"] + }, + "istanie2":{ + "label": "Istanie (monts dinariques)", + "cities": ["montenegro", "ishandra"] + }, + "istanie3":{ + "label": "Istanie (anatolie)", + "cities": ["ismyr", "istanbul", "ankara"] + }, + "pentapolie":{ + "label": "Pentapolie", + "cities": ["serone", "éole", "relais de l'affrevie", "relais de bragee", "géode", "théorie", "démos", "négoce", "lucé"] + }, + "venice":{ + "label": "Venice", + "cities": ["venice"] + }, + "rhodesiennes":{ + "label": "Provinces rhodesiennes", + "cities": ["alsyde", "spicule", "urbs", "les syénites"] + }, + "methalune":{ + "label": "Méthalune", + "cities": ["méthalune", "ferraille"] + }, + "gloriana":{ + "label": "Gloriana", + "cities": ["enclosure", "londres", "camelot", "hivernee"] + }, + "antipolie":{ + "label": "Antipolie", + "cities": ["paris", "ithar","candbury","abaya", "relais d'elphiel", "entrelace", "prague", "vienne"] + }, + "olmune":{ + "label": "Principautés d'Olmune", + "cities": ["entrepont", "olmune","arssens","braysine"] + }, + "lansk":{ + "label": "Lansk", + "cities": ["saint-petersbourg", "hypogée","sancre","moscou", "kiev","kryo"] + }, + "nordanie":{ + "label": "Nordanie", + "cities": ["souspente", "gottenborg","solth", "nacre", "dorvik", "mystille"] + }, + "terraincognita":{ + "label": "Terra Incognita", + "cities": ["chantier de transécryme"] + } + +} +*/ \ No newline at end of file diff --git a/module/system/dialogs.mjs b/module/system/dialogs.mjs new file mode 100644 index 0000000..39ab57c --- /dev/null +++ b/module/system/dialogs.mjs @@ -0,0 +1,71 @@ +export class WarningDialog extends Dialog { + + constructor(dialogData) { + let options = { classes: ["warning"] }; + let conf = { + title: "Avertissement", + content: dialogData.content + }; + super(conf, options); + this.dialogData = dialogData; + } + + /* -------------------------------------------- */ + activateListeners(html) { + /*super.activateListeners(html); + this.html = html; + this.setEphemere(this.dialogData.signe.system.ephemere); + html.find(".signe-aleatoire").click(event => this.setSigneAleatoire()); + html.find("[name='signe.system.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked)); + html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event)); + html.find("input.select-actor").change((event) => this.onSelectActor(event)); + html.find("input.select-tmr").change((event) => this.onSelectTmr(event));*/ + } + + + async onSelectActor(event) { + /*const actorId = this.html.find(event.currentTarget)?.data("actor-id"); + const actor = this.dialogData.actors.find(it => it.id == actorId); + if (actor) { + actor.selected = event.currentTarget.checked; + }*/ + } + + + } + + export class CombatResultDialog extends Dialog { + + constructor(dialogData, options) { + let options = { classes: ["combat", "result"], ...options }; + let conf = { + title: "Résultat de la confrontation", + content: dialogData.content + }; + super(conf, options); + this.dialogData = dialogData; + } + + /* -------------------------------------------- */ + activateListeners(html) { + /*super.activateListeners(html); + this.html = html; + this.setEphemere(this.dialogData.signe.system.ephemere); + html.find(".signe-aleatoire").click(event => this.setSigneAleatoire()); + html.find("[name='signe.system.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked)); + html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event)); + html.find("input.select-actor").change((event) => this.onSelectActor(event)); + html.find("input.select-tmr").change((event) => this.onSelectTmr(event));*/ + } + + + async onSelectActor(event) { + /*const actorId = this.html.find(event.currentTarget)?.data("actor-id"); + const actor = this.dialogData.actors.find(it => it.id == actorId); + if (actor) { + actor.selected = event.currentTarget.checked; + }*/ + } + + + } \ No newline at end of file diff --git a/module/system/effects.mjs b/module/system/effects.mjs new file mode 100644 index 0000000..8052b39 --- /dev/null +++ b/module/system/effects.mjs @@ -0,0 +1,63 @@ +/** + * Manage Active Effect instances through the Actor Sheet via effect control buttons. + * @param {MouseEvent} event The left-click event on the effect control + * @param {Actor|Item} owner The owning document which manages this effect + */ + export function onManageActiveEffect(event, owner) { + event.preventDefault(); + const a = event.currentTarget; + const li = a.closest("li"); + const effect = li.dataset.effectId ? owner.effects.get(li.dataset.effectId) : null; + switch ( a.dataset.action ) { + case "create": + return owner.createEmbeddedDocuments("ActiveEffect", [{ + label: "New Effect", + icon: "icons/svg/aura.svg", + origin: owner.uuid, + "duration.rounds": li.dataset.effectType === "temporary" ? 1 : undefined, + disabled: li.dataset.effectType === "inactive" + }]); + case "edit": + return effect.sheet.render(true); + case "delete": + return effect.delete(); + case "toggle": + return effect.update({disabled: !effect.disabled}); + } +} + +/** + * Prepare the data structure for Active Effects which are currently applied to an Actor or Item. + * @param {ActiveEffect[]} effects The array of Active Effect instances to prepare sheet data for + * @return {object} Data for rendering + */ +export function prepareActiveEffectCategories(effects) { + + // Define effect header categories + const categories = { + temporary: { + type: "temporary", + label: "Temporary Effects", + effects: [] + }, + passive: { + type: "passive", + label: "Passive Effects", + effects: [] + }, + inactive: { + type: "inactive", + label: "Inactive Effects", + effects: [] + } + }; + + // Iterate over active effects, classifying them into categories + for ( let e of effects ) { + e._getSourceName(); // Trigger a lookup for the source name + if ( e.disabled ) categories.inactive.effects.push(e); + else if ( e.isTemporary ) categories.temporary.effects.push(e); + else categories.passive.effects.push(e); + } + return categories; +} \ No newline at end of file diff --git a/module/system/fight.mjs b/module/system/fight.mjs new file mode 100644 index 0000000..6d5b2ef --- /dev/null +++ b/module/system/fight.mjs @@ -0,0 +1,424 @@ +import { TOTEM } from "./config.mjs"; +import { getActorSkillScore,updateActorSkillScore } from "./functions.mjs"; +import { CombatResultDialog } from "./dialogs.mjs"; + +export class TotemFight { + + async performTest(enemyAchievement, enemyConservation, skillKey, skill, params, actor) { + const dicePool = (params.spleen != undefined || params.purpose != undefined) ? '5' : '4'; + const r = new Roll(dicePool +`d6`); + let diceString = ''; + let dicePoolHint = ''; + let discardedRoll = false; + let bonus = 0; + let bonusText = '/+'; + let currentSkillScore = skill; + + + r.roll(); // dice are rolled + if (params.usure != undefined){ + currentSkillScore += params.usure; + bonus += params.usure; + } + + if (params.specialization != undefined){ + currentSkillScore += 2; + } + + if (params.trait != undefined){ + currentSkillScore += params.trait; + bonus += params.trait; + } + + bonusText += bonus; + + let targetText = game.i18n.format('TOTEM.Selected') + ' : ' + game.i18n.format(skillKey) + " " + skill + bonusText; + if (params.specialization != undefined){ + targetText += " (S)"; + } + // tri par ordre croissant + r.terms[0].results.sort((a,b) => a.result - b.result ); + + if (params.purpose != undefined){ + discardedRoll = r.terms[0].results.shift(); + dicePoolHint = ' - ' + game.i18n.format('TOTEM.PurposeTrait'); + } else if (params.spleen != undefined){ + discardedRoll = r.terms[0].results.pop(); + dicePoolHint = ' - ' + game.i18n.format('TOTEM.SpleenTrait'); + } + const discardedRollText = (discardedRoll.result != undefined) ? '

' + discardedRoll.result + '
' : ""; + + for (let i = 0; i < r.terms[0].results.length; i++) { + let result = r.terms[0].results[i].result; + diceString += '
  • ' + result + '
  • '; + } + + let hintText = game.i18n.format('TOTEM.ConfrontationHint'); + + // Build a dynamic html using the variables from above. + const html = ` +
    +
    +
    +
    + ` + dicePool + `d6 ` + dicePoolHint + ` +
    +
    +
    +
    + ` + targetText + ` +
    +
    +
      ` + diceString + `
    +
    ` + discardedRollText + `
    +
    +
    +
    ` + + `

    ` + hintText + `

    + +
    +
    +
    + `; + + // Check if the dice3d module exists (Dice So Nice). If it does, post a roll in that and then + // send to chat after the roll has finished. If not just send to chat. + if (game.dice3d) { + game.dice3d.showForRoll(r).then((displayed) => { + this.sendToChat(html, r, actor); + }); + } else { + this.sendToChat(html, r, actor); + }; + + // on fait les comptes + + } + + async sendToChat(content, roll, actor) { + let conf = { + user: game.user._id, + content: content, + roll: roll, + // sound: 'sounds/dice.wav' + }; + + if (actor) + conf.speaker = ChatMessage.getSpeaker({ actor: actor }); + // Send's Chat Message to foundry, if items are missing they will appear as false or undefined and this not be rendered. + ChatMessage.create(conf).then((msg) => { + return msg; + }); + } + + static instance = null; + + static get() { + if (!TotemFight.instance) + TotemFight.instance = new TotemFight(); + return TotemFight.instance; + } + + + // data injected to char data + static previousValues = { + dicePool: 4, + skills: TOTEM.skillsList, + cskills: TOTEM.cskills, + cephalic: false, + achievementReroll: TOTEM.achievementReroll, + conservationReroll: TOTEM.conservationReroll + }; + + static rollerTemplate = 'systems/totem/templates/fight.html'; + static CombatResultTemplate = 'systems/totem/templates/fight-result.html'; + + static async chatMessageHandler(message, html, data) { + // console.log("accès au fin du fin", message._id); + + // sélection du dé actif + html.on("click", '.confrontation .die.d6', event => { + const diceResult = parseInt($(event.target).html(),10); + html.find('.confrontation .die.d6').removeClass('active'); + $(event.target).addClass('active'); + }); + + // sélection des dés d'accomplissement + html.on("click", '.confrontation .add-to-achievement', event => { + const diceResult = parseInt(html.find('.confrontation .die.d6.active').html(),10); + html.find('.confrontation .die.d6.active').removeClass('min').addClass('max'); + }); + + // sélection des dés de conservation + html.on("click", '.confrontation .add-to-conservation', event => { + const diceResult = parseInt(html.find('.confrontation .die.d6.active').html(),10); + html.find('.confrontation .die.d6.active').removeClass('max').addClass('min'); + }); + + // reset de la sélection des pools + html.on("click", '.confrontation .reset', event => { + html.find('.confrontation .die.d6') + .removeClass('max') + .removeClass('min'); + }); + + // résolution de la confrontation + html.on("click", '.confrontation .resolve', async event => { + let achievementDice = 0; + let conservationDice = 0; + let achievementBasis = 0; + let conservationBasis = 0; + html.find('.confrontation .die.d6.max').each(function(index){ + achievementDice += parseInt($(this).html(), 10); + }); + html.find('.confrontation .die.d6.min').each(function(index){ + conservationDice += parseInt($(this).html(), 10); + }); + + // saisie des résultats + achievementBasis = html.find('td.achievement-result').data('achievement-basis'); + html.find('td.achievement-result').data('achievement-value', achievementDice); + html.find('td.achievement-result').html(achievementBasis + achievementDice); + + conservationBasis = html.find('td.conservation-result').data('conservation-basis'); + html.find('td.conservation-result').data('conservation-value', conservationDice); + html.find('td.conservation-result').html(conservationBasis + conservationDice); + + // calcul des marges + const achievementMargin = achievementBasis + achievementDice - parseInt(html.find('td.adv-achievement-result').html(),10); + const conservationMargin = conservationBasis + conservationDice - parseInt(html.find('td.adv-conservation-result').html(),10); + html.find('td.achievement-margin').html(achievementMargin); + html.find('td.conservation-margin').html(conservationMargin); + + }); + + + // fin de la résolution de la confrontation + + + } + + static async chatListeners(html) { + // supprime le masquage des résultats du dé + html.off("click", ".dice-roll"); + } + + /** + * main class function + * @returns + */ + static async ui(externalData = {}) { + let actor = {}; + + // get the actor + try { + actor = game.user.character; + } catch(e){ + throw("Aucun personnage défini !"); + } + + if (actor == null && externalData.speakerId != undefined && externalData.speakerId != null){ + // on récupère le speakerId, et de là l'objet actor + actor = game.actors.get(externalData.speakerId); + TotemFight.previousValues['speakerName'] = actor.name; + TotemFight.previousValues['speakerImg'] = actor.img; + } else { + TotemFight.previousValues['speakerName'] = "Anonyme"; + } + + // get the data + let charData = (externalData) => { + let o = Object.assign({ _template: TotemFight.rollerTemplate }, {...TotemFight.previousValues, ...externalData}); + return o; + }; + let data = charData(externalData); + console.log(data); + + // render template + let html = await renderTemplate(data._template, data); + + let ui = new Dialog({ + title: game.i18n.localize("TOTEM.FightTool"), + content: html, + buttons: { + roll: { + label: game.i18n.localize('TOTEM.Roll4Fight'), + callback: (html) => { + let form = html.find('#dice-pool-form'); + if (!form[0].checkValidity()) { + throw "Invalid Data"; + } + let enemyAchievement, enemyConservation, skillKey, skill = 5, enemySkill, params = {}; + form.serializeArray().forEach(e => { + switch (e.name) { + case "skill": + case "cephalic": + if (e.value !== ''){ + skillKey = e.value; + } + break; + case "skill-score": + skill = +e.value; + break; + case "specialization": + params.specialization = true; + break; + case "usure": + params.usure = +e.value; + break; + case "trait": + params.trait = +e.value; + break; + case "purpose": + params.purpose = true; + break; + case "spleen": + params.spleen = true; + break; + case "adv-skill": + enemySkill = +e.value; + break; + case "achievement": + enemyAchievement = +e.value; + break; + case "conservation": + enemyConservation = +e.value; + break; + } + }); + // prise en compte de l'usure sur la feuille de perso + if (params.usure != undefined){ + const newSpentScore = getActorSkillScore(actor, skillKey, 'spent') + params.usure; + console.log(newSpentScore); + updateActorSkillScore(actor, skillKey, 'spent', newSpentScore); + } + + return TotemFight.get().performTest(enemyAchievement + enemySkill, enemyConservation + enemySkill, skillKey, skill, params, actor); + } + }, + cancel: { + label: game.i18n.localize('Close'), + callback: () => { } + } + }, + render: function (h) { + h.on("change", 'select[name="skill"]', event => { + const skillLabel = $(event.target).val(); + const currentSkillScore = getActorSkillScore(actor, skillLabel) - getActorSkillScore(actor, skillLabel, 'spent'); + if (parseInt(currentSkillScore,10) >= 0){ + h.find('input#skillScore').val(currentSkillScore); + } + }); + } + }, { width: 601, height: 'fit-content' }); + ui.render(true); + return ui; + } +} + +export class TotemCombat extends Combat { + _encounterCheck(){ + console.log('encounter combat object', this); + } + + async rollInitiative(ids, formula = undefined, messageOptions = {}) { + // console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions); + // Structure input data + ids = typeof ids === "string" ? [ids] : ids; + + // étape 1 : on vérifie que le combattant est un pj + /*if (ids.length == 1){ + console.log("il n'y a qu'un actor en lice"); + } else { + console.log("il faut prendre le premier pj pour lancer la confrontation"); + }*/ + const combatant = this.combatants.get(ids[0]); + let token = canvas.scene.tokens.get(combatant.tokenId); + combatant.type = game.actors.get( combatant.actorId)?.type; + combatant.disposition = token.disposition; + let enemies = []; + + let adversaries = this.combatants.filter((cbt) => { + let token = canvas.scene.tokens.get(cbt.tokenId); + let enemy = token.actor; + const isEnemy = (token.disposition == -1) ? true : false; + if (isEnemy){ + enemies.push({ + id: enemy.id, + name: enemy.name, + img: enemy.img, + achievement: parseInt(enemy.system.reroll.achievement.value) + 7, + conservation: 7 - parseInt(enemy.system.reroll.conservation.value) + }) + } + return isEnemy; + }); + + let allies = this.combatants.filter((cbt) => { + let token = canvas.scene.tokens.get(cbt.tokenId); + return (token.disposition == 1 && cbt.id != combatant.id) ? true : false; + }); + + if (combatant.type != 'character'){ + let warningDialogHTML = await renderTemplate('systems/totem/templates/dialogs/warning.html', { + warningText: "Seuls les PJs peuvent initier des confrontations. Relancer l'opération au tour du PJ actif." + }); + Dialog.prompt({ + title: "Avertissement", + content: warningDialogHTML, + label: 'Okay !', + callback: () => { + // console.log('Il a compris'); + }, + }); + } else { + // étape 2 : on envoie les infos + let fightingActor = game.actors.get(combatant.actorId); + TotemFight.ui({ + speakerId: combatant.actorId, + speakerWeapons: fightingActor.items.filter(item => item.type == 'weapon'), + speakerExperience:fightingActor.system.attributes.experience.value, + speakerEffects: token.actor.effects, + adversaries: enemies, + allies: allies + }); + } + + } + + nextRound() { + /*let combatants = this.combatants.contents + for (let c of combatants) { + let actor = game.actors.get( c.actorId ) + actor.clearRoundModifiers() + }*/ + super.nextRound(); + } + + /************************************************************************************/ + startCombat() { + /*let combatants = this.combatants.contents + for (let c of combatants) { + let actor = game.actors.get( c.actorId ) + actor.storeVitaliteCombat() + }*/ + + return super.startCombat(); + } + + /************************************************************************************/ + _onDelete() { + /*let combatants = this.combatants.contents + for (let c of combatants) { + let actor = game.actors.get(c.actorId) + actor.clearInitiative() + actor.displayRecuperation() + } + super._onDelete()*/ + } +} \ No newline at end of file diff --git a/module/system/functions.mjs b/module/system/functions.mjs new file mode 100644 index 0000000..6a7c51c --- /dev/null +++ b/module/system/functions.mjs @@ -0,0 +1,109 @@ +import { TOTEM } from './config.mjs' +/** + * renvoie le score d'une compétence d'un actor existant + * @param {TotemActor} + * @return {number||null} Data for rendering or null + */ +export function getActorSkillScore(actor, skillLabel, property = "value") { + let returnedValue = null; + + for(let i in actor.system.skills){ + for(let j in actor.system.skills[i].data){ + if (actor.system.skills[i].data[j].label == skillLabel){ + returnedValue = actor.system.skills[i].data[j][property]; + } + } + } + if (returnedValue == null){ + for(let i in actor.system.cskills.data){ + if (actor.system.cskills.data[i].label == skillLabel){ + returnedValue = actor.system.cskills.data[i][property]; + } + } + } + + return returnedValue; +} + +/** + * renvoie le type d'une compétence + * @param {TotemActor} + * @return {string||null} Data for rendering or null + */ +export function getSkillTypeFromLabel(skillLabel) { + let returnedValue = null; + + for(let i in TOTEM.skills){ + for(let j in TOTEM.skills[i].data){ + if (TOTEM.skills[i].data[j].label == skillLabel){ + returnedValue = j; + } + } + } + + return returnedValue; +} + +/** + * met à jour le score d'une compétence d'un actor existant + * @param {TotemActor} + * @return {boolean} bool + */ +export function updateActorSkillScore(selectedActor, skillLabel, property = "value", updatedValue) { + try { + let updated = false; + // on recherche le label parmi les compétences + for (let st in selectedActor.system.skills){ + for (let s in selectedActor.system.skills[st].data){ + if (selectedActor.system.skills[st].data[s].label == skillLabel){ + selectedActor.system.skills[st].data[s][property] = updatedValue; // printing the new value + const systemSkillKey = `system.skills.${st}.data.${s}.${property}`; + selectedActor.update({[systemSkillKey]:updatedValue }); // updating actor's data + updated = true; + } + } + } + + if (updated == false){ + for (let s in selectedActor.system.cskills.data){ + if (selectedActor.system.cskills.data[s].label == skillLabel){ + selectedActor.system.cskills.data[s][property] = updatedValue; // printing the new value + const systemSkillKey = `system.cskills.data.${s}.${property}`; + selectedActor.update({[systemSkillKey]:updatedValue }); // updating actor's data + updated = true; + } + } + } + + return updated; + } catch(e){ + return false; + } +} + + +/** + * réinitialise toutes les dépenses d'usure + * @param {TotemActor} + * @return {boolean} bool + */ +export function resetActorSkillUsure(selectedActor) { + try { + // on recherche les usures des compétences + for (let st in selectedActor.system.skills){ + for (let s in selectedActor.system.skills[st].data){ + const systemSkillKey = `system.skills.${st}.data.${s}.spent`; + selectedActor.update({[systemSkillKey]:0 }); // updating actor's data + } + } + + // on recherche les usures des compétences céphaliques + for (let s in selectedActor.system.cskills.data){ + const systemSkillKey = `system.cskills.data.${s}.spent`; + selectedActor.update({[systemSkillKey]:0 }); // updating actor's data + } + return true; + } catch(e){ + return false; + } +} diff --git a/module/system/helpers.mjs b/module/system/helpers.mjs new file mode 100644 index 0000000..f3fa509 --- /dev/null +++ b/module/system/helpers.mjs @@ -0,0 +1,25 @@ +export const registerHandlebarsHelpers = function () { + Handlebars.registerHelper('concat', (...args) => args.slice(0, -1).join('')); + Handlebars.registerHelper('lower', e => e.toLocaleLowerCase()); + + Handlebars.registerHelper('toLowerCase', function(str) { + return str.toLowerCase(); + }); + + // Ifis not equal + Handlebars.registerHelper('ifne', function (v1, v2, options) { + if (v1 !== v2) return options.fn(this); + else return options.inverse(this); + }); + + // if equal + Handlebars.registerHelper('ife', function (v1, v2, options) { + if (v1 === v2) return options.fn(this); + else return options.inverse(this); + }); + // if equal + Handlebars.registerHelper('ifgt', function (v1, v2, options) { + if (v1 > v2) return options.fn(this); + else return options.inverse(this); + }); +} \ No newline at end of file diff --git a/module/system/hooks.mjs b/module/system/hooks.mjs new file mode 100644 index 0000000..28292f4 --- /dev/null +++ b/module/system/hooks.mjs @@ -0,0 +1,105 @@ +import { TotemFight } from './fight.mjs'; + +export const registerHooks = function () { + /** + * Ready hook loads tables, and override's foundry's entity link functions to provide extension to pseudo entities + */ + + Hooks.once("ready", async () => { + console.info("Totem | System Initialized."); + }); + + // changement de la pause + Hooks.on("renderPause", async function () { + if ($("#pause").attr("class") !== "paused") return; + $(".paused img").attr("src", 'systems/totem/images/pause.webp'); + $(".paused img").css({ "opacity": 1}); + $("#pause.paused").css({ "display": "flex", "justify-content": "center" }); + $("#pause.paused figcaption").css({ "width": `256px`, "height": `256px` }); + $("#pause.paused figcaption").text(game.i18n.localize("TOTEM.PausedText")); + }); + + /*Hooks.on("renderPause", ((_app, html) => { + html.find("img").attr("src", "systems/bol/ui/pause2.webp") + })) + + Hooks.on('renderChatLog', (log, html, data) => BoLUtility.chatListeners(html)) + Hooks.on('renderChatMessage', (message, html, data) => BoLUtility.chatMessageHandler(message, html, data)) + */ + console.log("rendering hooks"); + Hooks.on('renderChatLog', (log, html, data) => TotemFight.chatListeners(html)); + Hooks.on('renderChatMessage', (message, html, data) => TotemFight.chatMessageHandler(message, html, data)); + + /** + * Create a macro when dropping an entity on the hotbar + * Item - open roll dialog for item + * Actor - open actor sheet + * Journal - open journal sheet + */ + Hooks.on("hotbarDrop", async (bar, data, slot) => { + // console.log(data.type); + // Create item macro if rollable item - weapon, spell, prayer, trait, or skill + + return false; + }); + + Hooks.on('getSceneControlButtons', (controls) => { + controls.find((c) => c.name === 'token').tools.push({ + name: 'Dice Roller', + title: game.i18n.localize("TOTEM.RollTool"), + icon: 'fas fa-dice-d6', + button: true, + onClick() { + TotemRoll.ui(); + } + }); + }); + + /* -------------------------------------------- */ + /* PreCreate Hooks */ + /* -------------------------------------------- */ + + Hooks.on("preCreateActor", function (actor) { + console.log('pre create actor', actor); + if (actor.img == "icons/svg/mystery-man.svg") { + // actor.updateSource({"img": `systems/totem/icons/actors/${actor.type}.webp`}); + // item.updateSource({"img": `systems/totem/icons/competence.webp`}); + } + }); + + Hooks.on("preCreateItem", function (item) { + if (item.img == "icons/svg/item-bag.svg") { + item.updateSource({"img": `systems/totem/icons/items/${item.type}.webp`}); + // item.updateSource({"img": `systems/totem/icons/competence.webp`}); + } + }); + + /* -------------------------------------------- */ + /* Combat Hooks */ + /* -------------------------------------------- */ + + /* + Hooks.on("createCombatant", function (combatant) { + if (game.user.isGM) { + let actor = combatant.actor; + + console.log('create combatant', actor); + } + });*/ + + Hooks.on("updateCombat", function () { + if (game.user.isGM) { + let combatant = (game.combat.combatant) ? game.combat.combatant.actor : ""; + + console.log('update combat', game.combat); + + /*if (combatant.type == "marker" && combatant.system.settings.general.isCounter == true) { + let step = (!combatant.system.settings.general.counting) ? -1 : combatant.system.settings.general.counting; + let newQuantity = combatant.system.pools.quantity.value + step; + combatant.update({"system.pools.quantity.value": newQuantity}); + }*/ + } + }); + + +} diff --git a/module/system/roll.js b/module/system/roll.js new file mode 100644 index 0000000..cd8e706 --- /dev/null +++ b/module/system/roll.js @@ -0,0 +1,284 @@ +import { getActorSkillScore, updateActorSkillScore } from "./functions.mjs"; + +export class TotemRoll { + async performTest(dicePool, target, trait, usingSpecialization, difficulty, skill, params, actor) { + const r = new Roll(dicePool + 'd6'); + r.roll(); + let _trait = trait || 0; + let _usingSpecialization = usingSpecialization || 0; + let _skillLabel = (params.skill != undefined) ? game.i18n.format(params.skill) : ""; + let _used = (params.usure != undefined) ? params.usure : 0; + let diceString = ''; + let total = 0; + + // affichage des valeurs + let targetText = _skillLabel + ' : ' + skill + ' (+'+ _used +')'; + if (trait) + targetText += ', '+ game.i18n.format('TOTEM.Traits') + ' : ' + _trait; + if (_usingSpecialization != 0) + targetText += ', '+ game.i18n.format('TOTEM.UsingSpecialization'); + if (difficulty) + targetText += '
    '+ game.i18n.format('TOTEM.Against') +': ' + Math.abs(difficulty); + + // affichage des jets + for (let i = 0; i < dicePool; i++) { + let result = r.terms[0].results[i].result; + if (result == 6) { + diceString += '
  • ' + result + '
  • '; + } + else if (result <= 5) { + diceString += '
  • ' + result + '
  • '; + } + else if (result >= 1) { + diceString += '
  • ' + result + '
  • '; + } + total += result; + } + + // Here we want to check if the success was exactly one (as "1 Successes" doesn't make grammatical sense). + // We create a string for the Successes. + let successText = ''; + let successMargin = 0; + + successMargin = total + skill + _trait + _usingSpecialization + _used + difficulty; + if (params.usure != undefined){ + successMargin += parseInt(params.usure,10); + } + + // console.log(total, skill, _trait, _usingSpecialization, difficulty, successMargin); + // règle de la MR qui ne peut pas dépasser la compétence + if (successMargin > skill){ + successMargin = skill; + } + + if (successMargin > target + 1) { + successText = game.i18n.localize('TOTEM.RollSuccess') + ' (' + game.i18n.localize('TOTEM.SM') + ' ' + successMargin.toString() +')'; + } else if (successMargin == target + 1) { + successText = game.i18n.localize('TOTEM.RollSuccess'); + } else if (successMargin == target) { + successText = game.i18n.localize('TOTEM.PartialSuccess'); + } else { + successText = game.i18n.localize('TOTEM.Failure'); + } + + + // Build a dynamic html using the variables from above. + const html = ` +
    +
    +
    +
    + ` + dicePool + `d6 +
    +
    +
    +
    +
    + ` + targetText + ` +
    +
    +
      ` + diceString + `
    +
    +
    +
    + Résultat +

    ` + (total + skill + _trait + _usingSpecialization + _used).toString() + `

    +
    +
    +
    ` + + `

    ` + successText + `

    +
    +
    +
    + `; + + // Check if the dice3d module exists (Dice So Nice). If it does, post a roll in that and then + // send to chat after the roll has finished. If not just send to chat. + if (game.dice3d) { + game.dice3d.showForRoll(r).then((displayed) => { + this.sendToChat(html, r, actor); + }); + } else { + this.sendToChat(html, r, actor); + }; + } + + async sendToChat(content, roll, actor) { + let conf = { + user: game.user._id, + content: content, + roll: roll, + sound: 'sounds/dice.wav' + }; + if (actor) + conf.speaker = ChatMessage.getSpeaker({ actor: actor }); + // Send's Chat Message to foundry, if items are missing they will appear as false or undefined and this not be rendered. + ChatMessage.create(conf).then((msg) => { + return msg; + }); + } + + static instance = null; + + static get() { + if (!TotemRoll.instance) + TotemRoll.instance = new TotemRoll(); + return TotemRoll.instance; + } + + // Parse XdYtZfAc || XdYsZfAc + // {size of dice pool}d{target number}(t|s)[{skill level - for trait}f][{complication range}c][D] + async parse(cmd, usingSpecialization) { + let actor = game.user.character; + if (canvas.tokens.controlled.length > 0) + actor = canvas.tokens.controlled[0].actor; + let r = cmd.match(/([2-5])d([01]?[0-9])[ts](([4-8])f)?((20|[1][5-9])c)?(D)?/); + if (r) { + //console.log(r); + let dicePool = +r[1]; + let target = +r[2]; + let trait = +r[4]; + if (!!r[7]) usingSpecialization = true; + let difficulty = +r[6]; + this.performTest(dicePool, target, trait, usingSpecialization, difficulty, actor); + } else + ui.notifications.error("Unparsable command: " + cmd); + } + + // data injected to char data + static previousValues = { + dicePool: 2 + }; + + static rollerTemplate = 'systems/totem/templates/roll.html'; + + /** + * main class function + * @returns + */ + static async ui(externalData = {}) { + let charData = (externalData) => { + return Object.assign({ _template: TotemRoll.rollerTemplate }, {...TotemRoll.previousValues, ...externalData}); + }; + + // get the actor + let actor = null; + + try { + let actor = game.user.character; + + if (canvas.tokens.controlled.length > 0) + actor = canvas.tokens.controlled[0].actor; + } catch (e) { + console.log(e); + } + + if (actor == null && externalData.speakerId != undefined && externalData.speakerId != null){ + // on récupère le speakerId, et de là l'objet actor + actor = game.actors.get(externalData.speakerId); + } + + // get the data + let data = charData(externalData); + console.log('npc2', data); + + if (actor.type != undefined){ + data.actor_type = actor.type; + if (actor.type == 'character'){ + data.skillMaxScore = getActorSkillScore(actor, data.skill); + data.skillScore = data.skillMaxScore - getActorSkillScore(actor, data.skill, 'spent'); + data.skillSpent = getActorSkillScore(actor, data.skill, 'spent'); + } else if(actor.type == 'npc'){ + + if (data.specialization == 1){ + //data.skillMaxScore = getActorSkillScore(actor, data.skill); + // data.skillScore = data.skillMaxScore; + } else { + // compétence, il faut récupérer le score du skill type + data.skillScore = data.value; + } + } + } + + // render template + let html = await renderTemplate(data._template, data); + + let ui = new Dialog({ + title: game.i18n.localize("TOTEM.RollTool"), + content: html, + buttons: { + roll: { + label: game.i18n.localize('TOTEM.RollDice'), + callback: (html) => { + let form = html.find('#dice-pool-form'); + if (!form[0].checkValidity()) { + throw "Invalid Data"; + } + let target = 0, trait, usingSpecialization, difficulty, skill = 0, params = {}; + form.serializeArray().forEach(e => { + switch (e.name) { + case "difficulty": + if (e.value != "") + difficulty = -e.value; + break; + case "skillLabel": + params.skill = e.value; + break; + case "usure": + params.usure = +e.value; + break; + case "skill": + skill = +e.value; + break; + case "trait": + trait = +e.value; + break; + case "usingSpecialization": + if (e.value && +e.value > 1) + usingSpecialization = +e.value; + break; + } + + // prise en compte de l'usure sur la feuille de perso + if (params.usure != undefined){ + updateActorSkillScore(actor, data.skill, 'spent', data.skillSpent + parseInt(params.usure,10)); + } + }); + return TotemRoll.get().performTest(data.dicePool, target, trait, usingSpecialization, difficulty, skill, params, actor); + } + }, + close: { + label: game.i18n.localize('Close'), + callback: () => { } + } + }, + render: function (h) { + h.find("#skills-radio input").change(function () { + let s = $(this).attr("data-skill"); + h.find(".trait-list .hidden").removeClass("show"); + let f = h.find(".trait-list ." + s); + f.addClass("show"); + if (f.length == 0) { + h.find(".use-trait input").attr("disabled", "disabled").prop("checked", false); + } else + h.find(".use-trait input").attr("disabled", null); + }); + } + }); + ui.render(true); + return ui; + } +} + + +Hooks.on("chatCommandsReady", function (chatCommands) { + chatCommands.registerCommand(chatCommands.createCommandFromData({ + commandKey: "/dr", + invokeOnCommand: (chatlog, messageText, chatdata) => { + TotemRoll.get().parse(messageText); + }, + shouldDisplayToChat: false, + iconClass: "fa-dice-d6", + description: "Roll Totem check" + })); +}); diff --git a/module/system/settings.mjs b/module/system/settings.mjs new file mode 100644 index 0000000..ca9dc36 --- /dev/null +++ b/module/system/settings.mjs @@ -0,0 +1,29 @@ +export const registerSettings = function () { + game.settings.register("totem", "game-level", { + name: game.i18n.localize("TOTEM.WorldSettings.GameLevel.Name"), + hint: game.i18n.localize("TOTEM.WorldSettings.GameLevel.Hint"), + scope: "system", + config: true, + type: String, + choices: { + "e": "Totem", + "c": "Céphale", + "b": "Bohème", + "a": "Amertume" + }, + default: 'e', + onChange: value => { + console.log(value); + } + }); + + game.settings.register("totem", "granting_cephalie", { + name: game.i18n.localize("TOTEM.WorldSettings.GrantingCephales.Label"), + hint: game.i18n.localize("TOTEM.WorldSettings.GrantingCephales.Description"), + scope: "system", + config: true, + type: Boolean, + default: !1 + }) + +} \ No newline at end of file diff --git a/module/system/templates.mjs b/module/system/templates.mjs new file mode 100644 index 0000000..9cf5964 --- /dev/null +++ b/module/system/templates.mjs @@ -0,0 +1,17 @@ +/** + * Define a set of template paths to pre-load + * Pre-loaded templates are compiled and cached for fast access when rendering + * @return {Promise} + */ + export const preloadHandlebarsTemplates = async function() { + return loadTemplates([ + + // Actor partials. + "systems/totem/templates/actor/parts/actor-traits.html", + "systems/totem/templates/actor/parts/actor-background.html", + "systems/totem/templates/actor/parts/actor-skills.html", + "systems/totem/templates/actor/parts/actor-items.html", + "systems/totem/templates/actor/parts/actor-cephalie.html", + "systems/totem/templates/actor/parts/actor-effects.html", + ]); +}; diff --git a/template.json b/template.json index d4d3b7e..ee318dd 100644 --- a/template.json +++ b/template.json @@ -1,19 +1,20 @@ { "Actor": { - "types": ["character", "npc"], + "types": ["character", "npc", "creature"], "templates": { "base": { - "health": { - "value": 10, + "minorWound": { + "value": 0, "min": 0, - "max": 10 + "max": 4 }, - "power": { - "value": 5, + "majorWound": { + "value": 0, "min": 0, - "max": 5 + "max": 2 }, - "biography": "" + "totem":0, + "activity": "" } }, "character": { @@ -23,30 +24,378 @@ "value": 1 } }, - "abilities": { - "str": { - "value": 10 + "AbilityCategories": { + "physical": { + "label":"TOTEM.abilityCategory.physical" }, - "dex": { - "value": 10 + "manual": { + "label":"TOTEM.abilityCategory.manual" }, - "con": { - "value": 10 + "mental": { + "label":"TOTEM.abilityCategory.mental" }, - "int": { - "value": 10 - }, - "wis": { - "value": 10 - }, - "cha": { - "value": 10 + "social": { + "label":"TOTEM.abilityCategory.social" } + }, + "abilities": { + "vig": { + "label":"TOTEM.abilities.vigor", + "value": 0, + "min": 0, + "max": 5, + "category": "physical" + }, + "vie": { + "label":"TOTEM.abilities.health", + "value": 0, + "min": 0, + "max": 5, + "category": "physical" + }, + "pre": { + "label":"TOTEM.abilities.precision", + "value": 0, + "min": 0, + "max": 5, + "category": "manual" + }, + "ref": { + "label":"TOTEM.abilities.reflexes", + "value": 0, + "min": 0, + "max": 5, + "category": "manual" + }, + "sav": { + "label":"TOTEM.abilities.knowledge", + "value": 0, + "min": 0, + "max": 5, + "category": "mental" + }, + "per": { + "label":"TOTEM.abilities.perception", + "value": 0, + "min": 0, + "max": 5, + "category": "mental" + }, + "vol": { + "label":"TOTEM.abilities.will", + "value": 0, + "min": 0, + "max": 5, + "category": "social" + }, + "emp": { + "label":"TOTEM.abilities.empathy", + "value": 0, + "min": 0, + "max": 5, + "category": "social" + } + }, + "skillCategories": { + "man": { + "label":"TOTEM.skillCategory.man" + }, + "animal": { + "label":"TOTEM.skillCategory.animal" + }, + "machine": { + "label":"TOTEM.skillCategory.machine" + }, + "weapon": { + "label":"TOTEM.skillCategory.weapon" + }, + "survival": { + "label":"TOTEM.skillCategory.survival" + }, + "earth": { + "label":"TOTEM.skillCategory.earth" + } + }, + "skills": { + "arts": { + "label":"TOTEM.skills.arts", + "value": 0, + "min": 0, + "max": 5, + "category": "man", + "rarity":1 + }, + "civilization": { + "label":"TOTEM.skills.civilization", + "value": 0, + "min": 0, + "max": 5, + "category": "man", + "rarity":2 + }, + "psychology": { + "label":"TOTEM.skills.psychology", + "value": 0, + "min": 0, + "max": 5, + "category": "man", + "rarity":1 + }, + "rumors": { + "label":"TOTEM.skills.rumors", + "value": 0, + "min": 0, + "max": 5, + "category": "man", + "rarity":0 + }, + "healing": { + "label":"TOTEM.skills.healing", + "value": 0, + "min": 0, + "max": 5, + "category": "man", + "rarity":1 + }, + "animalism": { + "label":"TOTEM.skills.animalism", + "value": 0, + "min": 0, + "max": 5, + "category": "animal", + "rarity":1 + }, + "dissection": { + "label":"TOTEM.skills.dissection", + "value": 0, + "min": 0, + "max": 5, + "category": "animal", + "rarity":2 + }, + "wildlife": { + "label":"TOTEM.skills.wildlife", + "value": 0, + "min": 0, + "max": 5, + "category": "animal", + "rarity":1 + }, + "repulsion": { + "label":"TOTEM.skills.repulsion", + "value": 0, + "min": 0, + "max": 5, + "category": "animal", + "rarity":0 + }, + "tracks": { + "label":"TOTEM.skills.tracks", + "value": 0, + "min": 0, + "max": 5, + "category": "animal", + "rarity":0 + }, + "crafting": { + "label":"TOTEM.skills.crafting", + "value": 0, + "min": 0, + "max": 5, + "category": "machine", + "rarity":2 + }, + "diy": { + "label":"TOTEM.skills.diy", + "value": 0, + "min": 0, + "max": 5, + "category": "machine", + "rarity":0 + }, + "mecanical": { + "label":"TOTEM.skills.mecanical", + "value": 0, + "min": 0, + "max": 5, + "category": "machine", + "rarity":2 + }, + "driving": { + "label":"TOTEM.skills.driving", + "value": 0, + "min": 0, + "max": 5, + "category": "machine", + "rarity":1 + }, + "technology": { + "label":"TOTEM.skills.technology", + "value": 0, + "min": 0, + "max": 5, + "category": "machine", + "rarity":2 + }, + "firearms": { + "label":"TOTEM.skills.firearms", + "value": 0, + "min": 0, + "max": 5, + "category": "weapon", + "rarity":2 + }, + "archery": { + "label":"TOTEM.skills.archery", + "value": 0, + "min": 0, + "max": 5, + "category": "weapon", + "rarity":0 + }, + "armory": { + "label":"TOTEM.skills.armory", + "value": 0, + "min": 0, + "max": 5, + "category": "weapon", + "rarity":2 + }, + "throwing": { + "label":"TOTEM.skills.throwing", + "value": 0, + "min": 0, + "max": 5, + "category": "weapon", + "rarity":0 + }, + "melee": { + "label":"TOTEM.skills.melee", + "value": 0, + "min": 0, + "max": 5, + "category": "weapon", + "rarity":0 + }, + "feed": { + "label":"TOTEM.skills.feed", + "value": 0, + "min": 0, + "max": 5, + "category": "survival", + "rarity":0 + }, + "atletics": { + "label":"TOTEM.skills.atletics", + "value": 0, + "min": 0, + "max": 5, + "category": "survival", + "rarity":0 + }, + "brawling": { + "label":"TOTEM.skills.brawling", + "value": 0, + "min": 0, + "max": 5, + "category": "survival", + "rarity":0 + }, + "stealth": { + "label":"TOTEM.skills.stealth", + "value": 0, + "min": 0, + "max": 5, + "category": "survival", + "rarity":0 + }, + "alertness": { + "label":"TOTEM.skills.alertness", + "value": 0, + "min": 0, + "max": 5, + "category": "survival", + "rarity":0 + }, + "environment": { + "label":"TOTEM.skills.environment", + "value": 0, + "min": 0, + "max": 5, + "category": "earth", + "rarity":0 + }, + "flora": { + "label":"TOTEM.skills.flora", + "value": 0, + "min": 0, + "max": 5, + "category": "earth", + "rarity":0 + }, + "road": { + "label":"TOTEM.skills.road", + "value": 0, + "min": 0, + "max": 5, + "category": "earth", + "rarity":0 + }, + "toxics": { + "label":"TOTEM.skills.toxics", + "value": 0, + "min": 0, + "max": 5, + "category": "earth", + "rarity":0 + }, + "remains": { + "label":"TOTEM.skills.remains", + "value": 0, + "min": 0, + "max": 5, + "category": "earth", + "rarity":0 + } } }, "npc": { - "templates": ["base"], - "cr": 0 + "templates": ["base"], + "age": 15, + "threat": { + "value": 1, + "min": 1, + "max": 4 + }, + "experience": { + "value": 1, + "min": 1, + "max": 4 + }, + "role": { + "value": 1, + "min": 1, + "max": 4 + } + }, + "creature": { + "templates": ["base"], + "age": 15, + "template": { + "value": 1, + "min": 1, + "max": 4 + }, + "size": { + "value": 1, + "min": 1, + "max": 4 + }, + "role": { + "value": 1, + "min": 1, + "max": 4 + } } }, "Item": {