feat(database): refine weapon registry cards
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { databaseCategory } from '$lib/database/categories';
|
||||
import type { GameIconName } from '$lib/game-icons';
|
||||
import { weaponBaseRange } from '$lib/builder/loadout';
|
||||
import { gameDataIconUrl, type GameDataIconType } from '$lib/server/game-data-icons';
|
||||
import { getDatabase } from '$lib/server/database';
|
||||
import { getPagination, getRegistrySearch } from '$lib/server/pagination';
|
||||
@@ -247,6 +248,17 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
||||
const total = Number((await (await database.prepare(countSql)).get(...queryArgs))?.total ?? 0);
|
||||
const pagination = getPagination(url, total);
|
||||
const rows = await (await database.prepare(rowsSql)).all(...queryArgs, pagination.perPage, pagination.offset);
|
||||
const weaponRelations = category.slug === 'weapons' && rows.length
|
||||
? await (await database.prepare(`SELECT options.weapon_id,options.talent_slot,talents.*,
|
||||
(SELECT description FROM talent_tiers tiers WHERE tiers.talent_id=talents.id AND tiers.tier='I') AS tier_i,
|
||||
(SELECT description FROM talent_tiers tiers WHERE tiers.talent_id=talents.id AND tiers.tier='II') AS tier_ii,
|
||||
icons.updated_at AS icon_updated_at
|
||||
FROM weapon_talent_options options
|
||||
JOIN talents ON talents.id=options.talent_id AND talents.active=1
|
||||
LEFT JOIN game_data_icons icons ON icons.entity_type='talent' AND icons.entity_id=talents.id
|
||||
WHERE options.weapon_id IN (${rows.map(() => '?').join(',')})
|
||||
ORDER BY options.talent_slot,talents.name COLLATE NOCASE`)).all(...rows.map((row) => row.id))
|
||||
: [];
|
||||
const gearRelations = category.slug === 'gear' && rows.length
|
||||
? await (await database.prepare(`SELECT relation.*,icons.updated_at
|
||||
FROM (
|
||||
@@ -340,21 +352,69 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
||||
};
|
||||
}
|
||||
case 'weapons':
|
||||
{
|
||||
const relatedTalents = weaponRelations.filter((relation) => relation.weapon_id === row.id);
|
||||
const talentItems = (slot: number) => relatedTalents
|
||||
.filter((relation) => Number(relation.talent_slot) === slot)
|
||||
.map((relation) => {
|
||||
const talentIcon = iconUrl('talent', relation.id, relation.icon_updated_at);
|
||||
return {
|
||||
id: String(relation.id),
|
||||
name: String(relation.name),
|
||||
iconUrl: talentIcon,
|
||||
preview: {
|
||||
id: String(relation.id), name: String(relation.name), kicker: `WEAPON TALENT // SLOT ${slot}`,
|
||||
iconUrl: talentIcon,
|
||||
badges: [
|
||||
...(relation.cooldown_seconds ? [{ label: `${number(relation.cooldown_seconds)}s COOLDOWN` }] : []),
|
||||
...(relation.duration_seconds ? [{ label: `${number(relation.duration_seconds)}s DURATION` }] : []),
|
||||
...(relation.max_stacks ? [{ label: `${relation.max_stacks} STACKS` }] : [])
|
||||
],
|
||||
facts: [
|
||||
{ label: 'TIER I', value: relation.tier_i ? 'CONFIGURED' : 'MISSING' },
|
||||
{ label: 'TIER II', value: relation.tier_ii ? 'CONFIGURED' : 'MISSING' }
|
||||
],
|
||||
description: relation.tier_i ? `TIER I · ${relation.tier_i}` : 'Tier I description is not configured.',
|
||||
secondaryDescription: relation.tier_ii ? `TIER II · ${relation.tier_ii}` : 'Tier II description is not configured.'
|
||||
}
|
||||
};
|
||||
});
|
||||
const level50Damage = row.damage_min === null ? null : weaponBaseRange(row.damage_min, row.damage_max, 50);
|
||||
return {
|
||||
id: String(row.id), name: String(row.name), kicker: `${row.category} // ${row.damage_type}`,
|
||||
gameIcon: weaponIcon(row.category),
|
||||
badges: [{ label: `T${row.native_tier}` }, ...(Number(row.is_exotic) ? [{ label: 'EXOTIC', tone: 'exotic' }] : [])],
|
||||
headerBadge: `T${row.native_tier}`,
|
||||
headerMetaIcon: weaponIcon(row.damage_type),
|
||||
badges: Number(row.is_exotic) ? [{ label: 'EXOTIC', tone: 'exotic' }] : [],
|
||||
factLayout: 'stack' as const,
|
||||
facts: [
|
||||
{ label: 'DAMAGE RANGE', value: row.damage_min === null ? 'NOT CONFIGURED' : `${range(row.damage_min,row.damage_max)} · L${row.reference_level}` },
|
||||
{
|
||||
label: 'DAMAGE',
|
||||
value: level50Damage ? `${level50Damage.min.toLocaleString('en-US')}–${level50Damage.max.toLocaleString('en-US')}` : 'NOT CONFIGURED',
|
||||
emphasis: 'primary' as const,
|
||||
gameIcon: weaponIcon(row.damage_type),
|
||||
note: 'AT LEVEL 50'
|
||||
},
|
||||
{ label: 'RATE / MAG', value: `${number(row.rpm)} RPM · ${number(row.magazine)} MAG` },
|
||||
{ label: 'RELOAD', value: valueWithUnit(row.reload_speed,'s') },
|
||||
{ label: 'ACCURACY / STABILITY', value: `${number(row.accuracy)} / ${number(row.stability)}` }
|
||||
{
|
||||
label: 'HANDLING',
|
||||
value: '',
|
||||
meters: [
|
||||
{ label: 'ACCURACY', value: Number(row.accuracy) || 0 },
|
||||
{ label: 'STABILITY', value: Number(row.stability) || 0 }
|
||||
]
|
||||
}
|
||||
],
|
||||
lines: [
|
||||
{ label: 'TALENT POOLS', value: `${row.talent_1_count} TOP · ${row.talent_2_count} BOTTOM` },
|
||||
{ label: 'BASE BONUSES', value: String(row.bonus_count) }
|
||||
],
|
||||
iconGroups: [
|
||||
{ label: 'TALENT 1 POOL', items: talentItems(1), emptyLabel: 'NO TALENTS ASSIGNED' },
|
||||
{ label: 'TALENT 2 POOL', items: talentItems(2), emptyLabel: 'NO TALENTS ASSIGNED' }
|
||||
]
|
||||
};
|
||||
}
|
||||
case 'weapon-mods':
|
||||
return {
|
||||
id: String(row.id), name: String(row.name), kicker: `${row.slot_type} // WEAPON MOD`,
|
||||
|
||||
Reference in New Issue
Block a user