Advertisement
kissemisse

Build Manager

Mar 14th, 2021 (edited)
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.39 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.EventSystems;
  6.  
  7. public class BuildManager : MonoBehaviour {
  8.  
  9.     private UIController ui;
  10.     private CursorCollider cursor;
  11.     private ResourceManagmentScript resourceManager;
  12.  
  13.     private Vector3 placementRotation;
  14.  
  15.     private bool _destroyMode;
  16.  
  17.     [SerializeField] private List<StructurePrefabs> buildPrefabs;
  18.     private TutorialIntro tut;
  19.  
  20.     [SerializeField] private GameObject houseGhost,
  21.         cornGhost,
  22.         loggingGhost,
  23.         sheriffsGhost,
  24.         sawmillGhost,
  25.         tradeGhost,
  26.         mineGhost,
  27.         saloonGhost,
  28.         blacksmithGhost,
  29.         churchGhost,
  30.         storeGhost;
  31.    
  32.     [SerializeField] private GameObject roadStraight, roadDeadEnd, roadCorner, roadThreeWay, roadFourWay;
  33.    
  34.     private GameObject currentPrefab;
  35.     private bool canBuild;
  36.  
  37.     private CellPoint[,] grid;
  38.     private BaseGrid baseGrid;
  39.  
  40.     public Action<bool> DestroyModeActivated;
  41.  
  42.     void Start() {
  43.         ui = FindObjectOfType<UIController>();
  44.         ui.OnStructurePlacement += SelectStructure;
  45.         grid = FindObjectOfType<BaseGrid>().grid;
  46.         cursor = FindObjectOfType<CursorCollider>();
  47.         baseGrid = FindObjectOfType<BaseGrid>();
  48.         resourceManager = FindObjectOfType<ResourceManagmentScript>();
  49.         tut = FindObjectOfType<TutorialIntro>();
  50.     }
  51.  
  52.     private void Update() {
  53.        
  54.         // rotation
  55.         if(Input.GetKeyDown(KeyCode.E)) {
  56.             placementRotation += Vector3.up * 90;
  57.             cursor.RotateGhost(placementRotation);
  58.         } else if(Input.GetKeyDown(KeyCode.Q)) {
  59.             placementRotation += -Vector3.up * 90;
  60.             cursor.RotateGhost(placementRotation);
  61.         }
  62.  
  63.         if(Input.GetKeyDown(KeyCode.T)) SetDestroyMode(true);
  64.         else if(Input.GetKeyUp(KeyCode.T)) SetDestroyMode(false);
  65.        
  66.         // place structure
  67.  
  68.         BuildingType currentBuildingType = currentPrefab.GetComponent<IBuilding>().GetBuildingType();
  69.        
  70.         if(Input.GetKeyDown(KeyCode.Mouse0) && !EventSystem.current.IsPointerOverGameObject() && !_destroyMode && currentBuildingType != BuildingType.Road && currentBuildingType != BuildingType.Mine) {
  71.             PlaceStructure();
  72.         } else if(Input.GetKey(KeyCode.Mouse0) && !EventSystem.current.IsPointerOverGameObject() && !_destroyMode &&
  73.                   currentPrefab.GetComponent<IBuilding>().GetBuildingType() == BuildingType.Road) {
  74.             PlaceStructure();
  75.         }
  76.     }
  77.  
  78.     private void PlaceStructure() {
  79.  
  80.         if(!canBuild) return;
  81.  
  82.         IBuilding buildingInterface = currentPrefab.GetComponent<IBuilding>();
  83.        
  84.         // return if mine, can only build mine in caves
  85.         if(buildingInterface.GetBuildingType() == BuildingType.Mine) return;
  86.  
  87.         // if pop is at max, player can only build houses and roads
  88.         if(resourceManager.AtMaxPopulation()) {
  89.             BuildingType building = buildingInterface.GetBuildingType();
  90.            
  91.             if(building != BuildingType.Road && building != BuildingType.House) {
  92.                 return;
  93.             }
  94.         }
  95.        
  96.         // check if resources are enough
  97.         foreach(BuildingRequirements buildingRequirement in buildingInterface.GetBuildingRequirements()) {
  98.             if(resourceManager.CheckResourceEnough(buildingRequirement.resource, buildingRequirement.amount)) continue;
  99.             return;
  100.         }
  101.  
  102.         CellPoint buildCellPoint = cursor.GetNearestCell();
  103.         if(buildCellPoint == null || currentPrefab == null) return;
  104.  
  105.         int width = buildingInterface.GetWidth();
  106.         int length = buildingInterface.GetLength();
  107.  
  108.         int xPos = buildCellPoint.GetCellX();
  109.         int zPos = buildCellPoint.GetCellZ();
  110.  
  111.         int modifiedXPos = xPos - width / 2;
  112.         int modifiedZPos = zPos - length / 2;
  113.  
  114.         List<CellPoint> currentCells = new List<CellPoint>();
  115.  
  116.         // check if cells are empty
  117.         for(int i = 0; i < width; i++) {
  118.             for(int j = 0; j < length; j++) {
  119.                 if(!grid[modifiedXPos + i, modifiedZPos + j].IsEmpty()) {
  120.                     return;
  121.                 }
  122.                 currentCells.Add(grid[modifiedXPos + i, modifiedZPos + j]);
  123.             }
  124.         }
  125.        
  126.         CellType newCellType = currentPrefab.GetComponent<IBuilding>().GetCellType();
  127.  
  128.         if(newCellType == CellType.Structure) {
  129.             // check if near road
  130.             bool isNearRoad = false;
  131.             foreach(CellPoint cell in currentCells) {
  132.                 CellType[] neighbourCellTypes = baseGrid.GetCellNeighbourTypes(cell.GetCellX(), cell.GetCellZ());
  133.                 if(neighbourCellTypes.Any(cellType => cellType == CellType.Road)) {
  134.                     isNearRoad = true;
  135.                 }
  136.             }
  137.  
  138.             if(!isNearRoad) {
  139.                 return;
  140.             }
  141.         }
  142.  
  143.         // set new cell type
  144.         foreach(CellPoint cell in currentCells) {
  145.             cell.SetCellType(newCellType);
  146.         }
  147.  
  148.        
  149.         Vector3 buildPos = cursor.GetGhostPosition();
  150.         if(buildPos == Vector3.zero) return;
  151.  
  152.         GameObject newStructure = null;
  153.        
  154.         if(width > 1 || length > 1) { // Spawn big structure
  155.            
  156.             newStructure = Instantiate(currentPrefab, buildPos, Quaternion.Euler(placementRotation), transform);
  157.            
  158.             if(currentPrefab.GetComponent<IBuilding>().GetBuildingType() == BuildingType.CornFarm) {
  159.                 tut.WoodBuilt();
  160.             }
  161.            
  162.         } else {
  163.             switch(newCellType) {
  164.                 // spawn normal structure
  165.                 case CellType.Structure:
  166.                     newStructure = Instantiate(currentPrefab, buildCellPoint.transform.position, Quaternion.Euler(placementRotation), transform);
  167.                     BuildingType newBuilding = currentPrefab.GetComponent<IBuilding>()!.GetBuildingType();
  168.                     switch(newBuilding) {
  169.                         case BuildingType.House:
  170.                             tut.HouseBuiltUI();
  171.                             break;
  172.                         case BuildingType.Logging:
  173.                             tut.FarmBuilt();
  174.                             break;
  175.                     }
  176.                     break;
  177.                
  178.                 case CellType.Road: {
  179.                     // spawn road
  180.                     CellPoint[] neighbourCellTypes = baseGrid.GetCellNeighbours(buildCellPoint.GetCellX(), buildCellPoint.GetCellZ());
  181.                    
  182.                     GameObject newRoad = FixRoad(ref buildCellPoint.relatedStructure, neighbourCellTypes, buildCellPoint, true);
  183.                         tut.RoadPlacedUI();
  184.                     newRoad.GetComponent<IBuilding>().SetRelatedCells(currentCells);
  185.                     return;
  186.                 }
  187.             }
  188.         }
  189.  
  190.         if(newStructure is null) return;
  191.         newStructure.GetComponent<IBuilding>()?.SetRelatedCells(currentCells);
  192.         buildCellPoint.relatedStructure = newStructure;
  193.     }
  194.    
  195.     // 0 = down, 1 = up, 2 = right, 3 = left
  196.     public GameObject FixRoad(ref GameObject roadPiece, CellPoint[] neighbours, CellPoint buildCell, bool fixNeighbourRoads) {
  197.        
  198.         int roadConnections = neighbours.Count(neighbour => neighbour.GetCurrentCellType() == CellType.Road);
  199.  
  200.         if(roadPiece != null) { Destroy(roadPiece); }
  201.  
  202.         CellType[] neighbourCellTypes = baseGrid.GetCellNeighbourTypes(buildCell.GetCellX(), buildCell.GetCellZ());
  203.         switch(roadConnections) {
  204.             case 0:
  205.                 roadPiece = Instantiate(roadStraight, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
  206.                 break;
  207.            
  208.             case 1:
  209.                 // Dead end
  210.                 if(neighbourCellTypes[0] == CellType.Road) {
  211.                     roadPiece = Instantiate(roadDeadEnd, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 90, 0)));
  212.                 } else if(neighbourCellTypes[1] == CellType.Road) {
  213.                     roadPiece = Instantiate(roadDeadEnd, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 270, 0)));
  214.                 } else if(neighbourCellTypes[2] == CellType.Road) {
  215.                     roadPiece = Instantiate(roadDeadEnd, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
  216.                 } else if(neighbourCellTypes[3] == CellType.Road) {
  217.                     roadPiece = Instantiate(roadDeadEnd, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 180, 0)));
  218.                 }
  219.                 break;
  220.            
  221.             case 2: // Straights & Corners
  222.                 // Straights
  223.                 if(neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[1] == CellType.Road && neighbourCellTypes[2] != CellType.Road && neighbourCellTypes[3] != CellType.Road) { // up & down
  224.                     roadPiece = Instantiate(roadStraight, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 90, 0)));
  225.            
  226.                 } else if(neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[3] == CellType.Road && neighbourCellTypes[1] != CellType.Road && neighbourCellTypes[0] != CellType.Road) { // left & right
  227.                     roadPiece = Instantiate(roadStraight, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
  228.                    
  229.                    
  230.                 // Corners
  231.                 } else if(neighbourCellTypes[1] == CellType.Road && neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[3] != CellType.Road && neighbourCellTypes[0] != CellType.Road) {
  232.                     roadPiece = Instantiate(roadCorner, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 270, 0)));
  233.                    
  234.                 } else if(neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[3] != CellType.Road && neighbourCellTypes[1] != CellType.Road){
  235.                     roadPiece = Instantiate(roadCorner, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
  236.                    
  237.                 } else if(neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[3] == CellType.Road && neighbourCellTypes[2] != CellType.Road && neighbourCellTypes[1] != CellType.Road){
  238.                     roadPiece = Instantiate(roadCorner, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 90, 0)));
  239.                    
  240.                 } else if(neighbourCellTypes[3] == CellType.Road && neighbourCellTypes[1] == CellType.Road && neighbourCellTypes[0] != CellType.Road && neighbourCellTypes[2] != CellType.Road){
  241.                     roadPiece = Instantiate(roadCorner, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 180, 0)));
  242.                 }
  243.                 break;
  244.            
  245.             case 3:
  246.                 // Three way
  247.                 if(neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[1] == CellType.Road && neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[3] != CellType.Road) {
  248.                     roadPiece = Instantiate(roadThreeWay, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 180, 0)));
  249.                 } else if(neighbourCellTypes[1] == CellType.Road && neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[3] == CellType.Road && neighbourCellTypes[0] != CellType.Road) {
  250.                     roadPiece = Instantiate(roadThreeWay, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 90, 0)));
  251.                 } else if(neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[3] == CellType.Road && neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[1] != CellType.Road) {
  252.                     roadPiece = Instantiate(roadThreeWay, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 270, 0)));
  253.                 } else if(neighbourCellTypes[3] == CellType.Road && neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[1] == CellType.Road && neighbourCellTypes[2] != CellType.Road) {
  254.                     roadPiece = Instantiate(roadThreeWay, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
  255.                 }
  256.                 break;
  257.            
  258.             case 4:
  259.                 // Four way
  260.                 if(neighbourCellTypes[0] == CellType.Road && neighbourCellTypes[1] == CellType.Road &&
  261.                    neighbourCellTypes[2] == CellType.Road && neighbourCellTypes[3] == CellType.Road) {
  262.                     roadPiece = Instantiate(roadFourWay, buildCell.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
  263.                 }
  264.                 break;
  265.         }
  266.  
  267.         if(fixNeighbourRoads) {
  268.             // Fix the neighbouring roads
  269.             foreach(CellPoint neighbour in neighbours) {
  270.                 if(grid[neighbour.GetCellX(), neighbour.GetCellZ()].GetCurrentCellType() == CellType.Road)
  271.                     FixRoad(ref neighbour.relatedStructure, baseGrid.GetCellNeighbours(neighbour.GetCellX(), neighbour.GetCellZ()), neighbour, false);
  272.             }
  273.         }
  274.  
  275.         return roadPiece;
  276.     }
  277.  
  278.     public void SetDestroyMode(bool destroy) {
  279.         _destroyMode = destroy;
  280.         DestroyModeActivated?.Invoke(destroy);
  281.     }
  282.  
  283.     public bool GetDestroyMode() {
  284.         return _destroyMode;
  285.     }
  286. }
  287.  
  288. [Serializable]
  289. public struct StructurePrefabs {
  290.     public GameObject[] prefabs;
  291. }
  292.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement