Scenario generator for vore roleplay and story ideas. https://scenario-generator.deliciousreya.net/responses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

134 lines
7.0 KiB

import {
type RollTable,
type RollTableDetails,
type RollTableDetailsAndResults,
type RollTableResult
} from './rolltable';
// TODO: port the rest of these to preact
export function buildGeneratorPage<T, BuilderT extends TemplateBuilder<T>>(
{ results, generatorTargetUrl, clientId, creditsUrl, editable, selected, includesResponses, builder }:
{ readonly results: ReadonlyMap<RollTable, RollTableResult>,
readonly generatorTargetUrl: string,
readonly clientId: string,
readonly creditsUrl: string,
readonly editable: boolean,
readonly selected: ReadonlySet<RollTable>,
readonly includesResponses: boolean,
readonly builder: BuilderT}): ReturnType<BuilderT["makeDiv"]> {
return builder.makeDiv(
{id: "generator", classes: "page"},
builder.makeForm({method: FormMethod.Post, action: generatorTargetUrl, id: "generatorWindow", classes: ["window", "readable"]},
builder.makeHeading2({id: "generatorHead"}, builder.makeText("Your generated scenario")),
builder.makeUnorderedList({id: "generatedScenario"},
...Array.from(results.values()).map(result =>
buildGeneratedElement({
result,
selected: (editable && includesResponses && result.table.full === 'results') ? selected.has(result.table) : null,
includesResponses,
builder}))),
builder.makeDiv({id: "generatorControls"},
builder.makeDiv({id: "copyButtons", classes: ["buttons", "requiresJs", "jsPopupHost"]},
builder.makeButton({id: "copyMD"}, builder.makeText("Markdown")),
builder.makeButton({id: "copyBB"}, builder.makeText("BBCode")),
builder.makeButton({id: "copyEmojiText"}, builder.makeText("Text + Emoji")),
builder.makeButton({id: "copyText"}, builder.makeText("Text Only")),
),
...(editable ? [builder.makeDiv({id: "rollButtons", classes: ["buttons"]},
builder.makeButton({type: ButtonType.Submit, id: "reroll", name: "submit", value: "reroll"}, builder.makeText("Reroll Selected")),
builder.makeButton({id: "selectAll", classes: "requiresJs"}, builder.makeText("Select All")),
builder.makeButton({id: "selectNone", classes: "requiresJs"}, builder.makeText("Select None")),
)] : []),
builder.makeDiv({id: "scenarioButtons", classes: ["buttons"]},
...(editable ? [
builder.makeHyperlink({id: "rerollAll", url: generatorTargetUrl, destination: HyperlinkDestination.Internal, asButton: true}, builder.makeText("New Scenario")),
builder.makeButton({type: ButtonType.Submit, id: "saveScenario", name: "submit", value: "saveScenario"}, builder.makeText("Get Scenario Link"))
] : [
builder.makeHyperlink({url: generatorTargetUrl, destination: HyperlinkDestination.Internal, asButton: true}, builder.makeText("Open in Generator"))
])
),
...(clientId !== '' || includesResponses ? [builder.makeDiv({id: "generatorLinks", classes: ["buttons"]},
...(clientId !== '' ? [builder.makeHyperlink(
{
url: `https://discord.com/api/oauth2/authorize?client_id=${
encodeURIComponent(clientId)}&permissions=0&scope=applications.commands`,
destination: HyperlinkDestination.External,
asButton: true},
builder.makeText("Add to Discord"))] : []),
...(includesResponses ? [builder.makeHyperlink(
{
url: `#responses`,
destination: HyperlinkDestination.Internal,
asButton: true},
builder.makeText("View Possible Responses"))] : []),
)] : [])
)
),
buildFooter({includesResponses, includesGenerator: true, creditsUrl, builder})
) as ReturnType<BuilderT["makeDiv"]>
}
export function buildResponseTypeButton<T, BuilderT extends TemplateBuilder<T>>({table, builder}: {readonly table: RollTableDetails, readonly builder: BuilderT}): ReturnType<BuilderT["makeHyperlink"]> {
return builder.makeHyperlink({
url: `#responses-${htmlTableIdentifier(table)}`,
destination: HyperlinkDestination.Internal,
asButton: true,
}, builder.makeText(`${table.emoji} ${table.name}`)) as ReturnType<BuilderT["makeHyperlink"]>
}
export function buildResponse<T, BuilderT extends TemplateBuilder<T>>({result, active, includesGenerator, builder}: {readonly result: RollTableResult, readonly active: boolean, readonly includesGenerator: boolean, readonly builder: BuilderT}): ReturnType<BuilderT["makeListItem"]> {
return builder.makeListItem(
{
id: result.full ? `response-${result.mappingId}` : undefined,
classes: ["response", "jsPopupHost", ...(active ? ["active"] : []), ...(result.full ? ["attributed"] : [])],
},
builder.makeButton({classes: "resultText", data: buildResultData(result)}, builder.makeText(result.text)),
buildResultAttribution({
result,
button: result.full && includesGenerator ? builder.makeButton({classes: ["makeResponseActive", "requiresJs"]}, builder.makeText("Set in Generated Scenario")) : undefined,
builder})) as ReturnType<BuilderT["makeListItem"]>
}
export function buildResponseList<T, BuilderT extends TemplateBuilder<T>>({table, activeResult, includesGenerator, builder}: {readonly table: RollTableDetailsAndResults, readonly activeResult?: RollTableResult, readonly includesGenerator: boolean, readonly builder: BuilderT}): ReturnType<BuilderT["makeListItem"]> {
return builder.makeListItem(
{
classes: ["responseType", "window", "readable"],
id: `responses-${htmlTableIdentifier(table)}`
},
builder.makeHeading2(
{
classes: ["responseTypeHead", "tableHeader"],
data: buildTableData(table)
},
builder.makeSpan({classes: "tableEmoji"}, builder.makeText(table.emoji)),
builder.makeText(' '),
builder.makeSpan({classes: "tableTitle"}, builder.makeText(table.title)),
),
builder.makeUnorderedList({}, ...Array.from(table.resultsById.values())
.map(result =>
buildResponse({result, active: result === activeResult, includesGenerator, builder})))
) as ReturnType<BuilderT["makeListItem"]>
}
export function buildResponsesPage<T, BuilderT extends TemplateBuilder<T>>(
{ tables, results, creditsUrl, includesGenerator, builder }: {
readonly tables: Iterable<RollTableDetailsAndResults>,
readonly results?: ReadonlyMap<RollTable, RollTableResult>,
readonly creditsUrl: string,
readonly includesGenerator: boolean,
readonly builder: BuilderT}): ReturnType<BuilderT["makeDiv"]> {
return builder.makeDiv({id: "responses", classes: "page"},
builder.makeHeader({id: "responsesHeader", classes: "window"},
builder.makeHeading1({id: "responsesHead"}, builder.makeText("Possible Responses")),
builder.makeNav({id: "responsesHeaderNav", classes: "buttons"},
...Array.from(tables).map(table => buildResponseTypeButton({table, builder})),
builder.makeHyperlink({url: `#generator`, destination: HyperlinkDestination.Internal, asButton: true, id: "returnToGenerator"}, builder.makeText("Return to Generator"))
),
),
builder.makeUnorderedList({id: "responseLists"},
...Array.from(tables).map(table =>
buildResponseList({table, activeResult: results?.get(table), includesGenerator, builder}))),
buildFooter({builder, creditsUrl, includesResponses: true, includesGenerator}),
) as ReturnType<BuilderT["makeDiv"]>
}