diff --git a/myscripts/collateAchievement.js b/myscripts/collateAchievement.js new file mode 100644 index 000000000..635c45519 --- /dev/null +++ b/myscripts/collateAchievement.js @@ -0,0 +1,92 @@ +const xachieve = getExcel('AchievementExcelConfigData'); +const xgoal = getExcel('AchievementGoalExcelConfigData'); +const xreward = getExcel('RewardExcelConfigData'); +const xmat = getExcel('MaterialExcelConfigData'); + +function collateAchievement(lang) { + const language = getLanguage(lang); + let myachievement = xachieve.reduce((accum, obj) => { + if(obj.IsDeleteWatcherAfterFinish === true) { + // console.log(`disuse: ${obj.Id} ${language[obj.TitleTextMapHash]}`) + return accum; + } + if(obj.Id === 84517) return accum; // Instant Karma achievement is unobtainable + + if(obj.PreStageAchievementId) { + if(language[obj.DescTextMapHash] === '') return accum; + let data = Object.values(accum).find(ele => ele.Id.includes(obj.PreStageAchievementId)); + data.Id.push(obj.Id); + + data.stages = data.stages + 1; + if(data.stages > 3) console.log(`achievement ${obj.Id} has more than 3 stages`); + + data['stage'+data.stages] = addStage(obj, language); + + return accum; + } + + let data = {}; + data.Id = [obj.Id]; + + data.name = language[obj.TitleTextMapHash]; + if(data.name === '') return accum; + + data.achievementgroup = language[xgoal.find(e => e.Id === obj.GoalId).NameTextMapHash]; + data.ishidden = obj.IsShow === 'SHOWTYPE_HIDE' ? true : undefined; + data.sortorder = obj.OrderId; + data.stages = 1; + + data['stage'+data.stages] = addStage(obj, language); + + + let filename = makeFileName(getLanguage('EN')[obj.TitleTextMapHash]); + if(filename === '') return accum; + if(accum[filename] !== undefined) { + if(obj.Id !== 84004 && obj.Id !== 86007) + console.log('filename collision: ' + filename + ' disuse: ' + obj.IsDisuse); + filename+='a'; + } + // if(accum[filename] !== undefined) return accum; + accum[filename] = data; + return accum; + }, {}); + + const groups = [...new Set(xgoal.map(e => language[e.NameTextMapHash]))]; + // for(const g of groups) { showNumber(myachievement, g); }; + console.log('total: ' + Object.values(myachievement).reduce((accum, ele) => { accum+=ele.stages; return accum }, 0)); + + // const wonder = Object.values(myachievement).filter(e => e.achievementgroup === 'Wonders of the World'); + // console.log(wonder.sort((a, b) => a.sortorder - b.sortorder).map(e => e.name).slice(170)); + + return myachievement; +} + +function showNumber(myachievement, group) { + const tmp = Object.values(myachievement).filter(e => e.achievementgroup === group).reduce((accum, ele) => { + accum+=ele.stages; + return accum; + }, 0); + console.log(`${group}: ${tmp}`); +} + +function addStage(obj, language) { + let out = {}; + out.title = language[obj.TitleTextMapHash]; + if(language[obj.Ps5TitleTextMapHash] !== '') + out.ps5title = language[obj.Ps5TitleTextMapHash]; + out.description = sanitizeDescription(language[obj.DescTextMapHash]); + out.progress = obj.Progress; + const rewards = xreward.find(e => e.RewardId === obj.FinishRewardId).RewardItemList.filter(f => f.ItemId); + if(rewards.length === 0) console.log(`achievement ${obj.Id} has no rewards`); + if(rewards.length > 1) console.log(`achievement ${obj.Id} has multiple rewards`); + if(rewards[0].ItemId !== 201) console.log(`achievement ${obj.Id} has non-primogem reward`); + out.reward = rewards.map(ele => { + return { + name: language[xmat.find(mat => mat.Id === ele.ItemId).NameTextMapHash], + count: ele.ItemCount + }; + })[0]; + return out; +} + +module.exports = collateAchievement; \ No newline at end of file diff --git a/myscripts/collateAchievementGroup.js b/myscripts/collateAchievementGroup.js new file mode 100644 index 000000000..e4fa6a083 --- /dev/null +++ b/myscripts/collateAchievementGroup.js @@ -0,0 +1,38 @@ +const xgroup = getExcel('AchievementGoalExcelConfigData'); +const xreward = getExcel('RewardExcelConfigData'); +const xmat = getExcel('MaterialExcelConfigData'); + +function collateAchievementGroup(lang) { + const language = getLanguage(lang); + let myachievementgroup = xgroup.reduce((accum, obj) => { + let data = {}; + data.Id = obj.Id; + + data.name = language[obj.NameTextMapHash]; + data.sortorder = obj.OrderId; + + if(obj.FinishRewardId) { + const rewards = xreward.find(e => e.RewardId === obj.FinishRewardId).RewardItemList.filter(f => f.ItemId); + if(rewards.length > 1) console.log(`achievementgroup ${obj.Id} has multiple rewards`); + data.reward = rewards.map(ele => { + return { + name: language[xmat.find(mat => mat.Id === ele.ItemId).NameTextMapHash], + // count: ele.ItemCount + }; + })[0]; + } + + data.nameicon = obj.IconPath; + + + let filename = makeFileName(getLanguage('EN')[obj.NameTextMapHash]); + if(filename === '') return accum; + if(accum[filename] !== undefined) console.log('filename collision: ' + filename); + accum[filename] = data; + return accum; + }, {}); + + return myachievementgroup; +} + +module.exports = collateAchievementGroup; \ No newline at end of file diff --git a/myscripts/collateAnimal.js b/myscripts/collateAnimal.js new file mode 100644 index 000000000..af557f9e0 --- /dev/null +++ b/myscripts/collateAnimal.js @@ -0,0 +1,37 @@ +const xmat = getExcel('MaterialExcelConfigData'); +const xsource = getExcel('MaterialSourceDataExcelConfigData'); +const xcodex = getExcel('AnimalCodexExcelConfigData'); +const xdescribe = getExcel('AnimalDescribeExcelConfigData'); +const xcapture = getExcel('CaptureExcelConfigData'); + +function collateAnimal(lang) { + const language = getLanguage(lang); + let mydata = xcodex.reduce((accum, obj) => { + if(obj.Type === 'CODEX_MONSTER') return accum; + let data = {}; + data.Id = obj.Id; + + let mydescribe = xdescribe.find(ele => ele.Id === obj.DescribeId); + + data.name = language[mydescribe.NameTextMapHash]; + data.description = sanitizeDescription(language[obj.DescTextMapHash]); + data.category = language[xmanualtext.find(ele => ele.TextMapId === `UI_CODEX_ANIMAL_CATEGORY_${obj.SubType.substring(obj.SubType.lastIndexOf('_')+1)}`).TextMapContentTextMapHash] + data.capturable = xcapture.find(ele => ele.MonsterID === obj.Id) ? true : undefined; + data.sortorder = obj.SortOrder; + + data.nameicon = mydescribe.Icon; + + + let filename = makeFileName(getLanguage('EN')[mydescribe.NameTextMapHash]); + if(filename === '') return accum; + if(accum[filename] !== undefined) console.log('filename collision: ' + filename); + accum[filename] = data; + return accum; + }, {}); + + return mydata; +} + + + +module.exports = collateAnimal; \ No newline at end of file diff --git a/myscripts/collateEnemy.js b/myscripts/collateEnemy.js index 01d58a829..14cc76df4 100644 --- a/myscripts/collateEnemy.js +++ b/myscripts/collateEnemy.js @@ -58,9 +58,9 @@ function collateEnemy(lang) { data.rewardpreview = mapRewardList(eyestormreward, language); } else if(obj.Id === 21011501) { // Unusual Hilichurl data.rewardpreview = mapRewardList(unusualreward, language); - } else if(obj.Id === 22030101 || obj.Id === 22020101 || + } else if(obj.Id === 22030101 || obj.Id === 22020101 || obj.Id === 22030201 || obj.Id === 26060201 || obj.Id === 26060101 || obj.Id === 26060301) { - // Abyss Lector: Violet Lightning, Abyss Herald: Wicked Torrents + // Abyss Lector: Violet Lightning, Abyss Herald: Wicked Torrents, Abyss Lector: Fathomless Flames // Hydro Cicin, Electro Cicin, Cryo Cicin data.rewardpreview = []; } else if(obj.Id === 29010101) { // dvalin lvl90 @@ -78,6 +78,9 @@ function collateEnemy(lang) { } else if(obj.Id === 29050101) { // signora lvl90 let rewardpreview = xpreview.find(pre => pre.Id === 15034).PreviewItems.filter(pre => pre.Id); data.rewardpreview = mapRewardList(rewardpreview, language); + } else if(obj.Id === 26050801) { + let rewardpreview = xpreview.find(pre => pre.Id === 15177).PreviewItems.filter(pre => pre.Id); + data.rewardpreview = mapRewardList(rewardpreview, language); } } if(!data.rewardpreview) console.log('no reward list for '+data.name); @@ -144,6 +147,10 @@ function findInvestigation(monId) { else if(monId === 21030601) monId = 21030101; // Electro Samachurl else if(monId === 22010401) monId = 22010101; // Electro Abyss Mage else if(monId === 26010301) monId = 26010201; // Electro Whopperflower + else if(monId === 20060601) monId = 20060201; // Pyro Specter + else if(monId === 20060501) monId = 20060201; // Electro Specter + else if(monId === 20060401) monId = 20060201; // Cryo Specter + // Hydro Cicin // Electro Cicin // Cryo Cicin @@ -211,4 +218,18 @@ const unusualreward = [ } ] + +function fixAnimalCodexSubType() { + const fs = require('fs'); + let obfu = require('../[Obfuscated] ExcelBinOutput/AnimalCodexExcelConfigData.json'); + let out = require('../ExcelBinOutput/AnimalCodexExcelConfigData.json'); + for(let ob of obfu) { + let match = out.find(ele => ele.Id === ob.ODDLMOCCOPN); + match.SubType = ob.JOKMGBKIIKJ; + } + out = JSON.stringify(out, null, '\t'); + fs.writeFileSync('../ExcelBinOutput/AnimalCodexExcelConfigData.json', out); +} +fixAnimalCodexSubType(); + module.exports = collateEnemy; diff --git a/myscripts/collateGeography.js b/myscripts/collateGeography.js new file mode 100644 index 000000000..3a44ce776 --- /dev/null +++ b/myscripts/collateGeography.js @@ -0,0 +1,35 @@ +const xview = getExcel('ViewCodexExcelConfigData'); +// const xsource = getExcel('MaterialSourceDataExcelConfigData'); +const xcity = getExcel('CityConfigData'); +const xarea = getExcel('WorldAreaConfigData'); + +function collageGeography(lang) { + const language = getLanguage(lang); + let mygeography = xview.reduce((accum, obj) => { + + let data = {}; + data.Id = obj.Id; + + data.name = language[obj.NameTextMapHash]; + data.area = language[xarea.find(area => area.ID === obj.WorldAreaId).AreaNameTextMapHash]; + data.description = sanitizeDescription(language[obj.DescTextMapHash]); + data.region = language[xcity.find(city => city.CityId === obj.CityId).CityNameTextMapHash]; + data.hiddenactive = obj.IsSeenActive ? true : undefined; + data.sortorder = obj.SortOrder; + + + // console.log(obj.CityID); + + data.nameimage = obj.Image; + + let filename = makeFileName(getLanguage('EN')[obj.NameTextMapHash]); + if(filename === '') return accum; + if(accum[filename] !== undefined) console.log('filename collision: ' + filename); + accum[filename] = data; + return accum; + }, {}); + + return mygeography; +} + +module.exports = collageGeography; \ No newline at end of file diff --git a/myscripts/collateNamecard.js b/myscripts/collateNamecard.js new file mode 100644 index 000000000..2aa0bbcb8 --- /dev/null +++ b/myscripts/collateNamecard.js @@ -0,0 +1,34 @@ +const xmat = getExcel('MaterialExcelConfigData'); +const xsource = getExcel('MaterialSourceDataExcelConfigData'); + +function collateNamecard(lang) { + const language = getLanguage(lang); + let mynamecard = xmat.reduce((accum, obj) => { + if(obj.MaterialType !== 'MATERIAL_NAMECARD') return accum; + + let data = {}; + data.Id = obj.Id; + // data.RankLevel = obj.RankLevel; // all rarity 4 + + data.name = language[obj.NameTextMapHash]; + data.description = sanitizeDescription(language[obj.DescTextMapHash]); + + let sauce = xsource.find(ele => ele.Id === obj.Id); + data.source = sauce.TextList.map(ele => language[ele]).filter(ele => ele !== ''); + + + data.nameicon = obj.Icon; + data.namebanner = obj.UseParam[0] !== "" ? obj.UseParam[0] : undefined; + data.namebackground = obj.UseParam[1]; + + let filename = makeFileName(getLanguage('EN')[obj.NameTextMapHash]); + if(filename === '') return accum; + if(accum[filename] !== undefined) console.log('filename collision: ' + filename); + accum[filename] = data; + return accum; + }, {}); + + return mynamecard; +} + +module.exports = collateNamecard; \ No newline at end of file diff --git a/myscripts/collateOutfit.js b/myscripts/collateOutfit.js new file mode 100644 index 000000000..52e8cc510 --- /dev/null +++ b/myscripts/collateOutfit.js @@ -0,0 +1,69 @@ +const xmat = getExcel('MaterialExcelConfigData'); +const xsource = getExcel('MaterialSourceDataExcelConfigData'); +const xcostume = getExcel('AvatarCostumeExcelConfigData'); +const xavatar = getExcel('AvatarExcelConfigData'); + +const propertyMap = { + Id: 'BBMGPIGONBN', + AvatarId: 'PIFBBDBABNO', + IconName: 'JBHPBOFFFNN' +} + +// taken from collateCharacter.js +const playerIdToTextMapHash = { 10000005: 2329553598, 10000007: 3241049361 }; + +function collateOutfit(lang) { + const language = getLanguage(lang); + let myoutfit = xcostume.reduce((accum, obj) => { + + let data = {}; + data.Id = obj[propertyMap.Id]; + + data.name = language[obj.NameTextMapHash]; + data.description = sanitizeDescription(language[obj.DescTextMapHash]); + + data.isdefault = obj.IsDefault === true; + + const AvatarId = obj[propertyMap.AvatarId]; + if(playerIdToTextMapHash[AvatarId]) + data.character = language[playerIdToTextMapHash[AvatarId]]; + else + data.character = language[xavatar.find(ele => ele.Id === obj[propertyMap.AvatarId]).NameTextMapHash]; + + if(obj.ItemId) { + let sauce = xsource.find(ele => ele.Id === obj.ItemId); + data.source = sauce.TextList.map(ele => language[ele]).filter(ele => ele !== ''); + + data.namecard = xmat.find(ele => ele.Id === obj.ItemId).Icon; + } else { + data.namecard = 'UI_AvatarIcon_Costume_Card'; + } + + if(obj[propertyMap.IconName]) { + data.nameicon = obj[propertyMap.IconName]; + const name = data.nameicon.slice(data.nameicon.lastIndexOf('_')+1); + data.namesplash = `UI_Costume_${name}`; + } + if(obj.SideIconName) + data.namesideicon = obj.SideIconName; + + + + // data.nameicon = obj.Icon; + // data.namebanner = obj.UseParam[0] !== "" ? obj.UseParam[0] : undefined; + // data.namebackground = obj.UseParam[1]; + + let filename = makeFileName(getLanguage('EN')[obj.NameTextMapHash]); + if(filename === '') return accum; + if(filename === 'defaultoutfit') return accum; + if(playerIdToTextMapHash[AvatarId]) + filename += makeFileName(getLanguage('EN')[playerIdToTextMapHash[AvatarId]]); + if(accum[filename] !== undefined) console.log('filename collision: ' + filename); + accum[filename] = data; + return accum; + }, {}); + + return myoutfit; +} + +module.exports = collateOutfit; \ No newline at end of file diff --git a/myscripts/collateWeapon.js b/myscripts/collateWeapon.js index 8501f5c36..9a6a78bdc 100644 --- a/myscripts/collateWeapon.js +++ b/myscripts/collateWeapon.js @@ -7,7 +7,9 @@ const xmat = getExcel('MaterialExcelConfigData'); const xplayableWeapon = xweapon.filter(obj => { if(obj.RankLevel >= 3 && obj.SkillAffix[0] === 0) return false; if(obj.SkillAffix[1] !== 0) { console.log('danger'); return false }; - if(getLanguage('EN')[obj.NameTextMapHash] === '') return false; + const name = getLanguage('EN')[obj.NameTextMapHash]; + if(name === '') return false; + else if(name === 'The Flagstaff' || name === 'Quartz' || name === 'Ebony Bow' || name === 'Amber Bead') return false; return true; }); diff --git a/myscripts/collateWindGlider.js b/myscripts/collateWindGlider.js new file mode 100644 index 000000000..a78f324ee --- /dev/null +++ b/myscripts/collateWindGlider.js @@ -0,0 +1,38 @@ +const xmat = getExcel('MaterialExcelConfigData'); +const xsource = getExcel('MaterialSourceDataExcelConfigData'); +const xfly = getExcel('AvatarFlycloakExcelConfigData'); + +function collateWindGlider(lang) { + const language = getLanguage(lang); + let mydata = xfly.reduce((accum, obj) => { + let data = {}; + data.Id = obj.FlycloakId; + + data.name = language[obj.NameTextMapHash]; + data.description = sanitizeDescription(language[obj.DescTextMapHash]); + + let flymat = xmat.find(ele => ele.Id === obj.MaterialId) || {}; + + data.rarity = flymat.RankLevel+""; + data.sortorder = obj.FlycloakId; + data.ishidden = obj.Hide ? true : undefined; + + // let sauce = xsource.find(ele => ele.Id === obj.Id); + // data.source = sauce.TextList.map(ele => language[ele]).filter(ele => ele !== ''); + data.source = getMatSourceText(obj.MaterialId, language); + + data.nameicon = flymat.Icon; + data.namegacha = obj.Icon; + + + let filename = makeFileName(getLanguage('EN')[obj.NameTextMapHash]); + if(filename === '') return accum; + if(accum[filename] !== undefined) console.log('filename collision: ' + filename); + accum[filename] = data; + return accum; + }, {}); + + return mydata; +} + +module.exports = collateWindGlider; \ No newline at end of file diff --git a/myscripts/myscript.js b/myscripts/myscript.js index 6f6ee7fc8..5ecce3fb7 100644 --- a/myscripts/myscript.js +++ b/myscripts/myscript.js @@ -23,7 +23,7 @@ const langcodes = ['CHS', 'CHT', 'DE', 'EN', 'ES', 'FR', 'ID', 'JP', 'KR', 'PT', // UNUSED object map that converts AvatarAssocType into a TextMapHash const assocTextMapHash = ['ASSOC_TYPE_MONDSTADT', 'ASSOC_TYPE_LIYUE', 'ASSOC_TYPE_FATUI']; -global.isPlayer = function(data) { return data.CandSkillDepotIds.length !== 0; } +global.isPlayer = function(data) { return data.CandSkillDepotIds && data.CandSkillDepotIds.length !== 0; } global.getPlayerElement = function(SkillDepotId) { let tmp = xskilldepot.find(ele => ele.Id === SkillDepotId); return tmp === undefined ? tmp : tmp.TalentStarName.split('_').pop(); } global.getLanguage = function(abbriev) { return getTextMap(abbriev.toUpperCase()); } global.normalizeStr = function(str) { return str.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); } @@ -33,7 +33,8 @@ global.stripHTML = function(str) { return (str || '').replace(/(<([^>]+)>)/gi, ' global.capitalizeFirst = function(str) { return str[0].toUpperCase() + str.toLowerCase().slice(1); } global.replaceLayout = function(str) { return str.replace(/{LAYOUT_MOBILE#.*?}{LAYOUT_PC#(.*?)}{LAYOUT_PS#.*?}/gi,'$1').replace('#','').replaceAll('{NON_BREAK_SPACE}', ' '); } global.replaceNewline = function(str) { return str.replace(/\\n/gi, '\n'); } -global.sanitizeDescription = function(str) { return replaceNewline(replaceLayout(stripHTML(convertBold(str)))); } +global.sanitizeDescription = function(str) { return replaceNewline(replaceLayout(stripHTML(convertBold(str || '')))); } +global.getMatSourceText = function(id, textmap) { return getExcel('MaterialSourceDataExcelConfigData').find(e => e.Id === id).TextList.map(e => textmap[e]).filter(e => e !== ''); } /* ======================================================================================= */ // object map that converts the genshin coded element into a TextMapHash @@ -99,7 +100,7 @@ function exportData(folder, collateFunc, englishonly, skipwrite) { console.log("done "+folder); } -exportData('characters', require('./collateCharacter.js')); +// exportData('characters', require('./collateCharacter.js')); // exportCurve('characters', 'AvatarCurveExcelConfigData'); // exportData('constellations', require('./collateConstellation')); // exportData('talents', require('./collateTalent.js')); @@ -112,6 +113,15 @@ exportData('characters', require('./collateCharacter.js')); // exportData('enemies', require('./collateEnemy')); // exportData('domains', require('./collateDomainMonsterList')); // run only after both domains and enemies have run. sync // exportCurve('enemies', 'MonsterCurveExcelConfigData'); + +// exportData('outfits', require('./collateOutfit')); +// exportData('windgliders', require('./collateWindGlider')); +exportData('animals', require('./collateAnimal')); +// exportData('namecards', require('./collateNamecard')); +// exportData('geographies', require('./collateGeography')); +// exportData('achievements', require('./collateAchievement')); +// exportData('achievementgroups', require('./collateAchievementGroup')); + // // exportData('fishingpoints', require('./collateFishingPoint')); //console.log(collateCharacter('EN'))