Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 44 additions & 36 deletions src/components/new/MitPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@
save(`mitInvulnOrder-${partyKey}`, String(value));
}

// Only show the boss/invuln filters for plans that split tank entries by them.
let hasBossEntries = $derived(!!plan?.mechs.some((m) => m.mits.some((x) => x.boss)));
let hasInvulnEntries = $derived(!!plan?.mechs.some((m) => m.mits.some((x) => x.invuln)));

let groups = $derived(
plan
? groupMitsByPhase(plan, {
Expand Down Expand Up @@ -193,44 +197,48 @@
>
</div>
</div>
<div class="flex items-center gap-1">
<span class="text-xs font-medium text-surface-400 uppercase">P3 boss</span>
<div
class="inline-flex rounded-sm border border-surface-700 overflow-hidden text-sm"
role="group"
aria-label="P3 boss"
>
{#each ['Chaos', 'Exdeath'] as const as boss (boss)}
<button
type="button"
aria-pressed={tankBoss === boss}
class={tankBoss === boss
? 'px-2 py-0.5 bg-surface-700 text-foreground cursor-pointer'
: 'px-2 py-0.5 text-surface-300 hover:bg-surface-800 cursor-pointer'}
onclick={() => setTankBoss(boss)}>{boss}</button
>
{/each}
{#if hasBossEntries}
<div class="flex items-center gap-1">
<span class="text-xs font-medium text-surface-400 uppercase">P3 boss</span>
<div
class="inline-flex rounded-sm border border-surface-700 overflow-hidden text-sm"
role="group"
aria-label="P3 boss"
>
{#each ['Chaos', 'Exdeath'] as const as boss (boss)}
<button
type="button"
aria-pressed={tankBoss === boss}
class={tankBoss === boss
? 'px-2 py-0.5 bg-surface-700 text-foreground cursor-pointer'
: 'px-2 py-0.5 text-surface-300 hover:bg-surface-800 cursor-pointer'}
onclick={() => setTankBoss(boss)}>{boss}</button
>
{/each}
</div>
</div>
</div>
<div class="flex items-center gap-1">
<span class="text-xs font-medium text-surface-400 uppercase">P5 invuln</span>
<div
class="inline-flex rounded-sm border border-surface-700 overflow-hidden text-sm"
role="group"
aria-label="P5 invuln order"
>
{#each [1, 2] as const as order (order)}
<button
type="button"
aria-pressed={invulnOrder === order}
class={invulnOrder === order
? 'px-2 py-0.5 bg-surface-700 text-foreground cursor-pointer'
: 'px-2 py-0.5 text-surface-300 hover:bg-surface-800 cursor-pointer'}
onclick={() => setInvulnOrder(order)}>{order === 1 ? '1st' : '2nd'}</button
>
{/each}
{/if}
{#if hasInvulnEntries}
<div class="flex items-center gap-1">
<span class="text-xs font-medium text-surface-400 uppercase">P5 invuln</span>
<div
class="inline-flex rounded-sm border border-surface-700 overflow-hidden text-sm"
role="group"
aria-label="P5 invuln order"
>
{#each [1, 2] as const as order (order)}
<button
type="button"
aria-pressed={invulnOrder === order}
class={invulnOrder === order
? 'px-2 py-0.5 bg-surface-700 text-foreground cursor-pointer'
: 'px-2 py-0.5 text-surface-300 hover:bg-surface-800 cursor-pointer'}
onclick={() => setInvulnOrder(order)}>{order === 1 ? '1st' : '2nd'}</button
>
{/each}
</div>
</div>
</div>
{/if}
{/if}
</div>
{/if}
Expand Down
46 changes: 34 additions & 12 deletions src/components/new/ModernFightStratPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,23 @@
const resolvedMechs = resolveMechs(phaseStrat.mechs, phaseStrat.tag, stratState);
return {
...phaseStrat,
description: resolveStratItem(phaseStrat.description, phaseStrat.tag, stratState),
imageUrl: resolveStratItem(phaseStrat.imageUrl, phaseStrat.tag, stratState),
mask: resolveStratItem(phaseStrat.mask, phaseStrat.tag, stratState),
url: resolveStratItem(phaseStrat.url, phaseStrat.tag, stratState),
description: resolveStratItem(phaseStrat.description, phaseStrat.tag, stratState, stratName),
imageUrl: resolveStratItem(phaseStrat.imageUrl, phaseStrat.tag, stratState, stratName),
mask: resolveStratItem(phaseStrat.mask, phaseStrat.tag, stratState, stratName),
url: resolveStratItem(phaseStrat.url, phaseStrat.tag, stratState, stratName),
mechs: resolvedMechs?.map((phaseStratMech) => {
return {
...phaseStratMech,
description: resolveStratItem(phaseStratMech.description, phaseStrat.tag, stratState),
notes: resolveStratItem(phaseStratMech.notes, phaseStrat.tag, stratState),
imageUrl: resolveStratItem(phaseStratMech.imageUrl, phaseStrat.tag, stratState),
url: resolveStratItem(phaseStratMech.url, phaseStrat.tag, stratState),
description: resolveStratItem(
phaseStratMech.description,
phaseStrat.tag,
stratState,
stratName
),
action: resolveStratItem(phaseStratMech.action, phaseStrat.tag, stratState, stratName),
notes: resolveStratItem(phaseStratMech.notes, phaseStrat.tag, stratState, stratName),
imageUrl: resolveStratItem(phaseStratMech.imageUrl, phaseStrat.tag, stratState, stratName),
url: resolveStratItem(phaseStratMech.url, phaseStrat.tag, stratState, stratName),
strats:
phaseStratMech.strats &&
phaseStratMech.strats
Expand All @@ -191,10 +197,16 @@
description: resolveStratItem(
playerStrat.description,
phaseStrat.tag,
stratState
stratState,
stratName
),
imageUrl: resolveStratItem(playerStrat.imageUrl, phaseStrat.tag, stratState),
mask: resolveStratItem(playerStrat.mask, phaseStrat.tag, stratState)
imageUrl: resolveStratItem(
playerStrat.imageUrl,
phaseStrat.tag,
stratState,
stratName
),
mask: resolveStratItem(playerStrat.mask, phaseStrat.tag, stratState, stratName)
};
})
};
Expand Down Expand Up @@ -295,6 +307,13 @@
$effect(() => {
if (mitPlan) saveMitSetting('mitPlan', mitPlan.planName);
});
// Selecting a strat with a configured `mitPlan` switches the mit panel to it.
function applyStratMitPlan(stratName: string) {
const planName = effectiveConfigStrats[stratName]?.mitPlan;
if (planName && (config.mitPlans ?? []).some((p) => p.planName === planName)) {
mitPlanName = planName;
}
}
// Job is remembered per slot (role + party), so H1 and H2 keep separate picks.
let mitJobBySlot = $state<Record<string, Job>>({});
function mitJobFor(role: Role, party: number | undefined): Job {
Expand Down Expand Up @@ -430,7 +449,10 @@
strats={effectiveConfigStrats}
{stratName}
{stratOptions}
onSelectStrat={selectStrat}
onSelectStrat={(value) => {
selectStrat(value);
applyStratMitPlan(value);
}}
{stratState}
toggles={(config.toggles ?? []).map((toggle) => ({
key: toggle.key,
Expand Down
123 changes: 88 additions & 35 deletions src/components/new/ModernStratView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,18 @@
return `${phase?.phaseName ?? ''}-${index}`;
}

// Collapsible key for the "What's the difference" pane (participates in Collapse All).
const STRATDIFF_KEY = '__stratdiff__';

function getDefaultCollapsibleState() {
const newState: Record<string, boolean> = {};
individualStrat.forEach((phase: any, index: number) => {
if (phase?.phaseName) {
newState[phaseKey(phase, index)] = true;
}
});
// The "What's the difference" pane defaults closed.
newState[STRATDIFF_KEY] = false;
return newState;
}

Expand Down Expand Up @@ -169,6 +174,17 @@
(stratDifferences ?? []).filter((d: any) => !d.tab || d.tab === tab)
);

// Group consecutive entries by sub-category so each group renders under a heading.
let groupedStratDifferences = $derived.by(() => {
const groups: { category: string | undefined; items: any[] }[] = [];
for (const d of visibleStratDifferences) {
const last = groups[groups.length - 1];
if (!last || last.category !== d.category) groups.push({ category: d.category, items: [d] });
else last.items.push(d);
}
return groups;
});

// True when a difference entry maps to the currently-selected toggle option.
function isStratDiffSelected(diff: any): boolean {
if (!diff?.tag || diff?.value == null) return false;
Expand All @@ -183,9 +199,6 @@
return true;
}

// Collapsible key for the "What's the difference" pane (participates in Collapse All).
const STRATDIFF_KEY = '__stratdiff__';

let isAllExpanded = $derived(
(visibleStratDifferences.length === 0 || (collapsibleState[STRATDIFF_KEY] ?? true)) &&
individualStrat
Expand Down Expand Up @@ -379,36 +392,67 @@

{#if visibleStratDifferences.length > 0}
<Collapsible.Root
class="w-full max-w-2xl mb-6"
class="w-full max-w-4xl mb-6"
open={getCollapsibleOpen(STRATDIFF_KEY)}
onOpenChange={(open) => setCollapsibleOpen(STRATDIFF_KEY, open)}
>
<div class="card preset-outlined-secondary-500 p-4 flex flex-col gap-2 w-full">
<Collapsible.Trigger
class="flex flex-row gap-4 items-center text-sm md:text-base font-semibold cursor-pointer w-full"
class="flex flex-row gap-4 items-center text-sm md:text-lg font-semibold cursor-pointer w-full"
>
<CircleQuestionMark size={24} class="shrink-0" />
<span>What's the difference between the strats?</span>
<ChevronsUpDown size={18} class="ml-auto shrink-0" />
</Collapsible.Trigger>
<Collapsible.Content>
<ul class="text-sm md:text-base text-surface-100 flex flex-col gap-2 pt-2">
{#each visibleStratDifferences as diff}
{@const selected = isStratDiffSelected(diff)}
<li
class="rounded-xs px-2 -mx-2 py-0.5 transition-colors {selected
? 'bg-secondary-500/20 ring-1 ring-secondary-500/50'
: ''}"
>
<span class="font-semibold {selected ? 'text-foreground' : 'text-surface-200'}"
>{diff.label}:</span
>
<span class={selected ? 'text-foreground' : 'text-surface-200'}
>{diff.description}</span
>
</li>
{/each}
</ul>
<!-- Below md the rows stack (name over description, description indented);
at md+ they render as a real two-column table. -->
<table
class="mt-2 block w-full text-sm md:table md:border-separate md:border-spacing-x-0 md:border-spacing-y-1 md:text-base"
>
<tbody class="block md:table-row-group">
{#each groupedStratDifferences as group}
{#if group.category}
<tr class="block md:table-row">
<td
colspan="2"
class="block pt-2 pb-0.5 text-xs font-bold tracking-wide text-secondary-300 uppercase md:table-cell"
>
{group.category}
</td>
</tr>
{/if}
{#each group.items as diff}
{@const selected = isStratDiffSelected(diff)}
<tr class="mb-2 block transition-colors md:mb-0 md:table-row">
<!-- md:w-px + nowrap collapses the name column to the widest label so
every name cell shares one uniform width (table mode only). -->
<td
class="block rounded-t-md py-1 pl-2 align-top font-semibold whitespace-nowrap md:table-cell md:w-px md:rounded-t-none md:rounded-l-md md:pr-4 {selected
? 'bg-secondary-500/20 text-foreground'
: 'text-surface-200'}"
>
<div class="flex items-center gap-2">
{#if diff.badges}
{#each diff.badges as badge}
<span class="badge {badge.class} px-1.5 align-middle">{badge.text}</span>
{/each}
{/if}
{diff.label}
</div>
</td>
<td
class="block rounded-b-md pr-2 pb-1 pl-6 align-top md:table-cell md:rounded-r-md md:rounded-b-none md:py-1 md:pl-0 {selected
? 'bg-secondary-500/20 text-foreground'
: 'text-surface-200'}"
>
{diff.description}
</td>
</tr>
{/each}
{/each}
</tbody>
</table>
</Collapsible.Content>
</div>
</Collapsible.Root>
Expand Down Expand Up @@ -615,19 +659,6 @@
</p>
{/if}

{#if mech?.imageUrl}
{@const tf =
mech.alignmentTransforms?.[alignment] ?? mech.transform}
<div class="mt-4 overflow-hidden">
<img
class="w-auto h-auto rounded-sm object-contain max-w-full max-h-[350px] transition-transform duration-300 origin-center"
style:transform={tf || undefined}
src={mech.imageUrl}
alt={mech.mechanic}
/>
</div>
{/if}

<div class="flex items-start gap-1.5 text-base text-surface-100">
{#if mech.strats && mech.strats.length > 0 && mech.strats[0].description}
{#if mech.strats[0].toggleKey}
Expand All @@ -643,6 +674,28 @@
</div>
</div>

{#if mech?.imageUrl}
{@const tf =
mech.alignmentTransforms?.[alignment] ?? mech.transform}
<!-- When the image is shared across all roles it lives at the
mech level; the per-role mask (if any) overlays it, unless a
role-specific strat image is also present (rendered below). -->
{@const mechMask = mech?.strats?.[0]?.imageUrl
? undefined
: mech?.strats?.[0]?.mask}
<div class="mt-2 overflow-hidden relative w-fit h-fit">
<img
class="block rounded-sm max-w-full max-h-[350px] transition-transform duration-300 origin-center"
style:transform={tf || undefined}
src={mech.imageUrl}
alt={mech.mechanic}
/>
{#if spotlight && mechMask}
<SpotlightOverlay mask={mechMask} />
{/if}
</div>
{/if}

{#if mech?.strats && mech.strats[0]?.imageUrl}
<div class="mt-2 overflow-hidden relative w-fit h-fit">
<img
Expand Down
3 changes: 3 additions & 0 deletions src/lib/mitIcons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ const MIT_ICONS: Record<string, string | Partial<Record<Job, string>>> = {
GNB: 'superbolide'
},
'40%': { PLD: 'guardian', WAR: 'damnation', DRK: 'shadowed-vigil', GNB: 'great-nebula' },
// LPDU's name for the same cooldown
'120s': { PLD: 'guardian', WAR: 'damnation', DRK: 'shadowed-vigil', GNB: 'great-nebula' },
'90s': { PLD: 'bulwark', WAR: 'thrill-of-battle', DRK: 'dark-mind', GNB: 'camouflage' },
'Short Mit': {
PLD: 'holy-sheltron',
Expand Down Expand Up @@ -77,6 +79,7 @@ const MIT_ICONS: Record<string, string | Partial<Record<Job, string>>> = {
Holos: 'holos',
Panhaima: 'panhaima',
'Zoe Shields': 'zoe',
'Zoe Eprog': 'zoe',
Philosophia: 'philosophia'
};

Expand Down
Loading
Loading