"use strict"; class RenderBestiary { /** * @param mon Creature data. * @param [options] * @param [options.$btnScaleCr] CR scaler button. * @param [options.$btnResetScaleCr] CR scaler reset button. * @param [options.selSummonSpellLevel] Summon spell level selector. * @param [options.selSummonClassLevel] Summon spell level selector. * @param [options.isSkipExcludesRender] If the "this entity is blocklisted" display should be skipped. */ static $getRenderedCreature (mon, options) { const renderer = Renderer.get(); return Renderer.monster.getRenderWithPlugins({ renderer, mon, fn: () => RenderBestiary._$getRenderedCreature(mon, options, renderer), }); } static _$getRenderedCreature (mon, options, renderer) { options = options || {}; Renderer.monster.initParsed(mon); const fnGetSpellTraits = Renderer.monster.getSpellcastingRenderedTraits.bind(Renderer.monster, renderer); const allTraits = Renderer.monster.getOrderedTraits(mon, {fnGetSpellTraits}); const allActions = Renderer.monster.getOrderedActions(mon, {fnGetSpellTraits}); const allBonusActions = Renderer.monster.getOrderedBonusActions(mon, {fnGetSpellTraits}); const allReactions = Renderer.monster.getOrderedReactions(mon, {fnGetSpellTraits}); const legGroup = DataUtil.monster.getMetaGroup(mon); const renderedVariants = Renderer.monster.getRenderedVariants(mon, {renderer}); const htmlSourceAndEnvironment = this._$getRenderedCreature_getHtmlSourceAndEnvironment(mon, legGroup); const hasToken = Renderer.monster.hasToken(mon); const extraThClasses = hasToken ? ["mon__name--token"] : null; const ptsResource = mon.resource?.length ? mon.resource .map(res => `
${res.name} ${Renderer.monster.getRenderedResource(res)}
`) : []; return $$` ${Renderer.utils.getBorderTr()} ${!options.isSkipExcludesRender ? Renderer.utils.getExcludedTr({entity: mon, dataProp: "monster", page: UrlUtil.PG_BESTIARY}) : null} ${Renderer.utils.getNameTr(mon, {controlRhs: mon.soundClip ? RenderBestiary._getPronunciationButton(mon) : "", extraThClasses, page: UrlUtil.PG_BESTIARY, extensionData: {_scaledCr: mon._scaledCr, _scaledSpellSummonLevel: mon._scaledSpellSummonLevel, _scaledClassSummonLevel: mon._scaledClassSummonLevel}})}
${Renderer.monster.getTypeAlignmentPart(mon)}
Armor Class ${mon.ac == null ? "\u2014" : Parser.acToFull(mon.ac)}
Hit Points ${mon.hp == null ? "\u2014" : Renderer.monster.getRenderedHp(mon.hp)}
${ptsResource.join("")} Speed ${Parser.getSpeedString(mon)}
${Renderer.monster.getRenderedAbilityScores(mon)}
${mon.save ? `Saving Throws ${Renderer.monster.getSavesPart(mon)}` : ""} ${mon.skill ? `Skills ${Renderer.monster.getSkillsString(renderer, mon)}` : ""} ${mon.vulnerable ? `Damage Vulnerabilities ${Parser.getFullImmRes(mon.vulnerable)}` : ""} ${mon.resist ? `Damage Resistances ${Parser.getFullImmRes(mon.resist)}` : ""} ${mon.immune ? `Damage Immunities ${Parser.getFullImmRes(mon.immune)}` : ""} ${mon.conditionImmune ? `Condition Immunities ${Parser.getFullCondImm(mon.conditionImmune)}` : ""} Senses ${Renderer.monster.getSensesPart(mon)} Languages ${Renderer.monster.getRenderedLanguages(mon.languages)} ${Parser.crToNumber(mon.cr) < VeCt.CR_UNKNOWN ? $$` Challenge ${Parser.monCrToFull(mon.cr, {isMythic: !!mon.mythic})} ${options.$btnScaleCr || ""} ${options.$btnResetScaleCr || ""} ` : `Challenge \u2014`}${mon.pbNote || Parser.crToNumber(mon.cr) < VeCt.CR_CUSTOM ? `Proficiency Bonus ${mon.pbNote ?? UiUtil.intToBonus(Parser.crToPb(mon.cr), {isPretty: true})}` : ""} ${options.selSummonSpellLevel ? $$`Spell Level ${options.selSummonSpellLevel}` : ""} ${options.selSummonClassLevel ? $$`Class Level ${options.selSummonClassLevel}` : ""} ${allTraits?.length ? `
${RenderBestiary._getRenderedSection({prop: "trait", entries: allTraits})}` : ""} ${allActions?.length ? `${this._getRenderedSectionHeader({mon, title: "Actions", prop: "action"})} ${RenderBestiary._getRenderedSection({mon, prop: "action", entries: allActions})}` : ""} ${allBonusActions?.length ? `${this._getRenderedSectionHeader({mon, title: "Bonus Actions", prop: "bonus"})} ${RenderBestiary._getRenderedSection({mon, prop: "bonus", entries: allBonusActions})}` : ""} ${allReactions?.length ? `${this._getRenderedSectionHeader({mon, title: "Reactions", prop: "reaction"})} ${RenderBestiary._getRenderedSection({mon, prop: "reaction", entries: allReactions})}` : ""} ${mon.legendary ? `${this._getRenderedSectionHeader({mon, title: "Legendary Actions", prop: "legendary"})} ${RenderBestiary._getRenderedSection({mon, prop: "legendary", entries: mon.legendary, fnGetHeader: Renderer.monster.getLegendaryActionIntro.bind(Renderer.monster)})}` : ""} ${mon.mythic ? `${this._getRenderedSectionHeader({mon, title: "Mythic Actions", prop: "mythic"})} ${RenderBestiary._getRenderedSection({mon, prop: "mythic", entries: mon.mythic})}` : ""} ${legGroup && legGroup.lairActions ? `

Lair Actions

${RenderBestiary._getRenderedSection({prop: "lairaction", entries: legGroup.lairActions, depth: -1})}` : ""} ${legGroup && legGroup.regionalEffects ? `

Regional Effects

${RenderBestiary._getRenderedSection({prop: "regionaleffect", entries: legGroup.regionalEffects, depth: -1})}` : ""} ${renderedVariants ? `${renderedVariants}` : ""} ${mon.footer ? `${renderer.render({entries: mon.footer})}` : ""} ${mon.summonedBySpell ? `Summoned By: ${renderer.render(`{@spell ${mon.summonedBySpell}}`)}` : ""} ${htmlSourceAndEnvironment.length === 2 ? `${htmlSourceAndEnvironment[1]}` : ""} ${htmlSourceAndEnvironment[0]} ${Renderer.utils.getBorderTr()}`; } static _getRenderedSectionHeader ({mon, title, prop}) { const propNote = `${prop}Note`; return `

${title}${mon[propNote] ? ` (${mon[propNote]})` : ""}

`; } static _getRenderedSection ({mon = null, prop, entries, depth = 1, fnGetHeader = null}) { const renderer = Renderer.get(); const renderStack = []; switch (prop) { case "lairaction": case "regionaleffect": { renderer.setFirstSection(true).recursiveRender({entries: entries}, renderStack, {depth: depth + 1}); break; } case "legendary": case "mythic": { const cpy = MiscUtil.copy(entries).map(it => { if (it.name && it.entries) { it.name = `${it.name}.`; it.type = it.type || "item"; } return it; }); const toRender = {type: "list", style: "list-hang-notitle", items: cpy}; renderer.setFirstSection(true).recursiveRender(toRender, renderStack, {depth: depth}); break; } default: { entries.forEach(e => { if (e.rendered) renderStack.push(e.rendered); else renderer.setFirstSection(true).recursiveRender(e, renderStack, {depth: depth + 1}); }); } } const ptHeader = mon ? (fnGetHeader ? fnGetHeader(mon) : Renderer.monster.getSectionIntro(mon, {prop})) : ""; return `${ptHeader ? `${ptHeader}` : ""} ${renderStack.join("")}`; } static _getPronunciationButton (mon) { return ``; } static _$getRenderedCreature_getHtmlSourceAndEnvironment (mon, legGroup) { const srcCpy = { source: mon.source, page: mon.page, srd: mon.srd, sourceSub: mon.sourceSub, otherSources: mon.otherSources, additionalSources: mon.additionalSources, externalSources: mon.externalSources, reprintedAs: mon.reprintedAs, }; const additional = mon.additionalSources ? MiscUtil.copy(mon.additionalSources) : []; if (mon.variant?.length) { mon.variant.forEach(v => { if (!v.source) return ""; additional.push({ source: v.source, page: v.page, }); }); } if (legGroup) { if (legGroup.source !== mon.source) additional.push({source: legGroup.source, page: legGroup.page}); if (legGroup.additionalSources) additional.push(...MiscUtil.copy(legGroup.additionalSources)); } srcCpy.additionalSources = additional; const pageTrInner = Renderer.utils.getSourceAndPageTrHtml(srcCpy, {tag: "creature", fnUnpackUid: (uid) => DataUtil.generic.unpackUid(uid, "creature")}); if (!mon.environment?.length) return [pageTrInner]; return [pageTrInner, `
Environment: ${Renderer.monster.getRenderedEnvironment(mon.environment)}
`]; } static $getRenderedLegendaryGroup (legGroup) { return $$` ${Renderer.utils.getBorderTr()} ${Renderer.utils.getNameTr(legGroup)} ${legGroup.lairActions && legGroup.lairActions.length ? Renderer.get().render({type: "entries", entries: [{type: "entries", name: "Lair Actions", entries: legGroup.lairActions}]}) : ""} ${legGroup.regionalEffects && legGroup.regionalEffects.length ? Renderer.get().render({type: "entries", entries: [{type: "entries", name: "Regional Effects", entries: legGroup.regionalEffects}]}) : ""} ${legGroup.mythicEncounter && legGroup.mythicEncounter.length ? Renderer.get().render({type: "entries", entries: [{type: "entries", name: `<Creature Name> as a Mythic Encounter`, entries: legGroup.mythicEncounter}]}) : ""} ${Renderer.utils.getBorderTr()}`; } }