[#25] Ensure resource attribute values are clamped between their min and max. Ensure token attribute update deltas are applied correctly to resource attributes. Draw attribute bars appropriately when attribute min is non-zero.

This commit is contained in:
fyorl 2022-01-12 21:03:22 +00:00
parent abc9e949a7
commit d799fb1c56
No known key found for this signature in database
GPG key ID: 3A4E57DAE36AC3C4
5 changed files with 72 additions and 3 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);
}
/* -------------------------------------------- */
@ -236,4 +237,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);
}
/* -------------------------------------------- */

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);

38
module/token.js Normal file
View file

@ -0,0 +1,38 @@
/**
* Extend the base TokenDocument to allow resource 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;
}
}
/* -------------------------------------------- */
/**
* 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);
}
}