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); }
public void GenerateKingdomSettlementBases(Kingdom kingdom) { KingdomSettlements[kingdom] = new List <SettlementBase>(100); AddSettlementBaseToKingdom(kingdom, new SettlementBase(kingdom.CapitalChunk, 8, SettlementType.CAPITAL)); int kingdomSize = KingdomChunks[kingdom].Count; //int cityCount = 1; //int townCount = 1; //int villageCount = 1; int cityCount = MiscMaths.RandomRange(2, 3); int townCount = MiscMaths.RandomRange(7, 9); int villageCount = MiscMaths.RandomRange(18, 25); if (kingdomSize > 400) { // cityCount++; // townCount += MiscMaths.RandomRange(1, 3); // villageCount += MiscMaths.RandomRange(1, 8); } int distMult = 4; for (int i = 0; i < cityCount; i++) { Vec2i c = FindSpace(kingdom, 6 * distMult); if (c == null) { continue; } AddSettlementBaseToKingdom(kingdom, new SettlementBase(c, 6, SettlementType.CITY)); } for (int i = 0; i < townCount; i++) { Vec2i c = FindSpace(kingdom, 4 * distMult); if (c == null) { continue; } AddSettlementBaseToKingdom(kingdom, new SettlementBase(c, 4, SettlementType.TOWN)); } for (int i = 0; i < villageCount; i++) { Vec2i c = FindSpace(kingdom, 3 * distMult); if (c == null) { continue; } AddSettlementBaseToKingdom(kingdom, new SettlementBase(c, 3, SettlementType.VILLAGE)); } /* * Vec2i city1 = FindSpace(kingdom, 12); * AddSettlementBaseToKingdom(kingdom, new SettlementBase(city1, 6, SettlementType.CITY)); * Vec2i city2 = FindSpace(kingdom, 12); * AddSettlementBaseToKingdom(kingdom, new SettlementBase(city2, 6, SettlementType.CITY));*/ }
void SlowWorldTick() { List <LoadedProjectile> toRem = new List <LoadedProjectile>(); foreach (LoadedProjectile p in LoadedProjectiles) { if (!MiscMaths.WithinDistance(p.transform.position, Player.Position, 40)) { toRem.Add(p); } } foreach (LoadedProjectile proj in toRem) { LoadedProjectiles.Remove(proj); Destroy(proj.gameObject); } }
public static string GetRandomAltString(int length, int seed) { var s = ""; var rand = new System.Random(seed); for (var i = 0; i < length; i++) { if (MiscMaths.IsOdd(i)) { s += NUMERIC[rand.Next(NUMERIC.Length)]; } else { s += ALPHA[rand.Next(ALPHA.Length)]; } } return(s); }
public static string GetRandomString(string characters, int length, int seed) { var s = ""; var rand = new System.Random(seed); for (var i = 0; i < length; i++) { if (MiscMaths.IsOdd(i)) { s += characters[rand.Next(characters.Length)]; } else { s += characters[rand.Next(characters.Length)]; } } return(s); }
public static Vec2i AddEntrance(Building b, int entranceSide, int disp = -1) { if (disp == -1) { //If entrance is facing z axis, displacement in in x if (entranceSide == NORTH_ENTRANCE || entranceSide == SOUTH_ENTRANCE) { disp = MiscMaths.RandomRange(1, b.Width - 1); } else { disp = MiscMaths.RandomRange(1, b.Height - 1); } } Vec2i entrance = null; if (entranceSide == NORTH_ENTRANCE) { entrance = new Vec2i(disp, b.Height - 1); } else if (entranceSide == SOUTH_ENTRANCE) { entrance = new Vec2i(disp, 0); } else if (entranceSide == EAST_ENTRANCE) { entrance = new Vec2i(b.Width - 1, disp); } else if (entranceSide == WEST_ENTRANCE) { entrance = new Vec2i(0, disp); } b.BuildingObjects[entrance.x, entrance.z] = null; //TODO - Set to door of correct type return(entrance); }
/// <summary> /// Generates the world. /// Initiates a <see cref="TerrainGenerator"/> & generates the base Terrain <see cref="TerrainGenerator.GenerateBaseTerrain"/> /// Then Initiates a <see cref="KingdomsGenerator"/> that generates all the kingdoms, as well as claiming all their territory /// Then generates terrain details using <see cref="TerrainGenerator.GenerateWorldDetailTerrain"/> /// Finally, generates all settlements using <see cref="KingdomsGenerator.GenerateAllKingdomSettlements"/> /// /// TODO - Add dungeon generation, add settlement details generation (roads + paths) /// </summary> /// <returns></returns> public void GenerateWorld(WorldManager wm) { //Set Random init state based on seed Random.InitState(Seed); MiscMaths.SetRandomSeed(Seed); //Initiate empty world and generate base terrain World = new World(); wm.SetWorld(World); //Create a default RNG to be used by the generators (Not thread safe) MainGenerator = new GenerationRandom(Seed); //Generation starts TerrainGenerator = new TerrainGenerator(this, World); RiverGenerator = new RiverGenerator(this); LakeGenerator = new LakeGenerator(this); Debug.BeginDeepProfile("chunk_base_gen"); TerrainGenerator.GenerateChunkBases();//Generate the chunk bases, these only define if they are land or sea. //Generates fine terrain details: rivers, lakes, (todo - marshes, more variety to forrests?) TerrainGenerator.GenerateTerrainDetails(); Debug.EndDeepProfile("chunk_base_gen"); //TODO - check if this is still required (probably not) ChunkGenerator = new ChunkGenerator(this); Debug.BeginDeepProfile("kingdom_set_gen"); //We then generate empty kingdoms based on these empty chunks KingdomsGenerator kingGen = new KingdomsGenerator(World, this); //We also generate the all empty settlements for the world. kingGen.GenerateEmptyKingdomsFromBaseChunks(4); //Generates all settlement chunks PreGeneratedChunks = kingGen.GenerateSettlements(); Debug.EndDeepProfile("kingdom_set_gen"); Debug.BeginDeepProfile("chunk_struct_gen"); //Generate chunk structures (bandit camps, etc) StructureGenerator = new ChunkStructureGenerator(this); StructureGenerator.GenerateStructureShells(); //Iterate all chunks generated for chunk structures, add them to the PreGeneratedChunks foreach (KeyValuePair <Vec2i, ChunkData> kvp in StructureGenerator.GenerateAllStructures()) { PreGeneratedChunks.Add(kvp.Key, kvp.Value); } Debug.EndDeepProfile("chunk_struct_gen"); Debug.BeginDeepProfile("terrain_map_gen"); //Create a simple map based on the terrain of the world GenerateTerrainMap(TerrainGenerator.ChunkBases); Debug.EndDeepProfile("terrain_map_gen"); }
/// <summary> /// Takes a building plan and generates a full building from it. /// TODO - Currently messy, fix /// </summary> /// <param name="plan"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="entrance"></param> /// <returns></returns> public static Building CreateBuilding(BuildingPlan plan, int width = -1, int height = -1, int entrance = 0) { if (width == -1) { width = MiscMaths.RandomRange(plan.MinSize, plan.MaxSize); } else if (width < plan.MinSize) { width = plan.MinSize; } else if (width > plan.MaxSize) { width = plan.MaxSize; } if (height == -1) { height = MiscMaths.RandomRange(plan.MinSize, plan.MaxSize); } else if (height < plan.MinSize) { height = plan.MinSize; } else if (height > plan.MaxSize) { height = plan.MaxSize; } Tile[,] buildingBase = new Tile[width, height]; WorldObjectData[,] buildingObjects = new WorldObjectData[width, height]; if (plan == Building.HOUSE) { House h = new House(width, height); h.SetBuilding(buildingBase, buildingObjects); return(GenerateHouse(h, BuildingStyle.stone)); } if (plan == Building.BLACKSMITH) { Blacksmith b = new Blacksmith(width, height); b.SetBuilding(buildingBase, buildingObjects); return(GenerateBlacksmith(b, BuildingStyle.stone)); } if (plan == Building.MARKET) { MarketPlace market = new MarketPlace(width, height); market.SetBuilding(buildingBase, buildingObjects); return(GenerateMarket(market, BuildingStyle.stone)); } if (plan == Building.BARACKS) { Baracks baracks = new Baracks(width, height); baracks.SetBuilding(buildingBase, buildingObjects); return(GenerateBaracks(baracks)); } /* * if(plan == Building.MARKET) * { * MarketPlace market = new MarketPlace(width, height); * market.SetBuilding(buildingBase, buildingObjects); * return GenerateMarket(market, BuildingStyle.stone); * } * if(plan == Building.BARACKSCITY) * { * Baracks bar = new Baracks(width, height); * bar.SetBuilding(buildingBase, buildingObjects); * return GenerateCityBaracks(bar); * } * if (plan == Building.BARACKSCITY || plan == Building.BARACKSTOWN) * { * * }*/ //Default for now House ht = new House(width, height); ht.SetBuilding(buildingBase, buildingObjects); return(GenerateHouse(ht, BuildingStyle.stone)); }
/// <summary> /// Generates the basic walls, floor, and entrance for any building. /// Picks the exact position of entrance, and returns it /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="buildingObjects">Building objects to be filled with walls</param> /// <param name="buildTiles"></param> /// <param name="entranceID"></param> /// <param name="style"></param> /// <returns></returns> public static Vec2i GenerateWallsFloorAndEntrance(int width, int height, WorldObjectData[,] buildingObjects, Tile[,] buildTiles, int entranceID, BuildingStyle style, int entraceDis = -1, WorldObjectData wallType = null, Tile tileType = null) { int entWidth = 2; if (entraceDis == -1) { if (entranceID == NORTH_ENTRANCE || entranceID == SOUTH_ENTRANCE) { entraceDis = MiscMaths.RandomRange(1, width - 1); } else { entraceDis = MiscMaths.RandomRange(1, height - 1); } } //Decide the position of the entrance Vec2i entrance = null; if (entranceID == NORTH_ENTRANCE) { entrance = new Vec2i(entraceDis, height - 1); } else if (entranceID == SOUTH_ENTRANCE) { entrance = new Vec2i(entraceDis, 0); } else if (entranceID == EAST_ENTRANCE) { entrance = new Vec2i(width - 1, entraceDis); } else if (entranceID == WEST_ENTRANCE) { entrance = new Vec2i(0, entraceDis); } //Assign correct wall type if none given if (wallType == null) { switch (style) { case BuildingStyle.stone: wallType = new BrickWall(new Vec2i(0, 0)); break; case BuildingStyle.wood: //TODO - Add wallType = new BrickWall(new Vec2i(0, 0)); break; } }//Asign correct tile type if none given if (tileType == null) { switch (style) { case BuildingStyle.stone: tileType = Tile.STONE_FLOOR; break; case BuildingStyle.wood: tileType = Tile.WOOD_FLOOR; break; } } //Iterate all points for (int x = 0; x < width; x++) { for (int z = 0; z < height; z++) { //Asign tile buildTiles[x, z] = tileType; if (x == 0 || x == width - 1 || z == 0 || z == height - 1) { //Asign wall if no entrance if (!(entrance.x == x & entrance.z == z)) { if (x == 3) { buildingObjects[x, z] = new BuildingWall(new Vec2i(0, 0), "brick", 5, new GlassWindow(new Vec2i(0, 0), new Vec2i(0, 1)), 2); } else { buildingObjects[x, z] = new BuildingWall(new Vec2i(0, -1), "brick", 5); } } } } } //(buildingObjects[0, 0] as BuildingWall).AddRoof(new Roof(new Vec2i(0, 0), new Vec2i(width, height))); return(entrance); }
/// <summary> /// Physics update for the entity /// /// </summary> private void FixedUpdate() { //RigidBody.angularVelocity = Vector3.zero; if (GameManager.Paused) { return; } if (IsIdle) { return; } Debug.BeginDeepProfile("le_fixed_update"); if (!(Entity is Player)) { DebugGUI.Instance.SetData("ent", GameManager.Paused + "_" + IsIdle + "_" + MoveDirection); if (MiscMaths.DistanceSqr(transform.position, GameManager.PlayerManager.Player.Position) > (World.ChunkSize * 4) * (World.ChunkSize * 4)) { IsIdle = true; } } EntityHealthBar.SetHealthPct(Entity.CombatManager.CurrentHealth / Entity.CombatManager.MaxHealth); if (transform.position.y < 0) { transform.position = new Vector3(transform.position.x, 0, transform.position.z); } Vec2i cPos = World.GetChunkPosition(transform.position); //Check if the current chunk is loaded if (!GameManager.WorldManager.CRManager.IsCurrentChunkPositionLoaded(cPos)) { //If not, keep position dixed with +ve y value, to prevent falling through world. transform.position = new Vector3(transform.position.x, 1, transform.position.z); } //If we have a specified move direction if (MoveDirection != Vector2.zero) { float tileSpeed = 1; //TODO - get tile speed //Finds correct speed associated with running/walking for this entity float entitySpeed = IsRunning?Entity.MovementData.RunSpeed:Entity.MovementData.WalkSpeed; AnimationManager.SetSpeedPercentage(entitySpeed / Entity.MovementData.RunSpeed); Vector2 v2Pos = new Vector2(transform.position.x, transform.position.z); Vector2 targetDisp = TargetPosition - v2Pos; float targetMag = targetDisp.magnitude; Vector3 vel = new Vector3(MoveDirection.x, 0, MoveDirection.y) * tileSpeed * entitySpeed; RigidBody.velocity = new Vector3(MoveDirection.x, 0, MoveDirection.y) * tileSpeed * entitySpeed; //If the distance the body will move in a frame (|velocity|*dt) is more than the desired amount (target mag) //Then we must scale the velocity down if (RigidBody.velocity.magnitude * Time.fixedDeltaTime > targetMag) { RigidBody.velocity = RigidBody.velocity * targetMag / (Time.fixedDeltaTime * RigidBody.velocity.magnitude); } if (Entity is Player) { DebugGUI.Instance.SetData("Vel", RigidBody.velocity + " | " + vel); } } else { AnimationManager.SetSpeedPercentage(0); } //If we have a specified look direction if (LookTowards != Vector3.zero) { float angle = Vector3.SignedAngle(Vector3.forward, LookTowards - transform.position, Vector3.up); Quaternion quat = Quaternion.Euler(new Vector3(0, angle, 0)); transform.rotation = Quaternion.Slerp(transform.rotation, quat, Time.fixedDeltaTime * LOOK_ROTATION_SPEED); Entity.SetLookAngle(transform.rotation.eulerAngles.y); } //Check if we are on the ground bool IsOnGround = OnGround(); //Debug info for player Jumping if (Entity is Player) { DebugGUI.Instance.SetData("jump_vel", VerticalVelocity); DebugGUI.Instance.SetData("onGround", IsOnGround); DebugGUI.Instance.SetData("isJumping", IsJumping); DebugGUI.Instance.SetData("isFalling", IsFalling); } //Check if we are off the ground if (!IsOnGround) { //If so, update vertical position and velocity accordingly VerticalVelocity -= 9.81f * Time.fixedDeltaTime; transform.position += Vector3.up * VerticalVelocity * Time.fixedDeltaTime; //Next, if we are off the ground but not jumping, it must mean we're falling if (!IsJumping) { //If not currently falling, set it to true if (!IsFalling) { IsFalling = true; AnimationManager.SetFalling(); } } } else if (VerticalVelocity > 0) { //If we are on the ground, but our velocity is positive, we must be jumping VerticalVelocity -= 9.81f * Time.fixedDeltaTime; transform.position += Vector3.up * VerticalVelocity * Time.fixedDeltaTime; } else if ((IsJumping || IsFalling) && !IsWaitingForJump) { //If we are on the ground, but still jumping or falling, set both to false. reset velocity IsJumping = false; VerticalVelocity = 0; IsFalling = false; //Then play the land animation AnimationManager.LandJump(); } //Reset variables LookTowards = Vector3.zero; MoveDirection = Vector2.zero; Entity.SetPosition(transform.position); Debug.EndDeepProfile("le_fixed_update"); return; }