Release Healer Man 0.1.20
This commit is contained in:
1 parent
d9bebb4e81
commit
699fc858c9
22 files changed
+551
-295
No files matched your search
@@ -116,10 +116,12 @@ function reportMarkdown(report) {
|
||||
dungeon.proceduralModels, "|", dungeon.status, "|",
|
||||
].join(" "));
|
||||
return [
|
||||
"# WoW dungeon content report",
|
||||
"# WoW dungeon combat and animation report",
|
||||
"",
|
||||
"Status: **" + report.status + "**",
|
||||
"",
|
||||
"Scope: executable combat populations and creature animation bindings. This report does not certify instance scripts, doors, interactables, escorts, waves, vehicles, or navigation.",
|
||||
"",
|
||||
"Coverage: " + report.summary.dungeons + " dungeons, " + report.summary.mobs
|
||||
+ " mobs, " + report.summary.bosses + " bosses, " + report.summary.attacks
|
||||
+ " executable attacks, and " + report.summary.specialAttacks + " special attacks/mechanics.",
|
||||
@@ -177,6 +179,10 @@ for (const dungeon of definitions) {
|
||||
let specialAttacks = 0;
|
||||
let nativeModels = 0;
|
||||
let proceduralModels = 0;
|
||||
const optionalBossEntityIds = new Set((dungeon.objectiveOrder ?? [])
|
||||
.filter((objective) => objective.optional)
|
||||
.map((objective) => dungeon.staticSpawns?.find((spawn) => spawn.id === objective.id)?.entityId)
|
||||
.filter(Boolean));
|
||||
|
||||
if (!entities.length) dungeonIssues.push("has no combat entities.");
|
||||
if (!bosses.length) dungeonIssues.push("has no bosses.");
|
||||
@@ -203,7 +209,7 @@ for (const dungeon of definitions) {
|
||||
attacks += entityAttacks.length;
|
||||
const specials = entityAttacks.filter((attack) => attack.id !== "basic-attack");
|
||||
specialAttacks += specials.length;
|
||||
if (entity.kind === "boss" && !specials.length) {
|
||||
if (entity.kind === "boss" && !specials.length && !optionalBossEntityIds.has(entityId)) {
|
||||
const exceptionKey = dungeon.id + ":" + entityId;
|
||||
if (!basicOnlyBossExceptions.has(exceptionKey)) {
|
||||
dungeonIssues.push(entityId + " has no boss mechanic beyond its basic attack.");
|
||||
@@ -297,7 +303,7 @@ const summary = dungeons.reduce((result, dungeon) => ({
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
status: issues.length ? "blocked" : "green",
|
||||
scope: "HealerMan WoW five-player campaign",
|
||||
scope: "HealerMan WoW five-player combat and animation coverage",
|
||||
summary,
|
||||
documentedExceptions,
|
||||
animationFallbacks,
|
||||
@@ -317,4 +323,4 @@ console.log(JSON.stringify({
|
||||
documentedExceptions: report.documentedExceptions,
|
||||
issues: report.issues,
|
||||
}, null, 2));
|
||||
if (issues.length) process.exitCode = 1;
|
||||
if (issues.length) process.exitCode = 1;
|
||||
@@ -707,6 +707,18 @@ function smartAiMechanicsFor(entity, boss, spells, worldAi) {
|
||||
return mechanics;
|
||||
}
|
||||
|
||||
function initializationSpawnChance(entry, worldAi) {
|
||||
const despawnRows = (worldAi?.smartScriptsByEntry?.[String(entry)] ?? []).filter((row) => (
|
||||
Number(row.event_type) === 37
|
||||
&& Number(row.action_type) === 41
|
||||
&& Number(row.target_type) === 1
|
||||
));
|
||||
if (!despawnRows.length) return 1;
|
||||
return rounded(despawnRows.reduce((chance, row) => (
|
||||
chance * (1 - Math.max(0, Math.min(100, Number(row.event_chance) || 0)) / 100)
|
||||
), 1));
|
||||
}
|
||||
|
||||
function uniqueMechanics(mechanics) {
|
||||
const seenIds = new Set();
|
||||
const seenSpellIds = new Set();
|
||||
@@ -1233,6 +1245,7 @@ async function compile() {
|
||||
const id = encounter.eventOnly
|
||||
? "mutanus-spawn"
|
||||
: candidate?.id ?? `encounter-${encounter.encounterId}`;
|
||||
const spawnChance = initializationSpawnChance(encounter.creatureId, azerothCoreWorldAi);
|
||||
usedBossSpawnIds.add(id);
|
||||
return {
|
||||
id,
|
||||
@@ -1240,6 +1253,7 @@ async function compile() {
|
||||
name: encounter.name,
|
||||
position,
|
||||
yaw: candidate?.yaw ?? 0,
|
||||
...(spawnChance < 1 ? { optional: true } : {}),
|
||||
...(encounter.eventOnly ? { eventOnly: true } : {}),
|
||||
};
|
||||
});
|
||||
@@ -1248,6 +1262,7 @@ async function compile() {
|
||||
const roamingPacks = [];
|
||||
for (const spawn of sourceSpawns) {
|
||||
const entry = Number(spawn.entityId.replace("entry-", ""));
|
||||
const spawnChance = initializationSpawnChance(entry, azerothCoreWorldAi);
|
||||
const isBoss = bossEntries.has(entry);
|
||||
const transformedPosition = mapPosition(spawn.position);
|
||||
if (!isBoss && spawn.waypoints?.length >= 2) {
|
||||
@@ -1269,6 +1284,7 @@ async function compile() {
|
||||
pathId: spawn.pathId,
|
||||
formationSource: "database-solo",
|
||||
spawnMask: spawn.spawnMask,
|
||||
...(spawnChance < 1 ? { spawnChance } : {}),
|
||||
waypoints,
|
||||
members: [{
|
||||
id: "member",
|
||||
@@ -1286,6 +1302,7 @@ async function compile() {
|
||||
position: transformedPosition,
|
||||
yaw: spawn.yaw,
|
||||
spawnMask: spawn.spawnMask,
|
||||
...(spawnChance < 1 ? { spawnChance } : {}),
|
||||
});
|
||||
}
|
||||
for (const boss of bossObjectives) {
|
||||
@@ -1337,10 +1354,11 @@ async function compile() {
|
||||
...roamingPacks.flatMap((pack) => pack.waypoints),
|
||||
];
|
||||
const bounds = finiteBounds(allPoints);
|
||||
const bosses = bossObjectives.map(({ id, name, position, eventOnly }) => ({
|
||||
const bosses = bossObjectives.map(({ id, name, position, optional, eventOnly }) => ({
|
||||
id,
|
||||
name,
|
||||
position,
|
||||
...(optional ? { optional: true } : {}),
|
||||
...(eventOnly ? { eventOnly: true } : {}),
|
||||
}));
|
||||
const databaseKind = recipe.clientBuild === "3.3.5a-Epoch" || draft?.spawns?.length
|
||||
|
||||
Reference in new issue
Block a user