add lots of cool features

add side nav
add clipboard
add remove
This commit is contained in:
RussellChamp committed 2021-08-21 16:02:35 -04:00
1 parent 5949b6ad33
commit 9e8a22cd62
28 files changed
+379 -254

No files matched your search

+1
View File
@@ -2,4 +2,5 @@ Add Steadings tables
Change steadings and mounts to not show English names by default
Make everything look nicer
Maybe put roller button in a left nav bar and the results in the middle?
Add a copy-to-clipboard option
Add a 3d dice rolling visualizer
+53 -31
View File
@@ -1,5 +1,6 @@
<script lang="ts">
import { Accordion, AccordionHeader, AccordionItem } from "sveltestrap";
import { format as formatDate } from "date-fns";
import { Accordion, AccordionHeader, AccordionItem, Container, Row, Col } from "sveltestrap";
import SoundOptions from "./components/SoundOptions.svelte";
import CreatureRoller from "./components/CreatureRoller.svelte";
@@ -14,16 +15,26 @@
import RegionRoller from "./components/RegionRoller.svelte";
import SteadingRoller from "./components/SteadingRoller.svelte";
import Footer from "./components/Footer.svelte";
import MultiCard from "./components/MultiCard.svelte";
import { RollCard } from "./types/RollCard";
let rollThemBones = new Audio("https://soundbible.com/mp3/Shake And Roll Dice-SoundBible.com-591494296.mp3");
let playSounds = true;
let playSounds = localStorage?.getItem("playSounds") != "false";
let timeout: NodeJS.Timeout;
let cards: RollCard[] = [];
function setSoundOptions(event: any) {
function setSoundOptions(event: CustomEvent<{ soundEnabled: boolean }>) {
playSounds = event.detail.soundEnabled;
localStorage?.setItem("playSounds", String(playSounds));
}
function handleRoll(event: any) {
function handleRoll(event: CustomEvent<{ type: string; value: any }>) {
let timestamp = formatDate(new Date(), "P kk:mm:ss");
cards = [new RollCard(event?.detail?.type, event?.detail?.value, timestamp), ...cards];
playAudio();
}
function playAudio() {
clearTimeout(timeout);
rollThemBones.pause();
rollThemBones.currentTime = 0;
@@ -40,50 +51,57 @@
}, playTime);
}
}
function remove(event: CustomEvent<RollCard>) {
cards = cards.filter((c) => c.timestamp != event.detail.timestamp);
}
</script>
<main>
<Container fluid={true}>
<Row>
<h1>The Perilous Wilds</h1>
<h2>A web-app for rolling on tables and getting funny results</h2>
<hr />
<SoundOptions on:soundToggle={setSoundOptions} />
</Row>
<Row>
<Col sm="3">
<div class="sidebar">
<h3>Rollers:</h3>
<hr />
<Accordion>
<AccordionItem active header="Creatures">
<CreatureRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Dangers">
<DangerRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Details">
<DetailsRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Discoveries">
<DiscoveryRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Dungeons">
<DungeonRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Followers">
<FollowerRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Kingdoms">
<KingdomRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="NPCs">
<NpcRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Places">
<PlaceRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Regions">
<RegionRoller on:roll={handleRoll} />
</AccordionItem>
<AccordionItem header="Steadings">
<SteadingRoller on:roll={handleRoll} />
</AccordionItem>
</Accordion>
<h3>Kingdom:</h3>
<KingdomRoller on:roll={handleRoll} />
<h3>Details:</h3>
<DetailsRoller on:roll={handleRoll} />
<hr />
<h3>Options</h3>
<SoundOptions soundEnabled={playSounds} on:soundToggle={setSoundOptions} />
</div>
</Col>
<Col sm="9">
<h3>Results:</h3>
{#each cards as card}
<MultiCard {card} on:remove={remove} />
{/each}
</Col>
</Row>
<Row>
<Footer />
</Row>
</Container>
</main>
<style>
@@ -101,6 +119,10 @@
font-weight: 100;
}
.sidebar {
background-color: rgba(0, 0, 0, 0.03);
}
@media (min-width: 640px) {
main {
max-width: none;
+26
View File
@@ -0,0 +1,26 @@
<script lang="ts">
import { capitalize } from "lodash";
import { Button, Icon, Tooltip } from "sveltestrap";
export let dataType: string;
export let data: any;
function handleClick() {
if (data) {
prompt(`${capitalize(dataType)} data`, JSON.stringify(data));
// This won't work until I support a https connection
// navigator.clipboard.writeText(JSON.stringify(data));
}
}
</script>
<main>
<Button id="copyHelper" color="secondary" on:click={handleClick}>
<Icon name="clipboard-data" />
</Button>
<Tooltip target="copyHelper" placement="top">Copy to Clipboard</Tooltip>
</main>
<style>
</style>
+39 -3
View File
@@ -1,23 +1,55 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { capitalize } from "lodash";
import { Card, CardHeader, CardTitle, CardBody, CardSubtitle, CardText, CardFooter, Container, Row } from "sveltestrap";
import {
Card,
CardHeader,
CardTitle,
CardBody,
CardSubtitle,
CardText,
CardFooter,
Container,
Row,
Button,
Icon,
Tooltip,
} from "sveltestrap";
import ClipboardHelper from "./ClipboardHelper.svelte";
import NpcCard from "./NpcCard.svelte";
import DieIcon from "./DieIcon.svelte";
import type { Creature } from "../rollers/creatures";
const dispatch = createEventDispatcher();
export let creature: Creature;
export let timestamp: string;
function remove() {
dispatch("remove");
}
</script>
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle>
<div class="title">
<div class="description">
{capitalize(creature.type)}<DieIcon value={creature.roll} />
{#if creature.subtype !== ""}({creature.subtype})<DieIcon value={creature.subroll} />{/if}: {capitalize(
creature.description
)}<DieIcon value={creature.specificroll} />
</div>
<div class="buttons">
<ClipboardHelper data={creature} dataType="creature" />
<Button id="remove" outline color="danger" on:click={remove}>
<Icon name="x" />
</Button>
<Tooltip target="remove" placement="top">Remove Item</Tooltip>
</div>
</div>
</CardTitle>
</CardHeader>
<CardBody>
@@ -72,8 +104,12 @@
main {
text-align: left;
}
.card-subtitle {
padding-bottom: 1em;
.title {
display: flex;
justify-content: space-between;
}
.title .buttons {
display: flex;
}
ul {
margin-left: 2em;
+2 -13
View File
@@ -1,30 +1,19 @@
<script lang="ts">
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import { Button } from "sveltestrap";
import CreatureCard from "./CreatureCard.svelte";
import { Creature, rollCreature } from "../rollers/creatures";
import { rollCreature } from "../rollers/creatures";
const dispatch = createEventDispatcher();
let rollResults: { creature: Creature; timestamp: string }[] = [];
function roll(event: Event) {
let creature = rollCreature();
rollResults = [{ creature, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "creature", value: creature });
}
</script>
<main>
<Button color="primary" on:click={roll}>Roll Creature</Button>
{#each rollResults as { creature, timestamp }}
<CreatureCard {creature} {timestamp} />
{/each}
</main>
<style>
main {
text-align: left;
}
</style>
+41
View File
@@ -0,0 +1,41 @@
<script lang="ts">
import { capitalize } from "lodash";
import { Card, CardHeader, CardTitle, CardBody, CardText, CardFooter, Icon } from "sveltestrap";
import type { Danger } from "../rollers/dangers";
import DieIcon from "./DieIcon.svelte";
export let danger: Danger;
export let timestamp: string;
let icon = "";
$: icon =
danger.category == "unnatural entity"
? "person-square"
: danger.category == "hazard"
? "lightning-fill"
: danger.category == "creature"
? "emoji-neutral"
: "";
</script>
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle>
{capitalize(danger.category)}<DieIcon value={danger.roll} />
{#if danger.subcategory !== ""}({danger.subcategory})<DieIcon value={danger.subroll} />{/if}: {capitalize(
danger.description
)}<DieIcon value={danger.specificroll} />
</CardTitle>
</CardHeader>
<CardBody>
<CardText>
<Icon name={icon} />: {danger.description}
</CardText>
</CardBody>
<CardFooter>{timestamp}</CardFooter>
</Card>
</main>
<style>
</style>
+3 -23
View File
@@ -1,38 +1,18 @@
<script lang="ts">
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import { Button, Icon } from "sveltestrap";
import { Danger, rollDanger } from "../rollers/dangers";
import { Button } from "sveltestrap";
import { rollDanger } from "../rollers/dangers";
const dispatch = createEventDispatcher();
export let rollResults: { danger: Danger; icon: string; timestamp: string }[] = [];
function roll(event: Event) {
let danger = rollDanger();
let icon =
danger.category == "unnatural entity"
? "person-square"
: danger.category == "hazard"
? "lightning-fill"
: danger.category == "creature"
? "emoji-neutral"
: "";
rollResults = [{ danger, icon, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "danger", value: danger });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Danger</Button>
</span>
{#each rollResults as { danger, icon, timestamp }}
<h4>
{timestamp}: {danger.category} ({danger.subcategory}) <Icon name={icon} />: {danger.description}
</h4>
{/each}
</main>
<style>
+28
View File
@@ -0,0 +1,28 @@
<script lang="ts">
import { capitalize } from "lodash";
import { Card, CardHeader, CardTitle, CardBody, CardText, CardFooter } from "sveltestrap";
import type { Detail } from "../rollers/details";
import DieIcon from "./DieIcon.svelte";
export let detail: Detail;
export let timestamp: string;
</script>
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle>
{capitalize(detail.type)}
</CardTitle>
</CardHeader>
<CardBody>
<CardText>
{detail.description}<DieIcon value={detail.roll} />
</CardText>
</CardBody>
<CardFooter>{timestamp}</CardFooter>
</Card>
</main>
<style>
</style>
+4 -54
View File
@@ -1,8 +1,8 @@
<script lang="ts">
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import { Button, Icon } from "sveltestrap";
import { Button } from "sveltestrap";
import {
Detail,
rollAbility,
rollActivity,
rollAdjective,
@@ -24,83 +24,33 @@
rollVisibility,
} from "../rollers/details";
import DieIcon from "./DieIcon.svelte";
const dispatch = createEventDispatcher();
let rollResults: { type: string; roll: number; value: string; timestamp: string }[] = [];
function roll(item: { type: string; description: string; roll: number }) {
rollResults = [
{ type: item.type, roll: item.roll, value: item.description, timestamp: formatDate(new Date(), "P kk:mm:ss") },
...rollResults,
];
dispatch("roll");
function roll(value: Detail) {
dispatch("roll", { type: "detail", value });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={() => roll(rollAbility())}>Roll Ability</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollActivity())}>Roll Activity</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollAdjective())}>Roll Adjective</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollAge())}>Roll Age</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollAlignment())}>Roll Alignment</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollAspect())}>Roll Aspect</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollCondition())}>Roll Condition</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollDisposition())}>Roll Disposition</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollElement())}>Roll Element</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollFeature())}>Roll Feature</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollMagicType())}>Roll MagicType</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollNumAppearing())}>Roll NumAppearing</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollOddity())}>Roll Oddity</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollOrientation())}>Roll Orientation</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollRuination())}>Roll Ruination</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollSize())}>Roll Size</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollTag())}>Roll Tag</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollTerrain())}>Roll Terrain</Button>
</span>
<span class="btn">
<Button color="primary" on:click={() => roll(rollVisibility())}>Roll Visibility</Button>
</span>
{#each rollResults as { type, roll, value, timestamp }}
<h4>{timestamp}: ({type}): {value}<DieIcon value={roll} /></h4>
{/each}
</main>
<style>
+2 -23
View File
@@ -1,40 +1,19 @@
<script lang="ts">
import { Button } from "sveltestrap";
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import DiscoveryCard from "./DiscoveryCard.svelte";
import { Discovery, rollDiscovery } from "../rollers/discoveries";
import { rollDiscovery } from "../rollers/discoveries";
const dispatch = createEventDispatcher();
export let rollResults: { discovery: Discovery; timestamp: string }[] = [];
function roll(event: Event) {
let discovery = rollDiscovery();
rollResults = [{ discovery, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
}
function getIcon(t: string, c: string): string {
return "";
dispatch("roll", { type: "discovery", value: discovery });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Discovery</Button>
</span>
{#each rollResults as { discovery, timestamp }}
<DiscoveryCard {discovery} {timestamp} />
{/each}
</main>
<style>
main {
text-align: left;
}
.btn {
text-align: center;
}
</style>
+1 -3
View File
@@ -25,9 +25,7 @@
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle
>{capitalize(dungeon.size.description)} {dungeon.function.description} built by (a/an) {dungeon.builder.description}</CardTitle
>
<CardTitle>{capitalize(dungeon.size.description)} {dungeon.function.description} built by {dungeon.builder.description}</CardTitle>
</CardHeader>
<CardBody>
<CardSubtitle>
+2 -19
View File
@@ -1,37 +1,20 @@
<script lang="ts">
import { Button } from "sveltestrap";
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import DungeonCard from "./DungeonCard.svelte";
import { Dungeon, rollDungeon } from "../rollers/dungeons";
import { rollDungeon } from "../rollers/dungeons";
const dispatch = createEventDispatcher();
export let rollResults: { dungeon: Dungeon; timestamp: string }[] = [];
function roll(event: Event) {
let dungeon = rollDungeon();
rollResults = [{ dungeon, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "dungeon", value: dungeon });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Dungeon</Button>
</span>
{#each rollResults as { dungeon, timestamp }}
<DungeonCard {dungeon} {timestamp} />
{/each}
</main>
<style>
main {
text-align: left;
}
.btn {
text-align: center;
}
</style>
+3 -20
View File
@@ -1,37 +1,20 @@
<script lang="ts">
import { Button } from "sveltestrap";
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import FollowerCard from "./FollowerCard.svelte";
import { rollFollower, Follower } from "../rollers/followers";
import { rollFollower } from "../rollers/followers";
const dispatch = createEventDispatcher();
export let rollResults: { follower: Follower; timestamp: string }[] = [];
function roll(event: Event) {
let follower = rollFollower();
rollResults = [{ follower, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "follower", value: follower });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Followers</Button>
</span>
{#each rollResults as { follower, timestamp }}
<FollowerCard {follower} {timestamp} />
{/each}
<Button color="primary" on:click={roll}>Roll Follower</Button>
</main>
<style>
main {
text-align: left;
}
.btn {
text-align: center;
}
</style>
+31
View File
@@ -0,0 +1,31 @@
<script lang="ts">
import { capitalize } from "lodash";
import { Card, CardHeader, CardTitle, CardBody, CardText, CardFooter, Icon } from "sveltestrap";
import type { Kingdom, KingdomItem } from "../rollers/kingdoms";
export let item: KingdomItem;
export let timestamp: string;
let icon = "";
$: icon = String({ male: "person-fill", female: "person", steading: "house-door-fill", mount: "bicycle" }[item?.category] || "");
</script>
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle>
{capitalize(item.category)} from {item.kingdom.description}
</CardTitle>
</CardHeader>
<CardBody>
<CardText>
<Icon name={icon} />
{item.description}
</CardText>
</CardBody>
<CardFooter>{timestamp}</CardFooter>
</Card>
</main>
<style>
</style>
+9 -16
View File
@@ -1,47 +1,40 @@
<script lang="ts">
import { capitalize } from "lodash";
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import { Button, Icon } from "sveltestrap";
import { Button } from "sveltestrap";
import { kingdoms, rollCategory } from "../rollers/kingdoms";
import { KingdomItem, kingdoms, rollCategory } from "../rollers/kingdoms";
const dispatch = createEventDispatcher();
let rollResults: { value: string; icon: string; timestamp: string }[] = [];
let kingdom = "arpad";
let categories: string[];
function roll(category: string) {
let value = rollCategory(kingdom, category);
let icon = { male: "person-fill", female: "person", steading: "house-door-fill", mount: "bicycle" }[category] || "";
rollResults = [{ value, icon, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "kingdom", value: new KingdomItem(kingdoms[kingdom], category, value) });
}
$: categories = kingdoms[kingdom].categories;
</script>
<main>
<h2>
<select bind:value={kingdom}>
{#each Object.keys(kingdoms) as k}
<option value={k}>{kingdoms[k].description}</option>
{/each}
</select>
</h2>
<h3>{kingdoms[kingdom].subtitle}</h3>
<div>{kingdoms[kingdom].subtitle}</div>
{#each categories as category}
<span class="btn">
<Button color="primary" on:click={() => roll(category)}>Roll {capitalize(category)}</Button>
</span>
{/each}
{#each rollResults as { value, icon, timestamp }}
<h4>{timestamp}: <Icon name={icon} /> {value}</h4>
{/each}
</main>
<style>
select {
font-size: 0.8em;
}
</style>
+55
View File
@@ -0,0 +1,55 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import CreatureCard from "./CreatureCard.svelte";
import DangerCard from "./DangerCard.svelte";
import DetailsCard from "./DetailsCard.svelte";
import DiscoveryCard from "./DiscoveryCard.svelte";
import DungeonCard from "./DungeonCard.svelte";
import FollowerCard from "./FollowerCard.svelte";
import KingdomCard from "./KingdomCard.svelte";
import NpcCard from "./NpcCard.svelte";
import PlaceCard from "./PlaceCard.svelte";
import RegionCard from "./RegionCard.svelte";
import SteadingCard from "./SteadingCard.svelte";
import type { RollCard } from "../types/RollCard";
const dispatch = createEventDispatcher();
export let card: RollCard;
function remove() {
dispatch("remove", card);
}
</script>
<main>
{#if card.type == "creature"}
<CreatureCard creature={card.value} timestamp={card.timestamp} on:remove={remove} />
{:else if card.type == "danger"}
<DangerCard danger={card.value} timestamp={card.timestamp} />
{:else if card.type == "detail"}
<DetailsCard detail={card.value} timestamp={card.timestamp} />
{:else if card.type == "discovery"}
<DiscoveryCard discovery={card.value} timestamp={card.timestamp} />
{:else if card.type == "dungeon"}
<DungeonCard dungeon={card.value} timestamp={card.timestamp} />
{:else if card.type == "follower"}
<FollowerCard follower={card.value} timestamp={card.timestamp} />
{:else if card.type == "kingdom"}
<KingdomCard item={card.value} timestamp={card.timestamp} />
{:else if card.type == "npc"}
<NpcCard npc={card.value} timestamp={card.timestamp} />
{:else if card.type == "place"}
<PlaceCard place={card.value} timestamp={card.timestamp} />
{:else if card.type == "region"}
<RegionCard region={card.value} timestamp={card.timestamp} />
{:else if card.type == "steading"}
<SteadingCard steading={card.value} timestamp={card.timestamp} />
{:else}
<h3>Card type not supported: {card.type}</h3>
{/if}
</main>
<style>
</style>
+2 -19
View File
@@ -1,37 +1,20 @@
<script lang="ts">
import { Button } from "sveltestrap";
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import NpcCard from "./NpcCard.svelte";
import { Npc, rollNpc } from "../rollers/npcs";
import { rollNpc } from "../rollers/npcs";
const dispatch = createEventDispatcher();
export let rollResults: { npc: Npc; timestamp: string }[] = [];
function roll(event: Event) {
let npc = rollNpc();
rollResults = [{ npc, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "npc", value: npc });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Npc</Button>
</span>
{#each rollResults as { npc, timestamp }}
<NpcCard {npc} {timestamp} />
{/each}
</main>
<style>
main {
text-align: left;
}
.btn {
text-align: center;
}
</style>
+24
View File
@@ -0,0 +1,24 @@
<script lang="ts">
import { Card, CardHeader, CardTitle, CardBody, CardText, CardFooter } from "sveltestrap";
import type { Place } from "../rollers/places";
export let place: Place;
export let timestamp: string;
</script>
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle>Place</CardTitle>
</CardHeader>
<CardBody>
<CardText>
{place}
</CardText>
</CardBody>
<CardFooter>{timestamp}</CardFooter>
</Card>
</main>
<style>
</style>
+1 -11
View File
@@ -1,28 +1,18 @@
<script lang="ts">
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import { Button } from "sveltestrap";
import { rollPlace } from "../rollers/places";
const dispatch = createEventDispatcher();
export let rollResults: { place: string; timestamp: string }[] = [];
function roll(event: Event) {
let place = rollPlace();
rollResults = [{ place, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "place", value: place });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Place</Button>
</span>
{#each rollResults as { place, timestamp }}
<h4>{timestamp}: {place}</h4>
{/each}
</main>
<style>
+24
View File
@@ -0,0 +1,24 @@
<script lang="ts">
import { Card, CardHeader, CardTitle, CardBody, CardText, CardFooter } from "sveltestrap";
import type { Region } from "../rollers/regions";
export let region: Region;
export let timestamp: string;
</script>
<main>
<Card class="mb-3">
<CardHeader>
<CardTitle>Region</CardTitle>
</CardHeader>
<CardBody>
<CardText>
{region}
</CardText>
</CardBody>
<CardFooter>{timestamp}</CardFooter>
</Card>
</main>
<style>
</style>
+1 -11
View File
@@ -1,28 +1,18 @@
<script lang="ts">
import { format as formatDate } from "date-fns";
import { createEventDispatcher } from "svelte";
import { Button } from "sveltestrap";
import { rollRegion } from "../rollers/regions";
const dispatch = createEventDispatcher();
export let rollResults: { region: string; timestamp: string }[] = [];
function roll(event: Event) {
let region = rollRegion();
rollResults = [{ region, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
dispatch("roll");
dispatch("roll", { type: "region", value: region });
}
</script>
<main>
<span class="btn">
<Button color="primary" on:click={roll}>Roll Region</Button>
</span>
{#each rollResults as { region, timestamp }}
<h4>{timestamp}: {region}</h4>
{/each}
</main>
<style>
+1 -1
View File
@@ -2,8 +2,8 @@
import { createEventDispatcher } from "svelte";
import { Button, Icon } from "sveltestrap";
export let soundEnabled: boolean;
const dispatch = createEventDispatcher();
let soundEnabled = true;
function toggleSound() {
soundEnabled = !soundEnabled;
+6
View File
@@ -1,5 +1,11 @@
import { random, replace, sample, sampleSize } from "lodash";
// This is the general implemenetation of details.
// We are not doing strict class inheritance because that way leads to pain
export class Detail {
constructor(public type: string, public roll: number, public description: string) { }
}
export class Ability {
type: string = "ability";
constructor(public roll: number = 0, public description = "") { };
+6 -6
View File
@@ -102,21 +102,21 @@ function rollBuilder(roll: number = random(1, 12)): Builder {
if (roll <= 1) {
return new Builder(roll, sample(["aliens", "precursors"]));
} else if (roll <= 2) {
return new Builder(roll, sample(["demigod", "demon"]));
return new Builder(roll, sample(["a demigod", "a demon"]));
} else if (roll <= 3) {
return new Builder(roll, "natural(caves, etc.)");
return new Builder(roll, "natural means (caves, etc.)");
} else if (roll <= 5) {
return new Builder(roll, sample(["religious order", "cult"]));
return new Builder(roll, sample(["a religious order", "a cult"]));
} else if (roll <= 6) {
return new Builder(roll, rollHumanoid().description);
return new Builder(roll, `a ${rollHumanoid().description}`);
} else if (roll <= 8) {
return new Builder(roll, sample(["dwarves", "gnomes"]));
} else if (roll <= 10) {
return new Builder(roll, "elves");
} else if (roll <= 11) {
return new Builder(roll, sample(["wizard", "madman"]));
return new Builder(roll, sample(["a wizard", "a madman"]));
} else if (roll <= 12) {
return new Builder(roll, sample(["monarch", "warlord"]));
return new Builder(roll, sample(["a monarch", "a warlord"]));
}
return new Builder(roll);
+4
View File
@@ -9,6 +9,10 @@ export class Kingdom {
mount: string[];
}
export class KingdomItem {
constructor(public kingdom: Kingdom, public category: string = "", public description: string = "") { };
}
export const kingdoms: { [kingdom: string]: Kingdom } = {
arpad: {
description: 'The Kingdom of Arpad',
+3 -1
View File
@@ -1,6 +1,8 @@
import { sample } from "lodash";
import { bodgeString } from "./utils";
export type Place = string;
export const places = {
templates: [
'The [PLACE]',
@@ -15,7 +17,7 @@ export const places = {
noun: ['[Name]', 'Arm', 'Ash', 'Blood', 'Child', 'Cinder', 'Corpse', 'Crystal', 'Dagger', 'Death', 'Demon', 'Devil', 'Doom', 'Eye', 'Fear', 'Finger', 'Fire', 'Foot', 'Ghost', 'Giant', 'Goblin', 'God', 'Gold', 'Hand', 'Head', 'Heart', 'Hero', 'Hope', 'King', 'Knave', 'Knight', 'Muck', 'Mud', 'Priest', 'Queen', 'Sailor', 'Silver', 'Skull', 'Smoke', 'Souls', 'Spear', 'Spirit', 'Stone', 'Sword', 'Thief', 'Troll', 'Warrior', 'Water', 'Witch', 'Wizard',],
};
export function rollPlace(): string {
export function rollPlace(): Place {
let template = sample(places.templates);
let place = bodgeString(template, places);
+2
View File
@@ -1,6 +1,8 @@
import { sample } from "lodash";
import { bodgeString } from "./utils";
export type Region = string;
export const regions = {
templates: [
'[ADJECTIVE] [TERRAIN]',
+5
View File
@@ -0,0 +1,5 @@
// Generic type to hold data for multiple different card types
// Maybe down the road I'll just make the other types inherit this
export class RollCard {
constructor(public type: string, public value: any, public timestamp: string) { };
}