forked from phenom/healer-man
Release Healer Man 0.1.32
This commit is contained in:
1 parent
d3d6aaebdb
commit
6dcb1034e5
102 files changed
+10772
-788
No files matched your search
@@ -34,11 +34,11 @@ const EXPECTED_FALLBACK_BOSSES = Object.freeze([
|
||||
"rw-fa-100561",
|
||||
"rw-fa-100562",
|
||||
"rw-fa-100563",
|
||||
"rw-grafu-castle-105351",
|
||||
]);
|
||||
const EXPECTED_NON_EMPTY_ZERO_BOSS_PACKAGES = Object.freeze([
|
||||
"aeternal-circle",
|
||||
"dungeon-of-dalanis",
|
||||
"grafu-castle",
|
||||
"kal-turok-hive",
|
||||
"lair-demon-dragon",
|
||||
"tomb-seven-heroes",
|
||||
|
||||
@@ -148,6 +148,7 @@ export function validatePopulationRecipe(recipe, file = "population recipe") {
|
||||
actorIds.add(actor.id);
|
||||
}
|
||||
const templateIds = new Set();
|
||||
const templatesById = new Map();
|
||||
const classifications = new Set(["combat", "boss", "deferred-object", "unclassified"]);
|
||||
for (const template of recipe.templates) {
|
||||
if (!Number.isInteger(template.id)) throw new Error("Template ids must be integers.");
|
||||
@@ -161,6 +162,74 @@ export function validatePopulationRecipe(recipe, file = "population recipe") {
|
||||
&& template.proceduralFallback !== true) {
|
||||
throw new Error("Combat template " + template.id + " has no mapped actor or explicit procedural fallback.");
|
||||
}
|
||||
if (template.source?.scriptRoots !== undefined
|
||||
&& (!Array.isArray(template.source.scriptRoots)
|
||||
|| template.source.scriptRoots.some((root) => typeof root !== "string" || !root.trim()))) {
|
||||
throw new Error("Template " + template.id + " source.scriptRoots must contain non-empty strings.");
|
||||
}
|
||||
templatesById.set(template.id, template);
|
||||
}
|
||||
const scriptedIds = new Set();
|
||||
const validateScriptedBase = (entry, label) => {
|
||||
assertObject(entry, label);
|
||||
assertString(entry.id, label + ".id");
|
||||
if (scriptedIds.has(entry.id)) throw new Error("Duplicate scripted placement id " + entry.id + ".");
|
||||
scriptedIds.add(entry.id);
|
||||
if (!Number.isInteger(entry.sourceAnchorSpawnId) || entry.sourceAnchorSpawnId <= 0) {
|
||||
throw new Error(label + ".sourceAnchorSpawnId must be a positive integer.");
|
||||
}
|
||||
if (entry.controllerSpawnId !== undefined
|
||||
&& (!Number.isInteger(entry.controllerSpawnId) || entry.controllerSpawnId <= 0)) {
|
||||
throw new Error(label + ".controllerSpawnId must be a positive integer.");
|
||||
}
|
||||
if (!Array.isArray(entry.evidence) || !entry.evidence.length
|
||||
|| entry.evidence.some((value) => typeof value !== "string" || !value.trim())) {
|
||||
throw new Error(label + ".evidence must contain non-empty source references.");
|
||||
}
|
||||
};
|
||||
for (const [index, spawn] of (recipe.scriptedSpawns ?? []).entries()) {
|
||||
const label = file + ".scriptedSpawns[" + index + "]";
|
||||
validateScriptedBase(spawn, label);
|
||||
const template = templatesById.get(spawn.templateId);
|
||||
if (!template || !["combat", "boss"].includes(template.classification)) {
|
||||
throw new Error(label + ".templateId must reference a combat or boss template.");
|
||||
}
|
||||
if (spawn.sourceOffset !== undefined
|
||||
&& (!Array.isArray(spawn.sourceOffset) || spawn.sourceOffset.length !== 3
|
||||
|| spawn.sourceOffset.some((value) => !Number.isFinite(value)))) {
|
||||
throw new Error(label + ".sourceOffset must contain three finite source-unit values.");
|
||||
}
|
||||
if (spawn.direction !== undefined && !Number.isFinite(spawn.direction)) {
|
||||
throw new Error(label + ".direction must be finite.");
|
||||
}
|
||||
if (spawn.objective !== undefined && typeof spawn.objective !== "boolean") {
|
||||
throw new Error(label + ".objective must be boolean when provided.");
|
||||
}
|
||||
}
|
||||
for (const [index, formation] of (recipe.scriptedFormations ?? []).entries()) {
|
||||
const label = file + ".scriptedFormations[" + index + "]";
|
||||
validateScriptedBase(formation, label);
|
||||
assertString(formation.sourceScriptRoot, label + ".sourceScriptRoot");
|
||||
if (!(Number(formation.spacingSourceUnits) > 0)) {
|
||||
throw new Error(label + ".spacingSourceUnits must be positive.");
|
||||
}
|
||||
if (!Number.isFinite(formation.direction)) {
|
||||
throw new Error(label + ".direction must be finite.");
|
||||
}
|
||||
if (!Array.isArray(formation.members) || !formation.members.length) {
|
||||
throw new Error(label + ".members must be a non-empty array.");
|
||||
}
|
||||
for (const [memberIndex, member] of formation.members.entries()) {
|
||||
const memberLabel = label + ".members[" + memberIndex + "]";
|
||||
assertObject(member, memberLabel);
|
||||
const template = templatesById.get(member.templateId);
|
||||
if (!template || !["combat", "boss"].includes(template.classification)) {
|
||||
throw new Error(memberLabel + ".templateId must reference a combat or boss template.");
|
||||
}
|
||||
if (!Number.isInteger(member.row) || member.row < 1 || !Number.isInteger(member.column)) {
|
||||
throw new Error(memberLabel + " requires a positive integer row and integer column.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user