/// <summary> /// Investigate the given tile for it's info, and display it /// </summary> /// <param name="tile"></param> void investigate(Tile tile) { if (tile.type != null) { investigatedTileNameText.text = tile.type.Name; investigatedTilePositionText.text = $"({tile.axialKey.x}, {tile.height}, {tile.axialKey.z})"; /// if we have features, name them. string featureText; FeaturesByLayer features = selectedTileFeatures; if (features != null) { featureText = "Features:\n"; foreach (KeyValuePair <TileFeature.Layer, TileFeature> feature in features) { featureText += $"{feature.Value.type.Name} {(feature.Value.type.IsInteractive ? $"({feature.Value.remainingInteractions}/{feature.Value.type.NumberOfUses})" : "")}\n"; } } else { featureText = "Empty"; } investigatedTileFeaturesText.text = featureText; } }
/// <summary> /// Set a tile and it's features at once /// </summary> /// <param name="tile"></param> /// <param name="features"></param> public void set(Tile tile, FeaturesByLayer features) { set(tile); if (features != null) { set(tile.axialKey, features); } }
/// <summary> /// Use an equiped tool on the tile's feature /// </summary> /// <param name="actionTimer"></param> void holdDownActionOnSelectedTile() { IInventory drops = null; // check if the tile has a resource. If it does, we'll try to mine it FeaturesByLayer features = selectedTileFeatures; Item selectedItem = Universe.LocalPlayerManager.ItemHotBarController.selectedItem; ITool selectedTool = selectedItem is ITool tool ? tool : Player.EmptyHand; // try to mine a resource feature. if (features != null) { if (features.TryGetValue(TileFeature.Layer.Resource, out TileFeature resource) && resource.type.CanBeMinedBy(selectedTool, resource.mode) ) { TileFeature beforeResourceValues = resource; TileFeature?workedResource = resource.interact(selectedTool, actionTimer, out drops); // if the tile resource was null, destroy it. if (workedResource == null) { updateTileProgressBar(0, resource.type.TimeToUse); workOnTileIndicator.SetActive(false); // remove the tile feature and sent the update to the board to update the feature Universe.ActiveBoardManager.activeBoard.remove(selectedTile, beforeResourceValues.type.Layer); actionTimer = 0; Universe.EventSystem.notifyChannelOf( new TileFeatureDestroyed(selectedTile, beforeResourceValues.type.Layer), WorldScapeEventSystem.Channels.TileUpdates ); // if it wasn't we need to update it. } else { TileFeature updatedResource = (TileFeature)workedResource; updateTileProgressBar(updatedResource.remainingInteractions == 0 || !updatedResource.type.CanBeMinedBy(selectedTool, updatedResource.mode) ? 0 : actionTimer, resource.type.TimeToUse ); // if the updated resource doesn't match the old one, we need to update it if (!beforeResourceValues.Equals(updatedResource)) { Universe.ActiveBoardManager.activeBoard.update(selectedTile, updatedResource); actionTimer = 0; Universe.EventSystem.notifyChannelOf( new TileFeatureUpdated(selectedTile, updatedResource), WorldScapeEventSystem.Channels.TileUpdates ); // set the info to the updated tile. investigate(selectedTile); } } // shovels can break decorations } else if (selectedTool.ToolType == Tool.Type.Shovel && features.TryGetValue(TileFeature.Layer.Decoration, out TileFeature decoration)) { TileFeature beforeShoveledValues = decoration; TileFeature?shoveledDecoration = decoration.interact(selectedTool, actionTimer, out drops); if (shoveledDecoration == null) { updateTileProgressBar(0, resource.type.TimeToUse); // remove the tile feature and sent the update to the board to update the feature Universe.ActiveBoardManager.activeBoard.remove(selectedTile, beforeShoveledValues.type.Layer); actionTimer = 0; Universe.EventSystem.notifyChannelOf( new TileFeatureDestroyed(selectedTile, beforeShoveledValues.type.Layer), WorldScapeEventSystem.Channels.TileUpdates ); } } } // If the tile feature or decoration had drops, give them to the player or drop them if (drops != null) { Item[] leftoverDrops = Universe.LocalPlayerManager.tryToEmpty(drops); Universe.EventSystem.notifyChannelOf( new TileFeatureDropsLeftover(selectedTile, leftoverDrops), WorldScapeEventSystem.Channels.TileUpdates ); } }
/// <summary> /// Generate a forest with some rocky areas /// </summary> /// <returns></returns> public override (Tile tile, FeaturesByLayer features) generateAt(Coordinate axialKey, FastNoise[] noiseLayers, Coordinate chunkKeyOffset = default) { /// get the tile type and height Coordinate noiseKey = axialKey + chunkKeyOffset * RectangularBoard.ChunkWorldOffset; float heightNoise = noiseLayers[(int)NoiseLayers.Height].GetPerlinFractal(noiseKey.x * 20, noiseKey.z * 20); float tileTypeNoise = noiseLayers[(int)NoiseLayers.Terrain].GetPerlinFractal(noiseKey.x * 10, noiseKey.z * 10); int scaledHeightValue = Mathf.Max((int)heightNoise.scale(20, 1), 7); Tile.Type tileType = scaledHeightValue == 7 ? Tile.Types.Water : tileTypeNoise > 0 && scaledHeightValue > 10 ? Tile.Types.Rocky : Tile.Types.Grass; /// check for features FeaturesByLayer features = null; // trees if (tileType == Tile.Types.Grass) { float forestNoise = noiseLayers[(int)NoiseLayers.Forest].GetCellular(noiseKey.x * 20, noiseKey.z * 10); if (forestNoise >= 0) { features = new FeaturesByLayer { { TileFeature.Types.ConniferTrio.Layer, new TileFeature(TileFeature.Types.ConniferTrio) } }; } } // rocks float cloudNoise = noiseLayers[(int)NoiseLayers.Clouds].GetCellular(noiseKey.x * 50, noiseKey.z * 50); if ((tileType == Tile.Types.Rocky || tileType == Tile.Types.Grass) && (features == null || !features.ContainsKey(TileFeature.Layer.Decoration))) { bool hasResouce = features?.ContainsKey(TileFeature.Layer.Resource) ?? false; float rockNoise = noiseLayers[(int)NoiseLayers.Forest].GetCellular(noiseKey.x * 35, noiseKey.z * 40); if ((!hasResouce && tileType != Tile.Types.Grass && rockNoise >= 0) || rockNoise >= 0.5f) { TileFeature rockPile; if (hasResouce) { rockPile = new TileFeature(TileFeature.Types.DecorativeRocks); } else { int rockSize = (int)cloudNoise.scale(0, (tileType == Tile.Types.Grass) ? 2 : 4); if (rockSize == 3) { rockPile = new TileFeature(TileFeature.Types.IronVeinedRocks); } else { rockPile = new TileFeature(TileFeature.Types.RockPile); rockPile.setRemainingInteractions(rockSize); } } if (features == null) { features = new FeaturesByLayer { { rockPile.type.Layer, rockPile } }; } else { features.Add( rockPile.type.Layer, rockPile ); } } } // lilypads if (tileType == Tile.Types.Water) { float lillyNoise = noiseLayers[(int)NoiseLayers.Clouds].GetPerlinFractal(noiseKey.x * 25 + 10, noiseKey.z * 25 + 25); if (lillyNoise >= 0.3f) { features = new FeaturesByLayer { { TileFeature.Types.BloomingLilypads.Layer, new TileFeature(TileFeature.Types.BloomingLilypads) } }; } else if (lillyNoise >= 0.1f) { features = new FeaturesByLayer { { TileFeature.Types.SmallLilypads.Layer, new TileFeature(TileFeature.Types.SmallLilypads) } }; } } // clouds if (cloudNoise >= 0.7f) { int cloudMode = (int)cloudNoise.scale(0, 3); if (features == null) { features = new FeaturesByLayer { { TileFeature.Types.WhiteClouds.Layer, new TileFeature(TileFeature.Types.WhiteClouds, cloudMode) } }; } else { features.Add( TileFeature.Types.WhiteClouds.Layer, new TileFeature(TileFeature.Types.WhiteClouds, cloudMode) ); } } return( new Tile( tileType, axialKey, scaledHeightValue, chunkKeyOffset ), features ); }