149 lines
5.6 KiB
JavaScript
149 lines
5.6 KiB
JavaScript
import * as e from './common.mjs';
|
|
export function build(raw, season){
|
|
const equips=new Map(raw.GridFightEquipConfigRow.map(r=>[r.ID, r])),
|
|
seasonItems=new Set(raw.GridFightSeasonItemConfigRow.filter(r=>r.SeasonID===season).map(r=>r.ItemID)),
|
|
seasonCrafts=new Set(raw.GridFightSeasonCraftConfigRow.filter(r=>r.SeasonID===season).map(r=>r.CraftID)),
|
|
pool=[];
|
|
for(const id of [...seasonItems].sort((a, b)=>a-b)){
|
|
const row=equips.get(id);
|
|
if(!row)continue;
|
|
const entry={
|
|
id,
|
|
category:row.EquipCategory??0
|
|
};
|
|
if(row.EquipFunc){
|
|
entry.func=row.EquipFunc;
|
|
entry.func_params=row.EquipFuncParamList??[];
|
|
}
|
|
if(row.DressRule){
|
|
entry.dress_rule=row.DressRule;
|
|
entry.dress_params=row.DressRuleParamList??[];
|
|
}
|
|
pool.push(entry);
|
|
}
|
|
const basic=pool.filter(e=>e.category===1).map(e=>e.id),
|
|
recipes=[];
|
|
for(const row of raw.GridFightCraftConfigRow){
|
|
if(!seasonCrafts.has(row.CraftID))continue;
|
|
const cost=row.CostEquipList??[];
|
|
if(cost.length!==2||!equips.has(row.CraftEquipID)||cost.some(c=>!equips.has(c)))e.fail('craft '+row.CraftID+' has an unexpected shape');
|
|
recipes.push({
|
|
craft_id:row.CraftID,
|
|
result:row.CraftEquipID,
|
|
cost:cost.toSorted((a, b)=>a-b)
|
|
});
|
|
}
|
|
recipes.sort((a, b)=>a.craft_id-b.craft_id);
|
|
if(!basic.length||!recipes.length)e.fail('season has no basic components or recipes');
|
|
const poolIds=new Set(pool.map(e=>e.id)),
|
|
consumables=raw.GridFightConsumablesConfigRow.filter(r=>seasonItems.has(r.ID)).map(r=>({
|
|
id:r.ID,
|
|
rule:r.ConsumableRule??0,
|
|
params:r.ConsumableParamList??[],
|
|
stack:!!r.IfStack,
|
|
consume:!!r.IfConsume
|
|
})),
|
|
upgrades=raw.GridFightEquipUpgradeConfigRow.filter(r=>poolIds.has(r.PreID)&&poolIds.has(r.UpgradeID)).map(r=>({
|
|
from:r.PreID,
|
|
to:r.UpgradeID
|
|
}));
|
|
return {
|
|
season_id:season,
|
|
basic,
|
|
equipment:pool,
|
|
recipes,
|
|
consumables,
|
|
upgrades
|
|
};
|
|
}
|
|
export function add_catalog(data, catalog, seasonItems){
|
|
const tables=catalog.tables,
|
|
poolIds=new Set(data.equipment.map(e=>e.id)),
|
|
recommend=e.dict();
|
|
for(const r of tables.GridFightRoleRecommendEquipConfigRow){
|
|
const ids=(r.FirstRecommendEquipList??[]).filter(i=>poolIds.has(i)),
|
|
merged=recommend[r.RoleID]??=[];
|
|
for(const id of ids)if(!merged.includes(id))merged.push(id);
|
|
}
|
|
data.recommend=e.dict(Object.keys(recommend).sort((a, b)=>Number(a)-Number(b)).filter(k=>recommend[k].length).map(k=>[k, recommend[k]]));
|
|
const byId=new Map(data.equipment.map(e=>[e.id, e])),
|
|
items=new Map(catalog.seasons[data.season_id].items.map(i=>[i.id, i]));
|
|
for(const [id, target]of [[353301, 'wearer'], [353401, 'wearer'], [353501, 'teammate']]){
|
|
if(!byId.has(id))continue;
|
|
const row=e.need(items, id).equipment,
|
|
text=row.EquipDesc.text,
|
|
expected=target==='teammate'?'random teammate':'copy of this unit';
|
|
if(!text.includes(expected)||e.json(row.DressRuleParamList)!==e.json([150602]))e.fail('chip '+id+': reward contract changed; review matching client');
|
|
const period=row.ParamList[0].value;
|
|
if(period<=0||!Number.isInteger(period))e.fail('chip '+id+': invalid battle cadence');
|
|
byId.get(id).battle_reward={
|
|
period,
|
|
target
|
|
};
|
|
if(target==='wearer'){
|
|
const chance=row.ParamList[2].value;
|
|
if(!text.includes('whenever the wearer is obtained through any means')||!(chance>0&&chance<1))e.fail('chip '+id+': acquisition contract changed');
|
|
byId.get(id).acquisition_chance=chance;
|
|
}
|
|
}
|
|
if(byId.has(353507)){
|
|
const row=e.need(items, 353507).equipment;
|
|
if(!row.EquipDesc.text.includes('For every 2 battles')||e.json(row.EquipFuncParamList)!==e.json([100302]))e.fail('Phantasmoon cartridge reward contract changed');
|
|
byId.get(353507).battle_reward={
|
|
period:2,
|
|
target:'bond',
|
|
bond:100302
|
|
};
|
|
}
|
|
data.sw_console=tables.GridFightSPSilverWolfChooseConfigRow.filter(r=>poolIds.has(r.EquipID)).map(r=>({
|
|
star:r.Star??0,
|
|
equip:r.EquipID
|
|
}));
|
|
data.clara=tables.GridFightClaraEnhanceConfigRow.map(r=>({
|
|
id:r.ID,
|
|
category:r.Category??0,
|
|
cost:r.CostCoin??0,
|
|
limit:r.Limit??0,
|
|
module:'EnhanceSelectName'in r,
|
|
buff:r.BuffID??0
|
|
}));
|
|
data.clara_links=tables.GridFightClaraLinkRelationConfigRow.map(r=>({
|
|
id:r.ID,
|
|
convert:r.EnhanceConvert??[],
|
|
valid:r.ValidEnhanceList??[]
|
|
}));
|
|
data.phainon=tables.GridFightPhanionUniqueTraitConfigRow.map(r=>{
|
|
const normal=r.SavedValueAddList??[],
|
|
special=r.SpecialSavedValueAddList??[];
|
|
if(normal.length!==1||special.length!==1||normal[0][0]!=='GP_Avatar_S2_Phainon_00'||special[0][0]!==normal[0][0])e.fail(`Phainon row ${r.Rarity}/${r.Star}: saved value contract changed`);
|
|
return {
|
|
cost:r.Rarity,
|
|
star:r.Star,
|
|
add:normal[0][1],
|
|
special_add:special[0][1]
|
|
};
|
|
});
|
|
data.forges=tables.GridFightForgeConfigRow.filter(r=>seasonItems.has(r.ID)).map(r=>({
|
|
id:r.ID,
|
|
category:r.EquipCategory??0,
|
|
num:r.EquipNum??0,
|
|
func:r.FuncType??0,
|
|
params:r.ParamList??[]
|
|
}));
|
|
}
|
|
export function main(){
|
|
const a=e.cli([], {
|
|
items:e.resource('items.raw.json'),
|
|
season:2,
|
|
output:e.resource('equipment.json'),
|
|
catalog:e.catalogDefault
|
|
}),
|
|
raw=e.loadJSON(a.items),
|
|
data=build(raw, a.season),
|
|
items=new Set(raw.GridFightSeasonItemConfigRow.filter(r=>r.SeasonID===a.season).map(r=>r.ItemID));
|
|
add_catalog(data, e.loadJSON(a.catalog), items);
|
|
e.atomic_json(a.output, data, 1, true);
|
|
console.log(`${a.output}: ${data.equipment.length} equipment, ${data.basic.length} basic, ${data.recipes.length} recipes for season ${a.season}`);
|
|
}
|
|
e.runMain(import.meta.url, main);
|