feat(isac): author exotic talents in weapon editor
This commit is contained in:
@@ -21,7 +21,7 @@ export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
: filter === 'body-armor' ? "WHERE category IN ('Vest','Body Armor')" : '';
|
||||
const filteredRow = await (await db.prepare(`SELECT COUNT(*) AS total FROM talents ${where}`)).get();
|
||||
const pagination = getPagination(url, Number(filteredRow?.total ?? 0));
|
||||
const [talents, tiers, triggers, links, effects, stats, templates, weaponScopes, weaponSlots] = await Promise.all([
|
||||
const [talents, tiers, triggers, links, effects, stats, templates, weaponScopes, weaponSlots, exoticOwners] = await Promise.all([
|
||||
(await db.prepare(`SELECT * FROM talents ${where} ORDER BY active DESC,name COLLATE NOCASE LIMIT ? OFFSET ?`)).all(pagination.perPage, pagination.offset),
|
||||
(await db.prepare('SELECT id,talent_id,tier,description FROM talent_tiers')).all(),
|
||||
(await db.prepare('SELECT * FROM talent_triggers ORDER BY active DESC,name COLLATE NOCASE')).all(),
|
||||
@@ -30,7 +30,8 @@ export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
(await db.prepare('SELECT id,name,unit FROM stat_attributes WHERE active=1 ORDER BY name COLLATE NOCASE')).all(),
|
||||
(await db.prepare('SELECT talent_id,template FROM talent_description_templates')).all(),
|
||||
(await db.prepare('SELECT talent_id,scope FROM talent_weapon_scopes')).all(),
|
||||
(await db.prepare('SELECT talent_id,slot FROM weapon_talent_slots')).all()
|
||||
(await db.prepare('SELECT talent_id,slot FROM weapon_talent_slots')).all(),
|
||||
(await db.prepare('SELECT id,name,exotic_talent_id FROM weapons WHERE exotic_talent_id IS NOT NULL')).all()
|
||||
]);
|
||||
const [triggerSummary, slotSummary, exoticSummary, gearSummary] = await Promise.all([
|
||||
(await db.prepare('SELECT COUNT(*) AS total FROM talent_triggers')).get(),
|
||||
@@ -58,6 +59,8 @@ export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
? 'Weapon · Slot Unassigned'
|
||||
: talent.category,
|
||||
descriptionTemplate: templates.find((item) => item.talent_id === talent.id)?.template ?? '',
|
||||
ownerWeaponId: exoticOwners.find((weapon) => weapon.exotic_talent_id === talent.id)?.id ?? null,
|
||||
ownerWeaponName: exoticOwners.find((weapon) => weapon.exotic_talent_id === talent.id)?.name ?? null,
|
||||
tiers: tiers.filter((tier) => tier.talent_id === talent.id).map((tier) => ({
|
||||
...tier,
|
||||
triggerIds: links.filter((link) => link.talent_tier_id === tier.id).map((link) => String(link.trigger_id)),
|
||||
@@ -131,13 +134,13 @@ export const actions: Actions = {
|
||||
const triggerIds = [...new Set(form.getAll('triggerIds').map(String))];
|
||||
let sharedEffects: SharedEffect[];
|
||||
try { sharedEffects = parseEffects(form.get('effects')); } catch { return fail(400, { talentError: 'Effects could not be read.' }); }
|
||||
if (name.length < 2 || !['Weapon Talent 1', 'Weapon Talent 2', 'Exotic Weapon', 'Backpack', 'Body Armor'].includes(category)) return fail(400, { talentError: 'Provide a valid talent name and category.' });
|
||||
if (name.length < 2 || !['Weapon Talent 1', 'Weapon Talent 2', 'Backpack', 'Body Armor'].includes(category)) return fail(400, { talentError: 'Provide a valid talent name and category. Exotic talents are managed from their owning weapon.' });
|
||||
if (!descriptionTemplate || !triggerIds.length || !sharedEffects.length) return fail(400, { talentError: 'A description template, trigger, and at least one effect are required.' });
|
||||
if (sharedEffects.some((effect) => !effect.statId || !Number.isFinite(effect.valueI) || !Number.isFinite(effect.valueII))) return fail(400, { talentError: 'Every effect needs valid Tier I and Tier II values.' });
|
||||
if (new Set(sharedEffects.map((effect) => effect.statId)).size !== sharedEffects.length) return fail(400, { talentError: 'Each affected attribute can only be selected once.' });
|
||||
const placeholders = [...descriptionTemplate.matchAll(/\{(\d+)\}/g)].map((match) => Number(match[1]));
|
||||
if (placeholders.some((index) => index < 1 || index > sharedEffects.length)) return fail(400, { talentError: 'Description placeholders must reference an existing effect.' });
|
||||
const storedCategory = category === 'Body Armor' ? 'Vest' : category.startsWith('Weapon Talent') || category === 'Exotic Weapon' ? 'Weapon' : category;
|
||||
const storedCategory = category === 'Body Armor' ? 'Vest' : category.startsWith('Weapon Talent') ? 'Weapon' : category;
|
||||
const db = await getDatabase();
|
||||
if (await (await db.prepare('SELECT id FROM talents WHERE name=? COLLATE NOCASE AND category=? AND id<>?')).get(name, storedCategory, id || 'new')) return fail(409, { talentError: 'That talent already exists in this category.' });
|
||||
const statRows = await (await db.prepare(`SELECT id,unit FROM stat_attributes WHERE active=1 AND id IN (${sharedEffects.map(() => '?').join(',')})`)).all(...sharedEffects.map((effect) => effect.statId));
|
||||
@@ -150,14 +153,10 @@ export const actions: Actions = {
|
||||
if (storedCategory === 'Weapon') {
|
||||
await (await db.prepare(`INSERT INTO talent_weapon_scopes(talent_id,scope) VALUES(?,?)
|
||||
ON CONFLICT(talent_id) DO UPDATE SET scope=excluded.scope`))
|
||||
.run(talentId, category === 'Exotic Weapon' ? 'Exotic' : 'Standard');
|
||||
if (category === 'Exotic Weapon') {
|
||||
await (await db.prepare('DELETE FROM weapon_talent_slots WHERE talent_id=?')).run(talentId);
|
||||
} else {
|
||||
await (await db.prepare(`INSERT INTO weapon_talent_slots(talent_id,slot) VALUES(?,?)
|
||||
ON CONFLICT(talent_id) DO UPDATE SET slot=excluded.slot`))
|
||||
.run(talentId, category === 'Weapon Talent 1' ? 1 : 2);
|
||||
}
|
||||
.run(talentId, 'Standard');
|
||||
await (await db.prepare(`INSERT INTO weapon_talent_slots(talent_id,slot) VALUES(?,?)
|
||||
ON CONFLICT(talent_id) DO UPDATE SET slot=excluded.slot`))
|
||||
.run(talentId, category === 'Weapon Talent 1' ? 1 : 2);
|
||||
} else {
|
||||
await (await db.prepare('DELETE FROM talent_weapon_scopes WHERE talent_id=?')).run(talentId);
|
||||
await (await db.prepare('DELETE FROM weapon_talent_slots WHERE talent_id=?')).run(talentId);
|
||||
|
||||
Reference in New Issue
Block a user