Merge pull request #2 from ZoltanTheDM/features_branch_1

Races and Buttons
master 2.1.0
Matheus Clemente 2023-12-19 03:14:18 -03:00 committed by GitHub
commit 6fc06c7be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 223 additions and 15 deletions

View File

@ -56,7 +56,17 @@
}, },
"SETTING": { "SETTING": {
"Maxload.NAME": "Maximum load", "Maxload.NAME": "Maximum load",
"Maxload.HINT": "Maximum number of spells, feats, items, or NPCs to display; to see more use the filters. This setting is to allow manageing memory and server load." "Maxload.HINT": "Maximum number of spells, feats, items, or NPCs to display; to see more use the filters. This setting is to allow manageing memory and server load.",
"extraButtonsGlobal.NAME": "Globally Enable Buttons",
"extraButtonsGlobal.HINT": "Globally enable shortcut buttons to the browser that are added to sheets (Must re-open window for it to apply)",
"extraSheetButtons.NAME": "Enable Extra Sheet Buttons",
"extraSheetButtons.HINT": "Enable extra shortcut buttons that appear on PC sheets (Must re-open window for it to apply)",
"extraAdvancementButtons.NAME": "Enable Extra Advancement Buttons",
"extraAdvancementButtons.HINT": "Enable extra shortcut buttons that appear on advancement windows (Must re-open window for it to apply)",
"bannersGlobal.NAME": "Enable Banners - Global",
"bannersGlobal.HINT": "Enable Banners for missing key features on PC sheets for all players",
"bannersLocal.NAME": "Enable Banners - Local",
"bannersLocal.HINT": "Enable Banners for missing key features on PC sheets for self"
}, },
"LOADING": { "LOADING": {
"Message": "Loading..." "Message": "Loading..."
@ -70,6 +80,16 @@
}, },
"MaxLoaded": "(maximum displayed; to see more, use the filters)" "MaxLoaded": "(maximum displayed; to see more, use the filters)"
}, },
"ToolTip": {
"Feats": "Find Feats",
"Spells": "Find Spells",
"Features": "Find Features"
},
"FindA": {
"race": "Missing a Race, click to open list",
"background": "Missing a Background, click to open list",
"class": "Missing a Class, click to open list"
},
"Filters.ResetFilters": "Reset Filters" "Filters.ResetFilters": "Reset Filters"
} }
} }

View File

