/// <summary> /// Update the mode for a feature on a given tile. /// It needs to be on the same layer as the one being updated. /// </summary> /// <param name="tile"></param> /// <param name="featureLayer"></param> void updateFeature(Tile tile, TileFeature feature) { if (inUseControllers.TryGetValue(tile.parentChunkKey, out GridController chunkController)) { chunkController.updateFeatureModel(tile, feature); } }
/// <summary> /// Update the model for a given feature /// </summary> /// <param name="tile"></param> /// <param name="feature"></param> public void updateFeatureModel(Tile tile, TileFeature feature) { if (visibleFeatures.TryGetValue(tile.axialKey, out Dictionary <TileFeature.Layer, GameObject> features)) { if (features.TryGetValue(feature.type.Layer, out GameObject oldFeatureModel)) { GameObject newFeatureModel = instantiateFeature(tile, feature); newFeatureModel.transform.rotation = oldFeatureModel.transform.rotation; // TODO: change this to features[layer] = X; visibleFeatures[tile.axialKey][feature.type.Layer] = newFeatureModel; Destroy(oldFeatureModel); } } }
/// <summary> /// Instantiate a feature's model on the given tile /// </summary> /// <param name="tile"></param> /// <param name="feature"></param> /// <returns></returns> GameObject instantiateFeature(Tile tile, TileFeature feature, bool randomizeDirection = false) { return(Instantiate( TileFeatureDataMapper.GetModelFor(feature), new Vector3( tile.worldLocation.x, tile.worldLocation.y * Universe.StepHeight, tile.worldLocation.z ), feature.type.PlacementRotationType == TileFeature.RotationType.Random ? Quaternion.Euler(0, UnityEngine.Random.Range(1, 360), 0) : Quaternion.Euler(0, 0, 0), transform )); }
private void SetupTileMap() { mapState = new MapState(); for (var i = 0; i < tiles.Length; ++i) { tilesData[tiles[i]] = tileEnvs[i]; } foreach (var pos in tilemap.cellBounds.allPositionsWithin) { tilesFeature[pos] = new TileFeature(); var tile = tilemap.GetTile(pos); if (tile == null) { continue; } var tileEnv = tilesData[tile]; if (tileEnv.controlPoint) { tilesFeature[pos].isTriggered = false; ++mapState.numControlPoint; } } }
/// <summary> /// Make a new event /// </summary> /// <param name="tile"></param> /// <param name="feature"></param> public TileFeatureUpdated(Tile tile, TileFeature feature) { updatedTile = tile; updatedFeature = feature; }
/// <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> /// Set or update a tile and a feature on the tileboard /// </summary> /// <param name="selectedTile"></param> /// <param name="resource"></param> public abstract void update(Tile selectedTile, TileFeature resource);
/// <summary> /// update the data for an existing tile and feature /// </summary> /// <param name="selectedTile"></param> /// <param name="resource"></param> public override void update(Tile tile, TileFeature feature) { this[getChunkKeyFor(tile)]?.set(tile, feature); }
/// <summary> /// Get a model for an item /// </summary> /// <param name="item"></param> /// <returns></returns> public static GameObject GetModelFor(TileFeature feature) { return(TileFeatures[feature.type.Id].OverworldModelsByMode[Mathf.Max(feature.mode, 0)]); }
/// <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 ); }