TIL - 아웃런 파츠 NPC 설계

Kyu_·2026년 6월 26일

31주차

목록 보기
6/6

아웃런 파츠 NPC 설계


1. 목표

인 런 진입 전 거점에서 파츠를 미리 선택·장착할 수 있게 한다.

  • 영구 재화(CommonCurrency)를 소모해 개별 파츠를 언락(구매)
  • 언락한 파츠 중 1부위를 선택해 장착 저장 → 런 시작 시 Common 등급으로 적용
  • 비용·목록 등 모든 수치는 DataTable로 관리

2. 설계 원칙

  • 증강 동형 패턴: DT가 카탈로그·수치를 주도, 얇은 DA가 번들 페이로드(Icon/GE/GA/Mesh) 보유
  • DA 정체성 유지: 런타임·세이브 키는 TSoftObjectPtr<UNSPartDefinition> 그대로 → 세이브 마이그레이션 없음
  • 아웃런 = 저장 전용: 허브에서 GAS 즉시 장착 없음. 런 시작 시 기존 경로(ApplyEquippedPart)로 적용
  • 모든 수치는 DT: 언락 비용, ValueRange, bCanReroll 전부 DT_PartDefinition에서 읽음

3. 데이터 모델

3-1. 신설: FNSPartDefinitionRow : FTableRowBase (DT_PartDefinition)

카탈로그의 유일한 수치 출처. 파츠 1개 = row 1개.

필드타입설명
DefinitionTSoftObjectPtr<UNSPartDefinition>DA 참조 (정체성 앵커)
PartSlotENSPartSlotBody / Arm / Leg
bCanRerollbool레그 파츠는 false
UnlockCostint64언락(구매) 영구재화 비용
ValueRangeTMap<ENSPartRarity, FNSPartValueRange>등급별 수치 범위 (DA에서 이사)
bEnabledboolfalse면 카탈로그에서 제외 (증강 패턴)

3-2. UNSPartDefinition 변경 (얇아짐)

DA에서 DT로 이사하는 필드: ValueRange, bCanReroll, PartSlot

DA에 남는 필드 (PrimaryAsset·번들 로드 앵커로 유지):

필드번들
PartName (FText)
Icon (TSoftObjectPtr\<UTexture2D>)OutRunUI, InRunUI
PartMesh (TSoftObjectPtr\<USkeletalMesh>)온디맨드
EffectClass (TSoftClassPtr\<UGameplayEffect>)InRunData
GrantedAbilities (TArray\<TSoftClassPtr\<UGameplayAbility>>)InRunData

PartIconTool은 DA의 PartMesh → Icon 경로를 그대로 사용하므로 수정 없음.


4. 해석 인프라 (증강 패턴 복제)

4-1. NSDataSubsystem

UPROPERTY(EditDefaultsOnly)
TObjectPtr<UDataTable> PartDefinitionTable;  // DT_PartDefinition 참조

TMap<FPrimaryAssetId, FNSPartDefinitionRow> CachedPartRowsByDefId;  // 로드 시 빌드
  • 허브 로드 시(LoadOutGameAssets) PartAssetType DA 로드 완료 콜백에서 row 캐시 빌드
  • GetPartRow(FPrimaryAssetId) → const FNSPartDefinitionRow* 조회 함수 추가

4-2. NSPartUtils

기존 ResolvePartDefinition(WorldCtx, PartData) 유지.
신규 ResolvePartRow(WorldCtx, FPrimaryAssetId) → const FNSPartDefinitionRow* 추가.


5. 언락(구매) 흐름

[UI: 언락 버튼 클릭]
  → ProgressionSubsystem::PurchasePart(Def, Common, Cost)
      ← Cost는 UI가 직접 넘기지 않음
      ← NSDataSubsystem::GetPartRow(DefId).UnlockCost 에서 조회 (단일 출처)
      → CommonCurrency 차감
      → OwnedParts 에 FNSPartSaveData 추가 (Value 1회 롤 후 고정)
      → SaveNow()

PurchasePart 수정 포인트:

  • LoadSynchronous 제거 — ValueRange를 DT row에서 읽으므로 DA 로드 불필요
  • 비용 파라미터 제거 또는 row 조회로 대체

6. 장착 흐름 (저장 전용, 허브 GAS 없음)

[UI: 장착 버튼 클릭]
  → ProgressionSubsystem::SetEquippedPart(CharacterId, Def, Common)
      → IsPartOwned 검증
      → FNSCharacterSaveData.EquippedPartDefinition / Rarity 갱신
      → SaveNow()
  • 현재 위젯의 Server_RequestEquip (인런 GAS 즉시 장착 경로) 호출 제거
  • 허브에서 비주얼 프리뷰가 필요해지면 별도 추가 (현재 범위 밖)

7. 위젯 재연결 (NSPartEquipWidget)

현재 (잘못된 경로)변경 후 (아웃런 경로)
SelectableParts 정적 배열DT_PartDefinition rows (bEnabled=true)
Server_RequestEquip (인런 GAS)PurchasePart + SetEquippedPart (영구 저장)
Common 고정 직접 생성row의 ValueRange[Common] 범위로 Value 롤

UI 표시 항목 (row + OwnedParts 상태 결합):

  • 파츠 이름 / 슬롯 / 언락 비용
  • 상태: 미언락(비용 표시) / 언락됨(장착 가능) / 장착 중

8. 런 시작 적용

변경 없음. 기존 경로 그대로.

NSPlayerController::Server_UploadProgress
  → OwnedParts에서 EquippedPartDefinition + Rarity로 FNSPartSaveData 해석
  → Payload.EquippedPart 설정
  → Client_SaveProgress / ApplyEquippedPart()

0개의 댓글