Update Healer Man server
This commit is contained in:
1 parent
39458d5de6
commit
6cc1b9217f
203 files changed
+133929
-31271
No files matched your search
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env node
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.resolve(scriptDirectory, "../..");
|
||||
const inputPath = path.join(projectRoot, "src", "game", "generated", "romHeirloomReference.json");
|
||||
const outputPath = path.join(projectRoot, "src", "game", "generated", "romNativeDamageTrainingProfiles.generated.json");
|
||||
const classes = ["rom-knight", "rom-priest", "rom-scout", "rom-rogue", "rom-mage"];
|
||||
const slots = ["main-hand", "off-hand", "ranged"];
|
||||
const sha256 = (buffer) => createHash("sha256").update(buffer).digest("hex");
|
||||
|
||||
const inputBuffer = await readFile(inputPath);
|
||||
const catalog = JSON.parse(inputBuffer.toString("utf8"));
|
||||
const selectedItemIds = new Set(Object.values(catalog.profiles).flatMap((profile) =>
|
||||
Object.values(profile).flatMap((curve) => curve.flatMap((row) => row.referenceItemIds))));
|
||||
const selectedItems = catalog.sourceItems.filter((item) => selectedItemIds.has(item.itemId));
|
||||
const itemById = new Map(selectedItems.map((item) => [item.itemId, item]));
|
||||
if (selectedItems.length !== selectedItemIds.size || selectedItems.some((item) =>
|
||||
item.unmappedEffects?.length || item.unresolvedAttributeIds?.length)) {
|
||||
throw new Error("Training reference has unresolved native body channels.");
|
||||
}
|
||||
const profiles = {};
|
||||
for (const classId of classes) {
|
||||
const sourceProfile = catalog.profiles?.[classId];
|
||||
if (!sourceProfile) throw new Error(`Missing source training profile for ${classId}.`);
|
||||
const classProfile = {};
|
||||
for (const slot of slots) {
|
||||
const curve = sourceProfile[slot];
|
||||
if (!curve) continue;
|
||||
if (curve.length !== 79) throw new Error(`${classId}/${slot} must cover levels 1–79.`);
|
||||
let previousShieldDefense = 0;
|
||||
classProfile[slot] = curve.map((entry, index) => {
|
||||
const weaponDamage = entry.stats?.weaponDamage ?? 0;
|
||||
const magicalWeaponDamage = entry.stats?.magicalWeaponDamage ?? 0;
|
||||
const speedTenths = entry.speedTenths ?? null;
|
||||
const referenceItems = entry.referenceItemIds.map((id) => itemById.get(id));
|
||||
const weaponType = referenceItems.length && referenceItems.every((item) => item?.sourceCatalog === "weaponobject.db"
|
||||
&& item.type === referenceItems[0].type) ? referenceItems[0].type : null;
|
||||
const shields = referenceItems.length && referenceItems.every((item) => item?.sourceCatalog === "armorobject.db"
|
||||
&& item.type === 5) ? [...referenceItems].sort((left, right) => left.level - right.level) : [];
|
||||
if (shields.length) {
|
||||
const level = index + 1;
|
||||
const lower = shields[0];
|
||||
const upper = shields.at(-1);
|
||||
const blend = level < lower.level ? level / lower.level : level > upper.level ? level / upper.level
|
||||
: lower.level === upper.level ? 0 : (level - lower.level) / (upper.level - lower.level);
|
||||
const rawDefense = level < lower.level ? (upper.baseStats.physicalDefense ?? 0) * blend
|
||||
: level > upper.level ? (lower.baseStats.physicalDefense ?? 0) * blend
|
||||
: (lower.baseStats.physicalDefense ?? 0) * (1 - blend) + (upper.baseStats.physicalDefense ?? 0) * blend;
|
||||
previousShieldDefense = Math.max(previousShieldDefense, rawDefense > 0 ? Math.max(1, Math.round(rawDefense)) : 0);
|
||||
}
|
||||
if (![weaponDamage, magicalWeaponDamage].every(Number.isFinite)
|
||||
|| (speedTenths !== null && !Number.isFinite(speedTenths))) {
|
||||
throw new Error(`Non-finite source training weapon row ${classId}/${slot}/${index + 1}.`);
|
||||
}
|
||||
return {
|
||||
level: index + 1,
|
||||
sourceItemIds: entry.referenceItemIds,
|
||||
weaponDamage,
|
||||
magicalWeaponDamage,
|
||||
speedTenths,
|
||||
weaponType,
|
||||
...(shields.length ? { shieldDefense: previousShieldDefense } : {}),
|
||||
};
|
||||
});
|
||||
}
|
||||
profiles[classId] = classProfile;
|
||||
}
|
||||
|
||||
const output = {
|
||||
schemaVersion: 1,
|
||||
status: "compact source-selected training weapon references; simulator gear profile and level interpolation policy",
|
||||
source: {
|
||||
file: "src/game/generated/romHeirloomReference.json",
|
||||
sha256: sha256(inputBuffer),
|
||||
sourceItemDatabases: catalog.sourceFiles,
|
||||
quality: catalog.quality,
|
||||
levelCap: 79,
|
||||
selectedItemCount: selectedItems.length,
|
||||
// Selection excludes unmapped effects, including typed MPow/Resist/AllRange.
|
||||
// These are item contributions only; actor auras and racial/source base inputs remain separate.
|
||||
trainingItemBodyDefaults: {
|
||||
perSchoolMagicPowerRate: 1, perSchoolResistance: 0, perSchoolResistanceRate: 1,
|
||||
allRangeDamageRate: 1, throwDamageRate: 1, throwingWeaponDamage: 0,
|
||||
},
|
||||
},
|
||||
profiles,
|
||||
};
|
||||
await writeFile(outputPath, `${JSON.stringify(output, null, 2)}\n`);
|
||||
console.log(`Wrote compact native training weapon profiles to ${path.relative(projectRoot, outputPath)}.`);
|
||||
Reference in new issue
Block a user