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>; 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>; 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>; readonly equipment: readonly unknown[]; readonly animations: Readonly>>; 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[]; }