Files
horse/zenno/src/routes/doc/spark/+page.svelte
T

128 lines
3.5 KiB
Svelte

<script lang="ts">
import * as skill from '$lib/data/skill';
import * as spark from '$lib/data/spark';
import Pick from '$lib/Pick.svelte';
import { onMount } from 'svelte';
import { SvelteMap } from 'svelte/reactivity';
let sparks: spark.Spark[] = $state([]);
let skills: SvelteMap<number, skill.Skill> = new SvelteMap();
onMount(async () => {
const [sp, sk] = await Promise.all([spark.sparks(), skill.skills()]);
sparks = sp;
for (const s of sk) {
skills.set(s.skill_id, s);
}
});
let group: spark.SparkGroup | undefined = $state();
const groups = $derived(spark.byGroup(sparks));
function describe(eff: spark.Effect) {
if (eff.target === spark.Target.Skill) {
const sk = skills.get(eff.value1);
return `${sk?.name} ${spark.TARGET_NAMES[eff.target]} +${eff.value2}`;
}
return `${spark.TARGET_NAMES[eff.target]} +${eff.value1}`;
}
const curEffectGroups = $derived(group?.effects ?? []);
const curDescriptions = $derived(curEffectGroups.map((g) => g.map((e) => describe(e))));
function sparkClass(t: spark.Type | null | undefined): string[] {
if (t == null) {
return [];
}
switch (t) {
case 1:
return ['stat'];
case 2:
return ['aptitude'];
case 3:
return ['unique'];
case 5:
case 4:
case 6:
case 10:
case 8:
case 11:
case 9:
return ['white-spark'];
default:
return [];
}
}
const curClass = $derived(sparkClass(group?.type));
const key = (v: spark.SparkGroup) => ({id: v.spark_group, name: v.name})
</script>
<h1 class="text-4xl">Spark Explorer</h1>
<form class="mx-auto mt-8 rounded-md p-4 text-center shadow-md ring md:max-w-2xl">
<Pick id="spark" items={groups} class="w-full" {key} bind:value={group} required>
{#snippet option(g)}
<span class={['spark px-2 py-1 rounded', sparkClass(g.type)]}>{g.name}</span>
{/snippet}
</Pick>
</form>
<svelte:boundary>
<div
class={[
'spark mx-auto mt-8 max-w-md flex-1 flex-col rounded-md border p-2 text-center shadow-sm transition-shadow hover:shadow-md',
curClass,
]}
>
<span class="block text-xl">{group?.name}</span>
{#if group != null}
<span class="block">
{spark.TYPE_NAMES[group.type]} Spark
</span>
{/if}
<span class="block">{group?.description}</span>
</div>
<table class="mx-auto mt-8 w-full max-w-xl table-fixed border-separate border-spacing-2">
<caption class="text-xl">Possible Effects</caption>
<tbody>
{#each curDescriptions as s (s)}
<tr>
<td class="flex gap-2 p-1 text-center border border-mist-400 dark:border-mist-950">
{#each s as n (n)}
<span class="flex-1 my-auto">{n}</span>
{/each}
</td>
</tr>
{/each}
</tbody>
</table>
{#snippet pending()}
<div>Loading data...</div>
{/snippet}
</svelte:boundary>
<div class="mx-auto mt-12 w-full max-w-4xl border-t pt-4 md:mt-8">
<p>
When a spark activates during inspiration, it has an additional random roll for one of the effects listed in the table here.
All star levels of each spark have the same possible effects. Higher star levels are more likely to give better rewards.
</p>
</div>
<style>
.white-spark {
--spark-color: light-dark(var(--color-mist-200), var(--color-mist-800));
}
.stat {
--spark-color: light-dark(var(--color-sky-200), var(--color-sky-800));
}
.aptitude {
--spark-color: light-dark(var(--color-rose-300), var(--color-rose-800));
}
.unique {
--spark-color: light-dark(var(--color-lime-400), var(--color-lime-800));
}
.spark {
background-color: var(--spark-color);
}
</style>