mirror of
https://github.com/RoY7x/worldbuilding.git
synced 2025-07-04 13:47:10 -04:00
Initial commit of simple worldbuilding system to standalone repo
This commit is contained in:
parent
652a27f421
commit
f8c8e8c731
10 changed files with 1314 additions and 0 deletions
141
module/actor-sheet.js
Normal file
141
module/actor-sheet.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
*/
|
||||
export class SimpleActorSheet extends ActorSheet {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
/**
|
||||
* Keep track of the currently active sheet tab
|
||||
* @type {string}
|
||||
*/
|
||||
this._sheetTab = "description";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Extend and override the default options used by the 5e Actor Sheet
|
||||
* @returns {Object}
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
classes: ["worldbuilding", "sheet", "actor"],
|
||||
template: "public/systems/worldbuilding/templates/actor-sheet.html",
|
||||
width: 600,
|
||||
height: 600
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare data for rendering the Actor sheet
|
||||
* The prepared data object contains both the actor data as well as additional sheet options
|
||||
*/
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
data.dtypes = ["String", "Number", "Boolean"];
|
||||
for ( let attr of Object.values(data.data.attributes) ) {
|
||||
attr.isCheckbox = attr.dtype === "Boolean";
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Activate event listeners using the prepared sheet HTML
|
||||
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||
*/
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Activate tabs
|
||||
let tabs = html.find('.tabs');
|
||||
let initial = this._sheetTab;
|
||||
new Tabs(tabs, {
|
||||
initial: initial,
|
||||
callback: clicked => this._sheetTab = clicked.data("tab")
|
||||
});
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.actor.deleteOwnedItem(li.data("itemId"));
|
||||
li.slideUp(200, () => this.render(false));
|
||||
});
|
||||
|
||||
// Add or Remove Attribute
|
||||
html.find(".attributes").on("click", ".attribute-control", this._onClickAttributeControl.bind(this));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async _onClickAttributeControl(event) {
|
||||
event.preventDefault();
|
||||
const a = event.currentTarget;
|
||||
const action = a.dataset.action;
|
||||
const attrs = this.object.data.data.attributes;
|
||||
const form = this.form;
|
||||
|
||||
// Add new attribute
|
||||
if ( action === "create" ) {
|
||||
const nk = Object.keys(attrs).length + 1;
|
||||
let newKey = document.createElement("div");
|
||||
newKey.innerHTML = `<input type="text" name="data.attributes.attr${nk}.key" value="attr${nk}"/>`;
|
||||
newKey = newKey.children[0];
|
||||
form.appendChild(newKey);
|
||||
await this._onSubmit(event);
|
||||
}
|
||||
|
||||
// Remove existing attribute
|
||||
else if ( action === "delete" ) {
|
||||
const li = a.closest(".attribute");
|
||||
li.parentElement.removeChild(li);
|
||||
await this._onSubmit(event);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Implement the _updateObject method as required by the parent class spec
|
||||
* This defines how to update the subject of the form when the form is submitted
|
||||
* @private
|
||||
*/
|
||||
_updateObject(event, formData) {
|
||||
|
||||
// Handle the free-form attributes list
|
||||
const formAttrs = expandObject(formData).data.attributes || {};
|
||||
const attributes = Object.fromEntries(Object.entries(formAttrs).map(attr => {
|
||||
let [k, v] = attr;
|
||||
k = v["key"].trim();
|
||||
delete v["key"];
|
||||
return [k, v];
|
||||
}));
|
||||
|
||||
// Remove attributes which are no longer used
|
||||
for ( let k of Object.keys(this.object.data.data.attributes) ) {
|
||||
if ( !attributes.hasOwnProperty(k) ) attributes[`-=${k}`] = null;
|
||||
}
|
||||
|
||||
// Re-combine formData
|
||||
formData = Object.fromEntries(Object.entries(formData).filter(a => !a[0].startsWith("data.attributes")));
|
||||
formData["_id"] = this.object._id;
|
||||
formData["data.attributes"] = attributes;
|
||||
|
||||
// Update the Actor
|
||||
return this.object.update(formData);
|
||||
}
|
||||
}
|
125
module/item-sheet.js
Normal file
125
module/item-sheet.js
Normal file
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
*/
|
||||
export class SimpleItemSheet extends ItemSheet {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
/**
|
||||
* Keep track of the currently active sheet tab
|
||||
* @type {string}
|
||||
*/
|
||||
this._sheetTab = "description";
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend and override the default options used by the Simple Item Sheet
|
||||
* @returns {Object}
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
classes: ["worldbuilding", "sheet", "item"],
|
||||
template: "public/systems/worldbuilding/templates/item-sheet.html",
|
||||
width: 520,
|
||||
height: 480,
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare data for rendering the Item sheet
|
||||
* The prepared data object contains both the actor data as well as additional sheet options
|
||||
*/
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
data.dtypes = ["String", "Number", "Boolean"];
|
||||
for ( let attr of Object.values(data.data.attributes) ) {
|
||||
attr.isCheckbox = attr.dtype === "Boolean";
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Activate event listeners using the prepared sheet HTML
|
||||
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||
*/
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Activate tabs
|
||||
let tabs = html.find('.tabs');
|
||||
let initial = this._sheetTab;
|
||||
new Tabs(tabs, {
|
||||
initial: initial,
|
||||
callback: clicked => this._sheetTab = clicked.data("tab")
|
||||
});
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Add or Remove Attribute
|
||||
html.find(".attributes").on("click", ".attribute-control", this._onClickAttributeControl.bind(this));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async _onClickAttributeControl(event) {
|
||||
event.preventDefault();
|
||||
const a = event.currentTarget;
|
||||
const action = a.dataset.action;
|
||||
const attrs = this.object.data.data.attributes;
|
||||
const form = this.form;
|
||||
|
||||
// Add new attribute
|
||||
if ( action === "create" ) {
|
||||
const nk = Object.keys(attrs).length + 1;
|
||||
let newKey = document.createElement("div");
|
||||
newKey.innerHTML = `<input type="text" name="data.attributes.attr${nk}.key" value="attr${nk}"/>`;
|
||||
newKey = newKey.children[0];
|
||||
form.appendChild(newKey);
|
||||
await this._onSubmit(event);
|
||||
}
|
||||
|
||||
// Remove existing attribute
|
||||
else if ( action === "delete" ) {
|
||||
const li = a.closest(".attribute");
|
||||
li.parentElement.removeChild(li);
|
||||
await this._onSubmit(event);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Implement the _updateObject method as required by the parent class spec
|
||||
* This defines how to update the subject of the form when the form is submitted
|
||||
* @private
|
||||
*/
|
||||
_updateObject(event, formData) {
|
||||
|
||||
// Handle the free-form attributes list
|
||||
const formAttrs = expandObject(formData).data.attributes || {};
|
||||
const attributes = Object.fromEntries(Object.entries(formAttrs).map(attr => {
|
||||
let [k, v] = attr;
|
||||
k = v["key"].trim();
|
||||
delete v["key"];
|
||||
return [k, v];
|
||||
}));
|
||||
|
||||
// Remove attributes which are no longer used
|
||||
for ( let k of Object.keys(this.object.data.data.attributes) ) {
|
||||
if ( !attributes.hasOwnProperty(k) ) attributes[`-=${k}`] = null;
|
||||
}
|
||||
|
||||
// Re-combine formData
|
||||
formData = Object.fromEntries(Object.entries(formData).filter(a => !a[0].startsWith("data.attributes")));
|
||||
formData["_id"] = this.object._id;
|
||||
formData["data.attributes"] = attributes;
|
||||
|
||||
// Update the Item
|
||||
return this.object.update(formData);
|
||||
}
|
||||
}
|
29
module/simple.js
Normal file
29
module/simple.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* A simple and flexible system for world-building using an arbitrary collection of character and item attributes
|
||||
* Author: Atropos
|
||||
* Software License: GNU GPLv3
|
||||
*/
|
||||
|
||||
// Import Modules
|
||||
import { SimpleItemSheet } from "./item-sheet.js";
|
||||
import { SimpleActorSheet } from "./actor-sheet.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
Hooks.once("init", async function() {
|
||||
console.log(`Initializing Simple Worldbuilding System`);
|
||||
|
||||
/**
|
||||
* Set an initiative formula for the system
|
||||
* @type {String}
|
||||
*/
|
||||
CONFIG.initiative.formula = "1d20";
|
||||
|
||||
// Register sheet application classes
|
||||
Actors.unregisterSheet("core", ActorSheet);
|
||||
Actors.registerSheet("dnd5e", SimpleActorSheet, { makeDefault: true });
|
||||
Items.unregisterSheet("core", ItemSheet);
|
||||
Items.registerSheet("dnd5e", SimpleItemSheet, {makeDefault: true});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue