Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad02e0711d | ||
|
|
869235a8c2 |
@@ -32,7 +32,29 @@ export interface Conversation {
|
|||||||
/**
|
/**
|
||||||
* Some unknown number in the game's local database.
|
* Some unknown number in the game's local database.
|
||||||
*/
|
*/
|
||||||
condition_type: 0 | 1 | 2 | 3 | 4;
|
condition_type: Required;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Required {
|
||||||
|
None = 0,
|
||||||
|
All = 1,
|
||||||
|
Chara1 = 2,
|
||||||
|
Chara2 = 3,
|
||||||
|
Chara3 = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function convoCharas(c: Conversation): number[] {
|
||||||
|
return [c.chara_1, c.chara_2, c.chara_3].filter((id) => id != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requiredCharas(c: Conversation): number[] {
|
||||||
|
switch (c.condition_type) {
|
||||||
|
case Required.None: return []
|
||||||
|
case Required.All: return convoCharas(c);
|
||||||
|
case Required.Chara1: return [c.chara_1];
|
||||||
|
case Required.Chara2: return [c.chara_2!];
|
||||||
|
case Required.Chara3: return [c.chara_3!];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function conversation(): Promise<Conversation[]> {
|
export async function conversation(): Promise<Conversation[]> {
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { character, charaNames, type Character } from '$lib/data/character';
|
import { character, charaNames, type Character } from '$lib/data/character';
|
||||||
import { byChara, locations, groupPopulars, conversation, type Conversation } from '$lib/data/convo';
|
import {
|
||||||
|
byChara,
|
||||||
|
locations,
|
||||||
|
groupPopulars,
|
||||||
|
conversation,
|
||||||
|
type Conversation,
|
||||||
|
requiredCharas,
|
||||||
|
convoCharas,
|
||||||
|
} from '$lib/data/convo';
|
||||||
import CharaPick from '$lib/CharaPick.svelte';
|
import CharaPick from '$lib/CharaPick.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import CharaIcon from '$lib/CharaIcon.svelte';
|
||||||
|
|
||||||
let conversations: Conversation[] = $state([]);
|
let conversations: Conversation[] = $state([]);
|
||||||
const convoMap = $derived(byChara(conversations));
|
const convoMap = $derived(byChara(conversations));
|
||||||
const popular = $derived(groupPopulars(conversations));
|
const popular = $derived(groupPopulars(conversations));
|
||||||
let characters: Character[] = $state([]);
|
let characters: Character[] = $state([]);
|
||||||
const selCharas = $derived(characters.filter((c) => convoMap.has(c.chara_id)));
|
const selCharas = $derived(characters.filter((c) => convoMap.has(c.chara_id)));
|
||||||
const names = $derived(charaNames(characters ?? []));
|
const names = $derived(charaNames(characters));
|
||||||
const minSuggest = 8;
|
const minSuggest = 8;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
@@ -21,11 +30,9 @@
|
|||||||
|
|
||||||
const options = $derived(convoMap.get(chara?.chara_id ?? 0) ?? []);
|
const options = $derived(convoMap.get(chara?.chara_id ?? 0) ?? []);
|
||||||
const cur = $derived(options.find((c) => c.number === convo));
|
const cur = $derived(options.find((c) => c.number === convo));
|
||||||
const cur1Name = $derived(cur?.chara_1 && names.get(cur.chara_1)?.en);
|
const charaIDs = $derived(cur != null ? convoCharas(cur) : []);
|
||||||
const cur2Name = $derived(cur?.chara_2 && names.get(cur.chara_2)?.en);
|
const charas = $derived(charaIDs.map((id) => names.get(id)!));
|
||||||
const cur3Name = $derived(cur?.chara_3 && names.get(cur.chara_3)?.en);
|
const suggested = $derived.by(() => {
|
||||||
const alone = $derived([cur?.chara_1, cur?.chara_2, cur?.chara_3].filter((x) => x != null).length == 1 ? ' alone' : '');
|
|
||||||
const suggested = $derived.by(async () => {
|
|
||||||
if (cur == null) {
|
if (cur == null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -36,6 +43,7 @@
|
|||||||
return r.map(([chara_id, count]) => ({ chara_id, chara_name: names.get(chara_id), count }));
|
return r.map(([chara_id, count]) => ({ chara_id, chara_name: names.get(chara_id), count }));
|
||||||
});
|
});
|
||||||
const curLoc = $derived(cur != null ? locations[cur.location] : null);
|
const curLoc = $derived(cur != null ? locations[cur.location] : null);
|
||||||
|
const req = $derived(cur != null ? requiredCharas(cur) : []);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1 class="text-4xl">Lobby Conversations</h1>
|
<h1 class="text-4xl">Lobby Conversations</h1>
|
||||||
@@ -53,37 +61,38 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#await suggested}
|
{#if cur}
|
||||||
<div class="mt-4 w-full text-center text-3xl">Loading...</div>
|
<div class="shadow-sm transition-shadow hover:shadow-md">
|
||||||
{:then suggested}
|
<div class="mt-8 flex flex-col text-center text-lg md:flex-row">
|
||||||
{#if cur}
|
{#each charaIDs as id, i (id)}
|
||||||
<div class="shadow-sm transition-shadow hover:shadow-md">
|
<span class={{ 'flex-1': true, 'font-bold italic': req.includes(id) }}>
|
||||||
<div class="mt-8 flex text-center text-lg">
|
<CharaIcon chara_id={id} size={64} />
|
||||||
<span class="flex-1">{cur1Name}{alone}</span>
|
{charas[i].en}
|
||||||
{#if cur2Name}
|
</span>
|
||||||
<span class="flex-1">{cur2Name}</span>
|
|
||||||
{/if}
|
|
||||||
{#if cur3Name}
|
|
||||||
<span class="flex-1">{cur3Name}</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="flex w-full text-center text-lg">
|
|
||||||
<span class="flex-1">at {curLoc?.name.en}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-4 block text-center">
|
|
||||||
<span>Other characters who appear here most often:</span>
|
|
||||||
</div>
|
|
||||||
<div class="mt-4 grid text-center shadow-sm transition-shadow ease-in hover:shadow-md hover:ease-out md:grid-cols-4">
|
|
||||||
{#each suggested as s (s.chara_id)}
|
|
||||||
<span>{s.chara_name?.en}: {s.count}×</span>
|
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 block text-center">
|
<div class="block w-full text-center text-lg">
|
||||||
<span>
|
at the {curLoc?.name.en}
|
||||||
Set these characters to fixed positions (main, upgrades, story, races) to maximize the chance of getting this
|
|
||||||
conversation.
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{#if req.length > 0}
|
||||||
{/await}
|
<span class="mx-auto mt-4 block text-center text-sm">
|
||||||
|
The conversation will not appear unless you own a trainee or support card of all characters with names in
|
||||||
|
<span class="font-bold italic">bold italics</span>.
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 block text-center">
|
||||||
|
<span>Other characters who appear here most often:</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 grid text-center shadow-sm transition-shadow ease-in hover:shadow-md hover:ease-out md:grid-cols-4">
|
||||||
|
{#each suggested as s (s.chara_id)}
|
||||||
|
<span>{s.chara_name?.en}: {s.count}×</span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 block text-center">
|
||||||
|
<span>
|
||||||
|
Setting these characters to fixed positions (main, upgrades, story, races) may maximize the chance of getting this
|
||||||
|
conversation.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user