Updates to DAE, Archetypes, Backgrounds, Classes, Species, CSS/LESS, etc.

What the subject line said.
This commit is contained in:
Professor Bunbury 2020-12-11 13:23:21 -05:00
parent 3afef6c7f1
commit 14e9b0c341
67 changed files with 2357 additions and 818 deletions

View file

@ -131,7 +131,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
// Organize Features
const features = {
classes: { label: "SW5E.ItemTypeClassPl", items: [], hasActions: false, dataset: {type: "class"}, isClass: true },
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: false, dataset: {type: "classfeature"}, isClassfeature: true },
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: true, dataset: {type: "classfeature"}, isClassfeature: true },
archetype: { label: "SW5E.ItemTypeArchetype", items: [], hasActions: false, dataset: {type: "archetype"}, isArchetype: true },
species: { label: "SW5E.ItemTypeSpecies", items: [], hasActions: false, dataset: {type: "species"}, isSpecies: true },
background: { label: "SW5E.ItemTypeBackground", items: [], hasActions: false, dataset: {type: "background"}, isBackground: true },
@ -516,7 +516,7 @@ async function addFavorites(app, html, data) {
if (app.options.editable) {
favtabHtml.find('.item-image').click(ev => app._onItemRoll(ev));
let handler = ev => app._onDragItemStart(ev);
let handler = ev => app._onDragStart(ev);
favtabHtml.find('.item').each((i, li) => {
if (li.classList.contains("inventory-header")) return;
li.setAttribute("draggable", true);
@ -566,7 +566,14 @@ async function addFavorites(app, html, data) {
});
}
tabContainer.append(favtabHtml);
// if(app.options.editable) {
// let handler = ev => app._onDragItemStart(ev);
// tabContainer.find('.item').each((i, li) => {
// if (li.classList.contains("inventory-header")) return;
// li.setAttribute("draggable", true);
// li.addEventListener("dragstart", handler, false);
// });
//}
// try {
// if (game.modules.get("betterrolls5e") && game.modules.get("betterrolls5e").active) BetterRolls.addItemContent(app.object, favtabHtml, ".item .item-name h4", ".item-properties", ".item > .rollable div");
// }

View file

@ -0,0 +1,137 @@
import ActorSheet5e from "../base.js";
/**
* An Actor sheet for NPC type characters in the SW5E system.
* Extends the base ActorSheet5e class.
* @extends {ActorSheet5e}
*/
export default class ActorSheet5eNPCNew extends ActorSheet5e {
/** @override */
get template() {
if ( !game.user.isGM && this.actor.limited ) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
return `systems/sw5e/templates/actors/newActor/npc-sheet.html`;
}
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["sw5e", "sheet", "actor", "npc"],
width: 600,
width: 800,
tabs: [{
navSelector: ".root-tabs",
contentSelector: ".sheet-body",
initial: "attributes"
}],
});
}
/* -------------------------------------------- */
/**
* Organize Owned Items for rendering the NPC sheet
* @private
*/
_prepareItems(data) {
// Categorize Items as Features and Powers
const features = {
weapons: { label: game.i18n.localize("SW5E.AttackPl"), items: [] , hasActions: true, dataset: {type: "weapon", "weapon-type": "natural"} },
actions: { label: game.i18n.localize("SW5E.ActionPl"), items: [] , hasActions: true, dataset: {type: "feat", "activation.type": "action"} },
passive: { label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"} },
equipment: { label: game.i18n.localize("SW5E.Inventory"), items: [], dataset: {type: "loot"}}
};
// Start by classifying items into groups for rendering
let [powers, other] = data.items.reduce((arr, item) => {
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.hasUses = item.data.uses && (item.data.uses.max > 0);
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
if ( item.type === "power" ) arr[0].push(item);
else arr[1].push(item);
return arr;
}, [[], []]);
// Apply item filters
powers = this._filterItems(powers, this._filters.powerbook);
other = this._filterItems(other, this._filters.features);
// Organize Powerbook
const powerbook = this._preparePowerbook(data, powers);
// Organize Features
for ( let item of other ) {
if ( item.type === "weapon" ) features.weapons.items.push(item);
else if ( item.type === "feat" ) {
if ( item.data.activation.type ) features.actions.items.push(item);
else features.passive.items.push(item);
}
else features.equipment.items.push(item);
}
// Assign and return
data.features = Object.values(features);
data.powerbook = powerbook;
}
/* -------------------------------------------- */
/** @override */
getData() {
const data = super.getData();
// Challenge Rating
const cr = parseFloat(data.data.details.cr || 0);
const crLabels = {0: "0", 0.125: "1/8", 0.25: "1/4", 0.5: "1/2"};
data.labels["cr"] = cr >= 1 ? String(cr) : crLabels[cr] || 1;
return data;
}
/* -------------------------------------------- */
/* Object Updates */
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
// Format NPC Challenge Rating
const crs = {"1/8": 0.125, "1/4": 0.25, "1/2": 0.5};
let crv = "data.details.cr";
let cr = formData[crv];
cr = crs[cr] || parseFloat(cr);
if ( cr ) formData[crv] = cr < 1 ? cr : parseInt(cr);
// Parent ActorSheet update steps
super._updateObject(event, formData);
}
/* -------------------------------------------- */
/* Event Listeners and Handlers */
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
html.find(".health .rollable").click(this._onRollHealthFormula.bind(this));
}
/* -------------------------------------------- */
/**
* Handle rolling NPC health values using the provided formula
* @param {Event} event The original click event
* @private
*/
_onRollHealthFormula(event) {
event.preventDefault();
const formula = this.actor.data.data.attributes.hp.formula;
if ( !formula ) return;
const hp = new Roll(formula).roll().total;
AudioHelper.play({src: CONFIG.sounds.dice});
this.actor.update({"data.attributes.hp.value": hp, "data.attributes.hp.max": hp});
}
}

View file

@ -122,7 +122,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
// Organize Features
const features = {
classes: { label: "SW5E.ItemTypeClassPl", items: [], hasActions: false, dataset: {type: "class"}, isClass: true },
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: false, dataset: {type: "classfeature"}, isClassfeature: true },
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: true, dataset: {type: "classfeature"}, isClassfeature: true },
archetype: { label: "SW5E.ItemTypeArchetype", items: [], hasActions: false, dataset: {type: "archetype"}, isArchetype: true },
species: { label: "SW5E.ItemTypeSpecies", items: [], hasActions: false, dataset: {type: "species"}, isSpecies: true },
background: { label: "SW5E.ItemTypeBackground", items: [], hasActions: false, dataset: {type: "background"}, isBackground: true },
@ -285,7 +285,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
if ( !hasClass || addLevel ) {
const features = await Actor5e.getClassFeatures({
className: itemData.name,
subclassName: itemData.data.subclass,
archetypeName: itemData.data.archetype,
level: itemData.levels,
priorLevel: priorLevel
});
@ -296,4 +296,4 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
// Default drop handling if levels were not added
if ( !addLevel ) super._onDropItemCreate(itemData);
}
}
}