Enhance actor sheet

This commit is contained in:
2024-12-16 09:04:48 +01:00
parent eaba806fec
commit 2ac69e2108
37 changed files with 535 additions and 79 deletions

View File

@ -8,3 +8,4 @@ export { default as CthulhuEternalArmorSheet } from "./sheets/armor-sheet.mjs"
export { default as CthulhuEternalMentalDisorderSheet } from "./sheets/mentaldisorder-sheet.mjs"
export { default as CthulhuEternalGearSheet } from "./sheets/gear-sheet.mjs"
export { default as CthulhuEternalMotivationSheet } from "./sheets/motivation-sheet.mjs"
export { default as CthulhuEternalArchetypeSheet } from "./sheets/archetype-sheet.mjs"

View File

@ -0,0 +1,28 @@
import CthulhuEternalItemSheet from "./base-item-sheet.mjs"
export default class CthulhuEternalArchetypeSheet extends CthulhuEternalItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["archetype"],
position: {
width: 600,
},
window: {
contentClasses: ["archetype-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-cthulhu-eternal/templates/archetype.hbs",
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@ -32,7 +32,8 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin
editImage: CthulhuEternalActorSheet.#onEditImage,
toggleSheet: CthulhuEternalActorSheet.#onToggleSheet,
edit: CthulhuEternalActorSheet.#onItemEdit,
delete: CthulhuEternalActorSheet.#onItemDelete
delete: CthulhuEternalActorSheet.#onItemDelete,
updateCheckboxArray: CthulhuEternalActorSheet.#onUpdateCheckboxArray,
},
}
@ -223,6 +224,18 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin
this.render()
}
static #onUpdateCheckboxArray(event, target) {
console.log("Update checkbox array", event, target)
let arrayName = target.dataset.name
let arrayIdx = Number(target.dataset.index)
let dataPath = `system.san.${arrayName}`
let tab = foundry.utils.duplicate(this.document.system.san[arrayName])
tab[arrayIdx] = target.checked
this.actor.update( { [dataPath]: tab } )
// Dump
console.log("Array name", arrayName, arrayIdx, target.checked, dataPath)
}
/**
* Handle changing a Document's image.
*

View File

@ -1,11 +1,11 @@
export const CHARACTERISTICS = Object.freeze({
str: {
id: "str",
label: "CTHULHUETERNAL.Character.str.label"
label: "CTHULHUETERNAL.Label.strShort"
},
int: {
id: "int",
label: "CTHULHUETERNAL.Character.int.label"
label: "CTHULHUETERNAL.Label.intShort"
},
pow: {
id: "pow",

View File

@ -20,15 +20,18 @@ export const AVAILABLE_SETTINGS = {
}
export const ASCII = `
······················································································································
: :
:@@@ @@@@@@@@ @@@@@@@ @@@ @@@ @@@@@@ @@@ @@@@@@@@ @@@@@@ @@@ @@@ @@@@@@@ @@@@@@ @@@@@@ @@@ @@@ :
:@@! @@! @!! @@! @@@ @@! @@@ @@! @@! @@! @@@ @@!@!@@@ @!! @@! @@@ !@@ @@! !@@ :
:@!! @!!!:! @!! @!@!@!@! @!@!@!@! @!! @!!!:! @!@!@!@! @!@@!!@! @!! @!@!@!@! !@@!! !@!@! :
:!!: !!: !!: !!: !!! !!: !!! !!: !!: !!: !!! !!: !!! !!: !!: !!! !:! !!: :
:: ::.: : : :: :: : : : : : : : : ::.: : : : : : :: : : : : : ::.: : .: :
: :
······················································································································
▄████▄ ▄▄▄█████▓ ██░ ██ █ ██ ██▓ ██░ ██ █ ██ ▓█████▄▄▄█████▓▓█████ ██▀███ ███▄ █ ▄▄▄ ██▓
▒██▀ ▀█ ██▒ ▓▒▓██░ ██▒ ██ ▓██▒▓██▒ ▓██░ ██▒ ██ ▓██▒ ▓█ ▀▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ ██ ▀█ █ ▒████▄ ▓██▒
▒▓█ ▄ ▒ ▓██░ ▒░▒██▀▀██░▓██ ▒██░▒██░ ▒██▀▀██░▓██ ▒██░ ▒███ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒▓██ ▀█ ██▒▒██ ▀█▄ ▒██░
▒▓▓▄ ▄██▒░ ▓██▓ ░ ░▓█ ░██ ▓▓█ ░██░▒██░ ░▓█ ░██ ▓▓█ ░██░ ▒▓█ ▄░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ ▓██▒ ▐▌██▒░██▄▄▄▄██ ▒██░
▒ ▓███▀ ░ ▒██▒ ░ ░▓█▒░██▓▒▒█████▓ ░██████▒░▓█▒░██▓▒▒█████▓ ░▒████▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒▒██░ ▓██░ ▓█ ▓██▒░██████▒
░ ░▒ ▒ ▒ ░░ ▒ ░░▒░▒░▒▓▒ ▒ ▒ ░ ▒░▓ ░ ▒ ░░▒░▒░▒▓▒ ▒ ▒ ░░ ▒░ ░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░░ ▒░ ▒ ▒ ▒▒ ▓▒█░░ ▒░▓
░ ▒ ▒ ░▒░ ░░░▒░ ░ ░ ░ ░ ▒ ░ ▒ ░▒░ ░░░▒░ ░ ░ ░ ░ ░ ░ ░ ░ ░▒ ░ ▒░░ ░░ ░ ▒░ ▒ ▒▒ ░░ ░ ▒
░░ ░ ░░░ ░ ░ ░ ░ ░░ ░ ░░░ ░ ░ ░░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
`
/**

View File

@ -1 +1,21 @@
export default class CthulhuEternalItem extends Item {}
export const defaultItemImg = {
weapon: "systems/fvtt-cthulhu-eternal/assets/icons/icon_weapon.svg",
armor: "systems/fvtt-cthulhu-eternal/assets/icons/icon_armor.svg",
gear: "systems/fvtt-cthulhu-eternal/assets/icons/icon_gear.svg",
skill: "systems/fvtt-cthulhu-eternal/assets/icons/icon_skill.svg",
archetype: "systems/fvtt-cthulhu-eternal/assets/icons/icon_archetype.svg",
bond: "systems/fvtt-cthulhu-eternal/assets/icons/icon_bond.svg",
mentaldisorder: "systems/fvtt-cthulhu-eternal/assets/icons/icon_mentaldisorder.svg",
arcane: "systems/fvtt-cthulhu-eternal/assets/icons/icon_arcane.svg",
injury: "systems/fvtt-cthulhu-eternal/assets/icons/icon_injury.svg",
motivation: "systems/fvtt-cthulhu-eternal/assets/icons/icon_motivation.svg",
}
export default class CthulhuEternalItem extends Item {
constructor(data, context) {
if (!data.img) {
data.img = defaultItemImg[data.type];
}
super(data, context);
}
}

View File

@ -1,4 +1,3 @@
import CthulhuEternalUtils from "../utils.mjs"
export default class CthulhuEternalRoll extends Roll {
/**

View File

@ -8,3 +8,4 @@ export { default as CthulhuEternalMentalDisorder } from "./mentaldisorder.mjs"
export { default as CthulhuEternalBond } from "./bond.mjs"
export { default as CthulhuEternalGear } from "./gear.mjs"
export { default as CthulhuEternalMotivation } from "./motivation.mjs"
export { default as CthulhuEternalArchetype } from "./archetype.mjs"

View File

@ -0,0 +1,22 @@
import { SYSTEM } from "../config/system.mjs"
export default class CthulhuEternalArchetype extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.settings = new fields.StringField({ required: true, initial: "common", choices: SYSTEM.AVAILABLE_SETTINGS })
schema.description = new fields.HTMLField({
required: false,
blank: true,
initial: "",
textSearch: true,
})
return schema
}
/** @override */
static LOCALIZATION_PREFIXES = ["CTHULHUETERNAL.Archetype"]
}

View File

@ -41,10 +41,11 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
schema.san = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
recoverySAN: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
violence: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
helplessness: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
breakingPoint: new fields.BooleanField({ required: true, initial: false })
recovery: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
violence: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3}),
helplessness: new fields.ArrayField(new fields.BooleanField(), { required: true, initial: [false, false, false], min:3, max:3 }),
breakingPoint: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
})
schema.damageBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
@ -58,6 +59,7 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
schema.biodata = new fields.SchemaField({
age: new fields.NumberField({ ...requiredInteger, initial: 15, min: 6 }),
archetype: new fields.StringField({ required: true, nullable: false, initial: "" }),
height: new fields.NumberField({ ...requiredInteger, initial: 170, min: 50 }),
gender: new fields.StringField({ required: true, nullable: false, initial: "" }),
home: new fields.StringField({ required: true, nullable: false, initial: "" }),

View File

@ -1,4 +1,156 @@
export default class CthulhuEternalUtils {
export class CthulhuEternalUtils {
static registerHandlebarsHelpers() {
Handlebars.registerHelper('isNull', function (val) {
return val == null;
});
Handlebars.registerHelper('exists', function (val) {
return val != null && val !== undefined;
});
Handlebars.registerHelper('isEmpty', function (list) {
if (list) return list.length === 0;
else return false;
});
Handlebars.registerHelper('notEmpty', function (list) {
return list.length > 0;
});
Handlebars.registerHelper('isNegativeOrNull', function (val) {
return val <= 0;
});
Handlebars.registerHelper('isNegative', function (val) {
return val < 0;
});
Handlebars.registerHelper('isPositive', function (val) {
return val > 0;
});
Handlebars.registerHelper('equals', function (val1, val2) {
return val1 === val2;
});
Handlebars.registerHelper('neq', function (val1, val2) {
return val1 !== val2;
});
Handlebars.registerHelper('gt', function (val1, val2) {
return val1 > val2;
})
Handlebars.registerHelper('lt', function (val1, val2) {
return val1 < val2;
})
Handlebars.registerHelper('gte', function (val1, val2) {
return val1 >= val2;
})
Handlebars.registerHelper('lte', function (val1, val2) {
return val1 <= val2;
})
Handlebars.registerHelper('and', function (val1, val2) {
return val1 && val2;
})
Handlebars.registerHelper('or', function (val1, val2) {
return val1 || val2;
})
Handlebars.registerHelper('or3', function (val1, val2, val3) {
return val1 || val2 || val3;
})
Handlebars.registerHelper('for', function (from, to, incr, block) {
let accum = '';
for (let i = from; i < to; i += incr)
accum += block.fn(i);
return accum;
})
Handlebars.registerHelper('not', function (cond) {
return !cond;
})
Handlebars.registerHelper('count', function (list) {
return list.length;
})
Handlebars.registerHelper('countKeys', function (obj) {
return Object.keys(obj).length;
})
Handlebars.registerHelper('isEnabled', function (configKey) {
return game.settings.get("bol", configKey);
})
Handlebars.registerHelper('split', function (str, separator, keep) {
return str.split(separator)[keep];
})
// If you need to add Handlebars helpers, here are a few useful examples:
Handlebars.registerHelper('concat', function () {
let outStr = '';
for (let arg in arguments) {
if (typeof arguments[arg] != 'object') {
outStr += arguments[arg];
}
}
return outStr;
})
Handlebars.registerHelper('add', function (a, b) {
return parseInt(a) + parseInt(b);
});
Handlebars.registerHelper('mul', function (a, b) {
return parseInt(a) * parseInt(b);
})
Handlebars.registerHelper('sub', function (a, b) {
return parseInt(a) - parseInt(b);
})
Handlebars.registerHelper('abbrev2', function (a) {
return a.substring(0, 2);
})
Handlebars.registerHelper('abbrev3', function (a) {
return a.substring(0, 3);
})
Handlebars.registerHelper('valueAtIndex', function (arr, idx) {
return arr[idx];
})
Handlebars.registerHelper('includesKey', function (items, type, key) {
return items.filter(i => i.type === type).map(i => i.system.key).includes(key);
})
Handlebars.registerHelper('includes', function (array, val) {
return array.includes(val);
})
Handlebars.registerHelper('eval', function (expr) {
return eval(expr);
})
Handlebars.registerHelper('isOwnerOrGM', function (actor) {
console.log("Testing actor", actor.isOwner, game.userId)
return actor.isOwner || game.isGM;
})
Handlebars.registerHelper('upperFirst', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase() + text.slice(1)
})
Handlebars.registerHelper('upperFirstOnly', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase()
})
Handlebars.registerHelper('isCreature', function (key) {
return key === "creature" || key === "daemon";
})
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
}
}