Merge branch '0.6.x' into 'master'

Release 0.6.3

See merge request foundrynet/worldbuilding!23
This commit is contained in:
Kim Mantas 2022-01-13 15:52:15 +00:00
commit 5446680d9f
8 changed files with 113 additions and 20 deletions

View file

@ -11,6 +11,7 @@ export class SimpleActor extends Actor {
super.prepareDerivedData();
this.data.data.groups = this.data.data.groups || {};
this.data.data.attributes = this.data.data.attributes || {};
EntitySheetHelper.clampResourceValues(this.data.data.attributes);
}
/* -------------------------------------------- */
@ -20,6 +21,16 @@ export class SimpleActor extends Actor {
return EntitySheetHelper.createDialog.call(this, data, options);
}
/* -------------------------------------------- */
/**
* Is this Actor used as a template for other Actors?
* @type {boolean}
*/
get isTemplate() {
return !!this.getFlag("worldbuilding", "isTemplate");
}
/* -------------------------------------------- */
/* Roll Data Preparation */
/* -------------------------------------------- */
@ -236,4 +247,17 @@ export class SimpleActor extends Actor {
}
}
}
/* -------------------------------------------- */
/** @inheritdoc */
async modifyTokenAttribute(attribute, value, isDelta = false, isBar = true) {
const current = foundry.utils.getProperty(this.data.data, attribute);
if ( !isBar || !isDelta || (current?.dtype !== "Resource") ) {
return super.modifyTokenAttribute(attribute, value, isDelta, isBar);
}
const updates = {[`data.${attribute}.value`]: Math.clamped(current.value + value, current.min, current.max)};
const allowed = Hooks.call("modifyTokenAttribute", {attribute, value, isDelta, isBar}, updates);
return allowed !== false ? this.update(updates) : this;
}
}

View file

@ -587,4 +587,21 @@ export class EntitySheetHelper {
options: options
});
}
/* -------------------------------------------- */
/**
* Ensure the resource values are within the specified min and max.
* @param {object} attrs The Document's attributes.
*/
static clampResourceValues(attrs) {
const flat = foundry.utils.flattenObject(attrs);
for ( const [attr, value] of Object.entries(flat) ) {
const parts = attr.split(".");
if ( parts.pop() !== "value" ) continue;
const current = foundry.utils.getProperty(attrs, parts.join("."));
if ( current?.dtype !== "Resource" ) continue;
foundry.utils.setProperty(attrs, attr, Math.clamped(value, current.min || 0, current.max || 0));
}
}
}

View file

@ -11,6 +11,7 @@ export class SimpleItem extends Item {
super.prepareDerivedData();
this.data.data.groups = this.data.data.groups || {};
this.data.data.attributes = this.data.data.attributes || {};
EntitySheetHelper.clampResourceValues(this.data.data.attributes);
}
/* -------------------------------------------- */
@ -19,4 +20,14 @@ export class SimpleItem extends Item {
static async createDialog(data={}, options={}) {
return EntitySheetHelper.createDialog.call(this, data, options);
}
/* -------------------------------------------- */
/**
* Is this Item used as a template for other Items?
* @type {boolean}
*/
get isTemplate() {
return !!this.getFlag("worldbuilding", "isTemplate");
}
}

View file

