Add Document class changes to make the Token bars work with my attributes object
This commit is contained in:
parent
ae525ce1b8
commit
959f75d55c
2 changed files with 139 additions and 0 deletions
28
module/documents/Actor.mjs
Normal file
28
module/documents/Actor.mjs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { Logger } from "../utils/Logger.mjs";
|
||||
|
||||
const { Actor } = foundry.documents;
|
||||
|
||||
export class TAFActor extends Actor {
|
||||
async modifyTokenAttribute(attribute, value, isDelta = false, isBar = true) {
|
||||
Logger.table({ attribute, value, isDelta, isBar });
|
||||
const attr = foundry.utils.getProperty(this.system, attribute);
|
||||
const current = isBar ? attr.value : attr;
|
||||
const update = isDelta ? current + value : value;
|
||||
if ( update === current ) {
|
||||
return this;
|
||||
};
|
||||
|
||||
// Determine the updates to make to the actor data
|
||||
let updates;
|
||||
if (isBar) {
|
||||
updates = {[`system.${attribute}.value`]: Math.clamp(update, 0, attr.max)};
|
||||
} else {
|
||||
updates = {[`system.${attribute}`]: update};
|
||||
};
|
||||
|
||||
// Allow a hook to override these changes
|
||||
const allowed = Hooks.call(`modifyTokenAttribute`, {attribute, value, isDelta, isBar}, updates, this);
|
||||
|
||||
return allowed !== false ? this.update(updates) : this;
|
||||
}
|
||||
};
|
||||
111
module/documents/Token.mjs
Normal file
111
module/documents/Token.mjs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
import { Logger } from "../utils/Logger.mjs";
|
||||
|
||||
const { TokenDocument } = foundry.documents;
|
||||
const { getProperty, getType, hasProperty, isSubclass } = foundry.utils;
|
||||
|
||||
export class TAFTokenDocument extends TokenDocument {
|
||||
|
||||
/**
|
||||
* @override
|
||||
* This override's purpose is to make it so that Token attributes and bars can
|
||||
* be accessed from the data model's values directly instead of relying on only
|
||||
* the schema, which doesn't account for my TypedObjectField of attributes.
|
||||
*/
|
||||
static getTrackedAttributes(data, _path = []) {
|
||||
|
||||
// Case 1 - Infer attributes from schema structure.
|
||||
if ( (data instanceof foundry.abstract.DataModel) || isSubclass(data, foundry.abstract.DataModel) ) {
|
||||
return this._getTrackedAttributesFromObject(data, _path);
|
||||
}
|
||||
if ( data instanceof foundry.data.fields.SchemaField ) {
|
||||
return this._getTrackedAttributesFromSchema(data, _path);
|
||||
}
|
||||
|
||||
// Case 2 - Infer attributes from object structure.
|
||||
if ( [`Object`, `Array`].includes(getType(data)) ) {
|
||||
return this._getTrackedAttributesFromObject(data, _path);
|
||||
}
|
||||
|
||||
// Case 3 - Retrieve explicitly configured attributes.
|
||||
if ( !data || (typeof data === `string`) ) {
|
||||
const config = this._getConfiguredTrackedAttributes(data);
|
||||
if ( config ) {
|
||||
return config;
|
||||
}
|
||||
data = undefined;
|
||||
}
|
||||
|
||||
// Track the path and record found attributes
|
||||
if ( data !== undefined ) {
|
||||
return {bar: [], value: []};
|
||||
}
|
||||
|
||||
// Case 4 - Infer attributes from system template.
|
||||
const bar = new Set();
|
||||
const value = new Set();
|
||||
for ( const [type, model] of Object.entries(game.model.Actor) ) {
|
||||
const dataModel = CONFIG.Actor.dataModels?.[type];
|
||||
const inner = this.getTrackedAttributes(dataModel ?? model, _path);
|
||||
inner.bar.forEach(attr => bar.add(attr.join(`.`)));
|
||||
inner.value.forEach(attr => value.add(attr.join(`.`)));
|
||||
}
|
||||
|
||||
return {
|
||||
bar: Array.from(bar).map(attr => attr.split(`.`)),
|
||||
value: Array.from(value).map(attr => attr.split(`.`)),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getBarAttribute(barName, {alternative} = {}) {
|
||||
const attribute = alternative || this[barName]?.attribute;
|
||||
Logger.log(barName, attribute);
|
||||
if (!attribute || !this.actor) {
|
||||
return null;
|
||||
};
|
||||
const system = this.actor.system;
|
||||
|
||||
// Get the current attribute value
|
||||
const data = getProperty(system, attribute);
|
||||
if (data == null) {
|
||||
return null;
|
||||
};
|
||||
|
||||
if (Number.isNumeric(data)) {
|
||||
let editable = hasProperty(system, attribute);
|
||||
return {
|
||||
type: `value`,
|
||||
attribute,
|
||||
value: Number(data),
|
||||
editable,
|
||||
};
|
||||
};
|
||||
|
||||
if (`value` in data && `max` in data) {
|
||||
let editable = hasProperty(system, `${attribute}.value`);
|
||||
const isRange = getProperty(system, `${attribute}.isRange`);
|
||||
if (isRange) {
|
||||
return {
|
||||
type: `bar`,
|
||||
attribute,
|
||||
value: parseInt(data.value || 0),
|
||||
max: parseInt(data.max || 0),
|
||||
editable,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: `value`,
|
||||
attribute: `${attribute}.value`,
|
||||
value: Number(data.value),
|
||||
editable,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Otherwise null
|
||||
return null;
|
||||
};
|
||||
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue