public Settlement(Kingdom kingdom, string name, SettlementBuilder builder) { IMPORTANT = builder.ENTR_NODE; Name = name; KingdomID = kingdom.KingdomID; TileSize = builder.TileSize; Centre = builder.Centre; BaseCoord = builder.BaseCoord; SettlementBounds = new Recti(BaseCoord.x, BaseCoord.z, TileSize, TileSize); SettlementChunks = builder.SettlementChunks; Buildings = builder.Buildings; SettlementNPCIDs = new List <int>(); SettlementLeaderNPCIDs = new List <int>(); tNodes = builder.TestNodes2; //SettlementNPCs = new List<NPC>(); //setBuild = builder; PathNodes = builder.PathNodes; SettlementType = builder.SettlementType; foreach (Building b in Buildings) { b.SetSettlement(this); } SettlementPathFinder = builder.SettlementPathFinder; }
public void CreatePathBetweenNodes(SettlementPathNode firstNode, int secondNodeDirection, int width, int length = -1) { SettlementPathNode second = firstNode.Connected[secondNodeDirection]; if (second == null) { Debug.Error("Paths are not connected"); return; } Vec2i pathDiff = second.Position - firstNode.Position; //Find the vector that describes first->second int pathDiffLen = pathDiff.x + pathDiff.z; //Vector should have only 1 component, so total length can be written as sum int startPointOffset = pathDiffLen / 4; int startPoint = MiscMaths.RandomRange(startPointOffset, pathDiffLen - startPointOffset); //Generate node between two existing nodes SettlementPathNode interPathNode = new SettlementPathNode(firstNode.Position + SettlementPathNode.GetDirection(secondNodeDirection) * startPoint); int oppositeDir = SettlementPathNode.OppositeDirection(secondNodeDirection); //TestNodes.Add(interPathNode); //Update connections firstNode.AddConnection(secondNodeDirection, interPathNode); interPathNode.AddConnection(oppositeDir, firstNode); second.AddConnection(oppositeDir, interPathNode); interPathNode.AddConnection(secondNodeDirection, second); CreatePathFromNode(interPathNode, width, length: length); }
private SettlementPathNode[] AddPlot(Recti r) { SettlementPathNode[] nodes = new SettlementPathNode[4]; if (r.X > 0 && r.Y > 0) { Vec2i n1 = new Vec2i(r.X - 1, r.Y - 1); nodes[0] = new SettlementPathNode(n1); //Bottom left //PathNodes.Add(new Vec2i(r.X - 1, r.Y - 1)); } if (r.X > 0 && r.X + r.Width + 1 < TileSize && r.Y > 0) { //PathNodes.Add(new Vec2i(r.X + r.Width + 1, r.Y - 1)); nodes[1] = new SettlementPathNode(new Vec2i(r.X + r.Width + 1, r.Y - 1)); //Bottom right } if (r.X > 0 && r.Y > 0 && r.Y + r.Height + 1 < TileSize) { //PathNodes.Add(new Vec2i(r.X - 1, r.Y + r.Height + 1)); nodes[2] = new SettlementPathNode(new Vec2i(r.X - 1, r.Y + r.Height + 1)); //Top Left } if (r.X > 0 && r.X + r.Width + 1 < TileSize && r.Y > 0 && r.Y + r.Height + 1 < TileSize) { //PathNodes.Add(new Vec2i(r.X + r.Width + 1, r.Y + r.Height + 1)); nodes[3] = new SettlementPathNode(new Vec2i(r.X + r.Width + 1, r.Y + r.Height + 1)); //Top Right } if (nodes[0] != null) { if (nodes[1] != null) { nodes[0].AddConnection(SettlementPathNode.EAST, nodes[1]); nodes[1].AddConnection(SettlementPathNode.WEST, nodes[0]); } if (nodes[2] != null) { nodes[0].AddConnection(SettlementPathNode.NORTH, nodes[2]); nodes[2].AddConnection(SettlementPathNode.SOUTH, nodes[0]); } } if (nodes[3] != null) { if (nodes[1] != null) { nodes[3].AddConnection(SettlementPathNode.SOUTH, nodes[1]); nodes[1].AddConnection(SettlementPathNode.NORTH, nodes[3]); } if (nodes[2] != null) { nodes[3].AddConnection(SettlementPathNode.WEST, nodes[2]); nodes[2].AddConnection(SettlementPathNode.EAST, nodes[3]); } } //TestNodes.AddRange(nodes); BuildingPlots.Add(r); return(nodes); }
private SettlementPathNode GetNode(SettlementPathNode spn) { if (spn == null || spn.Position == null) { return(null); } int x = spn.Position.x / NODE_RES; int z = spn.Position.z / NODE_RES; return(TestNodes2[x, z]); }
public SettlementPathNode CreatePathFromNode(SettlementPathNode node, int width, bool extraLength = false, int chosenDirection = -1, int length = -1) { //If no direction is given, choose a null one if (chosenDirection == -1) { List <int> nullDirection = new List <int>(); for (int i = 0; i < 4; i++) { if (node.Connected[i] == null) { nullDirection.Add(i); } } Debug.Log(nullDirection.Count); //Choose a valid direction and find the vector step chosenDirection = GenerationRandom.RandomFromList(nullDirection); } Vec2i step = SettlementPathNode.GetDirection(chosenDirection); //If no length is given or given length is invalid, choose a path length if (length == -1 || !InBounds(node.Position + step * length)) { int attemptLength = length == -1 ? GenerationRandom.RandomInt(40, TileSize) : length; while (!InBounds(node.Position + step * attemptLength)) { attemptLength -= 1; } length = attemptLength; } int halfWidth = width / 2; Vec2i perpDirection = SettlementPathNode.GetPerpendicular(chosenDirection); if (extraLength) { length += halfWidth; } for (int l = 0; l < length; l++) { for (int w = -halfWidth; w <= halfWidth; w++) { Vec2i pos = node.Position + step * l + perpDirection * w; SetTile(pos.x, pos.z, Tile.TEST_BLUE); } } SettlementPathNode endNode = new SettlementPathNode(node.Position + step * length); node.AddConnection(chosenDirection, endNode); endNode.AddConnection(SettlementPathNode.OppositeDirection(chosenDirection), node); return(endNode); }
public List <Vec2i> GenerateSettlementPath(SettlementPathNode start, SettlementPathNode end, bool debug = false) { List <SettlementPathNode> result; if (SettlementPath(start, end, out result, debug: debug)) { List <Vec2i> outRes = new List <Vec2i>(result.Count); foreach (SettlementPathNode spn in result) { outRes.Add(spn.Position + BaseCoord); } return(outRes); } return(null); }
public void AddConnection(int direction, SettlementPathNode node) { //If the direction was NOT null, and will be set to null, our connection count goes down if (Connected[direction] != null && node == null) { ConnectedCount -= 1; } else if (Connected[direction] == null && node != null) { ConnectedCount += 1; } if (node != null) { Connected[direction] = node; } }
/// <summary> /// Connects the given node to the entrance node /// </summary> /// <param name="startNode"></param> /// <param name="width"></param> private void ConnectEntranceNode(SettlementPathNode startNode, int width) { return; /* * SettlementPathNode entranceNode = EntranceNode; * int entranceDirection = EntranceNodeDirection; * Vec2i entranceDirectionStep = SettlementPathNode.GetDirection(entranceDirection); * Vec2i diff = startNode.Position - entranceNode.Position; * * Vec2i midNodePosition = entranceNode.Position + new Vec2i(Mathf.Abs(diff.x) * entranceDirectionStep.x, Mathf.Abs(diff.z) * entranceDirectionStep.z); * SettlementPathNode midNode = new SettlementPathNode(midNodePosition); * entranceNode.AddConnection(entranceDirection, midNode); * midNode.AddConnection(SettlementPathNode.OppositeDirection(entranceDirection), entranceNode); * // TestNodes.Add(midNode);*/ }
public SettlementPathNode(Vec2i nodePosition) { if (nodePosition == null) { Debug.LogError("[SettlementPathNode] Node position cannot be null"); } if (nodePosition == new Vec2i(0, 0)) { Debug.Log("HEREHERHEHRE"); } Position = nodePosition; Connected = new SettlementPathNode[4] { null, null, null, null }; ConnectedCount = 0; }
public void ConnectPathNodes(SettlementPathNode first, SettlementPathNode second, int width) { Vec2i diff = second.Position - first.Position; //Find the vector between the two nodes //First generate the path in the x direction Vec2i xDiff = new Vec2i(diff.x, 0); int xDiffDirection = SettlementPathNode.GetDirection(xDiff); SettlementPathNode midNode = CreatePathFromNode(first, width, chosenDirection: xDiffDirection, length: Mathf.Abs(diff.x)); //TestNodes.Add(midNode); //Add connections first.AddConnection(xDiffDirection, midNode); midNode.AddConnection(SettlementPathNode.OppositeDirection(xDiffDirection), first); Vec2i zDiff = new Vec2i(0, diff.z); ConnectNodes(midNode, second, width); }
public void ConnectNodes(SettlementPathNode first, SettlementPathNode second, int width) { Vec2i diff = second.Position - first.Position; //Find the vector between the two nodes int length = diff.x + diff.z; int direction = SettlementPathNode.GetDirection(diff); //first.AddConnection(direction, second); //second.AddConnection(SettlementPathNode.OppositeDirection(direction), first); Vec2i step = SettlementPathNode.GetDirection(direction); Vec2i perpDirection = SettlementPathNode.GetPerpendicular(direction); int halfWidth = width / 2; for (int l = 0; l < length; l++) { for (int w = -halfWidth; w <= halfWidth; w++) { Vec2i pos = first.Position + step * l + perpDirection * w; SetTile(pos.x, pos.z, Tile.TEST_BLUE); } } }
private void DestroyNode(int x, int z) { SettlementPathNode node = TestNodes2[x, z]; if (node == null) { return; } for (int i = 0; i < 4; i++) { //SettlementPathNode coni = node.Connected[i]; if (node.Connected[i] != null) { GetNode(node.Connected[i])?.AddConnection(SettlementPathNode.OppositeDirection(i), null); node.Connected[i].AddConnection(SettlementPathNode.OppositeDirection(i), null); node.AddConnection(i, null); } } node = null; TestNodes2[x, z] = null; }
private void OnDrawGizmos() { if (doPath) { if (epf == null) { epf = new EntityPathFinder(GameManager.PathFinder); } Path_ = null; if (epf.IsRunning) { epf.ForceStop(); } else { epf.FindPath(Player.TilePos, Player.TilePos + GameManager.RNG.RandomVec2i(-100, 100)); } /*Debug.Log("calculating path"); * GenerationRandom genRan = new GenerationRandom(Time.frameCount); * Path_ = GameManager.PathFinder.GeneratePath(Vec2i.FromVector3(Player.Position), Vec2i.FromVector3(Player.Position) + genRan.RandomVec2i(-100, 100)); */ return; Settlement t = GameManager.TestSettle; if (t == null) { return; } int curDist = -1; Vec2i pPos = Vec2i.FromVector2(Player.Position2); foreach (SettlementPathNode pn in t.tNodes) { if (pn == null) { continue; } if (NearestNode == null) { NearestNode = pn; curDist = Vec2i.QuickDistance(pn.Position + t.BaseCoord, pPos); } else { if (Vec2i.QuickDistance(pn.Position + t.BaseCoord, pPos) < curDist) { curDist = Vec2i.QuickDistance(pn.Position + t.BaseCoord, pPos); NearestNode = pn; } } } path = new List <SettlementPathNode>(); if (SettlementPathFinder.SettlementPath(NearestNode, t.IMPORTANT, out path, debug: true)) { Debug.Log("Path found!"); } Debug.Log("Path len: " + path.Count); } if (Path_ == null && epf != null) { if (epf.IsComplete()) { Path_ = epf.GetPath(); } } if (Path_ != null && Path_.Count > 1) { Color old = Gizmos.color; Gizmos.color = Color.yellow; //Debug.Log(Vec2i.ToVector3(path[0].Position + t.BaseCoord)); //Gizmos.DrawCube(Vec2i.ToVector3(path[0].Position + GameManager.TestSettle.BaseCoord), Vector3.one * 2); Gizmos.DrawCube(Vec2i.ToVector3(Path_[0]), Vector3.one * 5); Gizmos.DrawCube(Vec2i.ToVector3(Path_[Path_.Count - 1]), Vector3.one * 5); for (int i = 0; i < Path_.Count - 1; i++) { Gizmos.DrawLine(Vec2i.ToVector3(Path_[i]), Vec2i.ToVector3(Path_[i + 1])); Gizmos.DrawCube(Vec2i.ToVector3(Path_[i]), Vector3.one * 0.5f); } Gizmos.color = old; } return; if (NearestNode == null) { Settlement t = GameManager.TestSettle; if (t == null) { return; } int curDist = -1; Vec2i pPos = Vec2i.FromVector2(Player.Position2); foreach (SettlementPathNode pn in t.tNodes) { if (pn == null) { continue; } if (NearestNode == null) { NearestNode = pn; curDist = Vec2i.QuickDistance(pn.Position + t.BaseCoord, pPos); } else { if (Vec2i.QuickDistance(pn.Position + t.BaseCoord, pPos) < curDist) { curDist = Vec2i.QuickDistance(pn.Position + t.BaseCoord, pPos); NearestNode = pn; } } } path = new List <SettlementPathNode>(); if (SettlementPathFinder.SettlementPath(NearestNode, t.IMPORTANT, out path, debug: true)) { Debug.Log("Path found!"); } Debug.Log("Path len: " + path.Count); } }
private static int NodeValue(SettlementPathNode node, SettlementPathNode end) { Vec2i disp = node.Position - end.Position; return(disp.x * disp.x + disp.z * disp.z); }
/// <summary> /// <para>Finds a path connecting the start and end node. /// Each node contains all nodes they are connected to. /// Returns true if a full path was found. /// Returns false if no path was found</para> /// the out path variable is the total path if one is found, or all total nodes checked. /// /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="path"></param> /// <param name="maxTest"></param> /// <param name="debug"></param> /// <returns></returns> public static bool SettlementPath(SettlementPathNode start, SettlementPathNode end, out List <SettlementPathNode> path, int maxTest = 500, bool debug = false) { List <SettlementPathNode> result = new List <SettlementPathNode>(); List <SettlementPathNode> tested = new List <SettlementPathNode>(32); if (debug) { Debug.Log("[SetPathFind] Attempting path: " + start + " -> " + end); } bool found = false; SettlementPathNode current = start; result.Add(current); int index = 0; while (!found) { index++; if (index > maxTest) { path = result; return(false); } int[] connectedVals = new int[4]; int minVal = -1; int minNode = -1; if (debug) { Debug.Log("[SetPathFind] Current node: " + current.Position); } //Iterate for (int i = 0; i < 4; i++) { if (debug) { Debug.Log("[SetPathFind] Checking node: " + i); if (current.Connected[i] != null) { Debug.Log("[SetPathFind] Not null: " + current.Connected[i]); } } //If the node is null, then the value is max if (current.Connected[i] == null) { if (debug) { Debug.Log("[SetPathFind] Node null -> inf val"); } connectedVals[i] = int.MaxValue; } //If the connected node is our final node, we finish the algorithm else if (current.Connected[i].Position == end.Position) { if (debug) { Debug.Log("[SetPathFind] Connected node is end"); } result.Add(current.Connected[i]); path = result; return(true); } else if (current.Connected[i].ConnectedCount < 2) { //If the connected node has less than two connections, it is an end node, and so goes no where //We can set the connected value as high if (debug) { Debug.Log("[SetPathFind] Node " + current.Connected[i] + " has few connections"); } connectedVals[i] = int.MaxValue; } else if (tested.Contains(current.Connected[i])) { if (debug) { Debug.Log("[SetPathFind] Node " + current.Connected[i] + "Alreaded tested"); } //if we have already tested a discarded a point, max val connectedVals[i] = int.MaxValue; } else if (result.Count > 1 && current.Connected[i] == result[result.Count - 1]) { if (debug) { Debug.Log("[SetPathFind] Node " + current.Connected[i] + " is previous point"); } //If the point is the previous point, max val connectedVals[i] = int.MaxValue; } else if (result.Count > 1 && result.Contains(current.Connected[i])) { if (debug) { Debug.Log("[SetPathFind] Node " + current.Connected[i] + " is circle"); } connectedVals[i] = int.MaxValue; } else { connectedVals[i] = NodeValue(current.Connected[i], end); if (debug) { Debug.Log("[SetPathFind] Node " + current.Connected[i] + " value of " + connectedVals[i]); } } if (minVal == -1) { minVal = connectedVals[i]; minNode = i; if (debug) { Debug.Log("[SetPathFind] Setting min val to " + minVal); } } else { if (connectedVals[i] < minVal) { minVal = connectedVals[i]; minNode = i; if (debug) { Debug.Log("[SetPathFind] Setting min val to " + minVal); } } } } //This means that no possible forward direction could be taken if (minVal > 1000000000) { //We take a step back if (result.Count == 1) { if (debug) { Debug.Log("[SetPathFind] No possible path"); } //If we find no valid direction on the first node, //then there is no path path = tested; return(false); } if (debug) { Debug.Log("[SetPathFind] Step back "); } //Ensure we don't check this one again tested.Add(current); //Move back 1 space current = result[result.Count - 1]; //Remove from result result.RemoveAt(result.Count - 1); } else { if (debug) { Debug.Log("[SetPathFind] Next node: " + current.Connected[minNode]); } result.Add(current.Connected[minNode]); current = current.Connected[minNode]; } } path = tested; return(false); }
private void AddInitPaths() { int nodeSize = TileSize / NODE_RES; int xStart = GenerationRandom.RandomInt(0 + 3, nodeSize - 3); int zLen = nodeSize - GenerationRandom.RandomInt(0, 3); //Ends 0-3 chunks from settlement end int zStartWest = GenerationRandom.RandomInt(2, nodeSize - 3); int xLenWest = GenerationRandom.RandomInt(xStart - 2, xStart); EntranceNode = new Vec2i(xStart, 0); //Add the path nodes along the z direction (start at south -> north) for (int z = 0; z < zLen; z++) { PathNodes[xStart, z] = 100; TestNodes2[xStart, z] = new SettlementPathNode(new Vec2i(xStart * NODE_RES, z * NODE_RES)); TestNodes2[xStart, z].IsMain = true; SetTile(xStart * NODE_RES, z * NODE_RES, Tile.TEST_BLUE); } ENTR_NODE = TestNodes2[xStart, 0]; int zStartEast = GenerationRandom.RandomInt(2, nodeSize - 3); int xLenEast = GenerationRandom.RandomInt(nodeSize - xStart - 2, nodeSize - xStart); for (int x = 0; x < xLenEast; x++) { PathNodes[xStart + x, zStartEast] = 100; } for (int x = 0; x < xLenWest; x++) { PathNodes[xStart - x, zStartWest] = 100; } for (int x = 0; x < nodeSize; x++) { for (int z = 0; z < nodeSize; z++) { if (PathNodes[x, z] != 0) { if (x > 0 && PathNodes[x - 1, z] != 0) { SetTiles((x - 1) * NODE_RES, z * NODE_RES - 2, (x) * NODE_RES, z * NODE_RES + 2, Tile.TEST_BLUE); } if (z > 0 && PathNodes[x, z - 1] != 0) { SetTiles((x) * NODE_RES - 2, (z - 1) * NODE_RES, (x) * NODE_RES + 2, z * NODE_RES, Tile.TEST_BLUE); } if (x < nodeSize - 1 && PathNodes[x + 1, z] != 0) { SetTiles((x) * NODE_RES, z * NODE_RES - 2, (x + 1) * NODE_RES, z * NODE_RES + 2, Tile.TEST_BLUE); } if (z < nodeSize - 1 && PathNodes[x, z + 1] != 0) { SetTiles((x) * NODE_RES - 2, (z) * NODE_RES, (x) * NODE_RES + 2, (z + 1) * NODE_RES, Tile.TEST_BLUE); } } } } }