private void GenerateRiver(Vec2i start) { Vec2i end = null; for (int i = 1; i < 100; i++) { if (end != null) { break; } for (int j = 0; j < DIRS.Length; j++) { Vec2i pos = start + DIRS[j] * i; if (GameGenerator2.InBounds(pos)) { if (GameGen.TerGen.ChunkBases[pos.x, pos.z].Biome == ChunkBiome.ocean) { end = pos; break; } } } } if (end == null) { return; } LineI li = new LineI(start, end); List <Vec2i> basic = li.ConnectPoints(); float val1 = GenRan.Random(0.1f, 0.001f); float val2 = GenRan.Random(0.1f, 0.001f); int val3 = GenRan.RandomInt(8, 32); int val4 = GenRan.RandomInt(8, 32); for (int i = 0; i < basic.Count; i++) { basic[i] += new Vec2i((int)(val3 * Mathf.Sin(i * val1)), (int)(val4 * Mathf.Sin(i * val2))); } for (int i = 0; i < basic.Count - 1; i++) { Vec2i v1 = basic[i]; Vec2i v2 = basic[i + 1]; LineI i2 = new LineI(v1, v2); foreach (Vec2i v in i2.ConnectPoints()) { GameGen.TerGen.ChunkBases[v.x, v.z].SetChunkFeature(new ChunkRiverNode(v)); } } return; }
/// <summary> /// Finds the tactical placement desirability /// </summary> /// <param name="gp"></param> /// <returns></returns> private float CalculateGridPointTacticalDesirability(GridPoint gp) { bool onBorder = false; bool onRiver = false; bool onCoast = false; bool onLake = false; bool onHill = false; //Get the chunk this grid point is on ChunkBase2 cb = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z]; int kingdomID = cb.KingdomID; //If ocean, contains settlement, or belongs to no kingdom, then we do not use it if (cb.Biome == ChunkBiome.ocean || gp.HasSet || kingdomID == -1) { return(-1); } if (cb.Pos.QuickDistance(GameGen.TerGen.EvilDragonMountainPeak) < 128 * 128) { return(-1); } if (cb.Pos.QuickDistance(GameGen.TerGen.GoodDragonMountainPeak) < 64 * 64) { return(-1); } if (gp.Shell != null) { return(-1); } //we create an array, which holds the sum of all points, for each line in the 8 octangonal directions float[] sumSurroundingHeight = new float[8]; //iterate away from search point for (int i = 1; i < GridPlacement.GridPointSize; i++) { int j = 0; //Search in 4 directions foreach (Vec2i v in Vec2i.OCT_DIRDIR) { //Find the point in this direction Vec2i p = cb.Pos + v * i; //Ensure in world bounds if (GameGenerator2.InBounds(p)) { //Get chunk here ChunkBase2 cb_p = GameGen.TerGen.ChunkBases[p.x, p.z]; if (cb_p.Biome == ChunkBiome.ocean) { onCoast = true; } if (cb_p.KingdomID != -1 && cb_p.KingdomID != kingdomID) { onBorder = true; } if (cb_p.ChunkFeature is ChunkRiverNode) { onRiver = true; } //Sum total height sumSurroundingHeight[j] += cb_p.Height; } j++; } } // Find chunk height, and create sum for surrounding heights float pointHeight = cb.Height; float averageSurrounding = 0; //iterte each surrounding height sum, and divide by 31 to find average height in each direction for (int j = 0; j < 8; j++) { sumSurroundingHeight[j] /= 31f; //If the height is lower, we increase 'averageSurrounding' by the height difference if (sumSurroundingHeight[j] + 1 < pointHeight) { averageSurrounding += pointHeight - sumSurroundingHeight[j]; } else if (sumSurroundingHeight[j] - 1 > pointHeight) { averageSurrounding += pointHeight - sumSurroundingHeight[j]; } } float des = 5 + (onRiver ? 4f : 0) + (onCoast ? 3f : 0) - (onLake ? 2f : 0) + (onBorder ? 10 : 0) + (onHill ? 6 : 0); return(des); }
/// <summary> /// Calculates the location data for the supplied shell /// </summary> /// <param name="shell">The shell to generate and store data to</param> private void GenerateLocationData(Shell shell) { GridPoint gp = shell.GridPoint; bool onBorder = false; bool onRiver = false; bool onCoast = false; bool onLake = false; //Get the chunk this grid point is on ChunkBase2 cb = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z]; int kingdomID = cb.KingdomID; if (kingdomID == -1) { Debug.Error("Shell " + shell + " lays on unclaimed territory - not valid"); } //iterate away from search point for (int i = 1; i < GridPlacement.GridPointSize; i++) { //Search in 4 directions foreach (Vec2i v in Vec2i.OCT_DIRDIR) { //Find the point in this direction Vec2i p = cb.Pos + v * i; //Ensure in world bounds if (GameGenerator2.InBounds(p)) { //Get chunk here ChunkBase2 cb_p = GameGen.TerGen.ChunkBases[p.x, p.z]; if (cb_p.Biome == ChunkBiome.ocean) { onCoast = true; } if (cb_p.KingdomID != -1 && cb_p.KingdomID != kingdomID) { onBorder = true; } if (cb_p.ChunkFeature is ChunkRiverNode) { onRiver = true; } } } } //Define entraces bool[] entrances = new bool[8]; for (int i = 0; i < 8; i++) { foreach (Vec2i v in Vec2i.OCT_DIRDIR) { Vec2i p = gp.GridPos + v; if (GridPlacement.InGridBounds(p)) { GridPoint gp2 = GameGen.GridPlacement.GridPoints[p.x, p.z]; if (gp2.HasRoad) { entrances[i] = true; } else { entrances[i] = false; } } } } LocationData ld = new LocationData() { OnCoast = onCoast, OnLake = onLake, OnRiver = onRiver, OnBorder = onBorder, EntranceDirections = entrances }; shell.SetLocationData(ld); Vec2i size = shell.GetSize(); ChunkBase2[,] bases = new ChunkBase2[size.x, size.z]; //Iterate chunk bases that belong to this shell, add them to the array for (int x = 0; x < size.x; x++) { for (int z = 0; z < size.z; z++) { bases[x, z] = GameGen.TerGen.ChunkBases[x, z]; } } //Set bases shell.SetChunkBases(bases); }
/// <summary> /// Finds the settlement placement desirability /// </summary> /// <param name="gp"></param> /// <returns></returns> private float CalculateGridPointSettlementDesirability(GridPoint gp) { bool onBorder = false; bool onRiver = false; bool onCoast = false; bool onLake = false; //Get the chunk this grid point is on ChunkBase2 cb = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z]; //desirability less than 0 means not valid if (cb.Biome == ChunkBiome.ocean) { return(-1); } int kingdomID = cb.KingdomID; //If this chunk is not claimed, then we don't use it if (kingdomID == -1) { return(-1); } if (cb.Pos.QuickDistance(GameGen.TerGen.EvilDragonMountainPeak) < 128 * 128) { return(-1); } if (cb.Pos.QuickDistance(GameGen.TerGen.GoodDragonMountainPeak) < 64 * 64) { return(-1); } if (gp.Shell != null) { return(-1); } //iterate away from search point for (int i = 1; i < GridPlacement.GridPointSize; i++) { //Search in 4 directions foreach (Vec2i v in Vec2i.OCT_DIRDIR) { //Find the point in this direction Vec2i p = cb.Pos + v * i; //Ensure in world bounds if (GameGenerator2.InBounds(p)) { //Get chunk here ChunkBase2 cb_p = GameGen.TerGen.ChunkBases[p.x, p.z]; if (cb_p.Biome == ChunkBiome.ocean) { onCoast = true; } if (cb_p.KingdomID != -1 && cb_p.KingdomID != kingdomID) { onBorder = true; } if (cb_p.ChunkFeature is ChunkRiverNode) { onRiver = true; } } } } float xGradient = Mathf.Abs(GameGen.TerGen.ChunkBases[gp.ChunkPos.x + 1, gp.ChunkPos.z].Height - GameGen.TerGen.ChunkBases[gp.ChunkPos.x - 1, gp.ChunkPos.z].Height); float zGradient = Mathf.Abs(GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z + 1].Height - GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z - 1].Height); if (xGradient > 3 || zGradient > 3 || xGradient + zGradient > 5) { return(-1); } float des = 5 + (onRiver ? 5f : 0) + (onCoast ? 8f : 0) + (onLake ? 3f : 0) - (onBorder ? 4 : 0) + GenRan.Random(); return(des); }