using System.Collections.Generic; using UnityEngine; using UnityEditor; using UnityEngine.AI; using Unity.AI.Navigation; public static class LaboratoryLevelGenerator { private const float WALL_HEIGHT = 4.5f; private const float WALL_THICKNESS = 0.35f; // Outer Perimeter: 100m x 100m (-50 to +50 in X and Z) private const float MIN_COORD = -50f; private const float MAX_COORD = 50f; [MenuItem("Tools/Generate Full Laboratory Location")] public static void Generate() { Debug.Log("=== GENERATING EXPANDED COMPLEX LABORATORY LOCATION (100x100m) ==="); // 1. Remove previous Laboratory_Complex or old maze if present var oldLab = GameObject.Find("Laboratory_Complex"); if (oldLab != null) { Undo.DestroyObjectImmediate(oldLab); } var oldMaze = GameObject.Find("Maze"); if (oldMaze != null) { oldMaze.SetActive(false); } // Disable or cleanup old planes for (int i = 0; i <= 6; i++) { string pName = i == 0 ? "Plane" : $"Plane ({i})"; var pl = GameObject.Find(pName); if (pl != null) { pl.SetActive(false); } } // Load assets and materials Material echoMat = AssetDatabase.LoadAssetAtPath("Assets/EchoCloudMat.mat"); if (echoMat == null) { echoMat = AssetDatabase.LoadAssetAtPath("Assets/EchoMat.mat"); } GameObject tablePrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/table with drawers.prefab"); GameObject shelfShowcasePrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/shelf showcase.prefab"); GameObject shelf2Prefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/shelf (2).prefab"); GameObject rackPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/rack.prefab"); GameObject chairPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/chair.prefab"); GameObject pillarPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/pillar.prefab"); GameObject boxPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/Box.prefab"); GameObject beakerPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/Beaker.prefab"); GameObject flaskPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/Erlenmeyer_flask.prefab"); GameObject testTubePrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/Glass_Lab_test_tube.prefab"); GameObject instPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/analytical_lab_instruments.prefab"); GameObject tapPrefab = AssetDatabase.LoadAssetAtPath("Assets/3D Laboratory Environment with Appratus/Prefabs/tap.prefab"); // Root object GameObject labRoot = new GameObject("Laboratory_Complex"); Undo.RegisterCreatedObjectUndo(labRoot, "Create Laboratory_Complex"); GameObject floorsParent = new GameObject("Floors"); floorsParent.transform.SetParent(labRoot.transform); GameObject wallsParent = new GameObject("Walls"); wallsParent.transform.SetParent(labRoot.transform); GameObject roomsParent = new GameObject("Rooms_Props"); roomsParent.transform.SetParent(labRoot.transform); GameObject lightsParent = new GameObject("Atmospheric_Lighting"); lightsParent.transform.SetParent(labRoot.transform); GameObject pickupsParent = new GameObject("Throwable_Distractions"); pickupsParent.transform.SetParent(labRoot.transform); // 2. Build Floor Grid (100m x 100m, from -50 to +50 in X and Z) CreateFloorGrid(floorsParent.transform, echoMat, MIN_COORD, MAX_COORD, MIN_COORD, MAX_COORD); // 3. Build Perimeter Exterior Walls (100m perimeter) CreateWall(wallsParent.transform, echoMat, new Vector3(0, WALL_HEIGHT / 2f, MIN_COORD), new Vector3(100f, WALL_HEIGHT, WALL_THICKNESS), "Wall_Perimeter_South"); CreateWall(wallsParent.transform, echoMat, new Vector3(0, WALL_HEIGHT / 2f, MAX_COORD), new Vector3(100f, WALL_HEIGHT, WALL_THICKNESS), "Wall_Perimeter_North"); CreateWall(wallsParent.transform, echoMat, new Vector3(MIN_COORD, WALL_HEIGHT / 2f, 0), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 100f), "Wall_Perimeter_West"); CreateWall(wallsParent.transform, echoMat, new Vector3(MAX_COORD, WALL_HEIGHT / 2f, 0), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 100f), "Wall_Perimeter_East"); // 4. Build Major Facility Wings & Rooms: // --- SECTOR A: Entrance & Decontamination Airlock (X: -8 to 8, Z: -50 to -38) --- BuildRoomWalls(wallsParent.transform, echoMat, -8f, 8f, -50f, -38f, southDoor: null, northDoor: new Vector2(-2.2f, 2.2f), // Main airlock door to South Concourse westDoor: null, eastDoor: null, roomName: "Decontamination_Airlock"); // --- SECTOR B: Cryogenics & Specimen Archive (Southwest, X: -48 to -26, Z: -48 to -26) --- BuildRoomWalls(wallsParent.transform, echoMat, -48f, -26f, -48f, -26f, southDoor: null, northDoor: new Vector2(-39f, -35f), // to West Mid Lab westDoor: null, eastDoor: new Vector2(-39f, -35f), // to South Concourse roomName: "Cryogenics_Vault"); // --- SECTOR C: High-Security Armory & CCTV (Southeast, X: 26 to 48, Z: -48 to -26) --- BuildRoomWalls(wallsParent.transform, echoMat, 26f, 48f, -48f, -26f, southDoor: null, northDoor: new Vector2(35f, 39f), // to East Mid Medical westDoor: new Vector2(-39f, -35f), // to South Concourse eastDoor: null, roomName: "Security_Armory"); // --- SECTOR D: Biochemistry Research Wing (West Mid, X: -48 to -24, Z: -22 to 2) --- BuildRoomWalls(wallsParent.transform, echoMat, -48f, -24f, -22f, 2f, southDoor: new Vector2(-39f, -35f), // to Cryo corridor northDoor: new Vector2(-39f, -35f), // to Quarantine Wing westDoor: null, eastDoor: new Vector2(-12f, -8f), // to Maintenance Pipe Slalom roomName: "Biochem_Research"); // --- SECTOR E: Surgical Theatre & ICU (East Mid, X: 24 to 48, Z: -22 to 2) --- BuildRoomWalls(wallsParent.transform, echoMat, 24f, 48f, -22f, 2f, southDoor: new Vector2(35f, 39f), // to Armory corridor northDoor: new Vector2(35f, 39f), // to Genetics Lab westDoor: new Vector2(-12f, -8f), // to East Slalom corridor eastDoor: null, roomName: "Surgical_ICU"); // --- SECTOR F: Quarantine Cellblock & Solitary Isolation (TIGHT / LABYRINTH, X: -48 to -22, Z: 6 to 26) --- // Narrow cramped corridors with individual solitary confinement cells BuildRoomWalls(wallsParent.transform, echoMat, -48f, -22f, 6f, 26f, southDoor: new Vector2(-39f, -35f), // from Biochem northDoor: new Vector2(-39f, -35f), // to Chemical Silo westDoor: null, eastDoor: new Vector2(14f, 18f), // to Grand Atrium West Entrance roomName: "Quarantine_Wing"); // --- SECTOR G: Genetics & Cybernetics Laboratory (East North, X: 22 to 48, Z: 6 to 26) --- BuildRoomWalls(wallsParent.transform, echoMat, 22f, 48f, 6f, 26f, southDoor: new Vector2(35f, 39f), // from Surgical northDoor: new Vector2(35f, 39f), // to Substation westDoor: new Vector2(14f, 18f), // to Grand Atrium East Entrance eastDoor: null, roomName: "Genetics_Cybernetics"); // --- SECTOR H: Chemical Silos & Toxic Waste (Northwest, X: -48 to -26, Z: 28 to 48) --- BuildRoomWalls(wallsParent.transform, echoMat, -48f, -26f, 28f, 48f, southDoor: new Vector2(-39f, -35f), // from Quarantine northDoor: new Vector2(-39f, -35f), // to North Maintenance Conduit westDoor: null, eastDoor: new Vector2(36f, 40f), // to Reactor Hall roomName: "Chemical_Silos"); // --- SECTOR I: Auxiliary Power Substation & Battery Banks (Northeast, X: 26 to 48, Z: 28 to 48) --- BuildRoomWalls(wallsParent.transform, echoMat, 26f, 48f, 28f, 48f, southDoor: new Vector2(35f, 39f), // from Genetics northDoor: new Vector2(35f, 39f), // to North Maintenance Conduit westDoor: new Vector2(36f, 40f), // to Reactor Hall eastDoor: null, roomName: "Power_Substation"); // --- SECTOR J: GRAND CENTRAL ATRIUM & BIO-DOME (VERY SPACIOUS! X: -18 to 18, Z: -6 to 24) --- // Huge 36m x 30m open amphitheatre / bio-dome BuildRoomWalls(wallsParent.transform, echoMat, -18f, 18f, -6f, 24f, southDoor: new Vector2(-4f, 4f), // Grand 8m South Portal to Concourse northDoor: new Vector2(-4f, 4f), // Grand 8m North Portal to Reactor Core westDoor: new Vector2(7f, 11f), // West Portal to Maintenance/Quarantine eastDoor: new Vector2(7f, 11f), // East Portal to Medical/Genetics roomName: "Grand_Atrium"); // --- SECTOR K: SUB-REACTOR & TURBINE POWER PLANT (VERY SPACIOUS! X: -22 to 22, Z: 28 to 48) --- // Huge 44m x 20m industrial turbine hall BuildRoomWalls(wallsParent.transform, echoMat, -22f, 22f, 28f, 48f, southDoor: new Vector2(-4f, 4f), // Direct entrance from Atrium northDoor: new Vector2(-2.5f, 2.5f),// Service door to North Maintenance Conduit westDoor: new Vector2(36f, 40f), // to Chemical Silos eastDoor: new Vector2(36f, 40f), // to Power Substation roomName: "Reactor_Turbine_Hall"); // 5. Build Complex Corridors, Tight Crawlways, and Slalom Alley BuildComplexCorridors(wallsParent.transform, echoMat); // 6. Build Quarantine Cellblock Interior (Cramped cells with narrow 1.3m doors) BuildQuarantineCells(wallsParent.transform, echoMat); // 7. Populate Rooms & Halls with Furniture, Machinery, Obstacles and Distractions PopulateAirlock(roomsParent.transform, pillarPrefab, rackPrefab, chairPrefab); PopulateGrandAtrium(roomsParent.transform, pillarPrefab, tablePrefab, instPrefab, boxPrefab, beakerPrefab, pickupsParent.transform); PopulateReactorHall(roomsParent.transform, pillarPrefab, boxPrefab, beakerPrefab, pickupsParent.transform); PopulateSouthConcourse(roomsParent.transform, pillarPrefab, chairPrefab, boxPrefab, pickupsParent.transform); PopulateBiochem(roomsParent.transform, tablePrefab, shelfShowcasePrefab, shelf2Prefab, tapPrefab, instPrefab, beakerPrefab, flaskPrefab, testTubePrefab, pickupsParent.transform); PopulateSurgical(roomsParent.transform, tablePrefab, shelfShowcasePrefab, chairPrefab, beakerPrefab, pickupsParent.transform); PopulateQuarantineProps(roomsParent.transform, boxPrefab, rackPrefab, chairPrefab, beakerPrefab, pickupsParent.transform); PopulateGenetics(roomsParent.transform, tablePrefab, shelfShowcasePrefab, instPrefab, chairPrefab, beakerPrefab, pickupsParent.transform); PopulateCryo(roomsParent.transform, rackPrefab, shelf2Prefab, boxPrefab, beakerPrefab, pickupsParent.transform); PopulateArmory(roomsParent.transform, rackPrefab, tablePrefab, instPrefab, boxPrefab, beakerPrefab, pickupsParent.transform); PopulateChemicalSilos(roomsParent.transform, pillarPrefab, boxPrefab, beakerPrefab, pickupsParent.transform); PopulateSubstation(roomsParent.transform, pillarPrefab, boxPrefab, beakerPrefab, pickupsParent.transform); PopulateSlalomAlleyProps(roomsParent.transform, boxPrefab, rackPrefab); // 8. Atmospheric Lighting setup across all sectors CreateLighting(lightsParent.transform); // 9. Reconfigure Player Position in Starting Airlock GameObject player = GameObject.Find("Player"); if (player == null) player = GameObject.FindWithTag("Player"); if (player == null) player = Object.FindAnyObjectByType()?.gameObject; if (player == null) player = GameObject.Find("Capsule"); if (player != null) { var cc = player.GetComponent(); if (cc != null) cc.enabled = false; player.transform.position = new Vector3(0f, 1.05f, -44f); player.transform.rotation = Quaternion.Euler(0f, 0f, 0f); if (cc != null) cc.enabled = true; Debug.Log("Positioned Player in Starting Airlock (0, 1.05, -44)."); var cam = Camera.main; if (cam != null) { cam.transform.position = new Vector3(0f, 2.5f, -48f); cam.transform.rotation = Quaternion.Euler(12f, 0f, 0f); } } // 10. Reconfigure Enemy (BlindMutantAI) & Comprehensive 32+ Point Patrol Route GameObject enemy = GameObject.Find("enemy"); if (enemy == null) enemy = Object.FindAnyObjectByType()?.gameObject; SetupPatrolWaypoints(labRoot.transform, enemy); // 11. Re-bake NavMesh Surface for entire 100x100m facility var navMeshSurface = Object.FindAnyObjectByType(); if (navMeshSurface != null) { navMeshSurface.transform.position = Vector3.zero; navMeshSurface.collectObjects = CollectObjects.All; navMeshSurface.BuildNavMesh(); Debug.Log("NavMesh successfully baked for the 100x100m complex facility!"); } // Mark scene dirty EditorUtility.SetDirty(labRoot); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); Debug.Log("=== EXPANDED LABORATORY COMPLEX GENERATION COMPLETE! ==="); } private static void CreateFloorGrid(Transform parent, Material mat, float minX, float maxX, float minZ, float maxZ) { // 16 large floor slabs (4x4 grid) for crisp rendering and solid physics int divisions = 4; float stepX = (maxX - minX) / divisions; float stepZ = (maxZ - minZ) / divisions; for (int ix = 0; ix < divisions; ix++) { for (int iz = 0; iz < divisions; iz++) { float x0 = minX + ix * stepX; float x1 = x0 + stepX; float z0 = minZ + iz * stepZ; float z1 = z0 + stepZ; var floorGo = GameObject.CreatePrimitive(PrimitiveType.Cube); floorGo.name = $"Floor_Chunk_{ix}_{iz}"; floorGo.transform.SetParent(parent); floorGo.transform.position = new Vector3((x0 + x1) / 2f, -0.25f, (z0 + z1) / 2f); floorGo.transform.localScale = new Vector3(stepX, 0.5f, stepZ); if (mat != null) floorGo.GetComponent().sharedMaterial = mat; } } } private static void BuildRoomWalls(Transform parent, Material mat, float minX, float maxX, float minZ, float maxZ, Vector2? southDoor, Vector2? northDoor, Vector2? westDoor, Vector2? eastDoor, string roomName) { GameObject roomWalls = new GameObject($"Walls_{roomName}"); roomWalls.transform.SetParent(parent); // South Wall (along X at Z = minZ) CreateWallWithDoor(roomWalls.transform, mat, minX, maxX, minZ, true, southDoor, $"{roomName}_South"); // North Wall (along X at Z = maxZ) CreateWallWithDoor(roomWalls.transform, mat, minX, maxX, maxZ, true, northDoor, $"{roomName}_North"); // West Wall (along Z at X = minX) CreateWallWithDoor(roomWalls.transform, mat, minZ, maxZ, minX, false, westDoor, $"{roomName}_West"); // East Wall (along Z at X = maxX) CreateWallWithDoor(roomWalls.transform, mat, minZ, maxZ, maxX, false, eastDoor, $"{roomName}_East"); } private static void CreateWallWithDoor(Transform parent, Material mat, float startCoord, float endCoord, float fixedCoord, bool isHorizontal, Vector2? doorRange, string wallName) { if (startCoord > endCoord) { float t = startCoord; startCoord = endCoord; endCoord = t; } if (!doorRange.HasValue) { float length = endCoord - startCoord; float mid = (startCoord + endCoord) / 2f; Vector3 pos = isHorizontal ? new Vector3(mid, WALL_HEIGHT / 2f, fixedCoord) : new Vector3(fixedCoord, WALL_HEIGHT / 2f, mid); Vector3 scale = isHorizontal ? new Vector3(length, WALL_HEIGHT, WALL_THICKNESS) : new Vector3(WALL_THICKNESS, WALL_HEIGHT, length); CreateWall(parent, mat, pos, scale, wallName); return; } float dMin = Mathf.Clamp(doorRange.Value.x, startCoord, endCoord); float dMax = Mathf.Clamp(doorRange.Value.y, startCoord, endCoord); // Left / Start section if (dMin > startCoord + 0.2f) { float len1 = dMin - startCoord; float mid1 = (startCoord + dMin) / 2f; Vector3 pos1 = isHorizontal ? new Vector3(mid1, WALL_HEIGHT / 2f, fixedCoord) : new Vector3(fixedCoord, WALL_HEIGHT / 2f, mid1); Vector3 scale1 = isHorizontal ? new Vector3(len1, WALL_HEIGHT, WALL_THICKNESS) : new Vector3(WALL_THICKNESS, WALL_HEIGHT, len1); CreateWall(parent, mat, pos1, scale1, $"{wallName}_PartA"); } // Right / End section if (endCoord > dMax + 0.2f) { float len2 = endCoord - dMax; float mid2 = (dMax + endCoord) / 2f; Vector3 pos2 = isHorizontal ? new Vector3(mid2, WALL_HEIGHT / 2f, fixedCoord) : new Vector3(fixedCoord, WALL_HEIGHT / 2f, mid2); Vector3 scale2 = isHorizontal ? new Vector3(len2, WALL_HEIGHT, WALL_THICKNESS) : new Vector3(WALL_THICKNESS, WALL_HEIGHT, len2); CreateWall(parent, mat, pos2, scale2, $"{wallName}_PartB"); } // Over-door Lintel (bulkhead arch) float doorLen = dMax - dMin; float doorMid = (dMin + dMax) / 2f; float lintelHeight = WALL_HEIGHT - 2.6f; float lintelPosY = 2.6f + (lintelHeight / 2f); Vector3 lintelPos = isHorizontal ? new Vector3(doorMid, lintelPosY, fixedCoord) : new Vector3(fixedCoord, lintelPosY, doorMid); Vector3 lintelScale = isHorizontal ? new Vector3(doorLen, lintelHeight, WALL_THICKNESS) : new Vector3(WALL_THICKNESS, lintelHeight, doorLen); CreateWall(parent, mat, lintelPos, lintelScale, $"{wallName}_Lintel"); } private static GameObject CreateWall(Transform parent, Material mat, Vector3 pos, Vector3 scale, string name) { var wall = GameObject.CreatePrimitive(PrimitiveType.Cube); wall.name = name; wall.transform.SetParent(parent); wall.transform.position = pos; wall.transform.localScale = scale; if (mat != null) wall.GetComponent().sharedMaterial = mat; return wall; } private static void BuildComplexCorridors(Transform parent, Material mat) { GameObject corrGo = new GameObject("Corridors_Complex_Layout"); corrGo.transform.SetParent(parent); // 1. GRAND SOUTH CONCOURSE (Z: -36 to -24, X: -26 to 26) // High, wide passage with central architectural dividers CreateWall(corrGo.transform, mat, new Vector3(-12f, WALL_HEIGHT / 2f, -30f), new Vector3(2.5f, WALL_HEIGHT, 4f), "Concourse_Pillar_West"); CreateWall(corrGo.transform, mat, new Vector3(12f, WALL_HEIGHT / 2f, -30f), new Vector3(2.5f, WALL_HEIGHT, 4f), "Concourse_Pillar_East"); // 2. WEST TIGHT MAINTENANCE SLALOM (CRAMPED / DIFFICULT CHOKEPOINT) // Flanking the Grand Atrium between X: -24 and -18, Z: -22 to 24. // Narrow 1.6m wide corridor with alternating zigzag baffles: CreateWall(corrGo.transform, mat, new Vector3(-20f, WALL_HEIGHT / 2f, -18f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 8f), "Slalom_W_Wall1"); CreateWall(corrGo.transform, mat, new Vector3(-22.5f, WALL_HEIGHT / 2f, -14f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_W_Baffle1"); // forces jog east CreateWall(corrGo.transform, mat, new Vector3(-19.5f, WALL_HEIGHT / 2f, -8f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_W_Baffle2"); // forces jog west CreateWall(corrGo.transform, mat, new Vector3(-22.5f, WALL_HEIGHT / 2f, 0f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_W_Baffle3"); CreateWall(corrGo.transform, mat, new Vector3(-19.5f, WALL_HEIGHT / 2f, 8f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_W_Baffle4"); CreateWall(corrGo.transform, mat, new Vector3(-22.5f, WALL_HEIGHT / 2f, 16f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_W_Baffle5"); // 3. EAST TIGHT CABLE-TRUNK SLALOM (CRAMPED / DIFFICULT CHOKEPOINT) // Flanking the Grand Atrium between X: 18 and 24, Z: -22 to 24. CreateWall(corrGo.transform, mat, new Vector3(20f, WALL_HEIGHT / 2f, -18f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 8f), "Slalom_E_Wall1"); CreateWall(corrGo.transform, mat, new Vector3(22.5f, WALL_HEIGHT / 2f, -14f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_E_Baffle1"); CreateWall(corrGo.transform, mat, new Vector3(19.5f, WALL_HEIGHT / 2f, -8f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_E_Baffle2"); CreateWall(corrGo.transform, mat, new Vector3(22.5f, WALL_HEIGHT / 2f, 0f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_E_Baffle3"); CreateWall(corrGo.transform, mat, new Vector3(19.5f, WALL_HEIGHT / 2f, 8f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_E_Baffle4"); CreateWall(corrGo.transform, mat, new Vector3(22.5f, WALL_HEIGHT / 2f, 16f), new Vector3(3.2f, WALL_HEIGHT, WALL_THICKNESS), "Slalom_E_Baffle5"); // 4. NORTH MAINTENANCE BYPASS CONDUIT (LONG NARROW RUNWAY, Z: 46 to 49) // Spans from X: -48 to +48 along the north perimeter, letting players bypass the loud reactor CreateWallWithDoor(corrGo.transform, mat, -48f, -24f, 46f, true, new Vector2(-39f, -35f), "NorthBypass_WestGuide"); CreateWallWithDoor(corrGo.transform, mat, -20f, 20f, 46f, true, new Vector2(-2.5f, 2.5f), "NorthBypass_MidGuide"); CreateWallWithDoor(corrGo.transform, mat, 24f, 48f, 46f, true, new Vector2(35f, 39f), "NorthBypass_EastGuide"); // Inter-conduit chokepoint baffles CreateWall(corrGo.transform, mat, new Vector3(-12f, WALL_HEIGHT / 2f, 47.5f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 2.5f), "Bypass_Baffle_W"); CreateWall(corrGo.transform, mat, new Vector3(12f, WALL_HEIGHT / 2f, 47.5f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 2.5f), "Bypass_Baffle_E"); } private static void BuildQuarantineCells(Transform parent, Material mat) { // Quarantine Sector is located X: -48 to -22, Z: 6 to 26 // We build a central cell corridor along X = -35 (from Z = 6 to 26) // With 6 individual high-security isolation cubicles GameObject qGo = new GameObject("Quarantine_Cell_Partitions"); qGo.transform.SetParent(parent); // West corridor wall (at X = -37) with doors into cells 1, 2, 3 CreateWallWithDoor(qGo.transform, mat, 6f, 12f, -37f, false, new Vector2(8f, 10f), "Cell_Door_1"); CreateWallWithDoor(qGo.transform, mat, 13f, 19f, -37f, false, new Vector2(15f, 17f), "Cell_Door_2"); CreateWallWithDoor(qGo.transform, mat, 20f, 26f, -37f, false, new Vector2(22f, 24f), "Cell_Door_3"); // Cell dividers on West side (Z = 12.5 and Z = 19.5, X from -48 to -37) CreateWall(qGo.transform, mat, new Vector3(-42.5f, WALL_HEIGHT / 2f, 12.5f), new Vector3(11f, WALL_HEIGHT, WALL_THICKNESS), "Cell_Divider_W1"); CreateWall(qGo.transform, mat, new Vector3(-42.5f, WALL_HEIGHT / 2f, 19.5f), new Vector3(11f, WALL_HEIGHT, WALL_THICKNESS), "Cell_Divider_W2"); // East corridor wall (at X = -33) with doors into cells 4, 5, 6 CreateWallWithDoor(qGo.transform, mat, 6f, 12f, -33f, false, new Vector2(8f, 10f), "Cell_Door_4"); CreateWallWithDoor(qGo.transform, mat, 13f, 19f, -33f, false, new Vector2(15f, 17f), "Cell_Door_5"); CreateWallWithDoor(qGo.transform, mat, 20f, 26f, -33f, false, new Vector2(22f, 24f), "Cell_Door_6"); // Cell dividers on East side (Z = 12.5 and Z = 19.5, X from -33 to -22) CreateWall(qGo.transform, mat, new Vector3(-27.5f, WALL_HEIGHT / 2f, 12.5f), new Vector3(11f, WALL_HEIGHT, WALL_THICKNESS), "Cell_Divider_E1"); CreateWall(qGo.transform, mat, new Vector3(-27.5f, WALL_HEIGHT / 2f, 19.5f), new Vector3(11f, WALL_HEIGHT, WALL_THICKNESS), "Cell_Divider_E2"); } private static void PopulateAirlock(Transform parent, GameObject pillarPrefab, GameObject rackPrefab, GameObject chairPrefab) { GameObject room = new GameObject("Airlock_Props"); room.transform.SetParent(parent); // Decon arch frames SpawnProp(pillarPrefab, room.transform, new Vector3(-3f, 0f, -42f), Quaternion.identity); SpawnProp(pillarPrefab, room.transform, new Vector3(3f, 0f, -42f), Quaternion.identity); // Lockers and benches SpawnProp(rackPrefab, room.transform, new Vector3(-6.5f, 0f, -46f), Quaternion.Euler(0f, 90f, 0f)); SpawnProp(rackPrefab, room.transform, new Vector3(-6.5f, 0f, -44f), Quaternion.Euler(0f, 90f, 0f)); SpawnProp(chairPrefab, room.transform, new Vector3(6.5f, 0f, -46f), Quaternion.Euler(0f, -90f, 0f)); SpawnProp(chairPrefab, room.transform, new Vector3(6.5f, 0f, -44f), Quaternion.Euler(0f, -90f, 0f)); } private static void PopulateGrandAtrium(Transform parent, GameObject pillarPrefab, GameObject tablePrefab, GameObject instPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("GrandAtrium_Props"); room.transform.SetParent(parent); // 8 Grand architectural colonnades ringing the open 36x30m atrium Vector3[] pillarPos = new Vector3[] { new Vector3(-12f, 0f, 0f), new Vector3(-12f, 0f, 18f), new Vector3(12f, 0f, 0f), new Vector3(12f, 0f, 18f), new Vector3(-6f, 0f, -3f), new Vector3(6f, 0f, -3f), new Vector3(-6f, 0f, 21f), new Vector3(6f, 0f, 21f) }; foreach (var pos in pillarPos) { SpawnProp(pillarPrefab, room.transform, pos, Quaternion.identity); } // Massive Central Mutant Observation Specimen Vat (Radius 4.5m) var coreCylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder); coreCylinder.name = "Grand_Mutant_Cryo_Vat"; coreCylinder.transform.SetParent(room.transform); coreCylinder.transform.position = new Vector3(0f, 2.25f, 9f); coreCylinder.transform.localScale = new Vector3(7f, 2.25f, 7f); // Observation Control Desks SpawnProp(tablePrefab, room.transform, new Vector3(-5f, 0f, 4f), Quaternion.Euler(0f, 45f, 0f)); SpawnProp(instPrefab, room.transform, new Vector3(-5f, 1.07f, 4f), Quaternion.Euler(0f, 45f, 0f)); SpawnProp(tablePrefab, room.transform, new Vector3(5f, 0f, 4f), Quaternion.Euler(0f, -45f, 0f)); SpawnProp(instPrefab, room.transform, new Vector3(5f, 1.07f, 4f), Quaternion.Euler(0f, -45f, 0f)); // Cover Crates around perimeter SpawnProp(boxPrefab, room.transform, new Vector3(-14f, 0f, 9f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(-14f, 1.08f, 9f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(14f, 0f, 9f), Quaternion.identity); // Distraction Throwables in Grand Atrium SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-4.8f, 1.15f, 4.2f), "Throwable_Beaker_Atrium_W"); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(4.8f, 1.15f, 4.2f), "Throwable_Beaker_Atrium_E"); } private static void PopulateReactorHall(Transform parent, GameObject pillarPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("ReactorHall_Props"); room.transform.SetParent(parent); // Two massive industrial reactor turbine housings var turbine1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder); turbine1.name = "Reactor_Turbine_Alpha"; turbine1.transform.SetParent(room.transform); turbine1.transform.position = new Vector3(-10f, 2.5f, 38f); turbine1.transform.localScale = new Vector3(6f, 2.5f, 6f); var turbine2 = GameObject.CreatePrimitive(PrimitiveType.Cylinder); turbine2.name = "Reactor_Turbine_Beta"; turbine2.transform.SetParent(room.transform); turbine2.transform.position = new Vector3(10f, 2.5f, 38f); turbine2.transform.localScale = new Vector3(6f, 2.5f, 6f); // High Voltage Pillars SpawnProp(pillarPrefab, room.transform, new Vector3(-18f, 0f, 32f), Quaternion.identity); SpawnProp(pillarPrefab, room.transform, new Vector3(-18f, 0f, 44f), Quaternion.identity); SpawnProp(pillarPrefab, room.transform, new Vector3(18f, 0f, 32f), Quaternion.identity); SpawnProp(pillarPrefab, room.transform, new Vector3(18f, 0f, 44f), Quaternion.identity); // Stacks of heavy shielded crates for stealth cover SpawnProp(boxPrefab, room.transform, new Vector3(0f, 0f, 34f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(0f, 1.08f, 34f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(0f, 0f, 42f), Quaternion.identity); // Throwable Beaker SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(0f, 1.15f, 34f), "Throwable_Beaker_Reactor_Core"); } private static void PopulateSouthConcourse(Transform parent, GameObject pillarPrefab, GameObject chairPrefab, GameObject boxPrefab, Transform pickupsParent) { GameObject concourse = new GameObject("SouthConcourse_Props"); concourse.transform.SetParent(parent); // Architectural rest benches SpawnProp(chairPrefab, concourse.transform, new Vector3(-6f, 0f, -32f), Quaternion.identity); SpawnProp(chairPrefab, concourse.transform, new Vector3(6f, 0f, -32f), Quaternion.identity); SpawnProp(chairPrefab, concourse.transform, new Vector3(-18f, 0f, -32f), Quaternion.identity); SpawnProp(chairPrefab, concourse.transform, new Vector3(18f, 0f, -32f), Quaternion.identity); // Crates for cover SpawnProp(boxPrefab, concourse.transform, new Vector3(-8f, 0f, -28f), Quaternion.identity); SpawnProp(boxPrefab, concourse.transform, new Vector3(8f, 0f, -28f), Quaternion.identity); } private static void PopulateBiochem(Transform parent, GameObject tablePrefab, GameObject showcasePrefab, GameObject shelfPrefab, GameObject tapPrefab, GameObject instPrefab, GameObject beakerPrefab, GameObject flaskPrefab, GameObject tubePrefab, Transform pickupsParent) { GameObject room = new GameObject("BiochemLab_Props"); room.transform.SetParent(parent); // Lab Island 1 SpawnProp(tablePrefab, room.transform, new Vector3(-40f, 0f, -14f), Quaternion.identity); SpawnProp(tablePrefab, room.transform, new Vector3(-36f, 0f, -14f), Quaternion.identity); SpawnProp(instPrefab, room.transform, new Vector3(-40f, 1.07f, -14f), Quaternion.identity); SpawnProp(tapPrefab, room.transform, new Vector3(-36f, 1.07f, -14f), Quaternion.identity); // Lab Island 2 SpawnProp(tablePrefab, room.transform, new Vector3(-40f, 0f, -6f), Quaternion.identity); SpawnProp(tablePrefab, room.transform, new Vector3(-36f, 0f, -6f), Quaternion.identity); SpawnProp(tubePrefab, room.transform, new Vector3(-39.5f, 1.07f, -6f), Quaternion.identity); SpawnProp(flaskPrefab, room.transform, new Vector3(-36.5f, 1.07f, -6f), Quaternion.identity); // Shelves SpawnProp(showcasePrefab, room.transform, new Vector3(-46f, 0f, -18f), Quaternion.Euler(0f, 90f, 0f)); SpawnProp(showcasePrefab, room.transform, new Vector3(-46f, 0f, -2f), Quaternion.Euler(0f, 90f, 0f)); // Throwables SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-35.5f, 1.15f, -14f), "Throwable_Beaker_Biochem1"); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-40.5f, 1.15f, -6f), "Throwable_Beaker_Biochem2"); } private static void PopulateSurgical(Transform parent, GameObject tablePrefab, GameObject showcasePrefab, GameObject chairPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("Surgical_Props"); room.transform.SetParent(parent); // Operating Tables SpawnProp(tablePrefab, room.transform, new Vector3(34f, 0f, -14f), Quaternion.identity); SpawnProp(tablePrefab, room.transform, new Vector3(40f, 0f, -14f), Quaternion.identity); SpawnProp(tablePrefab, room.transform, new Vector3(37f, 0f, -6f), Quaternion.identity); // Chairs SpawnProp(chairPrefab, room.transform, new Vector3(34f, 0f, -12.5f), Quaternion.Euler(0f, 180f, 0f)); SpawnProp(chairPrefab, room.transform, new Vector3(40f, 0f, -12.5f), Quaternion.Euler(0f, 180f, 0f)); // Medical Cabinets SpawnProp(showcasePrefab, room.transform, new Vector3(46f, 0f, -10f), Quaternion.Euler(0f, -90f, 0f)); // Throwable SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(37f, 1.15f, -6f), "Throwable_Beaker_Surgical"); } private static void PopulateQuarantineProps(Transform parent, GameObject boxPrefab, GameObject rackPrefab, GameObject chairPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("Quarantine_Props"); room.transform.SetParent(parent); // Clutter in cells (broken chairs, overturned cots, boxes) SpawnProp(chairPrefab, room.transform, new Vector3(-43f, 0f, 9f), Quaternion.Euler(0f, 45f, 0f)); SpawnProp(boxPrefab, room.transform, new Vector3(-44f, 0f, 16f), Quaternion.Euler(0f, 25f, 0f)); SpawnProp(boxPrefab, room.transform, new Vector3(-27f, 0f, 9f), Quaternion.identity); SpawnProp(rackPrefab, room.transform, new Vector3(-26f, 0f, 23f), Quaternion.Euler(0f, 90f, 0f)); // Distraction beaker hidden in isolation cell SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-43f, 0.5f, 23f), "Throwable_Beaker_Quarantine"); } private static void PopulateGenetics(Transform parent, GameObject tablePrefab, GameObject showcasePrefab, GameObject instPrefab, GameObject chairPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("Genetics_Props"); room.transform.SetParent(parent); SpawnProp(tablePrefab, room.transform, new Vector3(34f, 0f, 14f), Quaternion.identity); SpawnProp(instPrefab, room.transform, new Vector3(34f, 1.07f, 14f), Quaternion.identity); SpawnProp(tablePrefab, room.transform, new Vector3(40f, 0f, 14f), Quaternion.identity); SpawnProp(instPrefab, room.transform, new Vector3(40f, 1.07f, 14f), Quaternion.identity); SpawnProp(showcasePrefab, room.transform, new Vector3(46f, 0f, 18f), Quaternion.Euler(0f, -90f, 0f)); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(40f, 1.15f, 14f), "Throwable_Beaker_Genetics"); } private static void PopulateCryo(Transform parent, GameObject rackPrefab, GameObject shelfPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("Cryo_Props"); room.transform.SetParent(parent); // Aisles of cryogenic specimen racks for (int i = 0; i < 3; i++) { float x = -44f + i * 6f; SpawnProp(rackPrefab, room.transform, new Vector3(x, 0f, -44f), Quaternion.identity); SpawnProp(rackPrefab, room.transform, new Vector3(x, 0f, -38f), Quaternion.identity); SpawnProp(rackPrefab, room.transform, new Vector3(x, 0f, -32f), Quaternion.identity); } SpawnProp(boxPrefab, room.transform, new Vector3(-29f, 0f, -30f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(-29f, 1.08f, -30f), Quaternion.identity); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-38f, 1.15f, -38f), "Throwable_Beaker_Cryo"); } private static void PopulateArmory(Transform parent, GameObject rackPrefab, GameObject tablePrefab, GameObject instPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("Armory_Props"); room.transform.SetParent(parent); SpawnProp(tablePrefab, room.transform, new Vector3(36f, 0f, -35f), Quaternion.identity); SpawnProp(instPrefab, room.transform, new Vector3(36f, 1.07f, -35f), Quaternion.identity); SpawnProp(rackPrefab, room.transform, new Vector3(44f, 0f, -44f), Quaternion.identity); SpawnProp(rackPrefab, room.transform, new Vector3(44f, 0f, -38f), Quaternion.identity); SpawnProp(rackPrefab, room.transform, new Vector3(44f, 0f, -32f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(30f, 0f, -30f), Quaternion.identity); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(36f, 1.15f, -35f), "Throwable_Beaker_Armory"); } private static void PopulateChemicalSilos(Transform parent, GameObject pillarPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("ChemicalSilos_Props"); room.transform.SetParent(parent); var silo1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder); silo1.name = "Toxic_Silo_Alpha"; silo1.transform.SetParent(room.transform); silo1.transform.position = new Vector3(-37f, 2.5f, 38f); silo1.transform.localScale = new Vector3(5.5f, 2.5f, 5.5f); SpawnProp(boxPrefab, room.transform, new Vector3(-44f, 0f, 32f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(-44f, 1.08f, 32f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(-30f, 0f, 44f), Quaternion.identity); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-44f, 1.15f, 32f), "Throwable_Beaker_Silo"); } private static void PopulateSubstation(Transform parent, GameObject pillarPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent) { GameObject room = new GameObject("Substation_Props"); room.transform.SetParent(parent); var cap1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder); cap1.name = "Substation_Transformer"; cap1.transform.SetParent(room.transform); cap1.transform.position = new Vector3(37f, 2.5f, 38f); cap1.transform.localScale = new Vector3(5.5f, 2.5f, 5.5f); SpawnProp(boxPrefab, room.transform, new Vector3(44f, 0f, 32f), Quaternion.identity); SpawnProp(boxPrefab, room.transform, new Vector3(30f, 0f, 44f), Quaternion.identity); SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(44f, 1.15f, 32f), "Throwable_Beaker_Substation"); } private static void PopulateSlalomAlleyProps(Transform parent, GameObject boxPrefab, GameObject rackPrefab) { GameObject props = new GameObject("Slalom_Chokepoint_Props"); props.transform.SetParent(parent); // Obstacles placed right at the slalom bends to tighten passage SpawnProp(boxPrefab, props.transform, new Vector3(-21f, 0f, -11f), Quaternion.Euler(0f, 45f, 0f)); SpawnProp(boxPrefab, props.transform, new Vector3(-21f, 0f, 5f), Quaternion.Euler(0f, 25f, 0f)); SpawnProp(rackPrefab, props.transform, new Vector3(21f, 0f, -11f), Quaternion.Euler(0f, 90f, 0f)); SpawnProp(rackPrefab, props.transform, new Vector3(21f, 0f, 5f), Quaternion.Euler(0f, 90f, 0f)); } private static void SpawnProp(GameObject prefab, Transform parent, Vector3 pos, Quaternion rot) { if (prefab == null) return; GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, parent); if (instance != null) { instance.transform.position = pos; instance.transform.rotation = rot; } } private static void SpawnThrowableBeaker(GameObject beakerPrefab, Transform parent, Vector3 pos, string name) { GameObject beaker; if (beakerPrefab != null) { beaker = (GameObject)PrefabUtility.InstantiatePrefab(beakerPrefab, parent); } else { beaker = GameObject.CreatePrimitive(PrimitiveType.Cylinder); beaker.transform.localScale = new Vector3(0.3f, 0.5f, 0.3f); } beaker.name = name; beaker.transform.position = pos; var col = beaker.GetComponent(); if (col == null) { col = beaker.AddComponent(); } var rb = beaker.GetComponent(); if (rb == null) { rb = beaker.AddComponent(); } rb.mass = 1.0f; rb.collisionDetectionMode = CollisionDetectionMode.Continuous; var wave = beaker.GetComponent(); if (wave == null) { wave = beaker.AddComponent(); } wave.soundRadius = 22f; wave.minImpactForce = 1.5f; var pulsePrefab = AssetDatabase.LoadAssetAtPath("Assets/EchoPulse.prefab"); if (pulsePrefab != null) { wave.wavePrefab = pulsePrefab; } } private static void CreateLighting(Transform parent) { // Entrance Airlock - Warning Red CreatePointLight(parent, "Light_Decon_Red", new Vector3(0f, 3.8f, -44f), new Color(1f, 0.2f, 0.15f), 2.5f, 14f); // Grand South Concourse - Warm Bronze CreatePointLight(parent, "Light_Concourse_Mid", new Vector3(0f, 4f, -30f), new Color(1f, 0.75f, 0.4f), 2.2f, 20f); CreatePointLight(parent, "Light_Concourse_West", new Vector3(-18f, 4f, -30f), new Color(1f, 0.75f, 0.4f), 1.8f, 18f); CreatePointLight(parent, "Light_Concourse_East", new Vector3(18f, 4f, -30f), new Color(1f, 0.75f, 0.4f), 1.8f, 18f); // Grand Central Atrium - Bio-Luminescent Emerald & Cyan CreatePointLight(parent, "Light_Atrium_Core", new Vector3(0f, 4.2f, 9f), new Color(0.15f, 1f, 0.8f), 3.5f, 32f); CreatePointLight(parent, "Light_Atrium_South", new Vector3(0f, 4.2f, 0f), new Color(0.2f, 0.9f, 0.8f), 2.0f, 22f); CreatePointLight(parent, "Light_Atrium_North", new Vector3(0f, 4.2f, 18f), new Color(0.2f, 0.9f, 0.8f), 2.0f, 22f); // Sub-Reactor Hall - Warning Amber & Industrial High-Voltage CreatePointLight(parent, "Light_Reactor_Turbine_W", new Vector3(-10f, 4.2f, 38f), new Color(1f, 0.55f, 0.1f), 3.0f, 26f); CreatePointLight(parent, "Light_Reactor_Turbine_E", new Vector3(10f, 4.2f, 38f), new Color(1f, 0.55f, 0.1f), 3.0f, 26f); CreatePointLight(parent, "Light_Reactor_Core", new Vector3(0f, 4.2f, 38f), new Color(0.3f, 0.85f, 1f), 2.5f, 24f); // Quarantine Wing - Claustrophobic Flickering Crimson CreatePointLight(parent, "Light_Quarantine_1", new Vector3(-35f, 3.8f, 9f), new Color(1f, 0.1f, 0.1f), 2.0f, 16f); CreatePointLight(parent, "Light_Quarantine_2", new Vector3(-35f, 3.8f, 23f), new Color(1f, 0.1f, 0.1f), 2.0f, 16f); // Biochem Lab - Toxic Mint Green CreatePointLight(parent, "Light_Biochem", new Vector3(-37f, 3.8f, -10f), new Color(0.3f, 0.95f, 0.5f), 2.2f, 22f); // Surgical ICU - Cold Clinical White CreatePointLight(parent, "Light_Surgical", new Vector3(37f, 3.8f, -10f), new Color(0.85f, 0.95f, 1f), 2.2f, 22f); // Genetics Lab - Electric Violet CreatePointLight(parent, "Light_Genetics", new Vector3(37f, 3.8f, 16f), new Color(0.6f, 0.35f, 1f), 2.0f, 22f); // Cryo Vault - Deep Glacier Cyan CreatePointLight(parent, "Light_Cryo", new Vector3(-37f, 3.8f, -37f), new Color(0.2f, 0.65f, 1f), 2.0f, 22f); // Armory - Surveillance Amber CreatePointLight(parent, "Light_Armory", new Vector3(37f, 3.8f, -37f), new Color(1f, 0.65f, 0.2f), 2.0f, 22f); // Silos & Substation CreatePointLight(parent, "Light_Silos", new Vector3(-37f, 3.8f, 38f), new Color(0.8f, 0.9f, 0.2f), 2.0f, 22f); CreatePointLight(parent, "Light_Substation", new Vector3(37f, 3.8f, 38f), new Color(0.4f, 0.7f, 1f), 2.0f, 22f); // North Bypass Runways CreatePointLight(parent, "Light_Bypass_W", new Vector3(-25f, 3.2f, 47.5f), new Color(1f, 0.7f, 0.3f), 1.4f, 14f); CreatePointLight(parent, "Light_Bypass_Mid", new Vector3(0f, 3.2f, 47.5f), new Color(1f, 0.7f, 0.3f), 1.4f, 14f); CreatePointLight(parent, "Light_Bypass_E", new Vector3(25f, 3.2f, 47.5f), new Color(1f, 0.7f, 0.3f), 1.4f, 14f); } private static void CreatePointLight(Transform parent, string name, Vector3 pos, Color color, float intensity, float range) { GameObject lightGo = new GameObject(name); lightGo.transform.SetParent(parent); lightGo.transform.position = pos; var light = lightGo.AddComponent(); light.type = LightType.Point; light.color = color; light.intensity = intensity; light.range = range; light.shadows = LightShadows.Soft; } private static void SetupPatrolWaypoints(Transform parent, GameObject enemy) { var oldPatrol = GameObject.Find("PatrolWaypoints"); if (oldPatrol != null) { Undo.DestroyObjectImmediate(oldPatrol); } // Clean any old 1..15 in scene for (int i = 0; i <= 20; i++) { string oldName = i == 0 ? "1" : $"1 ({i})"; var oldGo = GameObject.Find(oldName); if (oldGo != null) { oldGo.SetActive(false); } } GameObject patrolParent = new GameObject("PatrolWaypoints"); patrolParent.transform.SetParent(parent); // 32 Waypoints looping smoothly through ALL wings and sectors of the 100x100m facility! Vector3[] waypoints = new Vector3[] { // South Concourse & Cryo new Vector3(0f, 0f, -30f), // WP0: Concourse Center new Vector3(-18f, 0f, -30f), // WP1: Concourse West new Vector3(-37f, 0f, -37f), // WP2: Cryogenics Vault new Vector3(-37f, 0f, -24f), // WP3: Cryo North Gate // Biochem & West Slalom new Vector3(-37f, 0f, -14f), // WP4: Biochem Lab South new Vector3(-37f, 0f, -4f), // WP5: Biochem Lab North new Vector3(-21f, 0f, -4f), // WP6: West Slalom Entry new Vector3(-21f, 0f, 6f), // WP7: West Slalom Mid // Quarantine Cellblock (Labyrinth) new Vector3(-35f, 0f, 8f), // WP8: Quarantine Cell Corridor South new Vector3(-43f, 0f, 9f), // WP9: Isolation Cell 1 new Vector3(-35f, 0f, 16f), // WP10: Quarantine Cell Corridor Mid new Vector3(-27f, 0f, 16f), // WP11: Isolation Cell 5 new Vector3(-35f, 0f, 23f), // WP12: Quarantine Cell Corridor North // Chemical Silos & North Bypass new Vector3(-37f, 0f, 38f), // WP13: Chemical Silos new Vector3(-37f, 0f, 47.5f), // WP14: North Bypass West new Vector3(-15f, 0f, 47.5f), // WP15: North Bypass Mid-West // Reactor Turbine Hall (Very Spacious) new Vector3(-10f, 0f, 38f), // WP16: Reactor Turbine Alpha new Vector3(0f, 0f, 38f), // WP17: Reactor Core Platform new Vector3(10f, 0f, 38f), // WP18: Reactor Turbine Beta // Substation & East North Bypass new Vector3(25f, 0f, 47.5f), // WP19: North Bypass East new Vector3(37f, 0f, 38f), // WP20: Power Substation // Genetics & Cybernetics new Vector3(37f, 0f, 22f), // WP21: Genetics Lab North new Vector3(37f, 0f, 10f), // WP22: Genetics Lab South // Grand Atrium (Very Spacious) new Vector3(12f, 0f, 9f), // WP23: Grand Atrium East Colonnade new Vector3(0f, 0f, 18f), // WP24: Grand Atrium North Observation new Vector3(-12f, 0f, 9f), // WP25: Grand Atrium West Colonnade new Vector3(0f, 0f, 0f), // WP26: Grand Atrium South Portal // East Slalom & Surgical ICU new Vector3(21f, 0f, 0f), // WP27: East Slalom Corridor new Vector3(37f, 0f, -4f), // WP28: Surgical ICU North new Vector3(37f, 0f, -14f), // WP29: Surgical ICU South // Security Armory & Return to Concourse new Vector3(37f, 0f, -37f), // WP30: Security Armory new Vector3(18f, 0f, -30f) // WP31: Concourse East }; Transform[] transforms = new Transform[waypoints.Length]; for (int i = 0; i < waypoints.Length; i++) { var wpGo = new GameObject($"Waypoint_{i}"); wpGo.transform.SetParent(patrolParent.transform); wpGo.transform.position = waypoints[i]; transforms[i] = wpGo.transform; } if (enemy != null) { // Position enemy in South Concourse right outside the starting airlock enemy.transform.position = new Vector3(0f, 0.08f, -28f); enemy.transform.rotation = Quaternion.Euler(0f, 90f, 0f); var ai = enemy.GetComponent(); if (ai != null) { Undo.RecordObject(ai, "Setup Patrol Points"); ai.patrolPoints = transforms; EditorUtility.SetDirty(ai); EditorUtility.SetDirty(enemy); Debug.Log($"Configured {transforms.Length} patrol points for SkinnyOrc BlindMutantAI in South Concourse (0, 0.08, -28)!"); } } } }