@ -4,13 +4,14 @@ import { registerSettings } from "./settings.js";
const STOP_SEARCH = "StopSearchException"; const STOP_SEARCH = "StopSearchException";
const NOT_MIGRATED = "NotMigratedException"; const NOT_MIGRATED = "NotMigratedException";
const COMPENDIUM_BROWSER = "compendium-browser";
class CompendiumBrowser extends Application { class CompendiumBrowser extends Application {
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return mergeObject(super.defaultOptions, {
title: "CMPBrowser.compendiumBrowser", title: "CMPBrowser.compendiumBrowser",
tabs: [{ navSelector: ".tabs", contentSelector: ".content", initial: "spell" }], tabs: [{ navSelector: ".tabs", contentSelector: ".content", initial: "spell" }],
classes: ["compendium-browser"], classes: [COMPENDIUM_BROWSER],
template: "modules/compendium-browser/templates/template.html", template: "modules/compendium-browser/templates/template.html",
width: 800, width: 800,
height: 730, height: 730,
@ -19,7 +20,27 @@ class CompendiumBrowser extends Application {
} }
get maxLoad() { get maxLoad() {
return game.settings.get("compendium-browser", "maxload"); return game.settings.get(COMPENDIUM_BROWSER, "maxload");
}
static get extraButtonsGlobal() {
return game.settings.get(COMPENDIUM_BROWSER, "extraButtonsGlobal");
}
static get extraSheetButtons() {
return game.settings.get(COMPENDIUM_BROWSER, "extraSheetButtons");
}
static get extraAdvancementButtons() {
return game.settings.get(COMPENDIUM_BROWSER, "extraAdvancementButtons");
}
static get bannersGlobal() {
return game.settings.get(COMPENDIUM_BROWSER, "bannersGlobal");
}
static get bannersLocal() {
return game.settings.get(COMPENDIUM_BROWSER, "bannersLocal");
} }
async setup() { async setup() {
@ -230,7 +251,7 @@ class CompendiumBrowser extends Application {
} else if (setting === "allow-npc-browser") { } else if (setting === "allow-npc-browser") {
this.settings.allowNpcBrowser = value; this.settings.allowNpcBrowser = value;
} }
game.settings.set("compendium-browser", "settings", this.settings); game.settings.set(COMPENDIUM_BROWSER, "settings", this.settings);
}); });
// activating or deactivating filters // activating or deactivating filters
@ -384,6 +405,8 @@ class CompendiumBrowser extends Application {
// 0.4.1: Load and filter just one of spells, feats, and items (specified by browserTab) // 0.4.1: Load and filter just one of spells, feats, and items (specified by browserTab)
let numItemsLoaded = 0; let numItemsLoaded = 0;
let compactItems = {}; let compactItems = {};
const FeatureList = ["feat", "class", "subclass", "background", "race"];
const NotItemList = ["spell", "feat", "class", "subclass", "background", "race"];
try { try {
// Filter the full list, but only save the core compendium information + displayed info // Filter the full list, but only save the core compendium information + displayed info
@ -452,7 +475,7 @@ class CompendiumBrowser extends Application {
if ( if (
decoratedItem decoratedItem
&& ["feat", "class", "subclass", "background"].includes(decoratedItem.type) && FeatureList.includes(decoratedItem.type)
&& this.passesFilter(decoratedItem, this.featFilters.activeFilters) && this.passesFilter(decoratedItem, this.featFilters.activeFilters)
) { ) {
itemsList[item5e.id] = { itemsList[item5e.id] = {
@ -485,7 +508,7 @@ class CompendiumBrowser extends Application {
if ( if (
decoratedItem decoratedItem
&& !["spell", "feat", "class", "subclass", "background"].includes( && !NotItemList.includes(
decoratedItem.type decoratedItem.type
) )
&& this.passesFilter(decoratedItem, this.itemFilters.activeFilters) && this.passesFilter(decoratedItem, this.itemFilters.activeFilters)
@ -1133,7 +1156,7 @@ class CompendiumBrowser extends Application {
} }
} }
// creating game setting container // creating game setting container
game.settings.register("compendium-browser", "settings", { game.settings.register(COMPENDIUM_BROWSER, "settings", {
name: "Compendium Browser Settings", name: "Compendium Browser Settings",
hint: "Settings to exclude packs from loading and visibility of the browser", hint: "Settings to exclude packs from loading and visibility of the browser",
default: defaultSettings, default: defaultSettings,
@ -1143,7 +1166,7 @@ class CompendiumBrowser extends Application {
this.settings = settings; this.settings = settings;
}, },
}); });
game.settings.register("compendium-browser", "maxload", { game.settings.register(COMPENDIUM_BROWSER, "maxload", {
name: game.i18n.localize("CMPBrowser.SETTING.Maxload.NAME"), name: game.i18n.localize("CMPBrowser.SETTING.Maxload.NAME"),
hint: game.i18n.localize("CMPBrowser.SETTING.Maxload.HINT"), hint: game.i18n.localize("CMPBrowser.SETTING.Maxload.HINT"),
scope: "world", scope: "world",
@ -1157,9 +1180,49 @@ class CompendiumBrowser extends Application {
step: 100, step: 100,
}, },
}); });
game.settings.register(COMPENDIUM_BROWSER, "extraButtonsGlobal", {
name: game.i18n.localize("CMPBrowser.SETTING.extraButtonsGlobal.NAME"),
hint: game.i18n.localize("CMPBrowser.SETTING.extraButtonsGlobal.HINT"),
scope: "world",
config: true,
default: true,
type: Boolean,
});
game.settings.register(COMPENDIUM_BROWSER, "extraSheetButtons", {
name: game.i18n.localize("CMPBrowser.SETTING.extraSheetButtons.NAME"),
hint: game.i18n.localize("CMPBrowser.SETTING.extraSheetButtons.HINT"),
scope: "client",
config: true,
default: true,
type: Boolean,
});
game.settings.register(COMPENDIUM_BROWSER, "extraAdvancementButtons", {
name: game.i18n.localize("CMPBrowser.SETTING.extraAdvancementButtons.NAME"),
hint: game.i18n.localize("CMPBrowser.SETTING.extraAdvancementButtons.HINT"),
scope: "client",
config: true,
default: true,
type: Boolean,
});
game.settings.register(COMPENDIUM_BROWSER, "bannersGlobal", {
name: game.i18n.localize("CMPBrowser.SETTING.bannersGlobal.NAME"),
hint: game.i18n.localize("CMPBrowser.SETTING.bannersGlobal.HINT"),
scope: "world",
config: true,
default: true,
type: Boolean,
});
game.settings.register(COMPENDIUM_BROWSER, "bannersLocal", {
name: game.i18n.localize("CMPBrowser.SETTING.bannersLocal.NAME"),
hint: game.i18n.localize("CMPBrowser.SETTING.bannersLocal.HINT"),
scope: "client",
config: true,
default: true,
type: Boolean,
});
// load settings from container and apply to default settings (available compendie might have changed) // load settings from container and apply to default settings (available compendie might have changed)
let settings = game.settings.get("compendium-browser", "settings"); let settings = game.settings.get(COMPENDIUM_BROWSER, "settings");
for (let compKey in defaultSettings.loadedSpellCompendium) { for (let compKey in defaultSettings.loadedSpellCompendium) {
// v0.7.1 Check for settings.loadedSpellCompendium // v0.7.1 Check for settings.loadedSpellCompendium
if (settings.loadedSpellCompendium && settings.loadedSpellCompendium[compKey] !== undefined) { if (settings.loadedSpellCompendium && settings.loadedSpellCompendium[compKey] !== undefined) {
@ -1407,6 +1470,7 @@ class CompendiumBrowser extends Application {
feat: "ITEM.TypeFeat", feat: "ITEM.TypeFeat",
subclass: "ITEM.TypeSubclass", subclass: "ITEM.TypeSubclass",
background: "DND5E.Background", background: "DND5E.Background",
race: "DND5E.Race",
}), }),
false false
); );
@ -1625,12 +1689,12 @@ class CompendiumBrowser extends Application {
if (filter.type in typeMap) { if (filter.type in typeMap) {
let component = html.element.find( let component = html.element.find(
`div.tab.active #${input.section}-${input.label} ${typeMap[filter.type]}` `${this.getHtmlStringFromInput(input)} ${typeMap[filter.type]}`
); );
component[0].value = input.value; component[0].value = input.value;
} else if (filter.type === "multiSelect") { } else if (filter.type === "multiSelect") {
let components = html.element.find(`div.tab.active #${input.section}-${input.label}`); let components = html.element.find(this.getHtmlStringFromInput(input));
for (let v of input.values) { for (let v of input.values) {
let c = components.find(`input[data-value=${v}]`); let c = components.find(`input[data-value=${v}]`);
@ -1647,6 +1711,10 @@ class CompendiumBrowser extends Application {
return this; return this;
} }
getHtmlStringFromInput(input) {
return `div.tab.active #${input.section}-${stripDotCharacters(input.label)}`;
}
findFilter(type, category, label) { findFilter(type, category, label) {
let target = `${type}Filters`; let target = `${type}Filters`;
let catId = stripSpecialCharacters(category); let catId = stripSpecialCharacters(category);
@ -1655,7 +1723,9 @@ class CompendiumBrowser extends Application {
return; return;
} }
let filter = this[target].registeredFilterCategorys[catId].filters.find((x) => x.labelId === label); const labelStripped = stripDotCharacters(label);
let filter = this[target].registeredFilterCategorys[catId].filters.find((x) => x.labelId === labelStripped);
if (!filter) { if (!filter) {
return; return;
@ -1717,12 +1787,29 @@ class CompendiumBrowser extends Application {
} }
static async addTidySheetButton(cb, html, actor) { static async addTidySheetButton(cb, html, actor) {
await CompendiumBrowser.createBanners(html);
await CompendiumBrowser.addButtons(html, actor);
}
static async addButtons(html, actor) {
// exit out because we dont want these
if (!CompendiumBrowser.extraButtonsGlobal || !CompendiumBrowser.extraSheetButtons) {
return;
}
await CompendiumBrowser.addTidyFeatureButton(html, "race");
await CompendiumBrowser.addTidyFeatureButton(html, "background");
await CompendiumBrowser.addTidyFeatureButton(html, "class");
await html.find(".spell-browser-btn").remove(); await html.find(".spell-browser-btn").remove();
let tabBar = html.find("div.tab.spellbook .spellcasting-ability"); let tabBar = html.find("div.tab.spellbook .spellcasting-ability");
const tooltip = game.i18n.localize("CMPBrowser.ToolTip.Spells");
const cbButton = $( const cbButton = $(
`<div style="flex: 0 0 22px; align-self: center; text-align: center;"> `<div style="flex: 0 0 22px; align-self: center; text-align: center;">
<a class="compendium-browser spell-browser-btn"> <a title="${tooltip}" class="compendium-browser spell-browser-btn">
<i class="fa-duotone fa-book"></i> <i class="fa-duotone fa-book"></i>
</a> </a>
</div>` </div>`
@ -1733,13 +1820,65 @@ class CompendiumBrowser extends Application {
CompendiumBrowser.addSpellsButton(cbButton, actor.actor); CompendiumBrowser.addSpellsButton(cbButton, actor.actor);
} }
static async createBanners(html) {
// Don't build the banners if configuration is turned off
if (!CompendiumBrowser.bannersGlobal || !CompendiumBrowser.bannersLocal) {
return;
}
let MAP_THING = {};
MAP_THING[game.i18n.localize("DND5E.Race")] = "race";
MAP_THING[game.i18n.localize("DND5E.Background")] = "background";
MAP_THING[game.i18n.localize("ITEM.TypeClassPl")] = "class";
let isSearchable = (name) => {
return Object.keys(MAP_THING).includes(name);
};
// searches in a similar way to how tidy sheets does it.
// probably should just use actor data instead of going through the html
html.find(".inventory-list.features-list .item-list").filter(function () {
// find any section that is searchable
return isSearchable($(this.previousElementSibling).find("h3.item-name")[0].innerText)
// find any section that is empty
&& $(this).find("li.item").length === 0;
}).each( function () {
let type = MAP_THING[$(this.previousElementSibling).find("h3.item-name")[0].innerText];
let banner = $(`<span class="notice" style="background:rgba(30, 30, 30, 1)">${game.i18n.localize(`CMPBrowser.FindA.${type}`)}</span>`);
banner.insertAfter(this);
banner.click(async (ev) => {
ev.preventDefault();
game.compendiumBrowser.renderWith("feat", [{ section: "CMPBrowsergeneral", label: "CMPBrowser.overall", value: type }]);
});
});
}
static async addDefaultSheetButton(cb, html, actor) { static async addDefaultSheetButton(cb, html, actor) {
// exit out because we dont want these
if (!CompendiumBrowser.extraButtonsGlobal || !CompendiumBrowser.extraSheetButtons) {
return;
}
if (cb.options.classes.includes("tidy5e")) {
// no need as tidy sheet render will handle it
return;
}
await CompendiumBrowser.addDefaultFeatureButton(html, "race");
await CompendiumBrowser.addDefaultFeatureButton(html, "background");
await CompendiumBrowser.addDefaultFeatureButton(html, "class");
// handle spell browser button
await html.find(".spell-browser-btn").remove(); await html.find(".spell-browser-btn").remove();
let tabBar = html.find("div.spellbook-filters"); let tabBar = html.find("div.spellbook-filters");
const cbButton = $( const cbButton = $(
`<div style="flex: 0 0 22px; align-self: center; text-align: center;"> `<div style="flex: 0 0 22px; align-self: center; text-align: center;">
<a class="compendium-browser spell-browser-btn"> <a data-tooltip="CMPBrowser.ToolTip.Spells" class="compendium-browser spell-browser-btn">
<i class="fa-duotone fa-book"></i> <i class="fa-duotone fa-book"></i>
</a> </a>
</div>` </div>`
@ -1763,13 +1902,62 @@ class CompendiumBrowser extends Application {
}); });
} }
static async addTidyFeatureButton(html, type) {
const featBars = html.find(`div.features a.item-create[data-type="${type}"]`);
const tooltip = game.i18n.localize("CMPBrowser.ToolTip.Features");
const cbButton = $(
`<a style="flex: 0 0 15px; align-self: center; text-align: center; class="compendium-browser ${type}-browser-btn" title="${tooltip}">
<i class="fa-duotone fa-book"></i>
</a>`
);
$(featBars[0].parentNode).append(cbButton);
cbButton.click(async (ev) => {
ev.preventDefault();
game.compendiumBrowser.renderWith("feat", [{ section: "CMPBrowsergeneral", label: "CMPBrowser.overall", value: type }]);
});
}
static async addDefaultFeatureButton(html, type) {
await html.find(`.${type}-browser-btn`).remove();
const featBars = html.find(`div.features li.items-header a.item-control[data-type="${type}"]`);
// Other sheets (like tidysheet) may cause this problem
if (!featBars.length) {
return;
}
const cbButton = $(
`<a style="flex: 0 0 15px; align-self: center; text-align: center; class="compendium-browser ${type}-browser-btn" data-tooltip="CMPBrowser.ToolTip.Features">
<i class="fa-duotone fa-book"></i>
</a>`
);
$(featBars[0].parentNode).append(cbButton);
$(featBars[0].parentNode).css({"flex-basis": "60px"});
cbButton.click(async (ev) => {
ev.preventDefault();
game.compendiumBrowser.renderWith("feat", [{ section: "CMPBrowsergeneral", label: "CMPBrowser.overall", value: type }]);
});
}
static async addASISheetButton(cb, html) { static async addASISheetButton(cb, html) {
// exit out because we dont want these
if (!CompendiumBrowser.extraButtonsGlobal || !CompendiumBrowser.extraAdvancementButtons) {
return;
}
await html.find(".feat-browser-btn").remove(); await html.find(".feat-browser-btn").remove();
let dropArea = html.find("h3:nth-child(3)"); let dropArea = html.find("h3:nth-child(3)");
const cbButton = $( const cbButton = $(
`<span style="font-size: 16px;"> `<span style="font-size: 16px;">
<a class="compendium-browser feat-browser-btn"> <a data-tooltip="CMPBrowser.ToolTip.Feats" class="compendium-browser feat-browser-btn">
<i class="fa-duotone fa-book"></i> <i class="fa-duotone fa-book"></i>
</a> </a>
</span>` </span>`