forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
f8314e7de1
commit
1fedb9368d
76 files changed
+20556
-2523
No files matched your search
@@ -0,0 +1,87 @@
|
||||
export const DEFAULT_COMPANION_COOLDOWN_POLICY = Object.freeze({
|
||||
schemaVersion: 1,
|
||||
generic: Object.freeze({
|
||||
defensiveHealthPercent: 55,
|
||||
emergencyHealthPercent: 35,
|
||||
healerMitigationHealthPercent: 80,
|
||||
offensiveMajorCooldownSeconds: 60,
|
||||
conserveOffensiveCooldownsForDurableTargets: true,
|
||||
}),
|
||||
mechanics: Object.freeze([]),
|
||||
});
|
||||
|
||||
function invalid(message) {
|
||||
const error = new Error(message);
|
||||
error.code = "invalid_companion_cooldown_policy";
|
||||
return error;
|
||||
}
|
||||
|
||||
function number(value, label, minimum, maximum) {
|
||||
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum) {
|
||||
throw invalid(`${label} must be a number from ${minimum} through ${maximum}.`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function string(value, label, allowEmpty = false) {
|
||||
if (typeof value !== "string" || (!allowEmpty && !value.trim()) || value.length > 256) {
|
||||
throw invalid(`${label} must be ${allowEmpty ? "a" : "a non-empty"} string no longer than 256 characters.`);
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
export function normalizeCompanionCooldownPolicy(value) {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value) || value.schemaVersion !== 1) {
|
||||
throw invalid("Companion cooldown policy schemaVersion must be 1.");
|
||||
}
|
||||
const generic = value.generic;
|
||||
if (!generic || typeof generic !== "object" || Array.isArray(generic)) throw invalid("generic rules are required.");
|
||||
if (typeof generic.conserveOffensiveCooldownsForDurableTargets !== "boolean") {
|
||||
throw invalid("generic.conserveOffensiveCooldownsForDurableTargets must be boolean.");
|
||||
}
|
||||
if (!Array.isArray(value.mechanics) || value.mechanics.length > 1_000) throw invalid("mechanics must be an array of at most 1,000 rules.");
|
||||
const seen = new Set();
|
||||
const mechanics = value.mechanics.map((rule, index) => {
|
||||
if (!rule || typeof rule !== "object" || Array.isArray(rule)) throw invalid(`mechanics[${index}] must be an object.`);
|
||||
const id = string(rule.id, `mechanics[${index}].id`);
|
||||
if (seen.has(id)) throw invalid(`mechanic rule id ${id} is duplicated.`);
|
||||
seen.add(id);
|
||||
if (typeof rule.enabled !== "boolean") throw invalid(`mechanics[${index}].enabled must be boolean.`);
|
||||
if (!new Set(["tank", "party"]).has(rule.scope)) throw invalid(`mechanics[${index}].scope is invalid.`);
|
||||
const serverEntry = rule.bossServerEntry;
|
||||
if (serverEntry !== null && (!Number.isInteger(serverEntry) || serverEntry <= 0)) {
|
||||
throw invalid(`mechanics[${index}].bossServerEntry must be null or a positive integer.`);
|
||||
}
|
||||
const bossName = string(rule.bossName, `mechanics[${index}].bossName`, true);
|
||||
if (serverEntry === null && !bossName) {
|
||||
throw invalid(`mechanics[${index}].bossName is required when bossServerEntry is null.`);
|
||||
}
|
||||
return {
|
||||
id,
|
||||
enabled: rule.enabled,
|
||||
bossKey: string(rule.bossKey, `mechanics[${index}].bossKey`, true),
|
||||
bossName,
|
||||
bossServerEntry: serverEntry,
|
||||
attackId: string(rule.attackId, `mechanics[${index}].attackId`),
|
||||
attackName: string(rule.attackName, `mechanics[${index}].attackName`),
|
||||
scope: rule.scope,
|
||||
leadTimeMs: number(rule.leadTimeMs, `mechanics[${index}].leadTimeMs`, 0, 15_000),
|
||||
minimumCooldownSeconds: number(rule.minimumCooldownSeconds, `mechanics[${index}].minimumCooldownSeconds`, 0, 600),
|
||||
};
|
||||
});
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
generic: {
|
||||
defensiveHealthPercent: number(generic.defensiveHealthPercent, "generic.defensiveHealthPercent", 1, 100),
|
||||
emergencyHealthPercent: number(generic.emergencyHealthPercent, "generic.emergencyHealthPercent", 1, 100),
|
||||
healerMitigationHealthPercent: number(generic.healerMitigationHealthPercent, "generic.healerMitigationHealthPercent", 1, 100),
|
||||
offensiveMajorCooldownSeconds: number(generic.offensiveMajorCooldownSeconds, "generic.offensiveMajorCooldownSeconds", 0, 600),
|
||||
conserveOffensiveCooldownsForDurableTargets: generic.conserveOffensiveCooldownsForDurableTargets,
|
||||
},
|
||||
mechanics,
|
||||
};
|
||||
}
|
||||
|
||||
export function cloneDefaultCompanionCooldownPolicy() {
|
||||
return JSON.parse(JSON.stringify(DEFAULT_COMPANION_COOLDOWN_POLICY));
|
||||
}
|
||||
Reference in new issue
Block a user