From 9ce20302a30c84dd60e17bbc6ce1ab35dbc894c8 Mon Sep 17 00:00:00 2001 From: Sakura Knoll Date: Sun, 9 Jul 2023 07:31:14 +0900 Subject: [PATCH] Import and convert battlesuit data --- src/lib/v2-pre/server/buildData.spec.ts | 12 + src/lib/v2-pre/server/buildData.ts | 380 ++++++++++++++++++ src/lib/v2-pre/server/fsUtils.spec.ts | 22 + src/lib/v2-pre/server/fsUtils.ts | 25 ++ src/lib/v2-pre/server/loadData.ts | 22 + src/lib/v2-pre/server/raw/avatarData.ts | 64 +++ src/lib/v2-pre/server/raw/avatarSkillData.ts | 40 ++ .../v2-pre/server/raw/avatarSubSkillData.ts | 55 +++ .../v2-pre/server/raw/avatarTagUnLockData.ts | 16 + src/lib/v2-pre/server/raw/loadRawData.ts | 13 + src/lib/v2-pre/server/raw/tagListData.ts | 19 + src/lib/v2-pre/server/raw/textMap.ts | 7 + src/scripts/compileRawData.ts | 37 ++ src/scripts/copyRawAssets.sh | 29 ++ 14 files changed, 741 insertions(+) create mode 100644 src/lib/v2-pre/server/buildData.spec.ts create mode 100644 src/lib/v2-pre/server/buildData.ts create mode 100644 src/lib/v2-pre/server/fsUtils.spec.ts create mode 100644 src/lib/v2-pre/server/fsUtils.ts create mode 100644 src/lib/v2-pre/server/loadData.ts create mode 100644 src/lib/v2-pre/server/raw/avatarData.ts create mode 100644 src/lib/v2-pre/server/raw/avatarSkillData.ts create mode 100644 src/lib/v2-pre/server/raw/avatarSubSkillData.ts create mode 100644 src/lib/v2-pre/server/raw/avatarTagUnLockData.ts create mode 100644 src/lib/v2-pre/server/raw/loadRawData.ts create mode 100644 src/lib/v2-pre/server/raw/tagListData.ts create mode 100644 src/lib/v2-pre/server/raw/textMap.ts create mode 100644 src/scripts/compileRawData.ts create mode 100644 src/scripts/copyRawAssets.sh diff --git a/src/lib/v2-pre/server/buildData.spec.ts b/src/lib/v2-pre/server/buildData.spec.ts new file mode 100644 index 00000000..bbb994f1 --- /dev/null +++ b/src/lib/v2-pre/server/buildData.spec.ts @@ -0,0 +1,12 @@ +import { buildBattlesuitList } from './buildData' + +describe('buildBattlesuitList', () => { + it('build list', () => { + const list = buildBattlesuitList() + expect(list[0]).toMatchObject({ + id: expect.any(String), + tags: ['physical-dmg', 'stun', 'burst', 'time-mastery'] + }) + // console.log(list[0]) + }) +}) diff --git a/src/lib/v2-pre/server/buildData.ts b/src/lib/v2-pre/server/buildData.ts new file mode 100644 index 00000000..07008915 --- /dev/null +++ b/src/lib/v2-pre/server/buildData.ts @@ -0,0 +1,380 @@ +import { + AttributeType, + Battlesuit, + BattlesuitSkill, + BattlesuitSubSkill, + CharacterType, + SkillTagItem, + SkillType, + TagType, + WeaponType +} from '../data/types' +import { getRawAvatarDataMap } from './raw/avatarData' +import { getRawAvatarSkillDataMap } from './raw/avatarSkillData' +import { getRawAvatarSubSkillDataMap } from './raw/avatarSubSkillData' +import { getRawAvatarTagUnLockDataMap } from './raw/avatarTagUnLockData' +import { getRawTextMap } from './raw/textMap' + +export function getText(id: string | number) { + const rawTextMap = getRawTextMap() + return rawTextMap[id]?.Text || null +} + +export function buildBattlesuitList(): Battlesuit[] { + const rawAvatarDataMap = getRawAvatarDataMap() + const rawSkillDataMap = getRawAvatarSkillDataMap() + const rawSubSkillDataMap = getRawAvatarSubSkillDataMap() + const rawAvatarTagUnLockDataMap = getRawAvatarTagUnLockDataMap() + + const rawAvatarDataEntries = Object.entries(rawAvatarDataMap) + const rawSubSkillEntries = Object.entries(rawSubSkillDataMap) + + const battlesuitList = rawAvatarDataEntries.map(([id, rawAvatarData]): Battlesuit => { + try { + return { + id, + fullName: getText(rawAvatarData.FullName), + shortName: getText(rawAvatarData.ShortName), + desc: getText(rawAvatarData.Desc), + firstName: getText(rawAvatarData.FirstName), + lastName: getText(rawAvatarData.LastName), + enFirstName: getText(rawAvatarData.EnFirstName), + enLastName: getText(rawAvatarData.EnLastName), + attributeType: convertAttributeToAttributeType(rawAvatarData.Attribute), + isEasterner: rawAvatarData.IsEasterner, + weapon: convertClassIdToWeaponType(rawAvatarData.ClassID), + character: convertRoleIdToCharacterType(rawAvatarData.RoleID), + initialStar: convertStar(rawAvatarData.UnlockStar, 0), + tags: rawAvatarData.TagUnlockList.map(rawTagId => { + const rawAvatarTagUnLock = rawAvatarTagUnLockDataMap[rawTagId] + + return convertRawTagIdToTagType(rawAvatarTagUnLock.TagID) + }), + skills: rawAvatarData.SkillList.map(rawSkillId => { + const rawSkillData = rawSkillDataMap[rawSkillId] + const skillIcon = rawSkillData.IconPath.split('/').pop() + const subSkills = rawSubSkillEntries.reduce((list, [subSkillId, rawSubSkillData]) => { + if (rawSubSkillData.SkillId === rawSkillId) { + const subSkillIcon = rawSubSkillData.IconPath.split('/').pop() + list.push({ + id: subSkillId, + name: getText(rawSubSkillData.Name), + info: getText(rawSubSkillData.Info), + brief: getText(rawSubSkillData.Brief), + icon: subSkillIcon || '', + maxLv: rawSubSkillData.MaxLv, + paramBase1: rawSubSkillData.ParamBase_1, + paramBase2: rawSubSkillData.ParamBase_2, + paramBase3: rawSubSkillData.ParamBase_3, + paramAdd1: rawSubSkillData.ParamAdd_1, + paramAdd2: rawSubSkillData.ParamAdd_2, + paramAdd3: rawSubSkillData.ParamAdd_3, + tags: rawSubSkillData.TagList.map(convertRawSkillTag), + toggle: rawSubSkillData.SkillToggle, + unlockStar: convertStar(rawSubSkillData.UnlockStar, rawSubSkillData.UnlockSubStar) + }) + return list + } + return list + }, []) + + return { + id: rawSkillId.toString(), + name: getText(rawSkillData.Name), + info: getText(rawSkillData.Info), + icon: skillIcon || '', + skillType: convertShowOrderToSkillType(rawSkillData.ShowOrder), + tags: rawSkillData.TagList.map(convertRawSkillTag), + paramSubId1: rawSkillData.ParamSubID_1, + paramSubId2: rawSkillData.ParamSubID_2, + paramSubId3: rawSkillData.ParamSubID_3, + subSkills + } + }) + } + } catch (error) { + console.error(`Failed to converting valk data id:${id}, name: ${getText(rawAvatarData.FullName)}`) + throw error + } + }) + + return battlesuitList +} + +function convertStar(rawStarValue: number, rawSubStarValue: number) { + switch (rawStarValue) { + case 1: + return 'b' + case 2: + return 'a' + case 3: + switch (rawSubStarValue) { + case 1: + return 's1' + case 2: + return 's2' + case 3: + return 's3' + case 0: + return 's' + } + case 4: + switch (rawSubStarValue) { + case 1: + return 'ss1' + case 2: + return 'ss2' + case 3: + return 'ss3' + case 0: + return 'ss' + } + case 5: + return 'sss' + } + throw new Error(`Unsupported Raw Star Value (${rawStarValue}, ${rawSubStarValue})`) +} + +function convertAttributeToAttributeType(rawValue: number): AttributeType { + switch (rawValue) { + case 1: + return 'bio' + case 2: + return 'psy' + case 3: + return 'mech' + case 4: + return 'qua' + case 5: + return 'img' + case 0: + return 'none' + default: + throw new Error(`Unsupported Raw Attribute(avatar type) (${rawValue})`) + } +} + +function convertClassIdToWeaponType(rawValue: number): WeaponType { + switch (rawValue) { + case 1: + return 'pistols' + case 2: + return 'katana' + case 3: + return 'cannon' + case 4: + return '2-handed' + case 5: + return 'cross' + case 6: + return 'fists' + case 7: + return 'scythe' + case 8: + return 'lance' + case 9: + return 'bow' + case 10: + return 'chakram' + case 11: + return 'javelin' + default: + throw new Error(`Unsupported raw classId(weapon type) (${rawValue})`) + } +} + +function convertRoleIdToCharacterType(rawValue: number): CharacterType { + switch (rawValue) { + case 1: + return 'kiana' + case 2: + return 'mei' + case 3: + return 'bronya' + case 4: + return 'himeko' + case 5: + return 'theresa' + case 6: + return 'fuhua' + case 7: + return 'rita' + case 8: + return 'olenyevas' + case 9: + return 'seele' + case 10: + return 'durandal' + case 11: + return 'asuka' + case 12: + return 'keqing' + case 13: + return 'fischl' + case 14: + return 'elysia' + case 15: + return 'mobius' + case 16: + return 'raven' + case 17: + return 'pardofelis' + case 18: + return 'aponia' + case 19: + return 'eden' + case 20: + return 'griseo' + case 21: + return 'vill-v' + case 22: + return 'sushang' + case 23: + return 'ai' + case 24: + return 'susannah' + case 25: + return 'hare' + case 26: + return 'prometheus' + case 27: + return 'kira' + case 101: + return 'sakura' + case 102: + return 'kallen' + case 103: + return 'apho-mei' + case 104: + return 'apho-adam' + case 105: + return 'apho-carol' + case 106: + return 'apho-bronya' + case 107: + return 'apho-timido' + default: + throw new Error(`Unsupported raw roleId(character type) (${rawValue})`) + } +} + +function convertShowOrderToSkillType(rawShowOrder: number): SkillType { + switch (rawShowOrder) { + case 1: + return 'basic' + case 2: + return 'special' + case 3: + return 'evasion' + case 4: + return 'ultimate' + case 5: + return 'leader' + case 6: + return 'passive' + case 7: + return 'sp' + case 0: + return 'none' + default: + throw new Error(`Unsupported raw show order(Skill) (${rawShowOrder})`) + } +} + +function convertRawTagIdToTagType(rawTagId: number): TagType { + switch (rawTagId) { + case 1001: + return 'branch' + case 1002: + return 'charge' + case 1003: + return 'physical-dmg' + case 1004: + return 'fire-dmg' + case 1005: + return 'ice-dmg' + case 1006: + return 'lightning-dmg' + case 1007: + return 'freeze' + case 1008: + return 'paralyze' + case 1009: + return 'stun' + case 1010: + return 'ignite' + case 1011: + return 'bleed' + case 1012: + return 'heavy-atk' + case 1013: + return 'weaken' + case 1014: + return 'impair' + case 1015: + return 'float' + case 1016: + return 'slow-down' + case 1017: + return 'time-mastery' + case 1018: + return 'gather' + case 1019: + return 'heal' + case 1020: + return 'fast-atk' + case 1021: + return 'burst' + case 1022: + return 'shield' + case 1023: + return 'aerial' + case 1024: + return 'ranged' + case 1025: + return 'meele' + } + + throw new Error(`Unsupported raw show order(Skill) (${rawTagId})`) +} + +function convertRawSkillTag(rawSkillTag: { Strength: number; TagID: number; TagComment: number }): SkillTagItem { + const comment = getText(rawSkillTag.TagComment) + return { + type: convertRawStrengthToType(rawSkillTag.Strength), + strength: convertRawTagIdToStrength(rawSkillTag.TagID), + comment + } + + function convertRawStrengthToType(rawStrength: number): TagType { + switch (rawStrength) { + case 239: + return 'freeze' + case 240: + return 'paralyze' + case 241: + return 'stun' + case 242: + return 'ignite' + case 243: + return 'bleed' + case 244: + return 'heavy-atk' + } + throw new Error(`Invalid raw strength (raw: ${rawStrength}, comment: ${comment})`) + } + + function convertRawTagIdToStrength(rawTagId: number): 1 | 2 | 3 | 4 { + switch (rawTagId) { + case 16777219: + return 1 + case 33554435: + return 2 + case 50331651: + return 3 + case 67108867: + return 4 + } + throw new Error(`Invalid raw tag Id (raw: ${rawTagId}, comment: ${comment})`) + } +} diff --git a/src/lib/v2-pre/server/fsUtils.spec.ts b/src/lib/v2-pre/server/fsUtils.spec.ts new file mode 100644 index 00000000..093f6d84 --- /dev/null +++ b/src/lib/v2-pre/server/fsUtils.spec.ts @@ -0,0 +1,22 @@ +import { doesDirExist } from './fsUtils' +import path from 'path' + +describe('doesDirExist', () => { + it('returns true if dir exists', () => { + const existingDir = path.join(process.cwd(), 'src') + const fn = jest.fn(doesDirExist) + + fn(existingDir) + + expect(fn).toReturnWith(true) + }) + + it('returns false if dir does not exist', () => { + const existingDir = path.join(process.cwd(), 'never-exists') + const fn = jest.fn(doesDirExist) + + fn(existingDir) + + expect(fn).toReturnWith(false) + }) +}) diff --git a/src/lib/v2-pre/server/fsUtils.ts b/src/lib/v2-pre/server/fsUtils.ts new file mode 100644 index 00000000..bfb15893 --- /dev/null +++ b/src/lib/v2-pre/server/fsUtils.ts @@ -0,0 +1,25 @@ +import fs from 'fs' + +export function doesDirExist(pathname: string) { + try { + const stat = fs.statSync(pathname) + if (stat.isDirectory()) { + return true + } + throw new Error('exists but not a dir') + } catch (error: any) { + if (error.code === 'ENOENT') { + return false + } + console.error(error) + throw error + } +} + +export function createDirIfNotExist(pathname: string) { + if (doesDirExist(pathname)) { + return + } + + fs.mkdirSync(pathname) +} diff --git a/src/lib/v2-pre/server/loadData.ts b/src/lib/v2-pre/server/loadData.ts new file mode 100644 index 00000000..6e9b0b52 --- /dev/null +++ b/src/lib/v2-pre/server/loadData.ts @@ -0,0 +1,22 @@ +import fs from 'fs' +import path from 'path' +import YAML from 'yaml' +import { BattlesuitCatalogItem } from '../data/types' + +export const dataDir = path.join(process.cwd(), 'data/v2-pre') +export const battlesuitsDir = path.join(dataDir, 'battlesuits') + +export const battlesuitCatalogPath = path.join(dataDir, 'battlesuit-catalog.yaml') + +export function loadBattlesuitCatalog(): BattlesuitCatalogItem[] { + return readYamlFile(battlesuitCatalogPath) +} + +export function loadBattlesuitData(id: string) { + const battlesuitDataPath = path.join(battlesuitsDir, `${id}.yaml`) + return readYamlFile(battlesuitDataPath) +} + +function readYamlFile(pathname: string) { + return YAML.parse(fs.readFileSync(pathname).toString()) +} diff --git a/src/lib/v2-pre/server/raw/avatarData.ts b/src/lib/v2-pre/server/raw/avatarData.ts new file mode 100644 index 00000000..1967cf84 --- /dev/null +++ b/src/lib/v2-pre/server/raw/avatarData.ts @@ -0,0 +1,64 @@ +import { loadRawData } from './loadRawData' + +export function getRawAvatarDataMap(): RawAvatarDataMap { + return loadRawData('AvatarData.json') +} + +export type RawAvatarDataMap = { + [key: string]: RawAvatarData +} + +export interface RawAvatarData { + ClassID: number + RoleID: number + AvatarType: number + FullName: number + ShortName: number + RomaName: number + Desc: number + AvatarRegistryKey: number + WeaponBaseTypeList: number[] + UnlockStar: number + SkillList: number[] + Attribute: number + InitialWeapon: number + AvatarCardID: number + AvatarFragmentID: number + ArtifactFragmentID: number + UltraSkillID: number + CaptainSkillID: number + SKL01SP: number + SKL01SPNeed: number + SKL01Charges: number + SKL01CD: number + SKL02SP: number + SKL02SPNeed: number + SKL02Charges: number + SKL02CD: number + SKL03SP: number + SKL03SPNeed: number + SKL03Charges: number + SKL03CD: number + SKL02ArtifactCD: number + SKL02ArtifactSP: number + SKL02ArtifactSPNeed: number + BaseAvatarID: number + FirstName: number + LastName: number + EnFirstName: number + EnLastName: number + UISelectVoice: string + UILevelUpVoice: string + DA_Name: string + DA_Type: string + ArtifactID: number + IsEasterner: boolean + FaceAnimationGroupName: string + AvatarEffects: number[] + TagUnlockList: number[] + DefaultDressId: number + AvatarStarUpType: number + AvatarStarSourceID: number[] + IsCollaboration: boolean + StarUpBG: string +} diff --git a/src/lib/v2-pre/server/raw/avatarSkillData.ts b/src/lib/v2-pre/server/raw/avatarSkillData.ts new file mode 100644 index 00000000..a03252fb --- /dev/null +++ b/src/lib/v2-pre/server/raw/avatarSkillData.ts @@ -0,0 +1,40 @@ +import { loadRawData } from './loadRawData' + +export function getRawAvatarSkillDataMap(): RawAvatarSkillDataMap { + return loadRawData('AvatarSkillData.json') +} + +export type RawAvatarSkillDataMap = { + [key: string]: RawAvatarSkillData +} + +export interface RawAvatarSkillData { + Name: number + Info: number + ShowOrder: number + UnlockLv: number + UnlockStar: number + SkillStep: number + IconPath: string + IconPathInLevel: string + ButtonName: string + ParamBase_1: number + ParamLogic_1: number + ParamSubID_1: number + ParamSubIndex_1: number + ParamBase_2: number + ParamLogic_2: number + ParamSubID_2: number + ParamSubIndex_2: number + ParamBase_3: number + ParamLogic_3: number + ParamSubID_3: number + ParamSubIndex_3: number + CanTry: number + TagList: { + Strength: number + TagID: number + TagComment: number + }[] + UnlockItemList: number[] +} diff --git a/src/lib/v2-pre/server/raw/avatarSubSkillData.ts b/src/lib/v2-pre/server/raw/avatarSubSkillData.ts new file mode 100644 index 00000000..729b7bc8 --- /dev/null +++ b/src/lib/v2-pre/server/raw/avatarSubSkillData.ts @@ -0,0 +1,55 @@ +import { loadRawData } from './loadRawData' + +export function getRawAvatarSubSkillDataMap(): RawAvatarSubSkillDataMap { + return loadRawData('AvatarSubSkillData.json') +} + +export type RawAvatarSubSkillDataMap = { + [key: string]: RawAvatarSubSkillData +} + +export interface RawAvatarSubSkillData { + Name: number + Info: number + Brief: number + ShowOrder: number + SkillId: number + IgnoreLeader: false + IconPath: string + UnlockStar: number + UnlockSubStar: number + UnlockLv: number + UnlockLvAdd: number + MaxLv: number + UpLevelSubStarNeedList: [ + { + Level: number + StarNeed: number + SubStarNeed: number + } + ] + ScoinCalc: false + UnlockScoin: number + ScoinLvAdd: number + ItemType: number + SkillToggle: boolean + ParamBase_1: number + ParamAdd_1: number + ParamBase_2: number + ParamAdd_2: number + ParamBase_3: number + ParamAdd_3: number + CanTry: false + ArtifactSkillID: number + UpLevelArtifactNeedList: [ + { + ArtifactLevel: number + SubSkillLevel: number + } + ] + TagList: { + Strength: number + TagID: number + TagComment: number + }[] +} diff --git a/src/lib/v2-pre/server/raw/avatarTagUnLockData.ts b/src/lib/v2-pre/server/raw/avatarTagUnLockData.ts new file mode 100644 index 00000000..26b6bd51 --- /dev/null +++ b/src/lib/v2-pre/server/raw/avatarTagUnLockData.ts @@ -0,0 +1,16 @@ +import { loadRawData } from './loadRawData' + +export function getRawAvatarTagUnLockDataMap(): RawAvatarTagUnLockDataMap { + return loadRawData('AvatarTagUnLock.json') +} + +export type RawAvatarTagUnLockDataMap = { + [key: string]: RawAvatarTagUnLockData +} + +export interface RawAvatarTagUnLockData { + TagID: number + TagSecondDesc: number + UnlockSkillIDList: number[] + UnlockSubSkillIDList: number[] +} diff --git a/src/lib/v2-pre/server/raw/loadRawData.ts b/src/lib/v2-pre/server/raw/loadRawData.ts new file mode 100644 index 00000000..5382231f --- /dev/null +++ b/src/lib/v2-pre/server/raw/loadRawData.ts @@ -0,0 +1,13 @@ +import fs from 'fs' +import path from 'path' + +const cacheMap = new Map() + +export function loadRawData(fileName: string): any { + let result = cacheMap.get(fileName) + if (result == null) { + result = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'dump/out', fileName)).toString()) + cacheMap.set(fileName, result) + } + return result +} diff --git a/src/lib/v2-pre/server/raw/tagListData.ts b/src/lib/v2-pre/server/raw/tagListData.ts new file mode 100644 index 00000000..af959f5c --- /dev/null +++ b/src/lib/v2-pre/server/raw/tagListData.ts @@ -0,0 +1,19 @@ +import { loadRawData } from './loadRawData' + +export function getRawTagListDataMap(): RawTagListDataMap { + return loadRawData('TagListData.json') +} + +export type RawTagListDataMap = { + [key: string]: RawTagListItem +} + +export interface RawTagListItem { + TagName: number + TagDec: number + Icon: string + Type: number + ShowInScreen: boolean + DisplayWeaponList: number[] + DisplayStigmataList: number[] +} diff --git a/src/lib/v2-pre/server/raw/textMap.ts b/src/lib/v2-pre/server/raw/textMap.ts new file mode 100644 index 00000000..414954d5 --- /dev/null +++ b/src/lib/v2-pre/server/raw/textMap.ts @@ -0,0 +1,7 @@ +import { loadRawData } from './loadRawData' + +export function getRawTextMap(): RawTextMap { + return loadRawData('TextMap.json') +} + +export type RawTextMap = { [key: string]: { Text: 'string' } } diff --git a/src/scripts/compileRawData.ts b/src/scripts/compileRawData.ts new file mode 100644 index 00000000..4cd390c3 --- /dev/null +++ b/src/scripts/compileRawData.ts @@ -0,0 +1,37 @@ +import { buildBattlesuitList } from '../lib/v2-pre/server/buildData' +import path from 'path' +import { createDirIfNotExist } from '../lib/v2-pre/server/fsUtils' +import fs from 'fs' +import YAML from 'yaml' +import { runScript } from './lib/utils' +import { battlesuitCatalogPath, battlesuitsDir, dataDir } from '../lib/v2-pre/server/loadData' +import { BattlesuitCatalogItem } from '../lib/v2-pre/data/types' + +runScript(async () => { + createDirIfNotExist(dataDir) + writeBattlesuitData() +}) + +function writeBattlesuitData() { + const battlesuitList = buildBattlesuitList() + + const simplifiedList: BattlesuitCatalogItem[] = battlesuitList.map(battlesuit => { + return { + id: battlesuit.id, + fullName: battlesuit.fullName, + attributeType: battlesuit.attributeType, + weapon: battlesuit.weapon, + character: battlesuit.character, + initialStar: battlesuit.initialStar + } + }) + + fs.writeFileSync(battlesuitCatalogPath, YAML.stringify(simplifiedList)) + + createDirIfNotExist(battlesuitsDir) + + for (const battlesuit of battlesuitList) { + const battlesuitDataPath = path.join(battlesuitsDir, `${battlesuit.id}.yaml`) + fs.writeFileSync(battlesuitDataPath, YAML.stringify(battlesuit)) + } +} diff --git a/src/scripts/copyRawAssets.sh b/src/scripts/copyRawAssets.sh new file mode 100644 index 00000000..16bad6a9 --- /dev/null +++ b/src/scripts/copyRawAssets.sh @@ -0,0 +1,29 @@ +cp -R \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarcardfigures \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarcardicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarchibiicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarfragmentfigures \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avataricon \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatariconside \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarstar \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarstarskill \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatartachie \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/avatarattricons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/skillicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/subskillicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/stateicon/newstateicon \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/stigmatafigures \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/stigmataicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/stigmatasmallicon \ +dump/sprite2-dump-67/assets/originalresrepos/art/ui/stigmatatype \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/elfcardfigures \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/elfcardicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/elffragmentfigures \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/elftalentbg \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/rogue/materialfigures \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/rogue/supportbufficon \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/rogue/godcloseup \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/weaponicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/weapontypeicons \ +dump/sprite2-dump-67/assets/asbres/spriteoutput/materialfigures \ +assets/raw