integrate befoulment into weapon edit views
- wire BefoulmentSelect into EditWeaponSidebar and WeaponEditPane - update hasAxSkills logic to use series.augmentType - add befoulment to save payloads and handlers - add hasBefoulment to modificationDetector - update TeamView to display befoulment with exorcism level - fix story mocks
This commit is contained in:
parent
afdeacd11e
commit
21e948be7e
6 changed files with 122 additions and 26 deletions
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
import { onMount } from 'svelte'
|
||||
import type { CollectionWeapon } from '$lib/types/api/collection'
|
||||
import type { AugmentSkill } from '$lib/types/api/weaponStatModifier'
|
||||
import type { AugmentSkill, Befoulment } from '$lib/types/api/weaponStatModifier'
|
||||
import {
|
||||
useUpdateCollectionWeapon,
|
||||
useRemoveWeaponFromCollection
|
||||
|
|
@ -89,7 +89,8 @@
|
|||
level: weapon.awakening.level
|
||||
}
|
||||
: null,
|
||||
axSkills: (weapon.ax as AugmentSkill[]) ?? []
|
||||
axSkills: (weapon.ax as AugmentSkill[]) ?? [],
|
||||
befoulment: (weapon.befoulment as Befoulment) ?? null
|
||||
})
|
||||
|
||||
// Element name for theming
|
||||
|
|
@ -143,15 +144,22 @@
|
|||
}
|
||||
|
||||
// AX skills
|
||||
if (updates.axModifier1 !== undefined) {
|
||||
input.axModifier1 = updates.axModifier1
|
||||
if (updates.axModifier1Id !== undefined) {
|
||||
input.axModifier1Id = updates.axModifier1Id
|
||||
input.axStrength1 = updates.axStrength1
|
||||
}
|
||||
if (updates.axModifier2 !== undefined) {
|
||||
input.axModifier2 = updates.axModifier2
|
||||
if (updates.axModifier2Id !== undefined) {
|
||||
input.axModifier2Id = updates.axModifier2Id
|
||||
input.axStrength2 = updates.axStrength2
|
||||
}
|
||||
|
||||
// Befoulment
|
||||
if (updates.befoulmentModifierId !== undefined) {
|
||||
input.befoulmentModifierId = updates.befoulmentModifierId
|
||||
input.befoulmentStrength = updates.befoulmentStrength
|
||||
input.exorcismLevel = updates.exorcismLevel
|
||||
}
|
||||
|
||||
const updatedWeapon = await updateMutation.mutateAsync({
|
||||
id: weapon.id,
|
||||
input
|
||||
|
|
|
|||
|
|
@ -11,12 +11,13 @@
|
|||
* - Awakening (for weapons with awakening support)
|
||||
*/
|
||||
import type { Weapon, Awakening } from '$lib/types/api/entities'
|
||||
import type { AugmentSkill } from '$lib/types/api/weaponStatModifier'
|
||||
import type { AugmentSkill, Befoulment } from '$lib/types/api/weaponStatModifier'
|
||||
import DetailsSection from '$lib/components/sidebar/details/DetailsSection.svelte'
|
||||
import Select from '$lib/components/ui/Select.svelte'
|
||||
import WeaponKeySelect from '$lib/components/sidebar/edit/WeaponKeySelect.svelte'
|
||||
import AwakeningSelect from '$lib/components/sidebar/edit/AwakeningSelect.svelte'
|
||||
import AxSkillSelect from '$lib/components/sidebar/edit/AxSkillSelect.svelte'
|
||||
import BefoulmentSelect from '$lib/components/sidebar/edit/BefoulmentSelect.svelte'
|
||||
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
|
||||
import { getElementIcon } from '$lib/utils/images'
|
||||
import { seriesHasWeaponKeys, getSeriesSlug } from '$lib/utils/weaponSeries'
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
level: number
|
||||
} | null
|
||||
axSkills: AugmentSkill[]
|
||||
befoulment?: Befoulment | null
|
||||
}
|
||||
|
||||
export interface WeaponEditUpdates {
|
||||
|
|
@ -51,6 +53,9 @@
|
|||
axStrength1?: number
|
||||
axModifier2Id?: string
|
||||
axStrength2?: number
|
||||
befoulmentModifierId?: string
|
||||
befoulmentStrength?: number
|
||||
exorcismLevel?: number
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
|
@ -74,6 +79,7 @@
|
|||
let selectedAwakening = $state<Awakening | undefined>(currentValues.awakening?.type)
|
||||
let awakeningLevel = $state(currentValues.awakening?.level ?? 1)
|
||||
let axSkills = $state<AugmentSkill[]>(currentValues.axSkills ?? [])
|
||||
let befoulment = $state<Befoulment | null>(currentValues.befoulment ?? null)
|
||||
|
||||
// Re-initialize when currentValues changes
|
||||
$effect(() => {
|
||||
|
|
@ -86,6 +92,7 @@
|
|||
selectedAwakening = currentValues.awakening?.type
|
||||
awakeningLevel = currentValues.awakening?.level ?? 1
|
||||
axSkills = currentValues.axSkills ?? []
|
||||
befoulment = currentValues.befoulment ?? null
|
||||
})
|
||||
|
||||
// Derived conditions
|
||||
|
|
@ -106,8 +113,10 @@
|
|||
const hasWeaponKeys = $derived(seriesHasWeaponKeys(series))
|
||||
const keySlotCount = $derived(seriesSlug ? (WEAPON_KEY_SLOTS[seriesSlug] ?? 2) : 0)
|
||||
|
||||
const hasAxSkills = $derived(weaponData?.ax === true)
|
||||
const axType = $derived(weaponData?.axType ?? 1)
|
||||
// Augment type from series determines AX skills vs befoulment
|
||||
const augmentType = $derived(series?.augmentType ?? 'none')
|
||||
const hasAxSkills = $derived(augmentType === 'ax')
|
||||
const hasBefoulment = $derived(augmentType === 'befoulment')
|
||||
const hasAwakening = $derived((weaponData?.maxAwakeningLevel ?? 0) > 0)
|
||||
const availableAwakenings = $derived(weaponData?.awakenings ?? [])
|
||||
|
||||
|
|
@ -195,6 +204,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Befoulment
|
||||
if (hasBefoulment) {
|
||||
if (befoulment?.modifier?.id) {
|
||||
updates.befoulmentModifierId = befoulment.modifier.id
|
||||
updates.befoulmentStrength = befoulment.strength
|
||||
updates.exorcismLevel = befoulment.exorcismLevel
|
||||
}
|
||||
}
|
||||
|
||||
onSave?.(updates)
|
||||
}
|
||||
</script>
|
||||
|
|
@ -267,7 +285,6 @@
|
|||
<DetailsSection title="AX Skills">
|
||||
<div class="section-content">
|
||||
<AxSkillSelect
|
||||
{axType}
|
||||
currentSkills={axSkills}
|
||||
onChange={(skills) => {
|
||||
axSkills = skills
|
||||
|
|
@ -277,6 +294,19 @@
|
|||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if hasBefoulment}
|
||||
<DetailsSection title="Befoulment">
|
||||
<div class="section-content">
|
||||
<BefoulmentSelect
|
||||
currentBefoulment={befoulment}
|
||||
onChange={(bef) => {
|
||||
befoulment = bef
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if hasAwakening && availableAwakenings.length > 0}
|
||||
<DetailsSection title="Awakening">
|
||||
<div class="section-content">
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
import type { GridWeapon } from '$lib/types/api/party'
|
||||
import type { WeaponKey } from '$lib/api/adapters/entity.adapter'
|
||||
import type { Awakening } from '$lib/types/api/entities'
|
||||
import type { AugmentSkill } from '$lib/types/api/weaponStatModifier'
|
||||
import type { AugmentSkill, Befoulment } from '$lib/types/api/weaponStatModifier'
|
||||
import DetailsSection from './details/DetailsSection.svelte'
|
||||
import ItemHeader from './details/ItemHeader.svelte'
|
||||
import Select from '$lib/components/ui/Select.svelte'
|
||||
import WeaponKeySelect from './edit/WeaponKeySelect.svelte'
|
||||
import AwakeningSelect from './edit/AwakeningSelect.svelte'
|
||||
import AxSkillSelect from './edit/AxSkillSelect.svelte'
|
||||
import BefoulmentSelect from './edit/BefoulmentSelect.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
import { getElementIcon } from '$lib/utils/images'
|
||||
|
|
@ -55,6 +56,9 @@
|
|||
// AX skill state - initialize from existing AX skills
|
||||
let axSkills = $state<AugmentSkill[]>(weapon.ax ?? [])
|
||||
|
||||
// Befoulment state - initialize from existing befoulment
|
||||
let befoulment = $state<Befoulment | null>(weapon.befoulment ?? null)
|
||||
|
||||
// Weapon data shortcuts
|
||||
const weaponData = $derived(weapon.weapon)
|
||||
const canChangeElement = $derived(weaponData?.element === 0)
|
||||
|
|
@ -77,8 +81,10 @@
|
|||
const hasWeaponKeys = $derived(seriesHasWeaponKeys(series))
|
||||
const keySlotCount = $derived(seriesSlug ? (WEAPON_KEY_SLOTS[seriesSlug] ?? 2) : 0)
|
||||
|
||||
const hasAxSkills = $derived(weaponData?.ax === true)
|
||||
const axType = $derived(weaponData?.axType ?? 1)
|
||||
// Augment type from series determines AX skills vs befoulment
|
||||
const augmentType = $derived(series?.augmentType ?? 'none')
|
||||
const hasAxSkills = $derived(augmentType === 'ax')
|
||||
const hasBefoulment = $derived(augmentType === 'befoulment')
|
||||
const hasAwakening = $derived((weaponData?.maxAwakeningLevel ?? 0) > 0)
|
||||
const availableAwakenings = $derived(weaponData?.awakenings ?? [])
|
||||
|
||||
|
|
@ -125,6 +131,9 @@
|
|||
axStrength1?: number | null
|
||||
axModifier2Id?: string | null
|
||||
axStrength2?: number | null
|
||||
befoulmentModifierId?: string | null
|
||||
befoulmentStrength?: number | null
|
||||
exorcismLevel?: number | null
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
|
|
@ -188,6 +197,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Befoulment - send modifier ID, strength, and exorcism level
|
||||
if (hasBefoulment) {
|
||||
const originalBef = weapon.befoulment
|
||||
|
||||
if (befoulment?.modifier?.id !== originalBef?.modifier?.id) {
|
||||
updates.befoulmentModifierId = befoulment?.modifier?.id ?? null
|
||||
}
|
||||
if (befoulment?.strength !== originalBef?.strength) {
|
||||
updates.befoulmentStrength = befoulment?.strength ?? null
|
||||
}
|
||||
if (befoulment?.exorcismLevel !== originalBef?.exorcismLevel) {
|
||||
updates.exorcismLevel = befoulment?.exorcismLevel ?? null
|
||||
}
|
||||
}
|
||||
|
||||
// Only call onSave if there are actual updates
|
||||
if (Object.keys(updates).length > 0) {
|
||||
onSave?.(updates as Partial<GridWeapon>)
|
||||
|
|
@ -206,6 +230,7 @@
|
|||
selectedAwakening = weapon.awakening?.type
|
||||
awakeningLevel = weapon.awakening?.level ?? 1
|
||||
axSkills = weapon.ax ?? []
|
||||
befoulment = weapon.befoulment ?? null
|
||||
onCancel?.()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -286,7 +311,6 @@
|
|||
<DetailsSection title="AX Skills">
|
||||
<div class="ax-skills-wrapper">
|
||||
<AxSkillSelect
|
||||
{axType}
|
||||
currentSkills={axSkills}
|
||||
onChange={(skills) => {
|
||||
axSkills = skills
|
||||
|
|
@ -296,6 +320,19 @@
|
|||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if hasBefoulment}
|
||||
<DetailsSection title="Befoulment">
|
||||
<div class="befoulment-wrapper">
|
||||
<BefoulmentSelect
|
||||
currentBefoulment={befoulment}
|
||||
onChange={(bef) => {
|
||||
befoulment = bef
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if hasAwakening && availableAwakenings.length > 0}
|
||||
<DetailsSection title="Awakening">
|
||||
<div class="awakening-select-wrapper">
|
||||
|
|
@ -428,7 +465,8 @@
|
|||
padding: spacing.$unit;
|
||||
}
|
||||
|
||||
.ax-skills-wrapper {
|
||||
.ax-skills-wrapper,
|
||||
.befoulment-wrapper {
|
||||
padding: spacing.$unit;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,17 +105,32 @@
|
|||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if modificationStatus.hasAxSkills && weapon.ax}
|
||||
{#if modificationStatus.hasAxSkills && weapon.ax?.length}
|
||||
<DetailsSection title="AX Skills">
|
||||
{#each weapon.ax as axSkill}
|
||||
<DetailRow
|
||||
label={formatAxSkill(axSkill).split('+')[0]?.trim() ?? ''}
|
||||
value={`+${axSkill.strength}${axSkill.modifier <= 2 ? '' : '%'}`}
|
||||
/>
|
||||
{#if axSkill.modifier?.id}
|
||||
<DetailRow
|
||||
label={axSkill.modifier.nameEn}
|
||||
value={`+${axSkill.strength}${axSkill.modifier.suffix ?? ''}`}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if modificationStatus.hasBefoulment && weapon.befoulment?.modifier}
|
||||
<DetailsSection title="Befoulment">
|
||||
<DetailRow
|
||||
label={weapon.befoulment.modifier.nameEn}
|
||||
value={`${weapon.befoulment.strength}${weapon.befoulment.modifier.suffix ?? ''}`}
|
||||
/>
|
||||
<DetailRow
|
||||
label="Exorcism Level"
|
||||
value={`${weapon.befoulment.exorcismLevel ?? 0}`}
|
||||
/>
|
||||
</DetailsSection>
|
||||
{/if}
|
||||
|
||||
{#if modificationStatus.hasElement && weapon.element}
|
||||
<DetailsSection title="Element Override">
|
||||
<DetailRow label="Weapon Element">
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export interface ModificationStatus {
|
|||
hasAwakening: boolean
|
||||
hasWeaponKeys: boolean
|
||||
hasAxSkills: boolean
|
||||
hasBefoulment: boolean
|
||||
hasRings: boolean
|
||||
hasEarring: boolean
|
||||
hasPerpetuity: boolean
|
||||
|
|
@ -25,6 +26,7 @@ export function detectModifications(
|
|||
hasAwakening: false,
|
||||
hasWeaponKeys: false,
|
||||
hasAxSkills: false,
|
||||
hasBefoulment: false,
|
||||
hasRings: false,
|
||||
hasEarring: false,
|
||||
hasPerpetuity: false,
|
||||
|
|
@ -60,6 +62,7 @@ export function detectModifications(
|
|||
status.hasAwakening = !!weapon.awakening
|
||||
status.hasWeaponKeys = !!(weapon.weaponKeys && weapon.weaponKeys.length > 0)
|
||||
status.hasAxSkills = !!(weapon.ax && weapon.ax.length > 0)
|
||||
status.hasBefoulment = !!weapon.befoulment?.modifier
|
||||
status.hasTranscendence = !!(weapon.transcendenceStep && weapon.transcendenceStep > 0)
|
||||
status.hasUncapLevel = weapon.uncapLevel !== undefined && weapon.uncapLevel !== null
|
||||
status.hasElement = !!(weapon.element && weapon.weapon?.element === 0)
|
||||
|
|
@ -68,6 +71,7 @@ export function detectModifications(
|
|||
status.hasAwakening ||
|
||||
status.hasWeaponKeys ||
|
||||
status.hasAxSkills ||
|
||||
status.hasBefoulment ||
|
||||
status.hasTranscendence ||
|
||||
status.hasUncapLevel ||
|
||||
status.hasElement
|
||||
|
|
@ -111,13 +115,14 @@ export function canWeaponBeModified(gridWeapon: GridWeapon | undefined): boolean
|
|||
// Weapon keys (series-specific) - use utility function that handles both formats
|
||||
const hasWeaponKeys = seriesHasWeaponKeys(weapon.series)
|
||||
|
||||
// AX skills
|
||||
const hasAxSkills = weapon.ax === true
|
||||
// AX skills or Befoulment - check augmentType from series
|
||||
const augmentType = weapon.series?.augmentType ?? 'none'
|
||||
const hasAugments = augmentType !== 'none'
|
||||
|
||||
// Awakening (maxAwakeningLevel > 0 means it can have awakening)
|
||||
const hasAwakening = (weapon.maxAwakeningLevel ?? 0) > 0
|
||||
|
||||
return canChangeElement || hasWeaponKeys || hasAxSkills || hasAwakening
|
||||
return canChangeElement || hasWeaponKeys || hasAugments || hasAwakening
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const mockOmegaSeries = {
|
|||
name: { en: 'Omega', ja: 'マグナ' },
|
||||
hasWeaponKeys: false,
|
||||
hasAwakening: true,
|
||||
hasAxSkills: true,
|
||||
augmentType: 'ax' as const,
|
||||
extra: false,
|
||||
elementChangeable: false
|
||||
};
|
||||
|
|
@ -19,7 +19,7 @@ const mockOpusSeries = {
|
|||
name: { en: 'Opus', ja: 'オプス' },
|
||||
hasWeaponKeys: true,
|
||||
hasAwakening: true,
|
||||
hasAxSkills: false,
|
||||
augmentType: 'none' as const,
|
||||
extra: false,
|
||||
elementChangeable: false
|
||||
};
|
||||
|
|
@ -30,7 +30,7 @@ const mockDraconicSeries = {
|
|||
name: { en: 'Draconic', ja: 'ドラゴニック' },
|
||||
hasWeaponKeys: true,
|
||||
hasAwakening: false,
|
||||
hasAxSkills: false,
|
||||
augmentType: 'none' as const,
|
||||
extra: false,
|
||||
elementChangeable: false
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue