138 lines
4.0 KiB
JavaScript
138 lines
4.0 KiB
JavaScript
import * as s from './stages.mjs';
|
|
const e=s.primitive;
|
|
export class Reader {
|
|
constructor(data){
|
|
this.b=data;
|
|
this.p=1;
|
|
}
|
|
var(){
|
|
let v=0n,
|
|
shift=0n;
|
|
for(; ; ){
|
|
if(this.p>=this.b.length)e.fail('Truncated table varint');
|
|
const x=this.b[this.p++];
|
|
v|=BigInt(x&127)<<shift;
|
|
shift+=7n;
|
|
if(x<128)return e.small(v);
|
|
}
|
|
}
|
|
text(){
|
|
const n=Number(this.var());
|
|
if(this.p+n>this.b.length)e.fail('Truncated table string');
|
|
const text=new TextDecoder('utf-8', {
|
|
fatal:true
|
|
}).decode(this.b.subarray(this.p, this.p+n));
|
|
this.p+=n;
|
|
return text;
|
|
}
|
|
done(name){
|
|
if(this.p!==this.b.length)e.fail(`${name}: decode stopped at ${this.p} of ${this.b.length}`);
|
|
}
|
|
}
|
|
export const zigzag=e.zigzag;
|
|
export function fixpoint(wire){
|
|
const raw=BigInt(zigzag(wire));
|
|
return Number(raw&~1n)/2**((raw&1n)?26:33);
|
|
}
|
|
// Python round uses ties-to-even; retain a float marker for identical JSON 0.0/1.0.
|
|
export function rounded(v, n=6){
|
|
const scale=10**n,
|
|
x=v*scale,
|
|
lo=Math.floor(x),
|
|
f=x-lo;
|
|
return new e.Float((f===0.5?(lo%2===0?lo:lo+1):Math.round(x))/scale);
|
|
}
|
|
export function effects(raw){
|
|
const r=new Reader(raw),
|
|
rows=e.dict(),
|
|
count=Number(r.var())/2;
|
|
for(let i=0; i<Math.floor(count); i++){
|
|
const mask=BigInt(r.var()),
|
|
row={
|
|
};
|
|
if(mask&1n)row.id=r.var();
|
|
if(mask&2n)row.type=zigzag(r.var());
|
|
if(mask&4n)row.f2=r.var();
|
|
if(mask&8n)row.json=r.text();
|
|
if(mask&16n)row.icon=r.text();
|
|
if(mask>>5n)e.fail('GridFightTraitEffect: unknown fields');
|
|
if(row.id===undefined||row.type===undefined)e.fail('Missing effect id/type');
|
|
rows[row.id]=row.type;
|
|
}
|
|
r.done('GridFightTraitEffect');
|
|
return rows;
|
|
}
|
|
export function layer_params(raw){
|
|
const r=new Reader(raw),
|
|
rows=e.dict(),
|
|
count=Number(r.var())/2;
|
|
for(let i=0; i<Math.floor(count); i++){
|
|
const mask=BigInt(r.var()),
|
|
row={
|
|
id:0,
|
|
layer:0,
|
|
params:[]
|
|
};
|
|
if(mask&1n)row.id=r.var();
|
|
if(mask&2n)row.layer=r.var();
|
|
if(mask&4n)row.params=Array.from({
|
|
length:Math.floor(Number(r.var())/2)
|
|
}, ()=>rounded(fixpoint(r.var())));
|
|
if(mask&8n)row.f3=[r.var(), r.var()];
|
|
if(mask&16n){
|
|
const count=Math.floor(Number(r.var())/2);
|
|
row.doubles=Array.from({
|
|
length:count
|
|
}, (_, k)=>r.b.readDoubleLE(r.p+k*8));
|
|
r.p+=8*count;
|
|
}
|
|
if(mask>>5n)e.fail('GridFightTraitEffectLayerPa: unknown fields');
|
|
rows[row.id]??=e.dict();
|
|
rows[row.id][row.layer]=row.params;
|
|
}
|
|
r.done('GridFightTraitEffectLayerPa');
|
|
return rows;
|
|
}
|
|
export function constants(raw){
|
|
const r=new Reader(raw);
|
|
function value(tag){
|
|
if(tag===0)return zigzag(r.var());
|
|
if(tag===6)return Array.from({
|
|
length:Math.floor(Number(r.var())/2)
|
|
}, ()=>value(r.b[r.p++]));
|
|
if(tag===10)return r.text();
|
|
e.fail('GridFightTraitConstValueS2: unknown value tag '+tag);
|
|
}
|
|
const rows=e.dict(),
|
|
count=Math.floor(Number(r.var())/2);
|
|
for(let i=0; i<count; i++){
|
|
if(r.var()!==3)e.fail('GridFightTraitConstValueS2: unknown fields');
|
|
const key=r.text(),
|
|
tag=r.b[r.p++];
|
|
rows[key]=value(tag);
|
|
}
|
|
r.done('GridFightTraitConstValueS2');
|
|
return rows;
|
|
}
|
|
export function main(){
|
|
const a=e.cli(['client'], {
|
|
output:e.resource('trait_effects.json')
|
|
}),
|
|
assets=new s.Assets(a.client),
|
|
proofs=[],
|
|
out={
|
|
};
|
|
for(const [key, name, decode]of [['effects', 'GridFightTraitEffect', effects], ['layer_params', 'GridFightTraitEffectLayerPa', layer_params], ['constants', 'GridFightTraitConstValueS2', constants]]){
|
|
const [raw, proof]=assets.get('BakedConfig/ExcelOutputGameCore/'+name+'.bytes');
|
|
out[key]=decode(raw);
|
|
proofs.push({
|
|
table:key,
|
|
...proof
|
|
});
|
|
}
|
|
out.provenance=proofs;
|
|
e.atomic_json(a.output, out, 1, true);
|
|
console.log(`${a.output}: ${Object.keys(out.effects).length} effects, ${Object.keys(out.layer_params).length} effect param sets, ${Object.keys(out.constants).length} constants`);
|
|
}
|
|
e.runMain(import.meta.url, main);
|