This commit is contained in:
TheGiddyLimit
2024-04-16 23:10:29 +01:00
parent 5e0cc455b9
commit adec95d4ab
36 changed files with 1730 additions and 294 deletions

View File

@@ -374,7 +374,7 @@ class BestiaryPage extends ListPageMultiSource {
this._$wrpBtnProf = null;
this._$btnProf = null;
this._profDicMode = _BestiaryConsts.PROF_MODE_BONUS;
this._profDiceMode = null;
this._encounterBuilder = null;
@@ -520,27 +520,36 @@ class BestiaryPage extends ListPageMultiSource {
}
async _pOnLoad_pPreDataAdd () {
this._pPageInit_profBonusDiceToggle();
await this._pPageInit_pProfBonusDiceToggle();
}
_pOnLoad_pPostLoad () {
this._encounterBuilder.render();
}
_pPageInit_profBonusDiceToggle () {
async _pPageInit_pProfBonusDiceToggle () {
const $btnProfBonusDice = $("button#profbonusdice");
this._profDiceMode = await StorageUtil.pGetForPage("proficiencyDiceMode") || _BestiaryConsts.PROF_MODE_BONUS;
const hk = () => {
$btnProfBonusDice.text(this._profDiceMode === _BestiaryConsts.PROF_MODE_DICE ? "Use Proficiency Bonus" : "Use Proficiency Dice");
this._$pgContent.attr("data-proficiency-dice-mode", this._profDiceMode);
StorageUtil.pSetForPage("proficiencyDiceMode", this._profDiceMode).then(null);
};
$btnProfBonusDice.click(() => {
if (this._profDicMode === _BestiaryConsts.PROF_MODE_DICE) {
this._profDicMode = _BestiaryConsts.PROF_MODE_BONUS;
$btnProfBonusDice.html("Use Proficiency Dice");
this._$pgContent.attr("data-proficiency-dice-mode", this._profDicMode);
} else {
this._profDicMode = _BestiaryConsts.PROF_MODE_DICE;
$btnProfBonusDice.html("Use Proficiency Bonus");
this._$pgContent.attr("data-proficiency-dice-mode", this._profDicMode);
if (this._profDiceMode === _BestiaryConsts.PROF_MODE_DICE) {
this._profDiceMode = _BestiaryConsts.PROF_MODE_BONUS;
hk();
return;
}
this._profDiceMode = _BestiaryConsts.PROF_MODE_DICE;
hk();
});
hk();
}
_handleBestiaryLiClick (evt, listItem) {
@@ -557,11 +566,9 @@ class BestiaryPage extends ListPageMultiSource {
}
_bindProfDiceHandlers () {
this._$pgContent.attr("data-proficiency-dice-mode", this._profDicMode);
this._$pgContent
.on(`mousedown`, `[data-roll-prof-type]`, evt => {
if (this._profDicMode !== _BestiaryConsts.PROF_MODE_BONUS) evt.preventDefault();
if (this._profDiceMode !== _BestiaryConsts.PROF_MODE_BONUS) evt.preventDefault();
})
.on(`click`, `[data-roll-prof-type]`, evt => {
const parent = evt.currentTarget.closest(`[data-roll-prof-type]`);
@@ -571,7 +578,7 @@ class BestiaryPage extends ListPageMultiSource {
switch (type) {
case "d20": {
if (this._profDicMode === _BestiaryConsts.PROF_MODE_BONUS) return;
if (this._profDiceMode === _BestiaryConsts.PROF_MODE_BONUS) return;
evt.stopPropagation();
evt.preventDefault();
@@ -585,7 +592,7 @@ class BestiaryPage extends ListPageMultiSource {
}
case "dc": {
if (this._profDicMode === _BestiaryConsts.PROF_MODE_BONUS) {
if (this._profDiceMode === _BestiaryConsts.PROF_MODE_BONUS) {
evt.stopPropagation();
evt.preventDefault();
return;
@@ -736,7 +743,7 @@ class BestiaryPage extends ListPageMultiSource {
if (isNaN(text) || expectedPB <= 0) return null;
const withoutPB = Number(text) - expectedPB;
const profDiceString = BestiaryPage._addSpacesToDiceExp(`+1d${(expectedPB * 2)}${withoutPB >= 0 ? "+" : ""}${withoutPB}`);
const profDiceString = BestiaryPage._addSpacesToDiceExp(`1d${(expectedPB * 2)}${withoutPB >= 0 ? "+" : ""}${withoutPB}`);
return `DC <span class="rd__dc rd__dc--rollable" data-roll-prof-type="dc" data-roll-prof-dice="${profDiceString.qq()}"><span class="rd__dc--rollable-text">${text}</span><span class="rd__dc--rollable-dice">${profDiceString}</span></span>`;
};

View File

@@ -1160,14 +1160,12 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
// region HP/hit dice
let $ptHp = null;
if (cls.hd) {
const hdEntry = Renderer.class.getHitDiceEntry(cls.hd);
$ptHp = $(`<tr></tr>`)
.fastSetHtml(`<td colspan="6" class="cls-side__section">
<h5 class="cls-side__section-head">Hit Points</h5>
<div><strong>Hit Dice:</strong> ${Renderer.getEntryDice(hdEntry, "Hit die")}</div>
<div><strong>Hit Dice:</strong> ${Renderer.get().render(Renderer.class.getHitDiceEntry(cls.hd))}</div>
<div><strong>Hit Points at 1st Level:</strong> ${Renderer.class.getHitPointsAtFirstLevel(cls.hd)}</div>
<div><strong>Hit Points at Higher Levels:</strong> ${Renderer.class.getHitPointsAtHigherLevels(cls.name, cls.hd, hdEntry)}</div>
<div><strong>Hit Points at Higher Levels:</strong> ${Renderer.class.getHitPointsAtHigherLevels(cls.name, cls.hd)}</div>
</td>`);
$ptsToToggle.push($ptHp);
}

View File

@@ -95,10 +95,6 @@ class RaceTraitTag {
traitTags.add("Magic Resistance");
}
if (/\bblindsight\b/i.test(str)) {
traitTags.add("Blindsight");
}
if (/\bsunlight sensitivity\b/i.test(str) || /\bdisadvantage [^.?!]+ direct sunlight\b/i.test(str)) {
traitTags.add("Sunlight Sensitivity");
}
@@ -143,11 +139,24 @@ class RaceLanguageTag {
return outStack;
}
static _LANGUAGES = new Set(["Abyssal", "Aquan", "Auran", "Celestial", "Common", "Draconic", "Dwarvish", "Elvish", "Giant", "Gnomish", "Goblin", "Halfling", "Ignan", "Infernal", "Orc", "Primordial", "Sylvan", "Terran", "Undercommon"]);
static _LANGUAGES = new Set([...Parser.LANGUAGES_STANDARD, ...Parser.LANGUAGES_EXOTIC]);
static _STOPWORDS = new Set(["Almost", "Elven", "Gifted", "It", "Languages", "Many", "Mimicry", "Only", "Or", "The", "Their", "They", "You", "Humans", "Conclave", "Kryta", "Hyperium", "Ithean", "Illyrian", "Speak"]);
static _isCaps (str) { return /^[A-Z]/.test(str); }
static _getTokens (str) {
let tokens = str.split(" ");
for (let i = 0; i < tokens.length; ++i) {
if (tokens[i] === "Deep" && /^Speech\W?$/.test(tokens[i + 1] || "")) {
tokens[i] = [tokens[i], tokens[i + 1]].join(" ");
tokens.splice(i + 1, 1);
}
}
return tokens;
}
static _handleString ({str, outStack, cbWarning, cbError}) {
// Remove the first word of each sentence, as it has non-title-based caps
str = str.trim().replace(/(^\w+|[.?!]\s*\w+)/g, "");
@@ -165,9 +174,9 @@ class RaceLanguageTag {
// Tokenize, removing anything that we don't care about
const reChoose = /^(?:choice|choose|choosing|chosen|chooses|chose)$/;
const tokens = str.split(" ")
const tokens = this._getTokens(str)
// replace all non-word characters (i.e. remove punctuation from tokens)
.map(it => it.replace(/\W/g, "").trim())
.map(it => it.replace(/[^\w ]/g, "").trim())
.filter(t => {
if (!t) return false;

View File

@@ -63,14 +63,26 @@ class PageFilterClassesRaw extends PageFilterClassesBase {
}
static async pPostLoad (data, {...opts} = {}) {
data = MiscUtil.copy(data);
// region Copy data
data = {...data};
const {propsCopied} = opts;
if (!data.class) data.class = [];
else data.class = MiscUtil.copyFast(data.class);
if (data.subclass) data.subclass = MiscUtil.copyFast(data.subclass);
if (propsCopied) {
propsCopied.add("class");
propsCopied.add("subclass");
}
// endregion
// Ensure prerelease/homebrew is initialised
await PrereleaseUtil.pGetBrewProcessed();
await BrewUtil2.pGetBrewProcessed();
if (!data.class) data.class = [];
// Attach subclasses to parent classes
if (data.subclass) {
// Do this sequentially, to avoid double-adding the same base classes
@@ -84,7 +96,7 @@ class PageFilterClassesRaw extends PageFilterClassesBase {
cls = await this._pGetParentClass(sc);
if (cls) {
// If a base class exists, make a stripped-down copy and override its subclasses with our own
cls = MiscUtil.copy(cls);
cls = MiscUtil.copyFast(cls);
cls.subclasses = [];
data.class.push(cls);
} else {
@@ -313,7 +325,7 @@ class PageFilterClassesRaw extends PageFilterClassesBase {
ent.name = name;
ent.source = source;
const entityRoot = raw != null ? MiscUtil.copy(raw) : await DataLoader.pCacheAndGet(`raw_${prop}`, ent.source, ent.hash, {isCopy: true});
const entityRoot = raw != null ? MiscUtil.copyFast(raw) : await DataLoader.pCacheAndGet(`raw_${prop}`, ent.source, ent.hash, {isCopy: true});
const loadedRoot = {
type: prop,
entity: entityRoot,
@@ -362,8 +374,8 @@ class PageFilterClassesRaw extends PageFilterClassesBase {
if (!sideData) return false;
if (sideData.isIgnored) return true;
if (sideData.entries) entity.entries = MiscUtil.copy(sideData.entries);
if (sideData.entryData) entity.entryData = MiscUtil.copy(sideData.entryData);
if (sideData.entries) entity.entries = MiscUtil.copyFast(sideData.entries);
if (sideData.entryData) entity.entryData = MiscUtil.copyFast(sideData.entryData);
return false;
}
@@ -679,7 +691,7 @@ class ModalFilterClasses extends ModalFilter {
if (it.data.ixSubclass == null) out.class = this._filterCache.allData[it.data.ixClass];
else out.subclass = this._filterCache.allData[it.data.ixClass].subclasses[it.data.ixSubclass];
});
resolve(MiscUtil.copy(out));
resolve(MiscUtil.copyFast(out));
doClose(true);
@@ -912,7 +924,7 @@ class ModalFilterClasses extends ModalFilter {
async _pLoadAllData () {
this._pLoadingAllData = this._pLoadingAllData || (async () => {
const [data, prerelease, brew] = await Promise.all([
MiscUtil.copy(await DataUtil.class.loadRawJSON()),
MiscUtil.copyFast(await DataUtil.class.loadRawJSON()),
PrereleaseUtil.pGetBrewProcessed(),
BrewUtil2.pGetBrewProcessed(),
]);
@@ -932,13 +944,13 @@ class ModalFilterClasses extends ModalFilter {
const clsProps = brewUtil.getPageProps({page: UrlUtil.PG_CLASSES});
if (!clsProps.includes("*")) {
clsProps.forEach(prop => data[prop] = [...(data[prop] || []), ...MiscUtil.copy(brew[prop] || [])]);
clsProps.forEach(prop => data[prop] = [...(data[prop] || []), ...MiscUtil.copyFast(brew[prop] || [])]);
return;
}
Object.entries(brew)
.filter(([, brewVal]) => brewVal instanceof Array)
.forEach(([prop, brewArr]) => data[prop] = [...(data[prop] || []), ...MiscUtil.copy(brewArr)]);
.forEach(([prop, brewArr]) => data[prop] = [...(data[prop] || []), ...MiscUtil.copyFast(brewArr)]);
}
_getListItems (pageFilter, cls, clsI) {

View File

@@ -2645,6 +2645,7 @@ Parser.SRC_MPP = "MPP";
Parser.SRC_BMT = "BMT";
Parser.SRC_DMTCRG = "DMTCRG";
Parser.SRC_QftIS = "QftIS";
Parser.SRC_VEoR = "VEoR";
Parser.SRC_GHLoE = "GHLoE";
Parser.SRC_DoDk = "DoDk";
Parser.SRC_HWCS = "HWCS";
@@ -2677,6 +2678,7 @@ Parser.SRC_LK = "LK";
Parser.SRC_CoA = "CoA";
Parser.SRC_PiP = "PiP";
Parser.SRC_DitLCoT = "DitLCoT";
Parser.SRC_VNotEE = "VNotEE";
Parser.SRC_LRDT = "LRDT";
Parser.SRC_AL_PREFIX = "AL";
@@ -2825,6 +2827,7 @@ Parser.SOURCE_JSON_TO_FULL[Parser.SRC_MPP] = "Morte's Planar Parade";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_BMT] = "The Book of Many Things";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_DMTCRG] = "The Deck of Many Things: Card Reference Guide";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_QftIS] = "Quests from the Infinite Staircase";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_VEoR] = "Vecna: Eve of Ruin";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_GHLoE] = "Grim Hollow: Lairs of Etharis";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_DoDk] = "Dungeons of Drakkenheim";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_HWCS] = "Humblewood Campaign Setting";
@@ -2857,6 +2860,7 @@ Parser.SOURCE_JSON_TO_FULL[Parser.SRC_LK] = "Lightning Keep";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_CoA] = "Chains of Asmodeus";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_PiP] = "Peril in Pinebrook";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_DitLCoT] = "Descent into the Lost Caverns of Tsojcanth";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_VNotEE] = "Vecna: Nest of the Eldritch Eye";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_LRDT] = "Red Dragon's Tale: A LEGO Adventure";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_ALCoS] = `${Parser.AL_PREFIX}Curse of Strahd`;
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_ALEE] = `${Parser.AL_PREFIX}Elemental Evil`;
@@ -2980,6 +2984,7 @@ Parser.SOURCE_JSON_TO_ABV[Parser.SRC_MPP] = "MPP";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_BMT] = "BMT";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_DMTCRG] = "DMTCRG";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_QftIS] = "QftIS";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_VEoR] = "VEoR";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_GHLoE] = "GHLoE";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_DoDk] = "DoDk";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_HWCS] = "HWCS";
@@ -3012,6 +3017,7 @@ Parser.SOURCE_JSON_TO_ABV[Parser.SRC_LK] = "LK";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_CoA] = "CoA";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_PiP] = "PiP";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_DitLCoT] = "DitLCoT";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_VNotEE] = "VNotEE";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_LRDT] = "LRDT";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_ALCoS] = "ALCoS";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_ALEE] = "ALEE";
@@ -3134,6 +3140,7 @@ Parser.SOURCE_JSON_TO_DATE[Parser.SRC_MPP] = "2023-10-17";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_BMT] = "2023-11-14";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_DMTCRG] = "2023-11-14";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_QftIS] = "2024-07-16";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_VEoR] = "2024-05-21";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_GHLoE] = "2023-11-30";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_DoDk] = "2023-12-21";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_HWCS] = "2019-06-17";
@@ -3166,6 +3173,7 @@ Parser.SOURCE_JSON_TO_DATE[Parser.SRC_LK] = "2023-09-26";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_CoA] = "2023-10-30";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_PiP] = "2023-11-20";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_DitLCoT] = "2024-03-26";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_VNotEE] = "2024-04-16";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_LRDT] = "2024-04-01";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_ALCoS] = "2016-03-15";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_ALEE] = "2015-04-07";
@@ -3185,6 +3193,7 @@ Parser.SOURCE_JSON_TO_DATE[Parser.SRC_MCV4EC] = "2023-09-21";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_MisMV1] = "2023-05-03";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_AATM] = "2023-10-17";
// region Source categories
Parser.SOURCES_ADVENTURES = new Set([
Parser.SRC_LMoP,
Parser.SRC_HotDQ,
@@ -3264,6 +3273,7 @@ Parser.SOURCES_ADVENTURES = new Set([
Parser.SRC_CoA,
Parser.SRC_PiP,
Parser.SRC_DitLCoT,
Parser.SRC_VNotEE,
Parser.SRC_LRDT,
Parser.SRC_HFStCM,
Parser.SRC_GHLoE,
@@ -3336,7 +3346,11 @@ Parser.SOURCES_PARTNERED_WOTC = new Set([
Parser.SRC_TD,
Parser.SRC_LRDT,
]);
// region Source categories
Parser.SOURCES_LEGACY_WOTC = new Set([
Parser.SRC_EEPC,
Parser.SRC_VGM,
Parser.SRC_MTF,
]);
// An opinionated set of source that could be considered "core-core"
Parser.SOURCES_VANILLA = new Set([
@@ -3564,6 +3578,8 @@ Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE = {};
Parser.SRC_HWAitW,
Parser.SRC_QftIS,
Parser.SRC_LRDT,
Parser.SRC_VEoR,
Parser.SRC_VNotEE,
].forEach(src => {
Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE[src] = src;
Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE[src.toLowerCase()] = src;

View File

@@ -399,7 +399,7 @@ class RendererMarkdown {
this._recursiveRender(by, tempStack, meta);
if (i < len - 1) tempStack[0] += "\n";
}
textStack[0] += `\u2014 ${tempStack.join("")}${entry.from ? `, *${entry.from}*` : ""}`;
textStack[0] += `\u2014 ${tempStack.join("")}${entry.from ? `, *${this.render(entry.from)}*` : ""}`;
}
}

View File

@@ -1172,7 +1172,7 @@ globalThis.Renderer = function () {
if (i < len - 1) tempStack[0] += "<br>";
}
}
textStack[0] += `<span class="rd__quote-by">\u2014 ${byArr ? tempStack.join("") : ""}${byArr && entry.from ? `, ` : ""}${entry.from ? `<i>${entry.from}</i>` : ""}</span>`;
textStack[0] += `<span class="rd__quote-by">\u2014 ${byArr ? tempStack.join("") : ""}${byArr && entry.from ? `, ` : ""}${entry.from ? `<i>${this.render(entry.from)}</i>` : ""}</span>`;
textStack[0] += `</p>`;
}
@@ -1251,7 +1251,21 @@ globalThis.Renderer = function () {
this._renderDice = function (entry, textStack, meta, options) {
const pluginResults = this._applyPlugins_getAll("dice", {textStack, meta, options}, {input: entry});
textStack[0] += Renderer.getEntryDice(entry, entry.name, {isAddHandlers: this._isAddHandlers, pluginResults});
for (const res of pluginResults) {
if (res.rendered) {
textStack[0] += res.rendered;
return;
}
}
const toDisplay = Renderer.getEntryDiceDisplayText(entry);
if (entry.rollable === true) {
textStack[0] += Renderer.getRollableEntryDice(entry, entry.name, toDisplay, {isAddHandlers: this._isAddHandlers, pluginResults});
return;
}
textStack[0] += toDisplay;
};
this._renderActions = function (entry, textStack, meta, options) {
@@ -2386,13 +2400,6 @@ Renderer._splitByPipeBase = function (leadingCharacter) {
Renderer.splitTagByPipe = Renderer._splitByPipeBase("@");
Renderer.getEntryDice = function (entry, name, opts = {}) {
const toDisplay = Renderer.getEntryDiceDisplayText(entry);
if (entry.rollable === true) return Renderer.getRollableEntryDice(entry, name, toDisplay, opts);
else return toDisplay;
};
Renderer.getRollableEntryDice = function (
entry,
name,
@@ -3685,7 +3692,12 @@ Renderer.utils = class {
if ((!fauxEntry.displayText && (rollText || "").includes("#$")) || (fauxEntry.displayText && fauxEntry.displayText.includes("#$"))) fauxEntry.displayText = (fauxEntry.displayText || rollText).replace(/#\$prompt_number[^$]*\$#/g, "(n)");
fauxEntry.displayText = fauxEntry.displayText || fauxEntry.toRoll;
if (tag === "@damage") fauxEntry.subType = "damage";
if (tag === "@damage") {
fauxEntry.subType = "damage";
const [damageType] = others;
if (damageType) fauxEntry.damageType = damageType;
}
if (tag === "@autodice") fauxEntry.autoRoll = true;
return fauxEntry;
@@ -4439,13 +4451,13 @@ Renderer.tag = class {
}
};
static TagHit = class extends this._TagBaseAt {
static TagHitText = class extends this._TagBaseAt {
tagName = "h";
_getStripped (tag, text) { return "Hit: "; }
};
static TagMiss = class extends this._TagBaseAt {
static TagMissText = class extends this._TagBaseAt {
tagName = "m";
_getStripped (tag, text) { return "Miss: "; }
@@ -4525,43 +4537,43 @@ Renderer.tag = class {
}
};
static TaChance = class extends this._TagDiceFlavor {
static TagChance = class extends this._TagDiceFlavor {
tagName = "chance";
};
static TaD20 = class extends this._TagDiceFlavor {
static TagD20 = class extends this._TagDiceFlavor {
tagName = "d20";
};
static TaDamage = class extends this._TagDiceFlavor {
static TagDamage = class extends this._TagDiceFlavor {
tagName = "damage";
};
static TaDice = class extends this._TagDiceFlavor {
static TagDice = class extends this._TagDiceFlavor {
tagName = "dice";
};
static TaAutodice = class extends this._TagDiceFlavor {
static TagAutodice = class extends this._TagDiceFlavor {
tagName = "autodice";
};
static TaHit = class extends this._TagDiceFlavor {
static TagHit = class extends this._TagDiceFlavor {
tagName = "hit";
};
static TaRecharge = class extends this._TagDiceFlavor {
static TagRecharge = class extends this._TagDiceFlavor {
tagName = "recharge";
};
static TaAbility = class extends this._TagDiceFlavor {
static TagAbility = class extends this._TagDiceFlavor {
tagName = "ability";
};
static TaSavingThrow = class extends this._TagDiceFlavor {
static TagSavingThrow = class extends this._TagDiceFlavor {
tagName = "savingThrow";
};
static TaSkillCheck = class extends this._TagDiceFlavor {
static TagSkillCheck = class extends this._TagDiceFlavor {
tagName = "skillCheck";
};
@@ -4970,8 +4982,8 @@ Renderer.tag = class {
new this.TagUnit(),
new this.TagHit(),
new this.TagMiss(),
new this.TagHitText(),
new this.TagMissText(),
new this.TagAtk(),
@@ -4981,16 +4993,16 @@ Renderer.tag = class {
new this.TagDcYourSpellSave(),
new this.TaChance(),
new this.TaD20(),
new this.TaDamage(),
new this.TaDice(),
new this.TaAutodice(),
new this.TaHit(),
new this.TaRecharge(),
new this.TaAbility(),
new this.TaSavingThrow(),
new this.TaSkillCheck(),
new this.TagChance(),
new this.TagD20(),
new this.TagDamage(),
new this.TagDice(),
new this.TagAutodice(),
new this.TagHit(),
new this.TagRecharge(),
new this.TagAbility(),
new this.TagSavingThrow(),
new this.TagSkillCheck(),
new this.TagScaledice(),
new this.TagScaledamage(),
@@ -5370,9 +5382,13 @@ Renderer.class = class {
return Renderer.hover.getGenericCompactRenderedString(clsEntry);
}
static getHitDiceEntry (clsHd) { return clsHd ? {toRoll: `${clsHd.number}d${clsHd.faces}`, rollable: true} : null; }
static getHitDiceEntry (clsHd) { return clsHd ? `{@dice ${clsHd.number}d${clsHd.faces}||Hit die}` : null; }
static getHitPointsAtFirstLevel (clsHd) { return clsHd ? `${clsHd.number * clsHd.faces} + your Constitution modifier` : null; }
static getHitPointsAtHigherLevels (className, clsHd, hdEntry) { return className && clsHd && hdEntry ? `${Renderer.getEntryDice(hdEntry, "Hit die")} (or ${((clsHd.number * clsHd.faces) / 2 + 1)}) + your Constitution modifier per ${className} level after 1st` : null; }
static getHitPointsAtHigherLevels (className, clsHd) {
return className && clsHd
? `${Renderer.get().render(Renderer.class.getHitDiceEntry(clsHd))} (or ${((clsHd.number * clsHd.faces) / 2 + 1)}) + your Constitution modifier per ${className} level after 1st`
: null;
}
static getRenderedArmorProfs (armorProfs) { return armorProfs.map(a => Renderer.get().render(a.full ? a.full : a === "light" || a === "medium" || a === "heavy" ? `{@filter ${a} armor|items|type=${a} armor}` : a)).join(", "); }
static getRenderedWeaponProfs (weaponProfs) { return weaponProfs.map(w => Renderer.get().render(w === "simple" || w === "martial" ? `{@filter ${w} weapons|items|type=${w} weapon}` : w.optional ? `<span class="help help--hover" title="Optional Proficiency">${w.proficiency}</span>` : w)).join(", "); }
@@ -6529,11 +6545,6 @@ Renderer.race = class {
if (cpySr.name) {
cpy._subraceName = cpySr.name;
if (cpySr.alias) {
cpy.alias = cpySr.alias.map(it => Renderer.race.getSubraceName(cpy.name, it));
delete cpySr.alias;
}
cpy.name = Renderer.race.getSubraceName(cpy.name, cpySr.name);
delete cpySr.name;
}
@@ -9533,6 +9544,7 @@ Renderer.variantrule = class {
static getCompactRenderedString (rule) {
const cpy = MiscUtil.copyFast(rule);
delete cpy.name;
if (cpy.entries && cpy.ruleType) cpy.entries.unshift(`{@i ${Parser.ruleTypeToFull(cpy.ruleType)} Rule}`);
return `
${Renderer.utils.getExcludedTr({entity: rule, dataProp: "variantrule", page: UrlUtil.PG_VARIANTRULES})}
${Renderer.utils.getNameTr(rule, {page: UrlUtil.PG_VARIANTRULES})}

View File

@@ -1886,7 +1886,7 @@ class DataLoader {
*/
static async pCacheAndGet (page, source, hash, {isCopy = false, isRequired = false, isSilent = false, lockToken2} = {}) {
const fromCache = this.getFromCache(page, source, hash, {isCopy, _isReturnSentinel: true});
if (fromCache === _DataLoaderConst.ENTITY_NULL) return null;
if (fromCache === _DataLoaderConst.ENTITY_NULL) return this._getVerifiedRequiredEntity({pageClean: page, sourceClean: source, hashClean: hash, ent: null, isRequired});
if (fromCache) return fromCache;
const {page: pageClean, source: sourceClean, hash: hashClean} = _DataLoaderInternalUtil.getCleanPageSourceHash({page, source, hash});

View File

@@ -117,6 +117,13 @@ PropOrder._ArrayKey = class {
}
};
PropOrder._PROPS_FOUNDRY_DATA = [
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
];
PropOrder._META = [
"sources",
@@ -472,10 +479,7 @@ PropOrder._SPELL = [
"fluff",
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
...PropOrder._PROPS_FOUNDRY_DATA,
new PropOrder._ObjectKey("roll20Spell", {
order: PropOrder._ROLL20_SPELL,
@@ -793,6 +797,17 @@ PropOrder._SUBCLASS__COPY_MOD = [
"_",
...PropOrder._SUBCLASS,
];
PropOrder._SUBCLASS_FLUFF = [
"name",
"source",
"className",
"classSource",
"_copy",
"entries",
"images",
];
PropOrder._FOUNDRY_SUBCLASS = [
"name",
"source",
@@ -973,6 +988,9 @@ PropOrder._LANGUAGE = [
];
PropOrder._LANGUAGE_SCRIPT = [
"name",
"source",
"fonts",
];
PropOrder._NAME = [
@@ -1017,10 +1035,7 @@ PropOrder._DISEASE = [
"entries",
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
...PropOrder._PROPS_FOUNDRY_DATA,
];
PropOrder._STATUS = [
"name",
@@ -1173,10 +1188,7 @@ PropOrder._FEAT = [
"fluff",
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
...PropOrder._PROPS_FOUNDRY_DATA,
];
PropOrder._FEAT__COPY_MOD = [
"*",
@@ -1450,10 +1462,7 @@ PropOrder._ITEM = [
"fluff",
"foundryType",
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
...PropOrder._PROPS_FOUNDRY_DATA,
];
PropOrder._ITEM__COPY_MOD = [
"*",
@@ -1586,10 +1595,7 @@ PropOrder._OPTIONALFEATURE = [
"fluff",
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
...PropOrder._PROPS_FOUNDRY_DATA,
];
PropOrder._OPTIONALFEATURE__COPY_MOD = [
"*",
@@ -1626,6 +1632,8 @@ PropOrder._REWARD = [
"hasFluffImages",
"fluff",
...PropOrder._PROPS_FOUNDRY_DATA,
];
PropOrder._VARIANTRULE = [
"name",
@@ -1694,10 +1702,7 @@ PropOrder._RACE_SUBRACE = [
"fluff",
"foundrySystem",
"foundryFlags",
"foundryEffects",
"foundryImg",
...PropOrder._PROPS_FOUNDRY_DATA,
new PropOrder._ArrayKey("_versions", {
fnGetOrder: () => [
@@ -2029,8 +2034,10 @@ PropOrder._PROP_TO_LIST = {
"background": PropOrder._BACKGROUND,
"legendaryGroup": PropOrder._LEGENDARY_GROUP,
"class": PropOrder._CLASS,
"classFluff": PropOrder._GENERIC_FLUFF,
"foundryClass": PropOrder._FOUNDRY_CLASS,
"subclass": PropOrder._SUBCLASS,
"subclassFluff": PropOrder._SUBCLASS_FLUFF,
"foundrySubclass": PropOrder._FOUNDRY_SUBCLASS,
"classFeature": PropOrder._CLASS_FEATURE,
"subclassFeature": PropOrder._SUBCLASS_FEATURE,

View File

@@ -2,7 +2,7 @@
// in deployment, `IS_DEPLOYED = "<version number>";` should be set below.
globalThis.IS_DEPLOYED = undefined;
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.204.0"/* 5ETOOLS_VERSION__CLOSE */;
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.205.0"/* 5ETOOLS_VERSION__CLOSE */;
globalThis.DEPLOYED_IMG_ROOT = undefined;
// for the roll20 script to set
globalThis.IS_VTT = false;
@@ -55,6 +55,7 @@ globalThis.VeCt = {
URL_BREW: `https://github.com/TheGiddyLimit/homebrew`,
URL_ROOT_BREW: `https://raw.githubusercontent.com/TheGiddyLimit/homebrew/master/`, // N.b. must end with a slash
URL_ROOT_BREW_IMG: `https://raw.githubusercontent.com/TheGiddyLimit/homebrew-img/main/`, // N.b. must end with a slash
URL_PRERELEASE: `https://github.com/TheGiddyLimit/unearthed-arcana`,
URL_ROOT_PRERELEASE: `https://raw.githubusercontent.com/TheGiddyLimit/unearthed-arcana/master/`, // As above
@@ -506,7 +507,7 @@ globalThis.SourceUtil = class {
static isLegacySourceWotc (source) {
if (source == null) return false;
return source === Parser.SRC_VGM || source === Parser.SRC_MTF;
return Parser.SOURCES_LEGACY_WOTC.has(source);
}
// TODO(Future) remove this in favor of simply checking existence in `PrereleaseUtil`
@@ -2975,6 +2976,7 @@ UrlUtil.URL_TO_HASH_BUILDER["skill"] = UrlUtil.URL_TO_HASH_GENERIC;
UrlUtil.URL_TO_HASH_BUILDER["sense"] = UrlUtil.URL_TO_HASH_GENERIC;
UrlUtil.URL_TO_HASH_BUILDER["raceFeature"] = (it) => UrlUtil.encodeArrayForHash(it.name, it.raceName, it.raceSource, it.source);
UrlUtil.URL_TO_HASH_BUILDER["citation"] = UrlUtil.URL_TO_HASH_GENERIC;
UrlUtil.URL_TO_HASH_BUILDER["languageScript"] = UrlUtil.URL_TO_HASH_GENERIC;
// Add lowercase aliases
Object.keys(UrlUtil.URL_TO_HASH_BUILDER)
@@ -5449,13 +5451,13 @@ globalThis.DataUtil = {
// region Populate fonts, based on script
const scriptLookup = {};
(rawData.languageScript || []).forEach(script => scriptLookup[script.name] = script);
(rawData.languageScript || []).forEach(script => MiscUtil.set(scriptLookup, script.source, script.name, script));
const out = {language: MiscUtil.copyFast(rawData.language)};
out.language.forEach(lang => {
if (!lang.script || lang.fonts === false) return;
const script = scriptLookup[lang.script];
const script = MiscUtil.get(scriptLookup, lang.source, lang.script);
if (!script) return;
lang._fonts = [...script.fonts];