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'; import { error } from '@sveltejs/kit'; import type { PageServerLoad } from './$types'; const number = (value: unknown) => { const numeric = Number(value); return Number.isFinite(numeric) ? (Number.isInteger(numeric) ? String(numeric) : numeric.toFixed(2).replace(/\.?0+$/, '')) : '—'; }; const valueWithUnit = (value: unknown, unit: unknown) => `${number(value)}${unit ? (unit === '%' ? '%' : ` ${unit}`) : ''}`; const range = (min: unknown, max: unknown, unit: unknown = '') => `${valueWithUnit(min, unit)}–${valueWithUnit(max, unit)}`; const list = (value: unknown, fallback = 'NONE') => typeof value === 'string' && value ? value : fallback; const gearIcon = (slot: unknown) => String(slot).toLowerCase().replaceAll(' ', '_') as GameIconName; const weaponIcon = (category: unknown) => String(category).toLowerCase() as GameIconName; const iconUrl = (type: GameDataIconType, id: unknown, updatedAt: unknown) => updatedAt ? gameDataIconUrl(type, String(id), updatedAt) : ''; export const load: PageServerLoad = async ({ params, url }) => { const category = databaseCategory(params.category); if (!category) error(404, 'Database category not found'); const database = await getDatabase(); const { search, pattern } = getRegistrySearch(url); const searchArgs = search ? [pattern] : []; const searchClause = search ? " AND item.name LIKE ? ESCAPE '\\' COLLATE NOCASE" : ''; let queryArgs: unknown[] = searchArgs; let filters: Array<{ key: string; label: string; kind: 'segmented' | 'searchable'; selected: string[]; options: Array<{ value: string; label: string; description?: string; searchText?: string; iconUrl?: string; gameIcon?: GameIconName }>; }> = []; let countSql = ''; let rowsSql = ''; switch (category.slug) { case 'gear': { const [brandRows, talentRows] = await Promise.all([ (await database.prepare(`SELECT brands.id,brands.name, (SELECT GROUP_CONCAT(DISTINCT attributes.name) FROM brand_set_effects effects JOIN stat_attributes attributes ON attributes.id=effects.stat_attribute_id WHERE effects.brand_set_id=brands.id) AS bonus_attributes, icons.updated_at FROM brand_sets brands LEFT JOIN game_data_icons icons ON icons.entity_type='brand_set' AND icons.entity_id=brands.id WHERE brands.active=1 ORDER BY brands.name COLLATE NOCASE`)).all(), (await database.prepare(`SELECT talents.id,talents.name, (SELECT description FROM talent_tiers tiers WHERE tiers.talent_id=talents.id AND tiers.tier='I') AS tier_i_description, icons.updated_at FROM talents LEFT JOIN game_data_icons icons ON icons.entity_type='talent' AND icons.entity_id=talents.id WHERE talents.active=1 AND talents.category IN ('Backpack','Body Armor','Vest') ORDER BY talents.name COLLATE NOCASE`)).all() ]); const slots = ['Holster', 'Gloves', 'Backpack', 'Knee Pads', 'Body Armor', 'Mask']; const validBrands = new Set(brandRows.map((row) => String(row.id))); const validTalents = new Set(talentRows.map((row) => String(row.id))); const selectedSlots = url.searchParams.getAll('slot').filter((value) => slots.includes(value)); const selectedBrands = url.searchParams.getAll('brand').filter((value) => validBrands.has(value)); const selectedTalents = url.searchParams.getAll('talent').filter((value) => validTalents.has(value)); const conditions = ['item.active=1']; queryArgs = []; if (search) { conditions.push("item.name LIKE ? ESCAPE '\\' COLLATE NOCASE"); queryArgs.push(pattern); } if (selectedSlots.length) { conditions.push(`item.slot IN (${selectedSlots.map(() => '?').join(',')})`); queryArgs.push(...selectedSlots); } if (selectedBrands.length) { conditions.push(`EXISTS (SELECT 1 FROM gear_brand_sets filter_brands WHERE filter_brands.gear_id=item.id AND filter_brands.brand_set_id IN (${selectedBrands.map(() => '?').join(',')}))`); queryArgs.push(...selectedBrands); } if (selectedTalents.length) { conditions.push(`EXISTS (SELECT 1 FROM gear_talents filter_talents WHERE filter_talents.gear_id=item.id AND filter_talents.talent_id IN (${selectedTalents.map(() => '?').join(',')}))`); queryArgs.push(...selectedTalents); } const where = conditions.join(' AND '); countSql = `SELECT COUNT(*) AS total FROM gear item WHERE ${where}`; rowsSql = `SELECT item.* FROM gear item WHERE ${where} ORDER BY item.slot,item.tier,item.name COLLATE NOCASE LIMIT ? OFFSET ?`; filters = [ { key: 'slot', label: 'GEAR SLOT', kind: 'segmented', selected: selectedSlots, options: slots.map((slot) => ({ value: slot, label: slot, gameIcon: gearIcon(slot) })) }, { key: 'brand', label: 'BRAND SETS', kind: 'searchable', selected: selectedBrands, options: brandRows.map((row) => ({ value: String(row.id), label: String(row.name), searchText: String(row.bonus_attributes ?? ''), iconUrl: iconUrl('brand_set', row.id, row.updated_at) })) }, { key: 'talent', label: 'TALENTS', kind: 'searchable', selected: selectedTalents, options: talentRows.map((row) => ({ value: String(row.id), label: String(row.name), description: String(row.tier_i_description ?? ''), iconUrl: iconUrl('talent', row.id, row.updated_at) })) } ]; break; } case 'weapons': { const talentRows = await (await database.prepare(`SELECT DISTINCT talents.id,talents.name, (SELECT description FROM talent_tiers tiers WHERE tiers.talent_id=talents.id AND tiers.tier='I') AS tier_i_description, icons.updated_at FROM weapon_talent_options options JOIN weapons source_weapons ON source_weapons.id=options.weapon_id AND source_weapons.active=1 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 ORDER BY talents.name COLLATE NOCASE`)).all(); const weaponTypes = ['Shotgun', 'Rifle', 'MMR', 'AR', 'LMG', 'SMG']; const damageTypes = ['Blast', 'Pierce', 'Shredding']; const validTalents = new Set(talentRows.map((row) => String(row.id))); const selectedTypes = url.searchParams.getAll('weaponType').filter((value) => weaponTypes.includes(value)); const selectedDamageTypes = url.searchParams.getAll('damageType').filter((value) => damageTypes.includes(value)); const selectedTalents = url.searchParams.getAll('weaponTalent').filter((value) => validTalents.has(value)); const conditions = ['item.active=1']; queryArgs = []; if (search) { conditions.push("item.name LIKE ? ESCAPE '\\' COLLATE NOCASE"); queryArgs.push(pattern); } if (selectedTypes.length) { conditions.push(`item.category IN (${selectedTypes.map(() => '?').join(',')})`); queryArgs.push(...selectedTypes); } if (selectedDamageTypes.length) { conditions.push(`item.damage_type IN (${selectedDamageTypes.map(() => '?').join(',')})`); queryArgs.push(...selectedDamageTypes); } if (selectedTalents.length) { conditions.push(`EXISTS (SELECT 1 FROM weapon_talent_options filter_talents WHERE filter_talents.weapon_id=item.id AND filter_talents.talent_id IN (${selectedTalents.map(() => '?').join(',')}))`); queryArgs.push(...selectedTalents); } const where = conditions.join(' AND '); countSql = `SELECT COUNT(*) AS total FROM weapons item WHERE ${where}`; rowsSql = `SELECT item.*, native.damage_min,native.damage_max,native.reference_level, (SELECT COUNT(*) FROM weapon_talent_options options WHERE options.weapon_id=item.id AND options.talent_slot=1) AS talent_1_count, (SELECT COUNT(*) FROM weapon_talent_options options WHERE options.weapon_id=item.id AND options.talent_slot=2) AS talent_2_count, (SELECT COUNT(*) FROM weapon_base_attribute_bonuses bonuses WHERE bonuses.weapon_id=item.id) AS bonus_count FROM weapons item LEFT JOIN weapon_tier_ranges native ON native.weapon_id=item.id AND native.tier=item.native_tier WHERE ${where} ORDER BY item.is_exotic DESC,item.category,item.name COLLATE NOCASE LIMIT ? OFFSET ?`; filters = [ { key: 'weaponType', label: 'WEAPON TYPE', kind: 'segmented', selected: selectedTypes, options: weaponTypes.map((type) => ({ value: type, label: type, gameIcon: weaponIcon(type) })) }, { key: 'damageType', label: 'DAMAGE TYPE', kind: 'segmented', selected: selectedDamageTypes, options: damageTypes.map((type) => ({ value: type, label: type, gameIcon: weaponIcon(type) })) }, { key: 'weaponTalent', label: 'TALENT POOL', kind: 'searchable', selected: selectedTalents, options: talentRows.map((row) => ({ value: String(row.id), label: String(row.name), description: String(row.tier_i_description ?? ''), iconUrl: iconUrl('talent', row.id, row.updated_at) })) } ]; break; } case 'weapon-mods': countSql = `SELECT COUNT(*) AS total FROM weapon_mods item WHERE item.active=1${searchClause}`; rowsSql = `SELECT item.*,weapons.name AS exotic_weapon, GROUP_CONCAT(DISTINCT categories.weapon_category) AS categories, (SELECT COUNT(*) FROM weapon_mod_secondary_options secondary WHERE secondary.weapon_mod_id=item.id) AS secondary_count, (SELECT COUNT(*) FROM weapon_mod_effects effects WHERE effects.weapon_mod_id=item.id) AS effect_count FROM weapon_mods item LEFT JOIN weapons ON weapons.id=item.exotic_weapon_id LEFT JOIN weapon_mod_compatible_categories categories ON categories.weapon_mod_id=item.id WHERE item.active=1${searchClause} GROUP BY item.id ORDER BY item.slot_type,item.name COLLATE NOCASE LIMIT ? OFFSET ?`; break; case 'gear-mods': countSql = `SELECT COUNT(*) AS total FROM gear_mods item WHERE item.active=1${searchClause}`; rowsSql = `SELECT item.*, (SELECT COUNT(*) FROM gear_mod_secondary_options secondary WHERE secondary.gear_mod_id=item.id) AS secondary_count, (SELECT MIN(primary_level_1_min) FROM gear_mod_quality_values quality WHERE quality.gear_mod_id=item.id) AS level_1_floor, (SELECT MAX(primary_level_20_max) FROM gear_mod_quality_values quality WHERE quality.gear_mod_id=item.id) AS level_20_ceiling FROM gear_mods item WHERE item.active=1${searchClause} ORDER BY item.name COLLATE NOCASE LIMIT ? OFFSET ?`; break; case 'os-protocols': countSql = `SELECT COUNT(*) AS total FROM os_protocols item WHERE item.active=1${searchClause}`; rowsSql = `SELECT item.*,attributes.name AS primary_stat,attributes.unit AS primary_unit, primary_effect.base_value,talents.name AS talent_name,icons.updated_at AS icon_updated_at FROM os_protocols item LEFT JOIN os_protocol_primary_effects primary_effect ON primary_effect.protocol_id=item.id LEFT JOIN stat_attributes attributes ON attributes.id=primary_effect.stat_attribute_id LEFT JOIN os_protocol_talents talents ON talents.protocol_id=item.id LEFT JOIN game_data_icons icons ON icons.entity_type='os_protocol' AND icons.entity_id=item.id WHERE item.active=1${searchClause} ORDER BY item.quality,item.primary_attribute_type,item.name COLLATE NOCASE LIMIT ? OFFSET ?`; break; case 'talents': { const talentSlots = [ { value: 'Backpack', label: 'Backpack', gameIcon: 'backpack' as const }, { value: 'Body Armor', label: 'Body Armor', gameIcon: 'body_armor' as const }, { value: 'Weapon 1', label: 'Weapon 1 · Top', gameIcon: 'smg' as const }, { value: 'Weapon 2', label: 'Weapon 2 · Bottom', gameIcon: 'smg' as const } ]; const selectedTalentSlots = url.searchParams.getAll('talentSlot') .filter((value) => talentSlots.some((slot) => slot.value === value)); const conditions = ['item.active=1']; queryArgs = []; if (search) { conditions.push("item.name LIKE ? ESCAPE '\\' COLLATE NOCASE"); queryArgs.push(pattern); } if (selectedTalentSlots.length) { const slotConditions = selectedTalentSlots.map((slot) => { if (slot === 'Backpack') return "item.category='Backpack'"; if (slot === 'Body Armor') return "item.category IN ('Body Armor','Vest')"; queryArgs.push(slot === 'Weapon 1' ? 1 : 2); return `item.category='Weapon' AND EXISTS ( SELECT 1 FROM weapon_talent_slots filter_slots WHERE filter_slots.talent_id=item.id AND filter_slots.slot=? )`; }); conditions.push(`(${slotConditions.map((condition) => `(${condition})`).join(' OR ')})`); } const where = conditions.join(' AND '); countSql = `SELECT COUNT(*) AS total FROM talents item WHERE ${where}`; rowsSql = `SELECT item.*, (SELECT description FROM talent_tiers tiers WHERE tiers.talent_id=item.id AND tiers.tier='I') AS tier_i, (SELECT description FROM talent_tiers tiers WHERE tiers.talent_id=item.id AND tiers.tier='II') AS tier_ii, (SELECT slot FROM weapon_talent_slots slots WHERE slots.talent_id=item.id) AS weapon_slot, (SELECT scope FROM talent_weapon_scopes scopes WHERE scopes.talent_id=item.id) AS weapon_scope, icons.updated_at AS icon_updated_at FROM talents item LEFT JOIN game_data_icons icons ON icons.entity_type='talent' AND icons.entity_id=item.id WHERE ${where} ORDER BY item.category,item.name COLLATE NOCASE LIMIT ? OFFSET ?`; filters = [{ key: 'talentSlot', label: 'TALENT SLOT', kind: 'segmented', selected: selectedTalentSlots, options: talentSlots }]; break; } case 'brands': countSql = `SELECT COUNT(*) AS total FROM brand_sets item WHERE item.active=1${searchClause}`; rowsSql = `SELECT item.*,icons.updated_at AS icon_updated_at FROM brand_sets item LEFT JOIN game_data_icons icons ON icons.entity_type='brand_set' AND icons.entity_id=item.id WHERE item.active=1${searchClause} ORDER BY item.name COLLATE NOCASE LIMIT ? OFFSET ?`; break; case 'skill-chips': countSql = `SELECT COUNT(*) AS total FROM skill_chip_sets item WHERE item.active=1${searchClause}`; rowsSql = `SELECT item.*,bonus.min_value,bonus.max_value,attributes.name AS bonus_stat,attributes.unit AS bonus_unit, talents.name AS talent_name,abilities.name AS ability_name,specializations.name AS specialization_name, (SELECT COUNT(*) FROM skill_chip_primary_options options WHERE options.skill_chip_set_id=item.id) AS primary_count, (SELECT COUNT(*) FROM skill_chip_secondary_options options WHERE options.skill_chip_set_id=item.id) AS secondary_count, icons.updated_at AS icon_updated_at FROM skill_chip_sets item LEFT JOIN skill_chip_two_piece_bonuses bonus ON bonus.skill_chip_set_id=item.id LEFT JOIN stat_attributes attributes ON attributes.id=bonus.stat_attribute_id LEFT JOIN skill_chip_talents talents ON talents.skill_chip_set_id=item.id LEFT JOIN specialization_abilities abilities ON abilities.id=item.specialization_ability_id LEFT JOIN specializations ON specializations.id=abilities.specialization_id LEFT JOIN game_data_icons icons ON icons.entity_type='skill_chip' AND icons.entity_id=item.id WHERE item.active=1${searchClause} ORDER BY item.name COLLATE NOCASE LIMIT ? OFFSET ?`; break; } 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 ( SELECT links.gear_id,'brand' AS kind,brands.id,brands.name, NULL AS category,NULL AS cooldown_seconds,NULL AS duration_seconds,NULL AS max_stacks, NULL AS tier_i,NULL AS tier_ii FROM gear_brand_sets links JOIN brand_sets brands ON brands.id=links.brand_set_id WHERE brands.active=1 UNION ALL SELECT links.gear_id,'talent' AS kind,talents.id,talents.name, talents.category,talents.cooldown_seconds,talents.duration_seconds,talents.max_stacks, (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 FROM gear_talents links JOIN talents ON talents.id=links.talent_id WHERE talents.active=1 ) relation LEFT JOIN game_data_icons icons ON icons.entity_id=relation.id AND icons.entity_type=CASE relation.kind WHEN 'brand' THEN 'brand_set' ELSE 'talent' END WHERE relation.gear_id IN (${rows.map(() => '?').join(',')}) ORDER BY relation.kind,relation.name COLLATE NOCASE`)).all(...rows.map((row) => row.id)) : []; const gearBrandEffects = category.slug === 'gear' && gearRelations.some((relation) => relation.kind === 'brand') ? await (await database.prepare(`SELECT effects.brand_set_id,effects.pieces_required,effects.value, attributes.name,attributes.unit FROM brand_set_effects effects JOIN stat_attributes attributes ON attributes.id=effects.stat_attribute_id WHERE effects.brand_set_id IN (${gearRelations.filter((relation) => relation.kind === 'brand').map(() => '?').join(',')}) ORDER BY effects.pieces_required`)).all(...gearRelations.filter((relation) => relation.kind === 'brand').map((relation) => relation.id)) : []; const brandEffects = category.slug === 'brands' && rows.length ? await (await database.prepare(`SELECT effects.brand_set_id,effects.pieces_required,effects.value, attributes.name,attributes.unit FROM brand_set_effects effects JOIN stat_attributes attributes ON attributes.id=effects.stat_attribute_id WHERE effects.brand_set_id IN (${rows.map(() => '?').join(',')}) ORDER BY effects.pieces_required`)).all(...rows.map((row) => row.id)) : []; const items = rows.map((row) => { switch (category.slug) { case 'gear': { const relations = gearRelations.filter((relation) => relation.gear_id === row.id); const relatedItems = (kind: 'brand' | 'talent', type: GameDataIconType) => relations .filter((relation) => relation.kind === kind) .map((relation) => { const relationIcon = iconUrl(type, relation.id, relation.updated_at); const effects = kind === 'brand' ? gearBrandEffects.filter((effect) => effect.brand_set_id === relation.id) : []; return { id: String(relation.id), name: String(relation.name), iconUrl: relationIcon, preview: kind === 'brand' ? { id: String(relation.id), name: String(relation.name), kicker: 'BRAND SET // EQUIPMENT', iconUrl: relationIcon, factLayout: 'stack' as const, actions: [{ label: 'FIND GEAR WITH THIS BRAND', href: `/database/gear?brand=${encodeURIComponent(String(relation.id))}` }], facts: effects.map((effect) => ({ label: `${effect.pieces_required} PIECES`, value: `${effect.name} · +${valueWithUnit(effect.value,effect.unit)}` })) } : { id: String(relation.id), name: String(relation.name), kicker: `${relation.category} // GEAR TALENT`, iconUrl: relationIcon, 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 iconGroups = [ { label: 'BRAND OPTIONS', items: relatedItems('brand', 'brand_set'), emptyLabel: 'NO BRANDS ASSIGNED' }, ...(['Backpack', 'Body Armor'].includes(String(row.slot)) ? [{ label: 'AVAILABLE TALENTS', items: relatedItems('talent', 'talent'), emptyLabel: 'NO TALENTS ASSIGNED' }] : []) ]; return { id: String(row.id), name: String(row.name), kicker: `${row.slot} // T${row.tier}`, gameIcon: gearIcon(row.slot), badges: [{ label: `T${row.tier}` }, { label: `${Number(row.tier) === 0 ? 1 : 2} MOD SLOT${Number(row.tier) === 0 ? '' : 'S'}` }], facts: [ { label: 'BASE HEALTH', value: range(row.base_health_min,row.base_health_max) }, ...(row.base_armor_min === null ? [] : [{ label: 'BASE ARMOR', value: range(row.base_armor_min,row.base_armor_max) }]) ], iconGroups }; } 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), 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', 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: 'HANDLING', value: '', meters: [ { label: 'ACCURACY', value: Number(row.accuracy) || 0 }, { label: 'STABILITY', value: Number(row.stability) || 0 } ] } ], lines: [ { 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`, badges: row.exotic_weapon_id ? [{ label: 'EXOTIC', tone: 'exotic' }] : [{ label: 'STANDARD → HIGH-END' }], facts: [ { label: 'LEVELS', value: '01–20' }, { label: 'SECONDARY POOL', value: row.exotic_weapon_id ? 'FIXED ATTRIBUTES' : `${row.secondary_count} OPTIONS` }, { label: 'MOD EFFECTS', value: row.exotic_weapon_id ? 'FIXED' : String(row.effect_count) } ], lines: [{ label: row.exotic_weapon_id ? 'ASSIGNED WEAPON' : 'WEAPON CATEGORIES', value: row.exotic_weapon_id ? list(row.exotic_weapon) : list(row.categories).toUpperCase() }] }; case 'gear-mods': return { id: String(row.id), name: String(row.name), kicker: 'GEAR MOD // STANDARD QUALITIES', badges: [{ label: 'STANDARD → HIGH-END' }], facts: [ { label: 'LEVELS', value: '01–20' }, { label: 'PRIMARY OPTIONS', value: '5' }, { label: 'SECONDARY POOL', value: `${row.secondary_count} OPTIONS` } ], lines: [{ label: 'OBSERVED PRIMARY ENVELOPE', value: `${number(row.level_1_floor)} → ${number(row.level_20_ceiling)}` }] }; case 'os-protocols': return { id: String(row.id), name: String(row.name), kicker: `${row.primary_attribute_type} // OS PROTOCOL`, iconUrl: iconUrl('os_protocol',row.id,row.icon_updated_at), badges: [{ label: String(row.quality), tone: String(row.quality).toLowerCase().replace('-','') }], facts: [ { label: 'LEVELS', value: '01–50' }, { label: 'PRIMARY EFFECT', value: row.primary_stat ? `${row.primary_stat} · ${valueWithUnit(row.base_value,row.primary_unit)}` : 'NOT CONFIGURED' }, { label: 'TALENT UPGRADES', value: '0–5' } ], lines: [{ label: 'UNIQUE TALENT', value: list(row.talent_name,'NOT CONFIGURED') }] }; case 'talents': { const talentCategory = String(row.category); const isWeaponTalent = talentCategory === 'Weapon'; const normalizedCategory = talentCategory === 'Vest' ? 'Body Armor' : talentCategory; const slotLabel = isWeaponTalent && row.weapon_slot ? `WEAPON ${row.weapon_slot}` : normalizedCategory.toUpperCase(); return { id: String(row.id), name: String(row.name), kicker: `${slotLabel} TALENT`, iconUrl: iconUrl('talent',row.id,row.icon_updated_at), headerMetaIcon: isWeaponTalent ? 'smg' : gearIcon(normalizedCategory), headerBadge: isWeaponTalent && row.weapon_slot ? `${row.weapon_slot} · ${Number(row.weapon_slot) === 1 ? 'TOP' : 'BOTTOM'}` : undefined, badges: [ ...(row.weapon_scope === 'Exotic' ? [{ label: 'EXOTIC', tone: 'exotic' }] : []), ...(row.duration_seconds ? [{ label: `${number(row.duration_seconds)}s DURATION` }] : []), ...(row.max_stacks ? [{ label: `${row.max_stacks} STACKS` }] : []) ], facts: [], description: row.tier_i ? String(row.tier_i) : 'Description is not available.', secondaryDescription: row.tier_ii ? String(row.tier_ii) : 'Description is not available.', descriptionStyle: 'data' as const, afterLines: row.cooldown_seconds ? [{ label: 'TALENT COOLDOWN', value: `${number(row.cooldown_seconds)} SECONDS` }] : [] }; } case 'brands': { const effects = brandEffects.filter((effect) => effect.brand_set_id === row.id); return { id: String(row.id), name: String(row.name), kicker: 'BRAND SET // EQUIPMENT', iconUrl: iconUrl('brand_set',row.id,row.icon_updated_at), factLayout: 'stack' as const, actions: [{ label: 'FIND GEAR WITH THIS BRAND', href: `/database/gear?brand=${encodeURIComponent(String(row.id))}` }], facts: effects.map((effect) => ({ label: `${effect.pieces_required} PIECES`, value: `${effect.name} · +${valueWithUnit(effect.value,effect.unit)}` })) }; } case 'skill-chips': return { id: String(row.id), name: String(row.name), kicker: 'SKILL CHIP SET // 2–3 PIECES', iconUrl: iconUrl('skill_chip',row.id,row.icon_updated_at), badges: [{ label: 'SUPERIOR' }, { label: 'HIGH-END' }], facts: [ { label: 'SPECIALIZATION ABILITY', value: row.ability_name ? `${row.ability_name} · ${row.specialization_name}` : 'UNASSIGNED' }, { label: '2-PIECE BONUS', value: row.bonus_stat ? `${row.bonus_stat} · ${range(row.min_value,row.max_value,row.bonus_unit)}` : 'NOT CONFIGURED' }, { label: 'PRIMARY POOL', value: `${row.primary_count} OPTIONS` }, { label: 'SECONDARY POOL', value: `${row.secondary_count} OPTIONS` } ], lines: [{ label: '3-PIECE TALENT', value: list(row.talent_name,'NOT CONFIGURED') }] }; } }); return { category, items, pagination, search, filters }; };