@ -6,6 +6,7 @@
* @returns {Promise}
*/
export async function createWorldbuildingMacro(data, slot) {
if ( !data.roll || !data.label ) return false;
const command = `const roll = new Roll("${data.roll}", actor ? actor.getRollData() : {});
roll.toMessage({speaker, flavor: "${data.label}"});`;
let macro = game.macros.find(m => (m.name === data.label) && (m.command === command));

View file

@ -10,7 +10,7 @@ import { SimpleItemSheet } from "./item-sheet.js";
import { SimpleActorSheet } from "./actor-sheet.js";
import { preloadHandlebarsTemplates } from "./templates.js";
import { createWorldbuildingMacro } from "./macro.js";
import { SimpleTokenDocument } from "./simpletokendocument.js";
import { SimpleToken, SimpleTokenDocument } from "./token.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@ -40,9 +40,8 @@ Hooks.once("init", async function() {
// Define custom Document classes
CONFIG.Actor.documentClass = SimpleActor;
CONFIG.Item.documentClass = SimpleItem;
// Update TokenDocument with overrided getBarAttribute method
CONFIG.Token.documentClass = SimpleTokenDocument;
CONFIG.Token.objectClass = SimpleToken;
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet);
@ -116,7 +115,7 @@ Hooks.on("getActorDirectoryEntryContext", (html, options) => {
icon: '<i class="fas fa-stamp"></i>',
condition: li => {
const actor = game.actors.get(li.data(idAttr));
return !actor.getFlag("worldbuilding", "isTemplate");
return !actor.isTemplate;
},
callback: li => {
const actor = game.actors.get(li.data(idAttr));
@ -130,7 +129,7 @@ Hooks.on("getActorDirectoryEntryContext", (html, options) => {
icon: '<i class="fas fa-times"></i>',
condition: li => {
const actor = game.actors.get(li.data(idAttr));
return actor.getFlag("worldbuilding", "isTemplate");
return actor.isTemplate;
},
callback: li => {
const actor = game.actors.get(li.data(idAttr));
@ -150,7 +149,7 @@ Hooks.on("getItemDirectoryEntryContext", (html, options) => {
icon: '<i class="fas fa-stamp"></i>',
condition: li => {
const item = game.items.get(li.data(idAttr));
return !item.getFlag("worldbuilding", "isTemplate");
return !item.isTemplate;
},
callback: li => {
const item = game.items.get(li.data(idAttr));
@ -164,7 +163,7 @@ Hooks.on("getItemDirectoryEntryContext", (html, options) => {
icon: '<i class="fas fa-times"></i>',
condition: li => {
const item = game.items.get(li.data(idAttr));
return item.getFlag("worldbuilding", "isTemplate");
return item.isTemplate;
},
callback: li => {
const item = game.items.get(li.data(idAttr));

View file

@ -1,11 +0,0 @@
export class SimpleTokenDocument extends TokenDocument {
/** @inheritdoc */
getBarAttribute(barName, {alternative}={}) {
const attr = super.getBarAttribute(barName, {alternative});
if ( attr === null ) return null;
attr.editable = true; // Attribute always editable, super requires attr to exist in actor template
return attr;
}
}

52
module/token.js Normal file
View file

@ -0,0 +1,52 @@
/**
* Extend the base TokenDocument to support resource type attributes.
* @extends {TokenDocument}
*/
export class SimpleTokenDocument extends TokenDocument {
/** @inheritdoc */
getBarAttribute(barName, {alternative}={}) {
const data = super.getBarAttribute(barName, {alternative});
const attr = alternative || this.data[barName]?.attribute;
if ( !data || !attr || !this.actor ) return data;
const current = foundry.utils.getProperty(this.actor.data.data, attr);
if ( "min" in current ) data.min = parseInt(current.min || 0);
data.editable = true;
return data;
}
/* -------------------------------------------- */
static getTrackedAttributes(data, _path=[]) {
if ( data || _path.length ) return super.getTrackedAttributes(data, _path);
data = {};
for ( const model of Object.values(game.system.model.Actor) ) {
foundry.utils.mergeObject(data, model);
}
for ( const actor of game.actors ) {
if ( actor.isTemplate ) foundry.utils.mergeObject(data, actor.toObject().data);
}
return super.getTrackedAttributes(data);
}
}
/* -------------------------------------------- */
/**
* Extend the base Token class to implement additional system-specific logic.
* @extends {Token}
*/
export class SimpleToken extends Token {
_drawBar(number, bar, data) {
if ( "min" in data ) {
// Copy the data to avoid mutating what the caller gave us.
data = {...data};
// Shift the value and max by the min to ensure that the bar's percentage is drawn accurately if this resource has
// a non-zero min.
data.value -= data.min;
data.max -= data.min;
}
return super._drawBar(number, bar, data);
}
}

View file

@ -2,7 +2,7 @@
"name": "worldbuilding",
"title": "Simple World-Building",
"description": "A minimalist game system which provides configurable Actor and Item templates to support free-form system agnostic game-play.",
"version": "0.6.2",
"version": "0.6.3",
"minimumCoreVersion": "0.8.9",
"compatibleCoreVersion": "9",
"author": "Atropos",
@ -22,6 +22,6 @@
"secondaryTokenAttribute": "power",
"url": "https://gitlab.com/foundrynet/worldbuilding/",
"manifest": "https://gitlab.com/foundrynet/worldbuilding/raw/0.6.x/system.json",
"download": "https://gitlab.com/foundrynet/worldbuilding/-/archive/release-062/worldbuilding-release-062.zip",
"download": "https://gitlab.com/foundrynet/worldbuilding/-/archive/release-063/worldbuilding-release-063.zip",
"license": "LICENSE.txt"
}