From 7d7ec478e5f8e9a9d0bb14c640401087128f23f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Guillois?= Date: Mon, 5 Jun 2023 15:27:58 +0200 Subject: [PATCH] protections --- module/documents/character.mjs | 89 ------------ module/documents/creature.mjs | 76 ---------- module/documents/npc.mjs | 76 ---------- module/sheets/actor-sheet.mjs | 142 ++++++++++++++++++- module/sheets/item-sheet.mjs | 2 +- module/system/handlebars-manager.mjs | 2 + module/totem.mjs | 7 +- system.json | 2 +- templates/actor/actor-character-sheet.html | 2 +- templates/actor/parts/actor-defenses.hbs | 29 ++++ templates/actor/parts/actor-id.hbs | 23 --- templates/actor/parts/actor-items.html | 16 +-- templates/actor/parts/actor-weapons.hbs | 21 +++ templates/actor/parts/character-features.hbs | 3 +- templates/actor/parts/character-header.hbs | 1 - templates/item/item-weapon-sheet.html | 1 - 16 files changed, 207 insertions(+), 285 deletions(-) delete mode 100644 module/documents/character.mjs delete mode 100644 module/documents/creature.mjs delete mode 100644 module/documents/npc.mjs create mode 100644 templates/actor/parts/actor-defenses.hbs create mode 100644 templates/actor/parts/actor-weapons.hbs diff --git a/module/documents/character.mjs b/module/documents/character.mjs deleted file mode 100644 index 82877dc..0000000 --- a/module/documents/character.mjs +++ /dev/null @@ -1,89 +0,0 @@ -import { TotemActor } from "./actor.mjs"; -/** - * @extends {TotemActor} - */ -export class TotemCharacter extends TotemActor { - - /** @override */ - prepareData() { - // Prepare data for the actor. Calling the super version of this executes - // the following, in order: data reset (to clear active effects), - // prepareBaseData(), prepareEmbeddedDocuments() (including active effects), - // prepareDerivedData(). - super.prepareData(); - } - - /** @override */ - prepareBaseData() { - // Data modifications in this step occur before processing embedded - // documents or derived data. - } - - /** - * @override - * Augment the basic actor data with additional dynamic data. Typically, - * you'll want to handle most of your calculated/derived data in this step. - * Data calculated in this step should generally not exist in template.json - * (such as ability modifiers rather than ability scores) and should be - * available both inside and outside of character sheets (such as if an actor - * is queried and has a roll executed directly from it). - */ - prepareDerivedData() { - const actorData = this; - const systemData = actorData.system; - const flags = actorData.flags.totem || {}; - - // Make separate methods for each Actor type (character, npc, etc.) to keep - // things organized. - this._prepareCharacterData(actorData); - } - - /** - * Prepare Character type specific data - */ - _prepareCharacterData(actorData) { - if (actorData.type !== 'character') return; - - // Make modifications to data here. For example: - const systemData = actorData.system; - - // Loop through ability scores, and add their modifiers to our sheet output. - for (let [key, ability] of Object.entries(systemData.abilities)) { - // Calculate the modifier using d20 rules. - ability.mod = Math.floor((ability.value - 10) / 2); - } - } - - /** - * Override getRollData() that's supplied to rolls. - */ - getRollData() { - const data = super.getRollData(); - - // Prepare character roll data. - this._getCharacterRollData(data); - - return data; - } - - /** - * Prepare character roll data. - */ - _getCharacterRollData(data) { - if (this.type !== 'character') return; - - // Copy the ability scores to the top level, so that rolls can use - // formulas like `@str.mod + 4`. - if (data.abilities) { - for (let [k, v] of Object.entries(data.abilities)) { - data[k] = foundry.utils.deepClone(v); - } - } - - // Add level for easier access, or fall back to 0. - if (data.attributes.level) { - data.lvl = data.attributes.level.value ?? 0; - } - } - -} \ No newline at end of file diff --git a/module/documents/creature.mjs b/module/documents/creature.mjs deleted file mode 100644 index 383a6b9..0000000 --- a/module/documents/creature.mjs +++ /dev/null @@ -1,76 +0,0 @@ -import { TotemActor } from "./actor.mjs"; -/** - * Extend the base Actor document by defining a custom roll data structure which is ideal for the Simple system. - * @extends {TotemActor} - */ -export class TotemCreature extends TotemActor { - - /** @override */ - prepareData() { - // Prepare data for the actor. Calling the super version of this executes - // the following, in order: data reset (to clear active effects), - // prepareBaseData(), prepareEmbeddedDocuments() (including active effects), - // prepareDerivedData(). - super.prepareData(); - } - - /** @override */ - prepareBaseData() { - // Data modifications in this step occur before processing embedded - // documents or derived data. - } - - /** - * @override - * Augment the basic actor data with additional dynamic data. Typically, - * you'll want to handle most of your calculated/derived data in this step. - * Data calculated in this step should generally not exist in template.json - * (such as ability modifiers rather than ability scores) and should be - * available both inside and outside of character sheets (such as if an actor - * is queried and has a roll executed directly from it). - */ - prepareDerivedData() { - const actorData = this; - const systemData = actorData.system; - const flags = actorData.flags.totem || {}; - - // Make separate methods for each Actor type (character, npc, etc.) to keep - // things organized. - this._prepareNpcData(actorData); - } - - - - /** - * Prepare NPC type specific data. - */ - _prepareNpcData(actorData) { - if (actorData.type !== 'npc') return; - - // Make modifications to data here. For example: - const systemData = actorData.system; - systemData.xp = (systemData.cr * systemData.cr) * 100; - } - - /** - * Override getRollData() that's supplied to rolls. - */ - getRollData() { - const data = super.getRollData(); - - // Prepare character roll data. - this._getNpcRollData(data); - - return data; - } - - /** - * Prepare NPC roll data. - */ - _getNpcRollData(data) { - if (this.type !== 'creature') return; - - // Process additional NPC data here. - } - -} \ No newline at end of file diff --git a/module/documents/npc.mjs b/module/documents/npc.mjs deleted file mode 100644 index ae5f97c..0000000 --- a/module/documents/npc.mjs +++ /dev/null @@ -1,76 +0,0 @@ -import { TotemActor } from "./actor.mjs"; -/** - * Extend the base Actor document by defining a custom roll data structure which is ideal for the Simple system. - * @extends {TotemActor} - */ -export class TotemNpc extends TotemActor { - - /** @override */ - prepareData() { - // Prepare data for the actor. Calling the super version of this executes - // the following, in order: data reset (to clear active effects), - // prepareBaseData(), prepareEmbeddedDocuments() (including active effects), - // prepareDerivedData(). - super.prepareData(); - } - - /** @override */ - prepareBaseData() { - // Data modifications in this step occur before processing embedded - // documents or derived data. - } - - /** - * @override - * Augment the basic actor data with additional dynamic data. Typically, - * you'll want to handle most of your calculated/derived data in this step. - * Data calculated in this step should generally not exist in template.json - * (such as ability modifiers rather than ability scores) and should be - * available both inside and outside of character sheets (such as if an actor - * is queried and has a roll executed directly from it). - */ - prepareDerivedData() { - const actorData = this; - const systemData = actorData.system; - const flags = actorData.flags.totem || {}; - - // Make separate methods for each Actor type (character, npc, etc.) to keep - // things organized. - this._prepareNpcData(actorData); - } - - - - /** - * Prepare NPC type specific data. - */ - _prepareNpcData(actorData) { - if (actorData.type !== 'npc') return; - - // Make modifications to data here. For example: - const systemData = actorData.system; - systemData.xp = (systemData.cr * systemData.cr) * 100; - } - - /** - * Override getRollData() that's supplied to rolls. - */ - getRollData() { - const data = super.getRollData(); - - // Prepare character roll data. - this._getNpcRollData(data); - - return data; - } - - /** - * Prepare NPC roll data. - */ - _getNpcRollData(data) { - if (this.type !== 'npc') return; - - // Process additional NPC data here. - } - -} \ No newline at end of file diff --git a/module/sheets/actor-sheet.mjs b/module/sheets/actor-sheet.mjs index 4979aa6..a743889 100644 --- a/module/sheets/actor-sheet.mjs +++ b/module/sheets/actor-sheet.mjs @@ -42,7 +42,7 @@ export class TotemActorSheet extends ActorSheet { // Prepare character data and items. if (actorData.type == 'character') { - this._prepareItems(context); + this._prepareCharacterItems(context); } // Prepare NPC data and items. @@ -59,5 +59,145 @@ export class TotemActorSheet extends ActorSheet { return context; } + /** @override */ + activateListeners(html) { + super.activateListeners(html); + // Render the item sheet for viewing/editing prior to the editable check. + html.find('.item-edit').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + const item = this.actor.items.get(li.data("itemId")); + item.sheet.render(true); + }); + + // ------------------------------------------------------------- + // Everything below here is only needed if the sheet is editable + if (!this.isEditable) return; + + // Add Inventory Item + html.find('.item-create').click(this._onItemCreate.bind(this)); + + // Delete Inventory Item + html.find('.item-delete').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + const item = this.actor.items.get(li.data("itemId")); + item.delete(); + li.slideUp(200, () => this.render(false)); + }); + + // Active Effect management + html.find(".effect-control").click(ev => onManageActiveEffect(ev, this.actor)); + + + // Drag events for macros. + if (this.actor.isOwner) { + let handler = ev => this._onDragStart(ev); + html.find('li.item').each((i, li) => { + if (li.classList.contains("inventory-header")) return; + li.setAttribute("draggable", true); + li.addEventListener("dragstart", handler, false); + }); + } + + } + + + /** + * Organize and classify Items for Character sheets. + * + * @param {Object} actorData The actor to prepare. + * + * @return {undefined} + */ + _prepareCharacterItems(context) { + // Initialize containers. + const gear = []; + const traits = []; + const defenses = []; + const specialties = []; + const abilities = []; + const weapons = []; + const evolutions = []; + const traumas = []; + const backgrounds = []; + const rumors = []; + + // Iterate through items, allocating to containers + for (let i of context.items) { + i.img = i.img || DEFAULT_TOKEN; + // Append to gear. + if (i.type === 'item') { + gear.push(i); + } + else if (i.type === 'trait') { + traits.push(i); + } + else if (i.type === 'defense') { + defenses.push(i); + } + else if (i.type === 'weapon') { + weapons.push(i); + } + else if (i.type === 'specialty') { + specialties.push(i); + } + else if (i.type === 'ability') { + abilities.push(i); + } + else if (i.type === 'evolution') { + evolutions.push(i); + } + else if (i.type === 'trauma') { + traumas.push(i); + } + else if (i.type === 'background') { + backgrounds.push(i); + } + else if (i.type === 'rumor') { + rumors.push(i); + } + /* // Append to cephalie. + else if (i.type === 'spell') { + if (i.system.spellLevel != undefined) { + cephalie[i.system.spellLevel].push(i); + } + }*/ + } + + // Assign and return + context.gear = gear; + context.weapons = weapons; + context.defenses = defenses; + context.traits = traits; + context.specialties = specialties; + context.abilities = abilities; + context.evolutions = evolutions; + context.traumas = traumas; + context.backgrounds = backgrounds; + context.rumors = rumors; + console.log("context", context); + } + + + async _onItemCreate(event) { + event.preventDefault(); + const header = event.currentTarget; + // Get the type of item to create. + const type = header.dataset.type; + // Grab any data associated with this control. + const data = duplicate(header.dataset); + // Initialize a default name. + const name = `New ${type.capitalize()}`; + // Prepare the item object. + const itemData = { + name: name, + type: type, + system: data + }; + // Remove the type from the dataset since it's in the itemData.type prop. + delete itemData.system["type"]; + + // Finally, create the item! + return await Item.create(itemData, {parent: this.actor}); + } } diff --git a/module/sheets/item-sheet.mjs b/module/sheets/item-sheet.mjs index d6a3cfc..829d7eb 100644 --- a/module/sheets/item-sheet.mjs +++ b/module/sheets/item-sheet.mjs @@ -34,7 +34,7 @@ export class TotemItemSheet extends ItemSheet { // Use a safe clone of the item data for further operations. const itemData = context.item; - + // Retrieve the roll data for TinyMCE editors. context.rollData = {}; let actor = this.object?.parent ?? null; diff --git a/module/system/handlebars-manager.mjs b/module/system/handlebars-manager.mjs index a4c935b..db0781e 100644 --- a/module/system/handlebars-manager.mjs +++ b/module/system/handlebars-manager.mjs @@ -16,6 +16,8 @@ "systems/totem/templates/actor/parts/character-features.hbs", "systems/totem/templates/actor/parts/character-header.hbs", "systems/totem/templates/actor/parts/actor-items.html", + "systems/totem/templates/actor/parts/actor-weapons.hbs", + "systems/totem/templates/actor/parts/actor-defenses.hbs", "systems/totem/templates/actor/parts/actor-effects.html", // additional templates diff --git a/module/totem.mjs b/module/totem.mjs index a22e478..66d6002 100644 --- a/module/totem.mjs +++ b/module/totem.mjs @@ -3,9 +3,6 @@ import { registerSettings } from "./system/settings.mjs"; // Import document classes. import { TotemActor } from "./documents/actor.mjs"; -import { TotemCharacter } from "./documents/character.mjs"; -import { TotemNpc } from "./documents/npc.mjs"; -import { TotemCreature } from "./documents/creature.mjs"; import { TotemCharacterSheet } from "./sheets/character-sheet.mjs"; import { TotemNpcSheet } from "./sheets/npc-sheet.mjs"; @@ -30,9 +27,7 @@ Hooks.once('init', async function() { // Add utility classes to the global game object so that they're more easily // accessible in global contexts. game.totem = { - TotemCharacter, - TotemNpc, - TotemCreature, + TotemActor, TotemItem, TotemRoll, TotemCombat diff --git a/system.json b/system.json index 75b6e42..20d6338 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "totem", "title": "Totem", "description": "The Totem system for FoundryVTT!", - "version": "0.0.9", + "version": "0.0.10", "compatibility": { "minimum": 10, "verified": "10.287", diff --git a/templates/actor/actor-character-sheet.html b/templates/actor/actor-character-sheet.html index 54cf791..57979ae 100644 --- a/templates/actor/actor-character-sheet.html +++ b/templates/actor/actor-character-sheet.html @@ -17,7 +17,7 @@ - + diff --git a/templates/actor/parts/actor-defenses.hbs b/templates/actor/parts/actor-defenses.hbs new file mode 100644 index 0000000..e423af2 --- /dev/null +++ b/templates/actor/parts/actor-defenses.hbs @@ -0,0 +1,29 @@ +
    +
  1. +
    {{ localize 'IDENTITY.name'}}
    +
    {{ localize 'TOTEM.clew'}}
    +
    {{ localize 'TOTEM.mobility'}}
    +
    {{ localize 'TOTEM.rarity'}}
    +
    {{ localize 'TOTEM.reliability'}}
    +
    +
  2. + {{#each defenses as |item id|}} +
  3. +
    +
    + +
    + {{item.name}} +
    +

    {{item.system.level}}

    +

    {{item.system.mobility}}

    +

    {{item.system.rarity}}

    +

    {{item.system.reliability}}

    +
    + +
    +
  4. + {{/each}} +
\ No newline at end of file diff --git a/templates/actor/parts/actor-id.hbs b/templates/actor/parts/actor-id.hbs index 6faeab6..3c1f01b 100644 --- a/templates/actor/parts/actor-id.hbs +++ b/templates/actor/parts/actor-id.hbs @@ -2,29 +2,6 @@