function createVisitor() {
const arr = [];
return {
visited: (obj) => {
if (arr.includes(obj)) return true;
arr.push(obj);
return false;
},
};
}
// file: momiji - 01 - mess with AI.js
(function(){
// WIP code messing around with AI, trying to understand it
logged(rebuildBin(reparsedBins.momiji, {
// // get some free space by removing gaps
// removeGapsFromTimelines: true,
// removeGapsFromInputCommands: true,
// removeGapsFromAiCombos: true,
transformAiBehaviors: (pAiBehaviorsMap) => {
const unique = pAiBehaviorsMap.filterUnique();
unique.forEach(behavior => {
// behavior.someFloats = [ 1.75, 2.25, 6.5, 1.45, 1.25 ];
// behavior.someFloats = [ 6.4, 6.5, 6.6, 6.5, 6.4 ];
// behavior.someFloats = [ 0.4, 0.5, 0.6, 0.5, 0.4 ];
// behavior.someFloats = [ 1.5, 2.2, 6.2, 1.4, 1.2 ];
behavior.someFloats = [ 0.3, 0.4, 6.2, 0.4, 0.3 ];
behavior.weights1 = [ 0, 0, 0, 100 ];
behavior.weights2 = [ 100, 0, 0, 0 ];
// behavior.someFloats = [ 1.5, 2.2, 6.2, 1.4, 1.2 ];
// // ai runs in until 1.8m
// // ai circles around until <= {firstFloat=0.8m} and then does i2=0 type=09 unknown4=05 unknown2=<whatever>
// // ai circles around until <= {secondFloat=0.9m} and then does i2=1 type=09 unknown4=05 unknown2=<whatever>
// // ai circles around until <= {thirdFloat=1.3m} and then does i2=2 type=09 unknown4=05 unknown2=<whatever>
// behavior.someFloats = [ 0.8, 0.9, 1.3, 1.1, 1.0 ];
// behavior.weights1 = [ 25, 25, 25, 25 ];
// behavior.weights2 = [ 25, 25, 25, 25 ];
});
return pAiBehaviorsMap;
},
transformAiWeightedCombos: (
{
pAiWeightedCombosLists1Map,
pAiWeightedCombosLists2Map,
},
addCombo,
) => {
// debugger;
// example 1: remove everything except 1st entry
[
...pAiWeightedCombosLists1Map,
...pAiWeightedCombosLists2Map,
].filterUnique().flatMap(e => e).filterUnique().forEach((e, i, a) => {
// remove everything except 1st entry
// e.splice(1, e.length - 1);
// remove everything
e.splice(0, e.length);
});
// example 2: parse type and modify one of the categories
const visitor = createVisitor();
[
pAiWeightedCombosLists1Map,
pAiWeightedCombosLists2Map,
].forEach((pAiWeightedCombosListsIMap, i0) => {
pAiWeightedCombosListsIMap.forEach((e, i1) => {
if (visitor.visited(e)) return;
e.forEach((e, i2, a) => {
if (visitor.visited(e)) return;
if (i0 === 0 && [28, 29].includes(i2)) {
// type "28and29" - ground attacks
} else
if (i0 === 0 && [30, 31].includes(i2)) {
// type "30and31" - combo throws and holds
} else {
// type "09"
// i2 === 0 = neutral / range < someFloats[0]
// i2 === 1 = neutral / range < someFloats[1]
// i2 === 2 = neutral / range < someFloats[2]
// defense against 2p with 7p: i0=0&i2=15,16,17; i0=1&i2=13
// modify the third "category"
if (i2 === 2) {
// remove everything
e.splice(0, e.length);
// add new weighted combo
e.push({
unknown1: 100, // weight
unknown2: 3, // idk // 00, FF, 01, 02 or 03
[magicLinks["unknown3->pAiCombosMap->pAiCombos"]]: [
"00 00 00 00", "78 1F 00 00", // start with 24p
"94 00 00 00", addCombo([ // if got 100% meter, go to this combo instead
"02 00 00 00", "79 1F 00 00", // cancel recovery into followup p+k
"28 00 00 00", "00 00 00 00", // done
]).asAob4Str,
"02 00 00 00", "F9 1F 00 00", // cancel recovery into followup p
"28 00 00 00", "00 00 00 00", // done
],
unknown4: "05",
// unknown5: bitmaskFromComLevels([ 6, 7, 8 ]),
unknown5: bitmaskFromComLevels([ 7 ]),
});
}
}
});
});
});
},
}));
}());
// file: rig - 01 - mess with AI.js
(function(){
// WIP code messing around with AI, trying to understand it
logged(rebuildBin(reparsedBins.rig, {
// get some free space by removing gaps
removeGapsFromTimelines: true,
removeGapsFromInputCommands: true,
removeGapsFromAiCombos: true,
transformAiBehaviors: (pAiBehaviorsMap) => {
return new Array(8).fill({
someFloats: [ 1.2, 2.25, 6.0, 2.25, 1.2 ],
weights1: [ 0, 0, 100, 0 ], // [ 25, 25, 25, 25 ],
weights2: [ 100, 0, 0, 0 ], // [ 25, 25, 25, 25 ],
});
},
transformAiWeightedCombos: (
{
pAiWeightedCombosLists1Map,
pAiWeightedCombosLists2Map,
},
addCombo,
) => {
// helper function to create a simple front-facing striking combo
function createCombo(...moveIdGroups) {
return addCombo([
...moveIdGroups.flatMap(moveIds => [
"00 00 00 00", moveIds[0].dehexUint.asAob4Str, // start with given move id
...moveIds.slice(1).flatMap(moveId => [
"02 00 00 00", moveId.dehexUint.asAob4Str, // cancel recovery into move id
]),
]),
"28 00 00 00", "00 00 00 00", // done
]).asAob2Str;
}
// helper function to create a simple bt striking combo
function createBtCombo(...moveIdGroups) {
return addCombo([
...moveIdGroups.flatMap(moveIds => [
"01 00 00 00", moveIds[0].dehexUint.asAob4Str, // start from bt with given move id
...moveIds.slice(1).flatMap(moveId => [
"02 00 00 00", moveId.dehexUint.asAob4Str, // cancel recovery into move id
]),
]),
"28 00 00 00", "00 00 00 00", // done
]).asAob2Str;
}
return {
// Fill all 8 slots with same data
pAiWeightedCombosLists1Map: new Array(8).fill(Object.entries({
// define data for all 48 sections
// Note: this example only adds 1 combo per section, but you could add more
0: [ `FF 00 00 00 ${ createCombo(["B1 00"])} 00 00 05 FF 00 00` ], // 3p // + weights1[0] neutral offense / close range
1: [ `FF 00 00 00 ${ createCombo(["53 1F"])} 00 00 05 FF 00 00` ], // 4p // + weights1[0] neutral offense / medium range
2: [ `FF 00 00 00 ${ createCombo(["59 1F"])} 00 00 05 FF 00 00` ], // 66p // neutral offense / long range weights1[0&1]
3: [ `FF 00 00 00 ${ createCombo(["B5 00"])} 00 00 05 FF 00 00` ], // 2k // high crushes / close range?.. weights1[1] / stun extender (close range)
4: [ `FF 00 00 00 ${ createCombo(["58 1F"])} 00 00 05 FF 00 00` ], // 1p // high crushes / medium range?.. weights1[1] / stun extender (medium range)
5: [ `FF 00 00 00 ${ createCombo(["D2 00"])} 00 00 05 FF 00 00` ], // wuk 2k // high crushes / long range?... weights1[1]
6: [ `FF 00 00 00 ${ "B9 00" } 00 00 01 FF 00 00` ], // bt k // + weights1[2] throw-like? offense against standing/block
// 6: [ `FF 00 00 00 ${ createCombo(["98 00"])} 00 00 05 FF 00 00` ], // 7h // + weights1[2] throw-like? offense against standing/block
7: [ `FF 00 00 00 ${ createCombo(["9C 00"])} 00 00 05 FF 00 00` ], // 1h // + weights1[2] throw-like? offense against crouching/block
8: [ `FF 00 00 00 ${ createCombo(["BF 00"])} 00 00 05 FF 00 00` ], // 8K // against high holds or throws? (launcher and throws)
9: [ `FF 00 00 00 ${ createCombo(["76 1F"])} 00 00 05 FF 00 00` ], // 33K // against low holds or throws? (launcher and low throws)
10: [ `FF 00 00 00 ${ createCombo(["9A 00"])} 00 00 05 FF 00 00` ], // 4h // + weights1[3] OH-like? offense against standing/block
11: [ `FF 00 00 00 ${ createCombo(["9B 00"])} 00 00 05 FF 00 00` ], // 6h // + weights1[3] OH-like? offense against crouching/block
12: [ `FF 00 00 00 ${ createCombo(["82 20"])} 00 00 05 FF 00 00` ], // S // weights2[0] general purpose defense?.. weights1[0&1] long range offense?.. neutral / against direct high punch/kick?
13: [ `FF 00 00 00 ${ createCombo(["65 1F"])} 00 00 05 FF 00 00` ], // 6k // neutral / against direct mid k?
14: [ `FF 00 00 00 ${ createCombo(["50 1F"])} 00 00 05 FF 00 00` ], // 6p // neutral / against direct mid p?
15: [ `FF 00 00 00 ${ createCombo(["8A 1F"])} 00 00 05 FF 00 00` ], // 2h+k // ??? neutral / against direct low?...
16: [ `FF 00 00 00 ${ createCombo(["8B 1F"])} 00 00 05 FF 00 00` ], // 1h+k // ??? neutral / against direct low?...
17: [ `FF 00 00 00 ${ createCombo(["80 1F"])} 00 00 05 FF 00 00` ], // bnd 8k // +- weights2[0] defense against low strikes; weights2[1] general purpose defense
18: [ `FF 00 00 00 ${ createCombo(["B2 00"])} 00 00 05 FF 00 00` ], // 2p // + defense against standing throw / weights2[2] defense against all strikes
19: [ `FF 00 00 00 ${ createCombo(["ED 1F"])} 00 00 05 FF 00 00` ], // 6Ap // + defense against crouching throw / weights2[2] defense against low strikes
20: [ `FF 00 00 00 ${ createCombo(["85 1F"])} 00 00 05 FF 00 00` ], // tlc k // + weights2[0] defense against high OHs (high throws) / weights2[3] defense against all strikes
21: [ `FF 00 00 00 ${ createCombo(["89 1F"])} 00 00 05 FF 00 00` ], // tlc kk4k // + weights2[0] defense against low OHs (low throws) / weights2[3] defense against low strikes
22: [ `FF 00 00 00 ${ createCombo(["F8 1F"])} 00 00 05 FF 00 00` ], // tlc 6k // ??? high throws?..
23: [ `FF 00 00 00 ${ createCombo(["BC 00"])} 00 00 05 FF 00 00` ], // 9p // juggles / mid range?
24: [ `FF 00 00 00 ${ createCombo(["A0 1F"])} 00 00 05 FF 00 00` ], // bnd 4h+k // +- juggle 1
25: [ `FF 00 00 00 ${ createCombo(["40 20"])} 00 00 05 FF 00 00` ], // bnd 6h+kk // +- juggle 2 (bound / low / far?..)
26: [], // `FF 00 00 00 ${createBtCombo(["B6 00"])} 00 00 05 FF 00 00` ], // bt p // +- bt close range?
27: [], // `FF 00 00 00 ${createBtCombo(["B7 00"])} 00 00 05 FF 00 00` ], // bt 4p // +- bt medium range?
28: [ ], // + 2p/2k-like ground attacks
29: [ ], // + 8p+k-like ground attacks (ones available from bt?..)
30: [ ], // + combo throws
31: [ ], // + combo holds
32: [ `FF 00 00 00 ${ createCombo(["94 20"])} 00 00 05 FF 00 00` ], // tlc 8p // + disadvantage/stun against high punches
33: [ `FF 00 00 00 ${ createCombo(["FF 1F"])} 00 00 05 FF 00 00` ], // tlc h+k // + disadvantage/stun against high kicks
34: [ `FF 00 00 00 ${ createCombo(["98 1F"])} 00 00 05 FF 00 00` ], // bnd p+k // + disadvantage/stun against mid punch
35: [ `FF 00 00 00 ${ createCombo(["36 20"])} 00 00 05 FF 00 00` ], // bnd 3k // + disadvantage/stun against mid kick
36: [ `FF 00 00 00 ${ createCombo(["41 1F"])} 00 00 05 FF 00 00` ], // ppp // + disadvantage/stun against low punch
37: [ `FF 00 00 00 ${ createCombo(["7F 1F"])} 00 00 05 FF 00 00` ], // h+k2k // + disadvantage/stun against low kick
38: [ `FF 00 00 00 ${ createCombo(["B8 00"])} 00 00 05 FF 00 00` ], // bt 2p // ??? (low block)
39: [ `FF 00 00 00 ${ createCombo(["D1 00"])} 00 00 05 FF 00 00` ], // wuk // ???
40: [ `FF 00 00 00 ${ createCombo(["D0 00"])} 00 00 05 FF 00 00` ], // high wuk // + hard punish against mid/high holds/throws
41: [ `FF 00 00 00 ${ createCombo(["91 20"])} 00 00 05 FF 00 00` ], // h+k6k // + hard punish against low holds/throws
42: [ `FF 00 00 00 ${ createCombo(["C1 00"])} 00 00 05 FF 00 00` ], // 7k // + main ground game
43: [ `FF 00 00 00 ${ createCombo(["BE 00"])} 00 00 05 FF 00 00` ], // 8p // ???
44: [ `FF 00 00 00 ${ createCombo(["B2 1F"])} 00 00 05 FF 00 00` ], // 426t // empty for all chars
45: [ `FF 00 00 00 ${ createCombo(["63 20"])} 00 00 05 FF 00 00` ], // 24k // ground game?..
46: [ `FF 00 00 00 ${ createCombo(["EC 1F"])} 00 00 05 FF 00 00` ], // Ap // ???
47: [ `FF 00 00 00 ${ createCombo(["71 20"])} 00 00 05 FF 00 00` ], // 4S // ???
}).sortAscending(e => Number(e[0])).map(e => {
return e[1].map(e => {
const aob = e.dehexUintAob;
return {
unknown1: aob[0],
unknown2: aob[1],
unknown3: aob.slice(4, 4 + 2).asAobStr,
unknown4: aob[8],
unknown5: aob[9],
};
});
})),
// Fill all 8 slots with same data
pAiWeightedCombosLists2Map: new Array(8).fill(Object.entries({
// ...
}).sortAscending(e => Number(e[0])).map(e => e[1])),
};
// Changes mai quest #132 rig's spam of 4P+K P to 6Ap
// const replacement = {
// unknown1: 0xFF, // weight
// unknown2: 0,
// [magicLinks["unknown3->pAiCombosMap->pAiCombos"]]: [
// "00 00 00 00", "ED 1F 00 00", // start with 6Ap
// "28 00 00 00", "00 00 00 00", // done
// ],
// unknown4: "05",
// unknown5: 0x80, // difficulty 1
// };
// pAiWeightedCombosLists1Map[7][0][0] = replacement;
// pAiWeightedCombosLists1Map[7][1][0] = replacement;
// pAiWeightedCombosLists1Map[7][2][0] = replacement;
},
}));
}());