788 lines
42 KiB
C#
788 lines
42 KiB
C#
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.25f;
|
|
private const float WALL_THICKNESS = 0.35f;
|
|
|
|
[MenuItem("Tools/Generate Full Laboratory Location")]
|
|
public static void Generate()
|
|
{
|
|
Debug.Log("<color=cyan>=== GENERATING LABORATORY LOCATION ===</color>");
|
|
|
|
// 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 <= 4; 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<Material>("Assets/EchoCloudMat.mat");
|
|
if (echoMat == null)
|
|
{
|
|
echoMat = AssetDatabase.LoadAssetAtPath<Material>("Assets/EchoMat.mat");
|
|
}
|
|
|
|
Material woodMat = AssetDatabase.LoadAssetAtPath<Material>("Assets/3D Laboratory Environment with Appratus/Materials/Laboratory03_Wood_BaseMap.mat");
|
|
Material otherMat = AssetDatabase.LoadAssetAtPath<Material>("Assets/3D Laboratory Environment with Appratus/Materials/Laboratory03_Others_BaseMap.mat");
|
|
Material glassMat = AssetDatabase.LoadAssetAtPath<Material>("Assets/3D Laboratory Environment with Appratus/Materials/Laboratory03_Glass_BaseMap 1.mat");
|
|
|
|
GameObject tablePrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/table with drawers.prefab");
|
|
GameObject shelfShowcasePrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/shelf showcase.prefab");
|
|
GameObject shelf2Prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/shelf (2).prefab");
|
|
GameObject rackPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/rack.prefab");
|
|
GameObject chairPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/chair.prefab");
|
|
GameObject pillarPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/pillar.prefab");
|
|
GameObject boxPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/Box.prefab");
|
|
GameObject beakerPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/Beaker.prefab");
|
|
GameObject flaskPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/Erlenmeyer_flask.prefab");
|
|
GameObject testTubePrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/Glass_Lab_test_tube.prefab");
|
|
GameObject instPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/3D Laboratory Environment with Appratus/Prefabs/analytical_lab_instruments.prefab");
|
|
GameObject tapPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("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 (64m x 64m, from -32 to +32 in X and Z)
|
|
CreateFloorGrid(floorsParent.transform, echoMat, -32f, 32f, -32f, 32f);
|
|
|
|
// 3. Build Perimeter Exterior Walls
|
|
CreateWall(wallsParent.transform, echoMat, new Vector3(0, WALL_HEIGHT / 2f, -32f), new Vector3(64f, WALL_HEIGHT, WALL_THICKNESS), "Wall_Perimeter_South");
|
|
CreateWall(wallsParent.transform, echoMat, new Vector3(0, WALL_HEIGHT / 2f, 32f), new Vector3(64f, WALL_HEIGHT, WALL_THICKNESS), "Wall_Perimeter_North");
|
|
CreateWall(wallsParent.transform, echoMat, new Vector3(-32f, WALL_HEIGHT / 2f, 0), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 64f), "Wall_Perimeter_West");
|
|
CreateWall(wallsParent.transform, echoMat, new Vector3(32f, WALL_HEIGHT / 2f, 0), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 64f), "Wall_Perimeter_East");
|
|
|
|
// 4. Build Rooms Walls with Doorways
|
|
// We define rooms as bounding boxes [minX, maxX, minZ, maxZ] and doors on specific sides with cutout [doorMin, doorMax]
|
|
// Room 1: Entrance / Decontamination (X: -6 to +6, Z: -32 to -22)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, -6f, 6f, -32f, -22f,
|
|
southDoor: null, // sealed
|
|
northDoor: new Vector2(-1.8f, 1.8f),
|
|
westDoor: null,
|
|
eastDoor: null,
|
|
roomName: "Decontamination");
|
|
|
|
// Room 4: Cryo Archive (X: -30 to -14, Z: -32 to -20)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, -30f, -14f, -32f, -20f,
|
|
southDoor: null,
|
|
northDoor: new Vector2(-24f, -20f),
|
|
westDoor: null,
|
|
eastDoor: new Vector2(-27f, -23f),
|
|
roomName: "CryoArchive");
|
|
|
|
// Room 8: Security & Surveillance (X: 14 to 30, Z: -32 to -20)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, 14f, 30f, -32f, -20f,
|
|
southDoor: null,
|
|
northDoor: new Vector2(20f, 24f),
|
|
westDoor: new Vector2(-27f, -23f),
|
|
eastDoor: null,
|
|
roomName: "SecurityOffice");
|
|
|
|
// Room 2: Biochemistry Research Lab (X: -30 to -14, Z: -14 to 2)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, -30f, -14f, -14f, 2f,
|
|
southDoor: new Vector2(-24f, -20f),
|
|
northDoor: new Vector2(-24f, -20f),
|
|
westDoor: null,
|
|
eastDoor: new Vector2(-8f, -4f),
|
|
roomName: "BiochemLab");
|
|
|
|
// Room 6: Surgical Theatre & Medical Bay (X: 14 to 30, Z: -14 to 2)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, 14f, 30f, -14f, 2f,
|
|
southDoor: new Vector2(20f, 24f),
|
|
northDoor: new Vector2(20f, 24f),
|
|
westDoor: new Vector2(-8f, -4f),
|
|
eastDoor: null,
|
|
roomName: "SurgicalBay");
|
|
|
|
// Room 3: Bio-Hazard Containment Vault (X: -30 to -12, Z: 8 to 26)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, -30f, -12f, 8f, 26f,
|
|
southDoor: new Vector2(-23f, -19f),
|
|
northDoor: new Vector2(-23f, -19f), // leads to North Maintenance bypass
|
|
westDoor: null,
|
|
eastDoor: new Vector2(15f, 19f),
|
|
roomName: "BioContainment");
|
|
|
|
// Room 5: Central Bio-Dome & Core Reactor (X: -7 to 7, Z: 8 to 26)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, -7f, 7f, 8f, 26f,
|
|
southDoor: new Vector2(-2f, 2f),
|
|
northDoor: new Vector2(-2f, 2f), // leads to North Maintenance bypass
|
|
westDoor: new Vector2(15f, 19f),
|
|
eastDoor: new Vector2(15f, 19f),
|
|
roomName: "CentralCore");
|
|
|
|
// Room 7: Genetics Sequencing Lab (X: 12 to 30, Z: 6 to 18)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, 12f, 30f, 6f, 18f,
|
|
southDoor: new Vector2(19f, 23f),
|
|
northDoor: new Vector2(19f, 23f),
|
|
westDoor: new Vector2(10f, 14f),
|
|
eastDoor: null,
|
|
roomName: "GeneticsLab");
|
|
|
|
// Room 9: Generator Substation (X: 12 to 30, Z: 20 to 30)
|
|
BuildRoomWalls(wallsParent.transform, echoMat, 12f, 30f, 20f, 30f,
|
|
southDoor: new Vector2(19f, 23f),
|
|
northDoor: null,
|
|
westDoor: new Vector2(23f, 27f), // leads to North Maintenance bypass
|
|
eastDoor: null,
|
|
roomName: "GeneratorRoom");
|
|
|
|
// 5. Build Tangled Corridor Internal Walls & Partitions (Maze structure)
|
|
BuildCorridorMaze(wallsParent.transform, echoMat);
|
|
|
|
// 6. Populate Rooms with Furniture & Props
|
|
PopulateDecontamination(roomsParent.transform, pillarPrefab, rackPrefab, chairPrefab, echoMat);
|
|
PopulateBiochemLab(roomsParent.transform, tablePrefab, shelfShowcasePrefab, shelf2Prefab, tapPrefab, instPrefab, beakerPrefab, flaskPrefab, testTubePrefab, pickupsParent.transform);
|
|
PopulateBioContainment(roomsParent.transform, pillarPrefab, tablePrefab, boxPrefab, beakerPrefab, instPrefab, pickupsParent.transform);
|
|
PopulateCryoArchive(roomsParent.transform, rackPrefab, shelf2Prefab, boxPrefab, beakerPrefab, pickupsParent.transform);
|
|
PopulateCentralCore(roomsParent.transform, pillarPrefab, tablePrefab, instPrefab, boxPrefab, beakerPrefab, pickupsParent.transform);
|
|
PopulateSurgicalBay(roomsParent.transform, tablePrefab, shelfShowcasePrefab, chairPrefab, beakerPrefab, pickupsParent.transform);
|
|
PopulateGeneticsLab(roomsParent.transform, tablePrefab, shelfShowcasePrefab, instPrefab, chairPrefab, beakerPrefab, pickupsParent.transform);
|
|
PopulateGeneratorRoom(roomsParent.transform, pillarPrefab, boxPrefab, beakerPrefab, pickupsParent.transform);
|
|
PopulateCorridorNiches(roomsParent.transform, pillarPrefab, boxPrefab, rackPrefab);
|
|
|
|
// 7. Atmospheric Lighting setup
|
|
CreateLighting(lightsParent.transform);
|
|
|
|
// 8. Reconfigure Player Position
|
|
var player = GameObject.Find("Capsule");
|
|
if (player != null)
|
|
{
|
|
player.transform.position = new Vector3(0f, 1.05f, -28f);
|
|
player.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
|
|
Debug.Log("Moved Player to Entrance Airlock (0, 1.05, -28)");
|
|
}
|
|
|
|
// 9. Reconfigure Enemy (BlindMutantAI) & Patrol Waypoints
|
|
var enemy = GameObject.Find("enemy");
|
|
SetupPatrolWaypoints(labRoot.transform, enemy);
|
|
|
|
// 10. Re-bake NavMesh Surface
|
|
var navMeshSurface = Object.FindAnyObjectByType<NavMeshSurface>();
|
|
if (navMeshSurface != null)
|
|
{
|
|
navMeshSurface.transform.position = Vector3.zero;
|
|
navMeshSurface.collectObjects = CollectObjects.All;
|
|
navMeshSurface.BuildNavMesh();
|
|
Debug.Log("<color=green>NavMesh successfully baked for the entire laboratory complex!</color>");
|
|
}
|
|
|
|
// Mark scene dirty
|
|
EditorUtility.SetDirty(labRoot);
|
|
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene());
|
|
Debug.Log("<color=green>=== LABORATORY COMPLEX GENERATION COMPLETE! ===</color>");
|
|
}
|
|
|
|
private static void CreateFloorGrid(Transform parent, Material mat, float minX, float maxX, float minZ, float maxZ)
|
|
{
|
|
// 4 large floor quadrants for clean rendering and collision
|
|
float midX = (minX + maxX) / 2f;
|
|
float midZ = (minZ + maxZ) / 2f;
|
|
float sizeX = (maxX - minX) / 2f;
|
|
float sizeZ = (maxZ - minZ) / 2f;
|
|
|
|
Vector2[] quads = new Vector2[]
|
|
{
|
|
new Vector2((minX + midX) / 2f, (minZ + midZ) / 2f),
|
|
new Vector2((midX + maxX) / 2f, (minZ + midZ) / 2f),
|
|
new Vector2((minX + midX) / 2f, (midZ + maxZ) / 2f),
|
|
new Vector2((midX + maxX) / 2f, (midZ + maxZ) / 2f)
|
|
};
|
|
|
|
for (int i = 0; i < quads.Length; i++)
|
|
{
|
|
var floorGo = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
floorGo.name = $"Floor_Quadrant_{i + 1}";
|
|
floorGo.transform.SetParent(parent);
|
|
floorGo.transform.position = new Vector3(quads[i].x, -0.25f, quads[i].y);
|
|
floorGo.transform.localScale = new Vector3(sizeX, 0.5f, sizeZ);
|
|
if (mat != null) floorGo.GetComponent<Renderer>().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)
|
|
{
|
|
// Full solid wall
|
|
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.5f;
|
|
float lintelPosY = 2.5f + (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<Renderer>().sharedMaterial = mat;
|
|
return wall;
|
|
}
|
|
|
|
private static void BuildCorridorMaze(Transform parent, Material mat)
|
|
{
|
|
GameObject mazeGo = new GameObject("Tangled_Corridors_Maze");
|
|
mazeGo.transform.SetParent(parent);
|
|
|
|
// 1. Central Core Elevator Shaft / Ventilation Pillar divider (splits Central Hallway into two paths)
|
|
// Position: X: -3 to +3, Z: -6 to 2
|
|
CreateWall(mazeGo.transform, mat, new Vector3(0f, WALL_HEIGHT / 2f, -2f), new Vector3(5f, WALL_HEIGHT, 6f), "Central_Ventilation_Core");
|
|
|
|
// 2. West Serpentine Hallway Dividers (creating zig-zags between X: -14 and -6)
|
|
// Horizontal baffle at Z = -17 (X from -14 to -9)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(-11.5f, WALL_HEIGHT / 2f, -17f), new Vector3(5f, WALL_HEIGHT, WALL_THICKNESS), "Baffle_West_1");
|
|
// Vertical wall at X = -9 (Z from -17 to -12) with opening
|
|
CreateWall(mazeGo.transform, mat, new Vector3(-9f, WALL_HEIGHT / 2f, -14.5f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 5f), "Baffle_West_2");
|
|
// Horizontal baffle at Z = -11 (X from -11 to -7)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(-9f, WALL_HEIGHT / 2f, -11f), new Vector3(4f, WALL_HEIGHT, WALL_THICKNESS), "Baffle_West_3");
|
|
// Vertical wall at X = -10 (Z from -4 to 3)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(-10f, WALL_HEIGHT / 2f, -0.5f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 7f), "Baffle_West_4");
|
|
// Alcove cover at X = -7 (Z = 5)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(-8.5f, WALL_HEIGHT / 2f, 5f), new Vector3(3f, WALL_HEIGHT, WALL_THICKNESS), "Baffle_West_Alcove");
|
|
|
|
// 3. East Serpentine Hallway Dividers (creating zig-zags between X: +6 and +14)
|
|
// Horizontal baffle at Z = -17 (X from 9 to 14)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(11.5f, WALL_HEIGHT / 2f, -17f), new Vector3(5f, WALL_HEIGHT, WALL_THICKNESS), "Baffle_East_1");
|
|
// Vertical wall at X = 9 (Z from -17 to -12)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(9f, WALL_HEIGHT / 2f, -14.5f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 5f), "Baffle_East_2");
|
|
// Horizontal baffle at Z = -11 (X from 7 to 11)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(9f, WALL_HEIGHT / 2f, -11f), new Vector3(4f, WALL_HEIGHT, WALL_THICKNESS), "Baffle_East_3");
|
|
// Vertical wall at X = 10 (Z from -4 to 3)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(10f, WALL_HEIGHT / 2f, -0.5f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 7f), "Baffle_East_4");
|
|
// Alcove cover at X = 7 (Z = 5)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(8.5f, WALL_HEIGHT / 2f, 5f), new Vector3(3f, WALL_HEIGHT, WALL_THICKNESS), "Baffle_East_Alcove");
|
|
|
|
// 4. North Maintenance Crawlway / Bypass (Long narrow bypass at Z: 28 to 31, spanning X: -27 to +27)
|
|
// Southern guide wall of the crawlway:
|
|
// Section A (X: -30 to -9 at Z = 28.5) with door into BioContainment at X: -21
|
|
CreateWallWithDoor(mazeGo.transform, mat, -30f, -9f, 28.5f, true, new Vector2(-23f, -19f), "NorthCrawl_WestGuide");
|
|
// Section B (X: -5 to +5 at Z = 28.5) behind Central Core with center access door
|
|
CreateWallWithDoor(mazeGo.transform, mat, -7f, 7f, 28.5f, true, new Vector2(-2f, 2f), "NorthCrawl_MidGuide");
|
|
// Section C (X: 9 to 30 at Z = 28.5) leading to Generator room with door at X: 21
|
|
CreateWallWithDoor(mazeGo.transform, mat, 9f, 30f, 28.5f, true, new Vector2(19f, 23f), "NorthCrawl_EastGuide");
|
|
|
|
// 5. South Crossroads Corridor Dividers (between Decontamination and Wings)
|
|
// Partition at X = -6, Z = -18 (creating blind corner from Decon to Cryo)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(-6f, WALL_HEIGHT / 2f, -18f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 4f), "Crossroad_West_Corner");
|
|
// Partition at X = +6, Z = -18 (creating blind corner from Decon to Security)
|
|
CreateWall(mazeGo.transform, mat, new Vector3(6f, WALL_HEIGHT / 2f, -18f), new Vector3(WALL_THICKNESS, WALL_HEIGHT, 4f), "Crossroad_East_Corner");
|
|
}
|
|
|
|
private static void PopulateDecontamination(Transform parent, GameObject pillarPrefab, GameObject rackPrefab, GameObject chairPrefab, Material echoMat)
|
|
{
|
|
GameObject room = new GameObject("Decontamination_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// Decontamination Frame (two pillars with lintel)
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-2f, 0f, -25f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(2f, 0f, -25f), Quaternion.identity);
|
|
|
|
// Lockers / Racks along West wall
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-4.8f, 0f, -29f), Quaternion.Euler(0f, 90f, 0f));
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-4.8f, 0f, -27f), Quaternion.Euler(0f, 90f, 0f));
|
|
|
|
// Benches along East wall
|
|
SpawnProp(chairPrefab, room.transform, new Vector3(4.5f, 0f, -29f), Quaternion.Euler(0f, -90f, 0f));
|
|
SpawnProp(chairPrefab, room.transform, new Vector3(4.5f, 0f, -27f), Quaternion.Euler(0f, -90f, 0f));
|
|
}
|
|
|
|
private static void PopulateBiochemLab(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);
|
|
|
|
// Central Lab Island 1
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(-24f, 0f, -8f), Quaternion.identity);
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(-20f, 0f, -8f), Quaternion.identity);
|
|
SpawnProp(instPrefab, room.transform, new Vector3(-24f, 1.07f, -8f), Quaternion.identity);
|
|
SpawnProp(tapPrefab, room.transform, new Vector3(-20f, 1.07f, -8f), Quaternion.identity);
|
|
|
|
// Central Lab Island 2
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(-24f, 0f, -4f), Quaternion.identity);
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(-20f, 0f, -4f), Quaternion.identity);
|
|
SpawnProp(tubePrefab, room.transform, new Vector3(-23.5f, 1.07f, -4f), Quaternion.identity);
|
|
SpawnProp(flaskPrefab, room.transform, new Vector3(-20.5f, 1.07f, -4f), Quaternion.identity);
|
|
|
|
// Shelves along West Wall
|
|
SpawnProp(showcasePrefab, room.transform, new Vector3(-29f, 0f, -10f), Quaternion.Euler(0f, 90f, 0f));
|
|
SpawnProp(showcasePrefab, room.transform, new Vector3(-29f, 0f, -2f), Quaternion.Euler(0f, 90f, 0f));
|
|
SpawnProp(shelfPrefab, room.transform, new Vector3(-29f, 0f, -6f), Quaternion.Euler(0f, 90f, 0f));
|
|
|
|
// Throwable Beaker distraction on bench
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-19.5f, 1.15f, -8f), "Throwable_Beaker_Biochem1");
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-24.5f, 1.15f, -4f), "Throwable_Beaker_Biochem2");
|
|
}
|
|
|
|
private static void PopulateBioContainment(Transform parent, GameObject pillarPrefab, GameObject tablePrefab, GameObject boxPrefab,
|
|
GameObject beakerPrefab, GameObject instPrefab, Transform pickupsParent)
|
|
{
|
|
GameObject room = new GameObject("BioContainment_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// 4 massive containment corner pillars
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-26f, 0f, 12f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-15f, 0f, 12f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-26f, 0f, 22f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-15f, 0f, 22f), Quaternion.identity);
|
|
|
|
// Broken containment center vat/chamber
|
|
var vatBase = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
|
vatBase.name = "Containment_Vat_Broken";
|
|
vatBase.transform.SetParent(room.transform);
|
|
vatBase.transform.position = new Vector3(-20.5f, 1.5f, 17f);
|
|
vatBase.transform.localScale = new Vector3(3.5f, 1.5f, 3.5f);
|
|
|
|
// Observation console desk
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(-20.5f, 0f, 10.5f), Quaternion.identity);
|
|
SpawnProp(instPrefab, room.transform, new Vector3(-20.5f, 1.07f, 10.5f), Quaternion.identity);
|
|
|
|
// Overturned boxes and cover
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-24f, 0f, 15f), Quaternion.Euler(0f, 35f, 0f));
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-24f, 0f, 16.5f), Quaternion.Euler(0f, 15f, 0f));
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-16f, 0f, 20f), Quaternion.Euler(0f, 60f, 0f));
|
|
|
|
// Throwable distraction beaker
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-20f, 1.15f, 10.5f), "Throwable_Beaker_Containment");
|
|
}
|
|
|
|
private static void PopulateCryoArchive(Transform parent, GameObject rackPrefab, GameObject shelfPrefab, GameObject boxPrefab,
|
|
GameObject beakerPrefab, Transform pickupsParent)
|
|
{
|
|
GameObject room = new GameObject("CryoArchive_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// Rows of storage racks creating narrow aisles
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-26f, 0f, -28f), Quaternion.identity);
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-26f, 0f, -24f), Quaternion.identity);
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-21f, 0f, -28f), Quaternion.identity);
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-21f, 0f, -24f), Quaternion.identity);
|
|
SpawnProp(rackPrefab, room.transform, new Vector3(-16f, 0f, -28f), Quaternion.identity);
|
|
|
|
// Storage boxes stacked for cover
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-28.5f, 0f, -22f), Quaternion.identity);
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-28.5f, 1.08f, -22f), Quaternion.identity);
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-17f, 0f, -22f), Quaternion.identity);
|
|
|
|
// Shelves along back wall
|
|
SpawnProp(shelfPrefab, room.transform, new Vector3(-23f, 0f, -31f), Quaternion.identity);
|
|
|
|
// Throwable distraction beaker in storage
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-26f, 1.15f, -28f), "Throwable_Beaker_Cryo");
|
|
}
|
|
|
|
private static void PopulateCentralCore(Transform parent, GameObject pillarPrefab, GameObject tablePrefab, GameObject instPrefab,
|
|
GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent)
|
|
{
|
|
GameObject room = new GameObject("CentralCore_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// 4 massive observation pillars
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-5.5f, 0f, 10.5f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(5.5f, 0f, 10.5f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(-5.5f, 0f, 23.5f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(5.5f, 0f, 23.5f), Quaternion.identity);
|
|
|
|
// Central Specimen Reactor Vat
|
|
var coreCylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
|
coreCylinder.name = "Central_Mutant_Reactor_Core";
|
|
coreCylinder.transform.SetParent(room.transform);
|
|
coreCylinder.transform.position = new Vector3(0f, 2.0f, 17f);
|
|
coreCylinder.transform.localScale = new Vector3(4.5f, 2.0f, 4.5f);
|
|
|
|
// Observation console desks
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(-3f, 0f, 13f), Quaternion.Euler(0f, 45f, 0f));
|
|
SpawnProp(instPrefab, room.transform, new Vector3(-3f, 1.07f, 13f), Quaternion.Euler(0f, 45f, 0f));
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(3f, 0f, 13f), Quaternion.Euler(0f, -45f, 0f));
|
|
SpawnProp(instPrefab, room.transform, new Vector3(3f, 1.07f, 13f), Quaternion.Euler(0f, -45f, 0f));
|
|
|
|
// Cover crates in corners
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(-5.5f, 0f, 17f), Quaternion.identity);
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(5.5f, 0f, 17f), Quaternion.identity);
|
|
|
|
// Throwable distraction beaker on console
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(-2.8f, 1.15f, 13.2f), "Throwable_Beaker_Core");
|
|
}
|
|
|
|
private static void PopulateSurgicalBay(Transform parent, GameObject tablePrefab, GameObject showcasePrefab, GameObject chairPrefab,
|
|
GameObject beakerPrefab, Transform pickupsParent)
|
|
{
|
|
GameObject room = new GameObject("SurgicalBay_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// Dual operating / dissection tables
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(18f, 0f, -6f), Quaternion.identity);
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(24f, 0f, -6f), Quaternion.identity);
|
|
|
|
// Surgeon stools
|
|
SpawnProp(chairPrefab, room.transform, new Vector3(18f, 0f, -4.5f), Quaternion.Euler(0f, 180f, 0f));
|
|
SpawnProp(chairPrefab, room.transform, new Vector3(24f, 0f, -4.5f), Quaternion.Euler(0f, 180f, 0f));
|
|
|
|
// Medical supply showcases along East Wall
|
|
SpawnProp(showcasePrefab, room.transform, new Vector3(29f, 0f, -10f), Quaternion.Euler(0f, -90f, 0f));
|
|
SpawnProp(showcasePrefab, room.transform, new Vector3(29f, 0f, -2f), Quaternion.Euler(0f, -90f, 0f));
|
|
|
|
// Throwable beaker
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(23.5f, 1.15f, -6f), "Throwable_Beaker_Surgery");
|
|
}
|
|
|
|
private static void PopulateGeneticsLab(Transform parent, GameObject tablePrefab, GameObject showcasePrefab, GameObject instPrefab,
|
|
GameObject chairPrefab, GameObject beakerPrefab, Transform pickupsParent)
|
|
{
|
|
GameObject room = new GameObject("GeneticsLab_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// Genetic sequencer workstations
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(18f, 0f, 12f), Quaternion.identity);
|
|
SpawnProp(instPrefab, room.transform, new Vector3(18f, 1.07f, 12f), Quaternion.identity);
|
|
SpawnProp(chairPrefab, room.transform, new Vector3(18f, 0f, 10.5f), Quaternion.identity);
|
|
|
|
SpawnProp(tablePrefab, room.transform, new Vector3(24f, 0f, 12f), Quaternion.identity);
|
|
SpawnProp(instPrefab, room.transform, new Vector3(24f, 1.07f, 12f), Quaternion.identity);
|
|
SpawnProp(chairPrefab, room.transform, new Vector3(24f, 0f, 10.5f), Quaternion.identity);
|
|
|
|
// Showcases along East Wall
|
|
SpawnProp(showcasePrefab, room.transform, new Vector3(29f, 0f, 12f), Quaternion.Euler(0f, -90f, 0f));
|
|
|
|
// Throwable beaker
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(24.5f, 1.15f, 12f), "Throwable_Beaker_Genetics");
|
|
}
|
|
|
|
private static void PopulateGeneratorRoom(Transform parent, GameObject pillarPrefab, GameObject boxPrefab, GameObject beakerPrefab, Transform pickupsParent)
|
|
{
|
|
GameObject room = new GameObject("GeneratorRoom_Props");
|
|
room.transform.SetParent(parent);
|
|
|
|
// 2 Massive Transformer Generator Blocks
|
|
var gen1 = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
gen1.name = "Generator_Core_1";
|
|
gen1.transform.SetParent(room.transform);
|
|
gen1.transform.position = new Vector3(18f, 2.0f, 25f);
|
|
gen1.transform.localScale = new Vector3(3f, 4f, 4f);
|
|
|
|
var gen2 = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
gen2.name = "Generator_Core_2";
|
|
gen2.transform.SetParent(room.transform);
|
|
gen2.transform.position = new Vector3(25f, 2.0f, 25f);
|
|
gen2.transform.localScale = new Vector3(3f, 4f, 4f);
|
|
|
|
// Support pillars
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(14f, 0f, 28f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, room.transform, new Vector3(28f, 0f, 28f), Quaternion.identity);
|
|
|
|
// Power supply crates
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(21.5f, 0f, 27.5f), Quaternion.identity);
|
|
SpawnProp(boxPrefab, room.transform, new Vector3(21.5f, 1.08f, 27.5f), Quaternion.identity);
|
|
|
|
// Throwable distraction
|
|
SpawnThrowableBeaker(beakerPrefab, pickupsParent, new Vector3(21.5f, 1.15f, 22f), "Throwable_Beaker_Generator");
|
|
}
|
|
|
|
private static void PopulateCorridorNiches(Transform parent, GameObject pillarPrefab, GameObject boxPrefab, GameObject rackPrefab)
|
|
{
|
|
GameObject niches = new GameObject("Corridor_Niches_Cover");
|
|
niches.transform.SetParent(parent);
|
|
|
|
// South Concourse pillars & crates
|
|
SpawnProp(pillarPrefab, niches.transform, new Vector3(-3f, 0f, -18f), Quaternion.identity);
|
|
SpawnProp(pillarPrefab, niches.transform, new Vector3(3f, 0f, -18f), Quaternion.identity);
|
|
SpawnProp(boxPrefab, niches.transform, new Vector3(0f, 0f, -17f), Quaternion.identity);
|
|
|
|
// West corridor alcove hiding spot
|
|
SpawnProp(boxPrefab, niches.transform, new Vector3(-8.5f, 0f, 6.5f), Quaternion.identity);
|
|
SpawnProp(rackPrefab, niches.transform, new Vector3(-8.5f, 0f, -12.5f), Quaternion.Euler(0f, 90f, 0f));
|
|
|
|
// East corridor alcove hiding spot
|
|
SpawnProp(boxPrefab, niches.transform, new Vector3(8.5f, 0f, 6.5f), Quaternion.identity);
|
|
SpawnProp(rackPrefab, niches.transform, new Vector3(8.5f, 0f, -12.5f), Quaternion.Euler(0f, -90f, 0f));
|
|
|
|
// North Crawlway mid-point cover
|
|
SpawnProp(boxPrefab, niches.transform, new Vector3(-8f, 0f, 30f), Quaternion.identity);
|
|
SpawnProp(boxPrefab, niches.transform, new Vector3(8f, 0f, 30f), Quaternion.identity);
|
|
}
|
|
|
|
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;
|
|
|
|
// Ensure collider
|
|
var col = beaker.GetComponent<Collider>();
|
|
if (col == null)
|
|
{
|
|
col = beaker.AddComponent<CapsuleCollider>();
|
|
}
|
|
|
|
// Rigidbody for throwing physics
|
|
var rb = beaker.GetComponent<Rigidbody>();
|
|
if (rb == null)
|
|
{
|
|
rb = beaker.AddComponent<Rigidbody>();
|
|
}
|
|
rb.mass = 1.0f;
|
|
rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
|
|
|
|
// ImpactWave component so it triggers echolocation wave and mutant alert when landing!
|
|
var wave = beaker.GetComponent<ImpactWave>();
|
|
if (wave == null)
|
|
{
|
|
wave = beaker.AddComponent<ImpactWave>();
|
|
}
|
|
wave.soundRadius = 18f;
|
|
wave.minImpactForce = 1.5f;
|
|
|
|
// Load EchoPulse prefab if available
|
|
var pulsePrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/EchoPulse.prefab");
|
|
if (pulsePrefab != null)
|
|
{
|
|
wave.wavePrefab = pulsePrefab;
|
|
}
|
|
}
|
|
|
|
private static void CreateLighting(Transform parent)
|
|
{
|
|
// Entrance Airlock - Warning Red emergency light
|
|
CreatePointLight(parent, "Light_Decon_Red", new Vector3(0f, 3.8f, -27f), new Color(1f, 0.2f, 0.15f), 2.5f, 12f);
|
|
|
|
// South Concourse - Dim Amber light
|
|
CreatePointLight(parent, "Light_SouthConcourse", new Vector3(0f, 3.8f, -18f), new Color(1f, 0.75f, 0.4f), 1.8f, 14f);
|
|
|
|
// Cryo Archive - Cold Cyan/Blue
|
|
CreatePointLight(parent, "Light_Cryo_Cyan", new Vector3(-20f, 3.8f, -26f), new Color(0.2f, 0.7f, 1f), 1.6f, 16f);
|
|
|
|
// Security Office - Amber Terminal light
|
|
CreatePointLight(parent, "Light_Security_Amber", new Vector3(20f, 3.8f, -26f), new Color(1f, 0.65f, 0.2f), 1.8f, 16f);
|
|
|
|
// Biochem Lab - Toxic Pale Green
|
|
CreatePointLight(parent, "Light_Biochem_Green", new Vector3(-20f, 3.8f, -6f), new Color(0.35f, 0.95f, 0.5f), 2.0f, 18f);
|
|
|
|
// Surgical Theatre - Clinical Cold White
|
|
CreatePointLight(parent, "Light_Surgery_White", new Vector3(20f, 3.8f, -6f), new Color(0.85f, 0.92f, 1f), 2.2f, 18f);
|
|
|
|
// Bio-Containment Vault - Deep Pulsing Red
|
|
CreatePointLight(parent, "Light_BioContainment_Alarm", new Vector3(-20f, 3.8f, 17f), new Color(1f, 0.1f, 0.1f), 2.5f, 20f);
|
|
|
|
// Central Core Bio-Reactor - Eerie Glowing Cyan/Emerald Spotlight from above
|
|
CreatePointLight(parent, "Light_CentralReactor_Glow", new Vector3(0f, 3.8f, 17f), new Color(0.2f, 1f, 0.85f), 3.0f, 22f);
|
|
|
|
// Genetics Lab - Blue / Violet
|
|
CreatePointLight(parent, "Light_Genetics_Violet", new Vector3(20f, 3.8f, 12f), new Color(0.6f, 0.4f, 1f), 1.8f, 16f);
|
|
|
|
// Generator Room - Warning Amber
|
|
CreatePointLight(parent, "Light_Generator_Amber", new Vector3(20f, 3.8f, 25f), new Color(1f, 0.5f, 0.1f), 2.0f, 16f);
|
|
|
|
// North Crawlway Corridor lights
|
|
CreatePointLight(parent, "Light_NorthCrawl_West", new Vector3(-15f, 3.2f, 29.5f), new Color(1f, 0.7f, 0.3f), 1.2f, 10f);
|
|
CreatePointLight(parent, "Light_NorthCrawl_Mid", new Vector3(0f, 3.2f, 29.5f), new Color(1f, 0.7f, 0.3f), 1.2f, 10f);
|
|
CreatePointLight(parent, "Light_NorthCrawl_East", new Vector3(15f, 3.2f, 29.5f), new Color(1f, 0.7f, 0.3f), 1.2f, 10f);
|
|
|
|
// Serpentine Corridor Waypoint lights
|
|
CreatePointLight(parent, "Light_WestSerpentine", new Vector3(-10f, 3.5f, -8f), new Color(0.5f, 0.6f, 0.7f), 1.0f, 10f);
|
|
CreatePointLight(parent, "Light_EastSerpentine", new Vector3(10f, 3.5f, -8f), new Color(0.5f, 0.6f, 0.7f), 1.0f, 10f);
|
|
}
|
|
|
|
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>();
|
|
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)
|
|
{
|
|
// Clean up any old patrol points
|
|
var oldPatrol = GameObject.Find("PatrolWaypoints");
|
|
if (oldPatrol != null)
|
|
{
|
|
Undo.DestroyObjectImmediate(oldPatrol);
|
|
}
|
|
|
|
// Also disable old 1 .. 1 (13) if present in scene root
|
|
for (int i = 0; i <= 15; 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);
|
|
|
|
// 20 Waypoints looping smoothly through all sections of the lab!
|
|
Vector3[] waypoints = new Vector3[]
|
|
{
|
|
new Vector3(0f, 0f, -20f), // WP0: South Concourse
|
|
new Vector3(-10f, 0f, -20f), // WP1: West Concourse
|
|
new Vector3(-20f, 0f, -26f), // WP2: Cryo Archive
|
|
new Vector3(-10f, 0f, -14f), // WP3: West Serpentine South
|
|
new Vector3(-20f, 0f, -10f), // WP4: Biochem Lab South
|
|
new Vector3(-20f, 0f, -2f), // WP5: Biochem Lab North
|
|
new Vector3(-10f, 0f, 4f), // WP6: West Serpentine North
|
|
new Vector3(-20f, 0f, 12f), // WP7: Bio-Containment South
|
|
new Vector3(-20f, 0f, 22f), // WP8: Bio-Containment North
|
|
new Vector3(-15f, 0f, 29.5f), // WP9: North Crawlway West
|
|
new Vector3(0f, 0f, 29.5f), // WP10: North Crawlway Center
|
|
new Vector3(15f, 0f, 29.5f), // WP11: North Crawlway East
|
|
new Vector3(20f, 0f, 25f), // WP12: Generator Room
|
|
new Vector3(20f, 0f, 12f), // WP13: Genetics Lab
|
|
new Vector3(0f, 0f, 21f), // WP14: Central Core North
|
|
new Vector3(0f, 0f, 13f), // WP15: Central Core South
|
|
new Vector3(10f, 0f, 4f), // WP16: East Serpentine North
|
|
new Vector3(20f, 0f, -6f), // WP17: Surgical Theatre
|
|
new Vector3(10f, 0f, -14f), // WP18: East Serpentine South
|
|
new Vector3(20f, 0f, -26f) // WP19: Security Office
|
|
};
|
|
|
|
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)
|
|
{
|
|
enemy.transform.position = new Vector3(0f, 0.5f, 17f); // Start mutant in Central Core
|
|
var ai = enemy.GetComponent<BlindMutantAI>();
|
|
if (ai != null)
|
|
{
|
|
ai.patrolPoints = transforms;
|
|
Debug.Log($"Configured {transforms.Length} patrol points on BlindMutantAI.");
|
|
}
|
|
}
|
|
}
|
|
}
|