mirror of
https://github.com/RoY7x/worldbuilding.git
synced 2025-04-30 02:31:41 -04:00
Tidy the worldbuilding system for 0.40 release
This commit is contained in:
parent
d641ff96b0
commit
6bf056b3d4
9 changed files with 72 additions and 184 deletions
|
@ -24,11 +24,7 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
/** @override */
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
|
||||
// Handle attribute groups.
|
||||
EntitySheetHelper.getAttributeData(data);
|
||||
|
||||
// Add shorthand.
|
||||
data.shorthand = !!game.settings.get("worldbuilding", "macroShorthand");
|
||||
return data;
|
||||
}
|
||||
|
@ -39,15 +35,13 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Handle rollable items.
|
||||
html.find(".items .rollable").on("click", this._onItemRoll.bind(this));
|
||||
|
||||
// Handle rollable attributes.
|
||||
html.find(".attributes").on("click", "a.attribute-roll", EntitySheetHelper.onAttributeRoll.bind(this));
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if ( !this.options.editable ) return;
|
||||
|
||||
// Handle rollable items and attributes
|
||||
html.find(".items .rollable").on("click", this._onItemRoll.bind(this));
|
||||
html.find(".attributes").on("click", "a.attribute-roll", EntitySheetHelper.onAttributeRoll.bind(this));
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
|
@ -80,36 +74,6 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async _onSubmit(event, {updateData=null, preventClose=false, preventRender=false}={}) {
|
||||
let attr = EntitySheetHelper.onSubmit(event);
|
||||
|
||||
// Submit the form if attr is true or an attr key.
|
||||
if ( attr ) {
|
||||
await super._onSubmit(event, {updateData: updateData, preventClose: preventClose, preventRender: preventRender});
|
||||
|
||||
// If attr is a key and not just true, set a very short timeout and retrigger focus after the original element is deleted and the new one is inserted.
|
||||
if ( attr !== true) {
|
||||
setTimeout(() => {
|
||||
$(`input[name="${attr}"]`).parents('.attribute').find('.attribute-value').focus();
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
setPosition(options={}) {
|
||||
const position = super.setPosition(options);
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - 192;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Listen for roll buttons on items.
|
||||
* @param {MouseEvent} event The originating left click event
|
||||
|
@ -126,14 +90,12 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
|
||||
// Handle attribute and group updates.
|
||||
formData = EntitySheetHelper.updateAttributes(formData, this);
|
||||
formData = EntitySheetHelper.updateGroups(formData, this);
|
||||
|
||||
// Update the Actor with the new form values.
|
||||
return this.object.update(formData);
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ export class EntitySheetHelper {
|
|||
const label = button.closest(".attribute").querySelector(".attribute-label")?.value;
|
||||
const chatLabel = label ?? button.parentElement.querySelector(".attribute-key").value;
|
||||
const shorthand = game.settings.get("worldbuilding", "macroShorthand");
|
||||
const rollData = this.actor.getRollData();
|
||||
const rollData = this.object.getRollData();
|
||||
let formula = button.closest(".attribute").querySelector(".attribute-value")?.value;
|
||||
|
||||
// If there's a formula, attempt to roll it.
|
||||
|
@ -527,18 +527,14 @@ export class EntitySheetHelper {
|
|||
if ( typeof formula != "string" || depth < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Replace attributes with their numeric equivalents.
|
||||
let dataRgx = new RegExp(/@([a-z.0-9_\-]+)/gi);
|
||||
let rollFormula = formula.replace(dataRgx, (match, term) => {
|
||||
// Replace matches with the value, or the missing value.
|
||||
let value = getProperty(data, term);
|
||||
value = value ? String(value).trim() : (missing != null ? missing : `@${term}`);
|
||||
// If there's still an attribute in the returned string, nest it in parentheses so that it's evaluated first in the roll.
|
||||
value = value && value.includes('@') ? `(${value})` : value;
|
||||
return value;
|
||||
if ( value === null ) return "0";
|
||||
if ( String(value).includes('@') ) return value;
|
||||
else return `@${term}`;
|
||||
});
|
||||
|
||||
return rollFormula;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,55 +23,22 @@ export class SimpleItemSheet extends ItemSheet {
|
|||
/** @override */
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
|
||||
// Handle attribute groups.
|
||||
EntitySheetHelper.getAttributeData(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async _onSubmit(event, {updateData=null, preventClose=false, preventRender=false}={}) {
|
||||
let attr = EntitySheetHelper.onSubmit(event);
|
||||
|
||||
// Submit the form if attr is true or an attr key.
|
||||
if ( attr ) {
|
||||
await super._onSubmit(event, {updateData: updateData, preventClose: preventClose, preventRender: preventRender});
|
||||
|
||||
// If attr is a key and not just true, set a very short timeout and retrigger focus after the original element is deleted and the new one is inserted.
|
||||
if ( attr !== true) {
|
||||
setTimeout(() => {
|
||||
$(`input[name="${attr}"]`).parents('.attribute').find('.attribute-value').focus();
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
setPosition(options={}) {
|
||||
const position = super.setPosition(options);
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - 192;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Handle rollable attributes.
|
||||
html.find(".attributes").on("click", "a.attribute-roll", EntitySheetHelper.onAttributeRoll.bind(this));
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Rollable attributes
|
||||
html.find(".attributes").on("click", "a.attribute-roll", EntitySheetHelper.onAttributeRoll.bind(this));
|
||||
|
||||
// Add draggable for macros.
|
||||
html.find(".attributes a.attribute-roll").each((i, a) => {
|
||||
a.setAttribute("draggable", true);
|
||||
|
|
128
module/simple.js
128
module/simple.js
|
@ -176,110 +176,66 @@ Hooks.on("getItemDirectoryEntryContext", (html, options) => {
|
|||
});
|
||||
|
||||
|
||||
/**
|
||||
* Adds the actor template selection dialog.
|
||||
*/
|
||||
ActorDirectory.prototype._onCreateEntity = async (event) => {
|
||||
// Do not allow the creation event to bubble to other listeners
|
||||
async function _onCreateEntity(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
_simpleDirectoryTemplates('actor', event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the item template selection dialog.
|
||||
*/
|
||||
ItemDirectory.prototype._onCreateEntity = async (event) => {
|
||||
// Do not allow the creation event to bubble to other listeners
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
_simpleDirectoryTemplates('item', event);
|
||||
return _simpleDirectoryTemplates(this, event);
|
||||
}
|
||||
ActorDirectory.prototype._onCreateEntity = _onCreateEntity; // For 0.7.x+
|
||||
ItemDirectory.prototype._onCreateEntity = _onCreateEntity;
|
||||
ActorDirectory.prototype._onCreate = _onCreateEntity; // TODO: for 0.6.6
|
||||
ItemDirectory.prototype._onCreate = _onCreateEntity;
|
||||
|
||||
/**
|
||||
* Display the entity template dialog.
|
||||
*
|
||||
* Helper function to display a dialog if there are multiple template types
|
||||
* defined for the entity type.
|
||||
*
|
||||
* @param {string} entityType - 'actor' or 'item'
|
||||
* Helper function to display a dialog if there are multiple template types defined for the entity type.
|
||||
* TODO: Refactor in 0.7.x to play more nicely with the Entity.createDialog method
|
||||
*1
|
||||
* @param {EntityCollection} entityType - The sidebar tab
|
||||
* @param {MouseEvent} event - Triggering event
|
||||
*/
|
||||
async function _simpleDirectoryTemplates(entityType = 'actor', event) {
|
||||
// Retrieve the collection and class.
|
||||
const entityCollection = entityType == 'actor' ? game.actors : game.items;
|
||||
const cls = entityType == 'actor' ? Actor : Item;
|
||||
async function _simpleDirectoryTemplates(collection, event) {
|
||||
|
||||
// Query for all entities of this type using the "isTemplate" flag.
|
||||
let entities = entityCollection.filter(a => a.data.flags?.worldbuilding?.isTemplate === true);
|
||||
|
||||
// Initialize variables related to the entity class.
|
||||
// Retrieve the collection and find any available templates
|
||||
const entityCollection = collection.tabName === "actors" ? game.actors : game.items;
|
||||
const cls = collection.tabName === "actors" ? Actor : Item;
|
||||
let templates = entityCollection.filter(a => a.getFlag("worldbuilding", "isTemplate"));
|
||||
let ent = game.i18n.localize(cls.config.label);
|
||||
|
||||
// Setup entity data.
|
||||
let type = entityType == 'actor' ? 'character' : 'item';
|
||||
// Setup default creation data
|
||||
let type = collection.tabName === "actors" ? 'character' : 'item';
|
||||
let createData = {
|
||||
name: `${game.i18n.localize("SIMPLE.New")} ${ent}`,
|
||||
type: type,
|
||||
folder: event.currentTarget.dataset.folder
|
||||
};
|
||||
if ( !templates.length ) return cls.create(createData, {renderSheet: true});
|
||||
|
||||
// If there's more than one entity template type, create a form.
|
||||
if (entities.length > 0) {
|
||||
// Build an array of types for the form, including an empty default.
|
||||
let types = [{
|
||||
value: null,
|
||||
label: game.i18n.localize("SIMPLE.NoTemplate")
|
||||
}];
|
||||
// Build an array of types for the form, including an empty default.
|
||||
let types = [{
|
||||
value: null,
|
||||
label: game.i18n.localize("SIMPLE.NoTemplate")
|
||||
}].concat(templates.map(a => { return { value: a.id, label: a.name } }));
|
||||
|
||||
// Append each of the user-defined actor/item types.
|
||||
types = types.concat(entities.map(a => {
|
||||
return {
|
||||
value: a.data.name,
|
||||
label: a.data.name
|
||||
// Render the confirmation dialog window
|
||||
const templateData = {upper: ent, lower: ent.toLowerCase(), types: types};
|
||||
const dlg = await renderTemplate(`systems/worldbuilding/templates/sidebar/entity-create.html`, templateData);
|
||||
return Dialog.confirm({
|
||||
title: `${game.i18n.localize("SIMPLE.Create")} ${createData.name}`,
|
||||
content: dlg,
|
||||
yes: html => {
|
||||
const form = html[0].querySelector("form");
|
||||
const template = entityCollection.get(form.type.value);
|
||||
if ( template ) {
|
||||
createData = mergeObject(template.data, createData, {inplace: false});
|
||||
createData.type = template.data.type;
|
||||
delete createData.flags.worldbuilding.isTemplate;
|
||||
}
|
||||
}));
|
||||
|
||||
// Render the entity creation form
|
||||
let templateData = {upper: ent, lower: ent.toLowerCase(), types: types},
|
||||
dlg = await renderTemplate(`systems/worldbuilding/templates/sidebar/entity-create.html`, templateData);
|
||||
|
||||
// Render the confirmation dialog window
|
||||
Dialog.confirm({
|
||||
title: `${game.i18n.localize("SIMPLE.Create")} ${createData.name}`,
|
||||
content: dlg,
|
||||
yes: html => {
|
||||
// Get the form data.
|
||||
const form = html[0].querySelector("form");
|
||||
const fd = new FormDataExtended(form);
|
||||
mergeObject(createData, fd.toObject());
|
||||
|
||||
// Store the type and name values, and retrieve the template entity.
|
||||
let templateActor = entityCollection.getName(createData.type);
|
||||
|
||||
// If there's a template entity, handle the data.
|
||||
if (templateActor) {
|
||||
// Update the object with the existing template's values.
|
||||
createData = mergeObject(templateActor.data, createData, {inplace: false});
|
||||
createData.type = templateActor.data.type;
|
||||
// Clear the flag so that this doesn't become a new template.
|
||||
delete createData.flags.worldbuilding.isTemplate;
|
||||
}
|
||||
// Otherwise, restore to a valid entity type (character/item).
|
||||
else {
|
||||
createData.type = type;
|
||||
}
|
||||
|
||||
cls.create(createData, {renderSheet: true});
|
||||
},
|
||||
no: () => {},
|
||||
defaultYes: false
|
||||
});
|
||||
}
|
||||
// Otherwise, just create a blank entity.
|
||||
else {
|
||||
cls.create(createData, {renderSheet: true});
|
||||
}
|
||||
createData.name = form.name.value;
|
||||
return cls.create(createData, {renderSheet: true});
|
||||
},
|
||||
no: () => {},
|
||||
defaultYes: false
|
||||
});
|
||||
}
|
|
@ -8,8 +8,11 @@
|
|||
padding: 5px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.worldbuilding form {
|
||||
height: 100%;
|
||||
}
|
||||
.worldbuilding .sheet-header {
|
||||
height: 100px;
|
||||
flex: 0 0 100px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -49,7 +52,7 @@
|
|||
height: 28px;
|
||||
}
|
||||
.worldbuilding .tabs {
|
||||
height: 40px;
|
||||
flex: 0 0 40px;
|
||||
border-top: 1px solid #AAA;
|
||||
border-bottom: 1px solid #AAA;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,12 @@
|
|||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sheet-header {
|
||||
height: 100px;
|
||||
flex: 0 0 100px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -52,7 +56,7 @@
|
|||
|
||||
/* Sheet Tabs */
|
||||
.tabs {
|
||||
height: 40px;
|
||||
flex: 0 0 40px;
|
||||
border-top: 1px solid #AAA;
|
||||
border-bottom: 1px solid #AAA;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"name": "worldbuilding",
|
||||
"title": "Simple World-Building",
|
||||
"description": "A minimalist game system with very simple Actor and Item models to support free-form system agnostic gameplay.",
|
||||
"version": 0.36,
|
||||
"minimumCoreVersion": "0.7.3",
|
||||
"description": "A minimalist game system which provides configurable Actor and Item templates to support free-form system agnostic game-play.",
|
||||
"version": 0.40,
|
||||
"minimumCoreVersion": "0.6.6",
|
||||
"compatibleCoreVersion": "0.7.3",
|
||||
"templateVersion": 2,
|
||||
"author": "Atropos",
|
||||
|
@ -23,6 +23,6 @@
|
|||
"secondaryTokenAttribute": "power",
|
||||
"url": "https://gitlab.com/foundrynet/worldbuilding/",
|
||||
"manifest": "https://gitlab.com/foundrynet/worldbuilding/raw/master/system.json",
|
||||
"download": "https://gitlab.com/foundrynet/worldbuilding/-/archive/release-036/worldbuilding-release-036.zip",
|
||||
"download": "https://gitlab.com/foundrynet/worldbuilding/-/archive/release-040/worldbuilding-release-040.zip",
|
||||
"license": "LICENSE.txt"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<form class="flexcol {{cssClass}}" autocomplete="off">
|
||||
|
||||
{{!-- Sheet Header --}}
|
||||
<header class="sheet-header">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<form class="flexcol {{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<div class="header-fields">
|
||||
|
|
Loading…
Add table
Reference in a new issue