299 lines
11 KiB
TypeScript
299 lines
11 KiB
TypeScript
import type {
|
|
MobPackDefinition,
|
|
MobVector3,
|
|
PopulationDefinitionMap,
|
|
StaticMobSpawnDefinition,
|
|
} from "./mobPopulation";
|
|
import type { DungeonEncounterDefinition } from "./dungeonEncounterTypes";
|
|
import type { DungeonWorldObjectDefinition } from "./dungeonWorldObjects";
|
|
|
|
export type Vector3Tuple = MobVector3;
|
|
export type DungeonEnvironmentMode = "global-wmo" | "adt-hybrid" | "runewaker-ros";
|
|
export type DungeonExpansion = "classic" | "burning-crusade" | "wrath" | "runewaker";
|
|
export type DungeonAvailability = "available" | "blocked" | "disabled";
|
|
export type DungeonDifficulty = "normal" | "heroic";
|
|
|
|
export const DUNGEON_SOURCE_RECIPE_SCHEMA_VERSION = 1;
|
|
export const DUNGEON_DEFINITION_SCHEMA_VERSION = 1;
|
|
export const CREATURE_ASSET_SCHEMA_VERSION = 1;
|
|
export const DUNGEON_PACK_SCHEMA_VERSION = 1;
|
|
|
|
export interface DungeonDifficultyVariant {
|
|
readonly id: string;
|
|
readonly difficulty: DungeonDifficulty;
|
|
readonly mapDifficultyId?: number;
|
|
readonly spawnMask: number;
|
|
readonly levelRange: readonly [minimum: number, maximum: number];
|
|
}
|
|
|
|
export interface DungeonSourceRecipe {
|
|
readonly schemaVersion: typeof DUNGEON_SOURCE_RECIPE_SCHEMA_VERSION;
|
|
readonly slug: string;
|
|
readonly title: string;
|
|
readonly mapId: number;
|
|
readonly lfgDungeonIds: readonly number[];
|
|
readonly expansion: DungeonExpansion;
|
|
readonly clientBuild: "3.3.5a" | "3.3.5a-Ascension" | "3.3.5a-Epoch";
|
|
readonly mapDirectory: string;
|
|
readonly environmentMode: DungeonEnvironmentMode | "detect";
|
|
readonly difficultyVariants: readonly DungeonDifficultyVariant[];
|
|
readonly clientSource: {
|
|
readonly rootEnvironmentVariable: "WOW_CLIENT_ROOT" | "EPOCH_CLIENT_ROOT";
|
|
readonly relativeDefault: string;
|
|
};
|
|
readonly serverSource: {
|
|
readonly rootEnvironmentVariable: "WOW_SERVER_DATA";
|
|
readonly adapter: "normalized-json" | "trinity-sql";
|
|
readonly readOnly: true;
|
|
};
|
|
readonly extraction: {
|
|
readonly rootWmo?: string;
|
|
readonly doodadSets?: readonly string[];
|
|
readonly adtTiles?: readonly string[] | "all-present";
|
|
};
|
|
/** Reviewed WC fixture input; later recipes receive these records from server/display discovery. */
|
|
readonly creatures?: readonly DungeonCreatureSource[];
|
|
readonly review: {
|
|
readonly entrance: "required" | "approved";
|
|
readonly bossOrder: "required" | "approved";
|
|
readonly optionalEncounters: "required" | "approved";
|
|
readonly presentation: "required" | "approved";
|
|
readonly offMeshLinks: "required" | "approved";
|
|
};
|
|
readonly exceptions: readonly string[];
|
|
}
|
|
|
|
export interface DungeonCreatureEquipmentSource {
|
|
readonly name: string;
|
|
readonly attachmentId: number;
|
|
readonly modelPath: string;
|
|
readonly skinTextures?: readonly string[];
|
|
readonly displayInfoId?: number;
|
|
readonly displayModelIndex?: number;
|
|
}
|
|
|
|
export interface DungeonCreatureSource {
|
|
readonly slug: string;
|
|
readonly name: string;
|
|
readonly entry: number;
|
|
readonly displayId: number;
|
|
readonly displayScale: number;
|
|
readonly rigType: "m2" | "character-composite";
|
|
readonly modelPath: string;
|
|
readonly skinTextures?: readonly string[];
|
|
readonly bakedTexture?: string;
|
|
readonly hairTexture?: string;
|
|
readonly textureOverrides?: Readonly<Record<string, string>>;
|
|
readonly geosets?: readonly (readonly [number, number])[];
|
|
readonly equipment?: readonly DungeonCreatureEquipmentSource[];
|
|
readonly animationIds?: readonly number[] | "all-source-clips";
|
|
readonly spellcaster?: boolean;
|
|
readonly fallbackExceptions?: readonly string[];
|
|
}
|
|
|
|
export interface DungeonAssetChunk {
|
|
readonly id: string;
|
|
readonly fileName: string;
|
|
/** Root-relative public asset URL for generated/shared environment packages. */
|
|
readonly url?: string;
|
|
readonly checksum?: string;
|
|
readonly size?: number;
|
|
readonly triangleCount?: number;
|
|
}
|
|
|
|
export interface DungeonEnvironmentAssets {
|
|
readonly visual: readonly DungeonAssetChunk[];
|
|
readonly collision: readonly DungeonAssetChunk[];
|
|
readonly navigation?: DungeonAssetChunk;
|
|
readonly minimap?: string;
|
|
readonly editableSource?: string;
|
|
}
|
|
|
|
export interface DungeonTransform {
|
|
readonly position: Vector3Tuple;
|
|
readonly rotation: Vector3Tuple;
|
|
readonly scale: number;
|
|
readonly fromWow?: "three(x,y,z)=(-wow.x,wow.z,wow.y)";
|
|
readonly fromRunewaker?: string;
|
|
}
|
|
|
|
export interface WorldSpawn {
|
|
readonly footPosition: Vector3Tuple;
|
|
readonly yaw: number;
|
|
}
|
|
|
|
export interface DungeonEntrance extends WorldSpawn {
|
|
readonly name: string;
|
|
readonly forward: Vector3Tuple;
|
|
}
|
|
|
|
export interface DungeonBounds {
|
|
readonly min: Vector3Tuple;
|
|
readonly max: Vector3Tuple;
|
|
}
|
|
|
|
export interface DungeonAreaCheckpoint {
|
|
readonly id: string;
|
|
readonly name: string;
|
|
readonly center: Vector3Tuple;
|
|
readonly radius: number;
|
|
}
|
|
|
|
export interface DungeonBossObjective {
|
|
readonly id: string;
|
|
readonly name: string;
|
|
readonly position: Vector3Tuple;
|
|
readonly optional?: boolean;
|
|
/** Spawned by an encounter state machine rather than the static population. */
|
|
readonly eventOnly?: boolean;
|
|
}
|
|
|
|
export interface DungeonNavigationLink {
|
|
readonly id: string;
|
|
readonly start: Vector3Tuple;
|
|
readonly end: Vector3Tuple;
|
|
readonly bidirectional: boolean;
|
|
readonly authoredReason: string;
|
|
}
|
|
|
|
/** Reviewed package-space walking proxy; the rendered staircase is unchanged. */
|
|
export interface DungeonTraversalRamp {
|
|
readonly id: string;
|
|
readonly start: Vector3Tuple;
|
|
readonly end: Vector3Tuple;
|
|
readonly width: number;
|
|
readonly navigationBridge: {
|
|
readonly linkId: string;
|
|
readonly startPortal: readonly [Vector3Tuple, Vector3Tuple];
|
|
readonly endPortal: readonly [Vector3Tuple, Vector3Tuple];
|
|
};
|
|
}
|
|
|
|
export interface DungeonEncounterSpawnGroupDefinition {
|
|
readonly id: string;
|
|
readonly spawns: readonly StaticMobSpawnDefinition[];
|
|
}
|
|
|
|
export interface DungeonMapPresentation {
|
|
readonly width: number;
|
|
readonly height: number;
|
|
readonly padding: number;
|
|
readonly contours: readonly string[];
|
|
}
|
|
|
|
export interface DungeonMaterialRoles {
|
|
readonly cutoutPatterns: readonly string[];
|
|
readonly cutoutNames: readonly string[];
|
|
readonly blendPatterns: readonly string[];
|
|
readonly blendNames: readonly string[];
|
|
readonly additivePatterns: readonly string[];
|
|
readonly additiveNames: readonly string[];
|
|
}
|
|
|
|
export interface DungeonPresentation {
|
|
readonly location: string;
|
|
readonly theme: string;
|
|
readonly summary: string;
|
|
readonly loadingMessage: string;
|
|
readonly unchartedAreaName: string;
|
|
readonly background: string;
|
|
readonly fog: { readonly color: string; readonly near: number; readonly far: number };
|
|
readonly ambientLight: { readonly color: string; readonly intensity: number };
|
|
readonly hemisphereLight: {
|
|
readonly skyColor: string;
|
|
readonly groundColor: string;
|
|
readonly intensity: number;
|
|
};
|
|
readonly directionalLight: { readonly color: string; readonly intensity: number; readonly offset: Vector3Tuple };
|
|
readonly materials: DungeonMaterialRoles;
|
|
readonly map: DungeonMapPresentation;
|
|
}
|
|
|
|
export interface DungeonSourceProvenance {
|
|
readonly clientBuild: string;
|
|
readonly coordinateAlignment?: "player-anchor" | "source" | "source-transform";
|
|
readonly clientArchiveHashes: Readonly<Record<string, string>>;
|
|
readonly databaseAdapter: string;
|
|
readonly databaseRevision?: string;
|
|
readonly sourceSnapshot?: string;
|
|
/** Auditable source-to-package basis; global WMO and ADT clients use different mappings. */
|
|
readonly coordinateTransform: string;
|
|
}
|
|
|
|
export interface DungeonValidationStatus {
|
|
readonly status: "green" | "blocked" | "unvalidated";
|
|
/** Navigation-only review state; permits routing without overstating encounter validation. */
|
|
readonly navigation?: "green" | "blocked" | "unvalidated";
|
|
readonly report?: string;
|
|
readonly validatedAt?: string;
|
|
readonly blockers: readonly string[];
|
|
readonly warnings: readonly string[];
|
|
}
|
|
|
|
export interface DungeonDefinition {
|
|
readonly schemaVersion: typeof DUNGEON_DEFINITION_SCHEMA_VERSION;
|
|
readonly id: string;
|
|
readonly title: string;
|
|
readonly mapId: number;
|
|
readonly lfgDungeonIds: readonly number[];
|
|
readonly expansion: DungeonExpansion;
|
|
readonly environmentMode: DungeonEnvironmentMode;
|
|
readonly difficultyVariants: readonly DungeonDifficultyVariant[];
|
|
readonly defaultDifficultyId: string;
|
|
readonly availability: DungeonAvailability;
|
|
readonly availabilityReason?: string;
|
|
readonly presentation: DungeonPresentation;
|
|
readonly assets: DungeonEnvironmentAssets;
|
|
readonly transform: DungeonTransform;
|
|
readonly bounds: DungeonBounds;
|
|
readonly entrance: DungeonEntrance;
|
|
readonly areas: readonly DungeonAreaCheckpoint[];
|
|
readonly entities: PopulationDefinitionMap;
|
|
readonly staticSpawns: readonly StaticMobSpawnDefinition[];
|
|
readonly roamingPacks: readonly MobPackDefinition[];
|
|
readonly bosses: readonly DungeonBossObjective[];
|
|
readonly objectiveOrder: readonly DungeonBossObjective[];
|
|
readonly navigationLinks: readonly DungeonNavigationLink[];
|
|
readonly traversalRamps?: readonly DungeonTraversalRamp[];
|
|
/** Serializable dungeon-wide orchestration kept separate from render state. */
|
|
readonly encounters?: readonly DungeonEncounterDefinition[];
|
|
/** Declarative groups activated by encounter actions; renderer ownership stays outside the reducer. */
|
|
readonly encounterSpawnGroups?: readonly DungeonEncounterSpawnGroupDefinition[];
|
|
readonly serverGameObjects: readonly DungeonWorldObjectDefinition[];
|
|
readonly provenance: DungeonSourceProvenance;
|
|
readonly validation: DungeonValidationStatus;
|
|
}
|
|
|
|
export type SemanticAnimation = "stand" | "walk" | "run" | "attack" | "cast" | "hit" | "death";
|
|
|
|
export interface CreatureAssetDefinition {
|
|
readonly schemaVersion: typeof CREATURE_ASSET_SCHEMA_VERSION;
|
|
readonly id: string;
|
|
readonly displayId: number;
|
|
readonly compositeRecipeHash?: string;
|
|
readonly sourceM2: string;
|
|
readonly sourceTextures: readonly string[];
|
|
readonly rigType: "m2" | "character-composite";
|
|
readonly bounds: DungeonBounds;
|
|
readonly scale: number;
|
|
readonly groundOffset: number;
|
|
readonly facing: { readonly axis: "+x" | "+z"; readonly runtimeRotationY: number };
|
|
readonly materialRoles: Readonly<Record<string, "opaque" | "cutout" | "blend" | "additive">>;
|
|
readonly equipment: readonly unknown[];
|
|
readonly animations: Readonly<Partial<Record<SemanticAnimation, string>>>;
|
|
readonly fallbackExceptions: readonly string[];
|
|
readonly assetUrl: string;
|
|
readonly checksum: string;
|
|
readonly size: number;
|
|
}
|
|
|
|
export interface DungeonPackManifest {
|
|
readonly schemaVersion: typeof DUNGEON_PACK_SCHEMA_VERSION;
|
|
readonly dungeonId: string;
|
|
readonly definitionChecksum: string;
|
|
readonly generatedAt: string;
|
|
readonly assets: readonly DungeonAssetChunk[];
|
|
readonly creatureDependencies: readonly string[];
|
|
readonly reports: readonly string[];
|
|
}
|