"use strict";
class SpellsSublistManager extends SublistManager {
static get _ROW_TEMPLATE () {
return [
new SublistCellTemplate({
name: "Name",
css: "bold ve-col-3-2 pl-0",
colStyle: "",
}),
new SublistCellTemplate({
name: "Level",
css: "capitalize ve-col-1-5 ve-text-center",
colStyle: "text-center",
}),
new SublistCellTemplate({
name: "Time",
css: "ve-col-1-8 ve-text-center",
colStyle: "text-center",
}),
new SublistCellTemplate({
name: "School",
css: "capitalize ve-col-1-6 ve-text-center",
colStyle: "text-center",
}),
new SublistCellTemplate({
name: "C.",
css: "concentration--sublist ve-col-0-7 ve-text-center",
colStyle: "text-center",
}),
new SublistCellTemplate({
name: "Range",
css: "range ve-col-3-2 pr-0 text-right",
colStyle: "text-right",
}),
];
}
pGetSublistItem (spell, hash) {
const school = Parser.spSchoolAndSubschoolsAbvsShort(spell.school, spell.subschools);
const time = PageFilterSpells.getTblTimeStr(spell.time[0]);
const concentration = spell._isConc ? "×" : "";
const range = Parser.spRangeToFull(spell.range);
const cellsText = [
spell.name,
PageFilterSpells.getTblLevelStr(spell),
time,
new SublistCell({
text: school,
title: Parser.spSchoolAndSubschoolsAbvsToFull(spell.school, spell.subschools),
css: `sp__school-${spell.school}`,
style: Parser.spSchoolAbvToStyle(spell.school),
}),
new SublistCell({
text: concentration,
title: concentration ? "Concentration" : "",
}),
range,
];
const $ele = $(`
`)
.contextmenu(evt => this._handleSublistItemContextMenu(evt, listItem))
.click(evt => this._listSub.doSelect(listItem, evt));
const listItem = new ListItem(
hash,
$ele,
spell.name,
{
hash,
school,
level: spell.level,
time,
concentration,
range,
normalisedTime: spell._normalisedTime,
normalisedRange: spell._normalisedRange,
},
{
entity: spell,
mdRow: [...cellsText],
},
);
return listItem;
}
}
class SpellsPageSettingsManager extends ListPageSettingsManager {
_getSettings () {
return {
...RenderSpells.SETTINGS,
};
}
}
class SpellPageBookView extends ListPageBookView {
static _BOOK_VIEW_MODE_K = "bookViewMode";
constructor (opts) {
super({
pageTitle: "Spells Book View",
namePlural: "spells",
propMarkdown: "spell",
...opts,
});
this._bookViewLastOrder = null;
this._$wrpContent = null;
}
_getSorted (a, b) {
return this._bookViewLastOrder === "0" ? SortUtil.ascSort(a.level, b.level) : SortUtil.ascSortLower(a.name, b.name);
}
async _$pGetWrpControls ({$wrpContent}) {
const out = await super._$pGetWrpControls({$wrpContent});
const {$wrpPrint} = out;
this._bookViewLastOrder = StorageUtil.syncGetForPage(SpellPageBookView._BOOK_VIEW_MODE_K);
if (this._bookViewLastOrder != null) this._bookViewLastOrder = `${this._bookViewLastOrder}`;
const $selSortMode = $(``)
.change(() => {
if (!this._bookViewToShow.length && Hist.lastLoadedId != null) return;
const val = $selSortMode.val();
if (val === "0") this._renderByLevel();
else this._renderByAlpha();
StorageUtil.syncSetForPage(SpellPageBookView._BOOK_VIEW_MODE_K, val);
});
if (this._bookViewLastOrder != null) $selSortMode.val(this._bookViewLastOrder);
$$`Sort order:
${$selSortMode}
`.appendTo($wrpPrint);
return out;
}
_renderSpell ({stack, sp}) {
stack.push(``);
stack.push(Renderer.spell.getCompactRenderedString(sp));
stack.push(`
`);
}
_renderByLevel () {
let isAnyEntityRendered = false;
const stack = [];
for (let i = 0; i < 10; ++i) {
const atLvl = this._bookViewToShow.filter(sp => sp.level === i);
if (atLvl.length) {
stack.push(``);
stack.push(`
${Parser.spLevelToFullLevelText(i)}
`);
atLvl.forEach(sp => this._renderSpell({stack, sp}));
isAnyEntityRendered = true;
stack.push(`
`);
}
}
this._$wrpContent.empty().append(stack.join(""));
this._bookViewLastOrder = "0";
return {isAnyEntityRendered};
}
_renderByAlpha () {
const stack = [];
this._bookViewToShow.forEach(sp => this._renderSpell({stack, sp}));
this._$wrpContent.empty().append(stack.join(""));
this._bookViewLastOrder = "1";
return {isAnyEntityRendered: !!this._bookViewToShow.length};
}
_renderNoneSelected () {
const stack = [];
stack.push(``);
this._renderSpell({stack, sp: this._fnGetEntLastLoaded()});
stack.push(`
`);
this._$wrpContent.empty().append(stack.join(""));
return {isAnyEntityRendered: false};
}
_renderSpells () {
if (!this._bookViewToShow.length && Hist.lastLoadedId != null) return this._renderNoneSelected();
else if (this._bookViewLastOrder === "1") return this._renderByAlpha();
else return this._renderByLevel();
}
async _pGetRenderContentMeta ({$wrpContent, $wrpControls}) {
this._$wrpContent = $wrpContent;
$wrpContent.addClass("p-2");
this._bookViewToShow = this._sublistManager.getSublistedEntities()
.sort((a, b) => SortUtil.ascSortLower(a.name, b.name));
const {isAnyEntityRendered} = this._renderSpells();
return {
cntSelectedEnts: this._bookViewToShow.length,
isAnyEntityRendered,
};
}
}
class SpellsPage extends ListPageMultiSource {
constructor () {
const pFnGetFluff = Renderer.spell.pGetFluff.bind(Renderer.spell);
super({
pageFilter: new PageFilterSpells(),
listOptions: {
fnSort: PageFilterSpells.sortSpells,
},
dataProps: ["spell"],
pFnGetFluff,
bookViewOptions: {
ClsBookView: SpellPageBookView,
},
tableViewOptions: {
title: "Spells",
colTransforms: {
name: UtilsTableview.COL_TRANSFORM_NAME,
source: UtilsTableview.COL_TRANSFORM_SOURCE,
page: UtilsTableview.COL_TRANSFORM_PAGE,
level: {name: "Level", transform: (it) => Parser.spLevelToFull(it)},
time: {name: "Casting Time", transform: (it) => PageFilterSpells.getTblTimeStr(it[0])},
duration: {name: "Duration", transform: (it) => Parser.spDurationToFull(it)},
_school: {
name: "School",
transform: (sp) => {
const ptMeta = Parser.spMetaToArr(sp.meta);
return `${Parser.spSchoolAndSubschoolsAbvsToFull(sp.school, sp.subschools)}${ptMeta.length ? ` (${ptMeta.join(", ")})` : ""}`;
},
},
range: {name: "Range", transform: (it) => Parser.spRangeToFull(it)},
_components: {name: "Components", transform: (sp) => Parser.spComponentsToFull(sp.components, sp.level, {isPlainText: true})},
_classes: {
name: "Classes",
transform: (sp) => {
const [current] = Parser.spClassesToCurrentAndLegacy(Renderer.spell.getCombinedClasses(sp, "fromClassList"));
return Parser.spMainClassesToFull(current);
},
},
_classesVariant: {
name: "Optional/Variant Classes",
transform: (sp) => {
const [current] = Parser.spVariantClassesToCurrentAndLegacy(Renderer.spell.getCombinedClasses(sp, "fromClassListVariant"));
return Parser.spMainClassesToFull(current);
},
},
entries: {name: "Text", transform: (it) => Renderer.get().render({type: "entries", entries: it}, 1), flex: 3},
entriesHigherLevel: {name: "At Higher Levels", transform: (it) => Renderer.get().render({type: "entries", entries: (it || [])}, 1), flex: 2},
},
},
propLoader: "spell",
listSyntax: new ListSyntaxSpells({fnGetDataList: () => this._dataList, pFnGetFluff}),
compSettings: new SpellsPageSettingsManager(),
});
this._lastFilterValues = null;
this._subclassLookup = {};
this._bookViewLastOrder = null;
}
get _bindOtherButtonsOptions () {
return {
upload: {
pFnPreLoad: (...args) => this._pPreloadSublistSources(...args),
},
sendToBrew: {
mode: "spellBuilder",
fnGetMeta: () => ({
page: UrlUtil.getCurrentPage(),
source: Hist.getHashSource(),
hash: Hist.getHashParts()[0],
}),
},
other: [
this._bindOtherButtonsOptions_openAsSinglePage({slugPage: "spells", fnGetHash: () => Hist.getHashParts()[0]}),
].filter(Boolean),
};
}
getListItem (spell, spI) {
const hash = UrlUtil.autoEncodeHash(spell);
if (this._seenHashes.has(hash)) return null;
this._seenHashes.add(hash);
const isExcluded = ExcludeUtil.isExcluded(hash, "spell", spell.source);
this._pageFilter.mutateAndAddToFilters(spell, isExcluded);
const source = Parser.sourceJsonToAbv(spell.source);
const time = PageFilterSpells.getTblTimeStr(spell.time[0]);
const school = Parser.spSchoolAndSubschoolsAbvsShort(spell.school, spell.subschools);
const concentration = spell._isConc ? "×" : "";
const range = Parser.spRangeToFull(spell.range);
const eleLi = e_({
tag: "div",
clazz: `lst__row ve-flex-col ${isExcluded ? "lst__row--blocklisted" : ""}`,
click: (evt) => this._list.doSelect(listItem, evt),
contextmenu: (evt) => this._openContextMenu(evt, this._list, listItem),
children: [
e_({
tag: "a",
href: `#${hash}`,
clazz: "lst--border lst__row-inner",
children: [
e_({tag: "span", clazz: `bold ve-col-2-9 pl-0`, text: spell.name}),
e_({tag: "span", clazz: `ve-col-1-5 ve-text-center`, text: PageFilterSpells.getTblLevelStr(spell)}),
e_({tag: "span", clazz: `ve-col-1-7 ve-text-center`, text: time}),
e_({
tag: "span",
clazz: `ve-col-1-2 sp__school-${spell.school} ve-text-center`,
title: Parser.spSchoolAndSubschoolsAbvsToFull(spell.school, spell.subschools),
style: Parser.spSchoolAbvToStylePart(spell.school),
text: school,
}),
e_({tag: "span", clazz: `ve-col-0-6 ve-text-center`, title: "Concentration", text: concentration}),
e_({tag: "span", clazz: `ve-col-2-4 text-right`, text: range}),
e_({
tag: "span",
clazz: `ve-col-1-7 ve-text-center ${Parser.sourceJsonToSourceClassname(spell.source)} pr-0`,
style: Parser.sourceJsonToStylePart(spell.source),
title: `${Parser.sourceJsonToFull(spell.source)}${Renderer.utils.getSourceSubText(spell)}`,
text: source,
}),
],
}),
],
});
const listItem = new ListItem(
spI,
eleLi,
spell.name,
{
hash,
source,
level: spell.level,
time,
school: Parser.spSchoolAbvToFull(spell.school),
concentration,
normalisedTime: spell._normalisedTime,
normalisedRange: spell._normalisedRange,
},
{
isExcluded,
},
);
return listItem;
}
_tabTitleStats = "Spell";
_renderStats_doBuildStatsTab ({ent}) {
this._$pgContent.empty().append(RenderSpells.$getRenderedSpell(ent, this._subclassLookup, {settings: this._compSettings.getValues()}));
}
async _pOnLoad_pPreDataLoad () {
const subclassLookup = await DataUtil.class.pGetSubclassLookup();
Object.assign(this._subclassLookup, subclassLookup);
}
async _pOnLoad_pPreDataAdd () {
Renderer.spell.populatePrereleaseLookup(await PrereleaseUtil.pGetBrewProcessed());
Renderer.spell.populateBrewLookup(await BrewUtil2.pGetBrewProcessed());
}
async _pPreloadSublistSources (json) {
const loaded = Object.keys(this._loadedSources)
.filter(it => this._loadedSources[it].loaded);
const lowerSources = json.sources.map(it => it.toLowerCase());
const toLoad = Object.keys(this._loadedSources)
.filter(it => !loaded.includes(it))
.filter(it => lowerSources.includes(it.toLowerCase()));
const loadTotal = toLoad.length;
if (loadTotal) {
await Promise.all(toLoad.map(src => this._pLoadSource(src, "yes")));
}
}
}
const spellsPage = new SpellsPage();
spellsPage.sublistManager = new SpellsSublistManager();
window.addEventListener("load", () => spellsPage.pOnLoad());