- Rename original files - Allow exclusions and blacklist to be disabled completely - Add "valid locations" option - Add option to overwrite the files in the output folder ("chaining") - Add console output for how many models have been replaced, excluded, or are non valid
198 lines
4.7 KiB
JavaScript
198 lines
4.7 KiB
JavaScript
// https://docs.google.com/spreadsheets/d/1-3E_t-KsFIw2rpM0hZIKOdNdGm5-GnQjvJb3cysOawE/edit#gid=1532331536
|
|
|
|
const fs = require("fs");
|
|
const _ = require("underscore");
|
|
const { _models, shuffledModels } = require("./models");
|
|
|
|
if (!fs.existsSync("config.js")) {
|
|
fs.writeFileSync("config.js", fs.readFileSync("config.default.js"));
|
|
}
|
|
|
|
if (!fs.existsSync("output")) {
|
|
fs.mkdirSync("output");
|
|
fs.writeFileSync(
|
|
"output/character_character_data.bin",
|
|
fs.readFileSync("original/character_character_data.bin")
|
|
);
|
|
fs.writeFileSync(
|
|
"output/character_model_model_data.bin",
|
|
fs.readFileSync("original/character_model_model_data.bin")
|
|
);
|
|
}
|
|
|
|
const {
|
|
mode,
|
|
overwrite,
|
|
sameType,
|
|
singleModel,
|
|
randomModels,
|
|
exclusions,
|
|
blacklist,
|
|
valid,
|
|
} = require("./config");
|
|
|
|
// Check if a model is excluded from modification
|
|
function isModelExcluded(fb, sb) {
|
|
if (!exclusions.enabled) return false;
|
|
|
|
for (let i = 0; i < exclusions.models.length; i++) {
|
|
const model = exclusions.models[i];
|
|
|
|
if (
|
|
(model[0] === fb && model[1] === -1) ||
|
|
(model[0] === -1 && model[1] === sb)
|
|
) {
|
|
return !exclusions.isWhitelist;
|
|
} else if (model[0] === fb && model[1] === sb) {
|
|
return !exclusions.isWhitelist;
|
|
}
|
|
}
|
|
return exclusions.isWhitelist;
|
|
}
|
|
|
|
// Check if a model is blacklisted
|
|
function isModelBlacklisted(fb, sb) {
|
|
if (!blacklist.enabled) return false;
|
|
|
|
for (let i = 0; i < blacklist.models.length; i++) {
|
|
const model = blacklist.models[i];
|
|
|
|
if (
|
|
(model[0] === fb && model[1] === -1) ||
|
|
(model[0] === -1 && model[1] === sb)
|
|
) {
|
|
return !blacklist.isWhitelist;
|
|
} else if (model[0] === fb && model[1] === sb) {
|
|
return !blacklist.isWhitelist;
|
|
}
|
|
}
|
|
return blacklist.isWhitelist;
|
|
}
|
|
|
|
function isValidLocation(loc) {
|
|
if (!valid.enabled) return true;
|
|
if (!valid.locations.length) return true;
|
|
|
|
for (let i = 0; i < valid.locations.length; i++) {
|
|
if (valid.locations[i] === loc) return valid.isWhitelist;
|
|
}
|
|
return !valid.isWhitelist;
|
|
}
|
|
|
|
function replaceModels(doReplace = true) {
|
|
const data = fs.readFileSync(
|
|
`${overwrite ? "output" : "original"}/character_character_data.bin`
|
|
);
|
|
|
|
let nonValid = 0;
|
|
let excluded = 0;
|
|
let replaced = 0;
|
|
|
|
if (doReplace) {
|
|
// Magic
|
|
if (mode === 0) {
|
|
for (let i = 0x16194; i < 0x18ea8; i += 4) {
|
|
if (!isValidLocation(i)) {
|
|
nonValid++;
|
|
continue;
|
|
}
|
|
|
|
if (isModelExcluded(data[i], data[i + 1])) {
|
|
excluded++;
|
|
continue;
|
|
}
|
|
|
|
data[i] = singleModel[0];
|
|
data[i + 1] = singleModel[1];
|
|
replaced++;
|
|
}
|
|
} else if (mode === 1) {
|
|
for (let i = 0x16194; i < 0x18ea8; i += 4) {
|
|
if (!isValidLocation(i)) {
|
|
nonValid++;
|
|
continue;
|
|
}
|
|
|
|
if (isModelExcluded(data[i], data[i + 1])) {
|
|
excluded++;
|
|
continue;
|
|
}
|
|
|
|
const model = randomModels[_.random(randomModels.length - 1)];
|
|
|
|
data[i] = model[0];
|
|
data[i + 1] = model[1];
|
|
replaced++;
|
|
}
|
|
} else if (mode === 2) {
|
|
for (let i = 0x16194; i < 0x18ea8; i += 4) {
|
|
if (!isValidLocation(i)) {
|
|
nonValid++;
|
|
continue;
|
|
}
|
|
|
|
const id = data[i];
|
|
const type = data[i + 1];
|
|
|
|
if (isModelExcluded(id, type)) {
|
|
excluded++;
|
|
continue;
|
|
}
|
|
|
|
if (sameType) {
|
|
const models = shuffledModels[type];
|
|
|
|
let modelId = models[_.random(models.length - 1)];
|
|
|
|
while (isModelBlacklisted(modelId, type)) {
|
|
modelId = models[_.random(models.length - 1)];
|
|
}
|
|
|
|
data[i] = modelId;
|
|
data[i + 1] = type;
|
|
} else {
|
|
let [modelId, modelType] = _models[_.random(_models.length - 1)];
|
|
|
|
while (isModelBlacklisted(modelId, modelType)) {
|
|
[modelId, modelType] = _models[_.random(_models.length - 1)];
|
|
}
|
|
|
|
data[i] = modelId;
|
|
data[i + 1] = modelType;
|
|
}
|
|
|
|
replaced++;
|
|
}
|
|
}
|
|
// -----
|
|
}
|
|
|
|
console.log(
|
|
`Replaced ${replaced} models - Excluded ${excluded} - Non-Valid ${nonValid}`
|
|
);
|
|
|
|
fs.writeFileSync("output/character_character_data.bin", data);
|
|
}
|
|
|
|
// TODO: Create a reverse-lookup map of some sort to fit the proper model height with other models?
|
|
// Only does scaling, so not that needed apparently...
|
|
function replaceHeights(doReplace = true) {
|
|
const data = fs.readFileSync(
|
|
`${overwrite ? "output" : "original"}/character_model_model_data.bin`
|
|
);
|
|
|
|
if (doReplace) {
|
|
// Magic
|
|
for (let i = 0x23220; i < 0x24910; i += 2) {
|
|
data[i] = 0xb9;
|
|
data[i + 1] = 0x00;
|
|
}
|
|
// -----
|
|
}
|
|
|
|
fs.writeFileSync("output/character_model_model_data.bin", data);
|
|
}
|
|
|
|
replaceModels();
|
|
replaceHeights(false);
|