/// <summary> /// Makes terrain visible and sets its appearance to its regular value, and ensures that it will /// remain as such as long as it is visible. /// </summary> /// <param name="terrain">Terrain to modify.</param> protected override void UpdateTerrainSeen(RogueLikeCell terrain) { // Invalid use of MemoryFieldOfViewHandlerBase if (!(terrain is MemoryAwareRogueLikeCell awareTerrain)) { throw new InvalidOperationException( $"{nameof(MemoryFieldOfViewHandlerBase)} must only be used on a map that contains {nameof(MemoryAwareRogueLikeCell)} instances as its terrain."); } // If the appearances don't match currently, synchronize them if (!awareTerrain.LastSeenAppearance.Matches(awareTerrain.TrueAppearance)) { awareTerrain.LastSeenAppearance.CopyAppearanceFrom(awareTerrain.TrueAppearance); awareTerrain.LastSeenAppearance.IsVisible = awareTerrain.TrueAppearance.IsVisible; } // Set up an event handler that will keep the actual appearance in sync with the // true one, so long as the tile remains visible to the player. Because this could be // called twice in certain state changes, we make sure we do not add the handler twice. // // Removing the event even if it does not exist does not throw exception and appears to be the // most performant way to account for duplicates. awareTerrain.TrueAppearance.IsDirtySet -= On_VisibleTileTrueAppearanceIsDirtySet; awareTerrain.TrueAppearance.IsDirtySet += On_VisibleTileTrueAppearanceIsDirtySet; }
/// <summary> /// Makes terrain visible and sets its foreground color to its regular value. /// </summary> /// <param name="terrain">Terrain to modify.</param> protected override void UpdateTerrainSeen(RogueLikeCell terrain) { terrain.Appearance.IsVisible = true; if (terrain.Appearance.Decorators.Contains(ExploredDecorator)) { // If there is only 1 decorator, it must be ours so we can replace // the array with a static blank one terrain.Appearance.Decorators = terrain.Appearance.Decorators.Length == 1 ? Array.Empty <CellDecorator>() : terrain.Appearance.Decorators.Where(i => i != ExploredDecorator).ToArray(); } }
/// <summary> /// Makes terrain invisible if it is not explored. Makes terrain visible but tints it using /// <see cref="ExploredDecorator"/> if it is explored. /// </summary> /// <param name="terrain">Terrain to modify.</param> protected override void UpdateTerrainUnseen(RogueLikeCell terrain) { // Parent can't be null because of invariants enforced by structure for when // this function is called var parent = Parent !; // If the unseen terrain is outside of FOV, apply the decorator to tint the square appropriately. if (parent.PlayerExplored[terrain.Position]) { terrain.Appearance.Decorators = terrain.Appearance.Decorators.Append(ExploredDecorator).ToArray(); } else // If the unseen tile isn't explored, it's invisible { terrain.Appearance.IsVisible = false; } }
/// <summary> /// Makes terrain invisible if it is not explored. Changes the appearance by calling /// <see cref="ApplyMemoryAppearance"/> if it is explored. The terrain will continue to /// appear as set by that function (even if its true appearance changes) until the player /// sees it again. /// </summary> /// <param name="terrain">Terrain to modify.</param> protected override void UpdateTerrainUnseen(RogueLikeCell terrain) { // Invalid use of MemoryFieldOfViewHandlerBase if (!(terrain is MemoryAwareRogueLikeCell awareTerrain)) { throw new InvalidOperationException( $"{nameof(MemoryFieldOfViewHandlerBase)} must only be used on a map that contains {nameof(MemoryAwareRogueLikeCell)} instances as its terrain."); } // If the event handler for synchronizing the appearance with true appearance is added, remove it // which will cause the appearance to remain as last-seen if it changes awareTerrain.TrueAppearance.IsDirtySet -= On_VisibleTileTrueAppearanceIsDirtySet; // If the unseen terrain is explored (eg. it was in FOV previously), apply the visual change // as appropriate if (Parent !.PlayerExplored[terrain.Position]) { ApplyMemoryAppearance(awareTerrain); }