forked from phenom/healer-man
86 lines
5.0 KiB
TypeScript
86 lines
5.0 KiB
TypeScript
import type { DungeonDefinition, DungeonPresentation, DungeonTraversalRamp } from "./dungeonTypes";
|
|
import stairCatalog from "./generated/wowDungeonStairs.generated.json";
|
|
|
|
type LightingProfile = Pick<DungeonPresentation, "background" | "ambientLight" | "hemisphereLight" | "directionalLight"> & {
|
|
readonly fog: Pick<DungeonPresentation["fog"], "color" | "near">;
|
|
};
|
|
|
|
// Imported WoW environments do not carry the original client's baked lighting.
|
|
// Stockades' reviewed fill levels are the baseline; color remains environment-specific.
|
|
export const WOW_DUNGEON_LIGHTING: Readonly<Record<string, LightingProfile>> = {
|
|
stone: {
|
|
background: "#171815", fog: { color: "#1b1c18", near: 44 },
|
|
ambientLight: { color: "#d8c9aa", intensity: 0.58 },
|
|
hemisphereLight: { skyColor: "#cfc3a5", groundColor: "#292820", intensity: 0.86 },
|
|
directionalLight: { color: "#ffe0a8", intensity: 1.1, offset: [10, 18, -5] },
|
|
},
|
|
cavern: {
|
|
background: "#121914", fog: { color: "#172019", near: 44 },
|
|
ambientLight: { color: "#bcccaf", intensity: 0.58 },
|
|
hemisphereLight: { skyColor: "#b2c6b5", groundColor: "#242b22", intensity: 0.86 },
|
|
directionalLight: { color: "#dce5bc", intensity: 1.1, offset: [10, 18, -5] },
|
|
},
|
|
fire: {
|
|
background: "#211612", fog: { color: "#291c17", near: 44 },
|
|
ambientLight: { color: "#d3bca9", intensity: 0.58 },
|
|
hemisphereLight: { skyColor: "#d1bca6", groundColor: "#30251f", intensity: 0.86 },
|
|
directionalLight: { color: "#ffd3a1", intensity: 1.1, offset: [10, 18, -5] },
|
|
},
|
|
arcane: {
|
|
background: "#161827", fog: { color: "#1c2030", near: 44 },
|
|
ambientLight: { color: "#c4c8de", intensity: 0.58 },
|
|
hemisphereLight: { skyColor: "#bdc9e6", groundColor: "#25283a", intensity: 0.86 },
|
|
directionalLight: { color: "#e0e9ff", intensity: 1.1, offset: [10, 18, -5] },
|
|
},
|
|
crypt: {
|
|
background: "#171721", fog: { color: "#1d1d28", near: 44 },
|
|
ambientLight: { color: "#c8c3d1", intensity: 0.58 },
|
|
hemisphereLight: { skyColor: "#c0c2d3", groundColor: "#282530", intensity: 0.86 },
|
|
directionalLight: { color: "#e7ddcf", intensity: 1.1, offset: [10, 18, -5] },
|
|
},
|
|
outdoor: {
|
|
background: "#293330", fog: { color: "#35423e", near: 80 },
|
|
ambientLight: { color: "#d4dccb", intensity: 0.58 },
|
|
hemisphereLight: { skyColor: "#c9d9e5", groundColor: "#30382b", intensity: 0.86 },
|
|
directionalLight: { color: "#fff0cd", intensity: 1.1, offset: [10, 18, -5] },
|
|
},
|
|
};
|
|
|
|
const PROFILE_DUNGEONS: Readonly<Record<string, readonly string[]>> = {
|
|
cavern: ["wailing-caverns", "razorfen-kraul", "razorfen-downs", "blackfathom-deeps", "maraudon", "underbog", "slave-pens", "steamvault"],
|
|
fire: ["ragefire-chasm", "blackrock-depths", "blackrock-spire", "hellfire-ramparts", "blood-furnace", "shattered-halls"],
|
|
arcane: ["gnomeregan", "arcatraz", "botanica", "mechanar", "magisters-terrace", "the-nexus", "the-oculus", "violet-hold", "tinkertech-showdown"],
|
|
crypt: ["shadowfang-keep", "scholomance", "stratholme", "sunken-temple", "auchenai-crypts", "mana-tombs", "sethekk-halls", "shadow-labyrinth", "azjol-nerub", "ahnkahet-old-kingdom", "forge-of-souls", "halls-of-reflection"],
|
|
outdoor: ["zulfarrak", "black-morass", "escape-from-durnholde", "culling-of-stratholme", "trial-of-the-champion", "pit-of-saron", "frozen-reach"],
|
|
};
|
|
|
|
export function wowDungeonLightingProfile(id: string): string {
|
|
return Object.entries(PROFILE_DUNGEONS).find(([, ids]) => ids.includes(id))?.[0] ?? "stone";
|
|
}
|
|
|
|
/** Shared adapter also covers authored Wailing Caverns and survives campaign regeneration. */
|
|
export function withWowDungeonEnvironment(definition: DungeonDefinition): DungeonDefinition {
|
|
if (definition.expansion === "runewaker") return definition;
|
|
const profile = WOW_DUNGEON_LIGHTING[wowDungeonLightingProfile(definition.id)];
|
|
const stairs = (stairCatalog.dungeons as unknown as Readonly<Record<string, {
|
|
readonly collision: readonly { readonly url: string; readonly checksum: string }[];
|
|
readonly navigation?: { readonly url: string; readonly checksum: string };
|
|
readonly ramps: readonly DungeonTraversalRamp[];
|
|
}>>)[definition.id];
|
|
// Never apply package-space coordinates to a newly replaced environment.
|
|
const matchingAssets = stairs && definition.assets.collision.length === stairs.collision.length
|
|
&& definition.assets.collision.every((asset, index) => asset.url === stairs.collision[index].url
|
|
&& asset.checksum === stairs.collision[index].checksum);
|
|
const matchingNavigation = !stairs?.ramps.some((ramp) => ramp.navigationBridges?.length)
|
|
|| (definition.assets.navigation?.url === stairs?.navigation?.url
|
|
&& definition.assets.navigation?.checksum === stairs?.navigation?.checksum);
|
|
return {
|
|
...definition,
|
|
presentation: definition.id === "stormwind-stockade" ? definition.presentation : {
|
|
...definition.presentation, ...profile,
|
|
fog: { ...definition.presentation.fog, ...profile.fog },
|
|
},
|
|
...(matchingAssets && matchingNavigation && stairs.ramps.length ? { traversalRamps: stairs.ramps } : {}),
|
|
};
|
|
}
|