Add a trait PlayerRadarTerrain to track explored terrain
This commit is contained in:
@@ -48,6 +48,8 @@ namespace OpenRA
|
|||||||
|
|
||||||
public Player[] Players = new Player[0];
|
public Player[] Players = new Player[0];
|
||||||
|
|
||||||
|
public event Action<Player> RenderPlayerChanged;
|
||||||
|
|
||||||
public void SetPlayers(IEnumerable<Player> players, Player localPlayer)
|
public void SetPlayers(IEnumerable<Player> players, Player localPlayer)
|
||||||
{
|
{
|
||||||
if (Players.Length > 0)
|
if (Players.Length > 0)
|
||||||
@@ -84,7 +86,12 @@ namespace OpenRA
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (LocalPlayer == null || LocalPlayer.UnlockedRenderPlayer)
|
if (LocalPlayer == null || LocalPlayer.UnlockedRenderPlayer)
|
||||||
|
{
|
||||||
renderPlayer = value;
|
renderPlayer = value;
|
||||||
|
|
||||||
|
if (RenderPlayerChanged != null)
|
||||||
|
RenderPlayerChanged(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
119
OpenRA.Mods.Common/Traits/Player/PlayerRadarTerrain.cs
Normal file
119
OpenRA.Mods.Common/Traits/Player/PlayerRadarTerrain.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
public class PlayerRadarTerrainInfo : ITraitInfo, Requires<ShroudInfo>
|
||||||
|
{
|
||||||
|
public object Create(ActorInitializer init)
|
||||||
|
{
|
||||||
|
return new PlayerRadarTerrain(init.Self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlayerRadarTerrain : IWorldLoaded
|
||||||
|
{
|
||||||
|
public bool IsInitialized { get; private set; }
|
||||||
|
|
||||||
|
readonly World world;
|
||||||
|
CellLayer<Pair<int, int>> terrainColor;
|
||||||
|
readonly HashSet<MPos> dirtyTerrainCells = new HashSet<MPos>();
|
||||||
|
readonly Shroud shroud;
|
||||||
|
|
||||||
|
public event Action<MPos> CellTerrainColorChanged = null;
|
||||||
|
|
||||||
|
public PlayerRadarTerrain(Actor self)
|
||||||
|
{
|
||||||
|
world = self.World;
|
||||||
|
shroud = self.Trait<Shroud>();
|
||||||
|
shroud.CellsChanged += OnShroudCellsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnShroudCellsChanged(IEnumerable<PPos> puvs)
|
||||||
|
{
|
||||||
|
foreach (var puv in puvs)
|
||||||
|
{
|
||||||
|
foreach (var uv in world.Map.Unproject(puv))
|
||||||
|
{
|
||||||
|
if (dirtyTerrainCells.Contains(uv))
|
||||||
|
{
|
||||||
|
UpdateTerrainCellColor(uv);
|
||||||
|
dirtyTerrainCells.Remove(uv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTerrainCell(CPos cell)
|
||||||
|
{
|
||||||
|
var uv = cell.ToMPos(world.Map);
|
||||||
|
if (!world.Map.CustomTerrain.Contains(uv))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!shroud.IsVisible(uv))
|
||||||
|
dirtyTerrainCells.Add(uv);
|
||||||
|
else
|
||||||
|
UpdateTerrainCellColor(uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTerrainCellColor(MPos uv)
|
||||||
|
{
|
||||||
|
terrainColor[uv] = GetColor(world.Map, uv);
|
||||||
|
|
||||||
|
if (CellTerrainColorChanged != null)
|
||||||
|
CellTerrainColorChanged(uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WorldLoaded(World w, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
terrainColor = new CellLayer<Pair<int, int>>(w.Map);
|
||||||
|
|
||||||
|
w.AddFrameEndTask(_ =>
|
||||||
|
{
|
||||||
|
// Set initial terrain data
|
||||||
|
foreach (var uv in world.Map.AllCells.MapCoords)
|
||||||
|
UpdateTerrainCellColor(uv);
|
||||||
|
|
||||||
|
world.Map.Tiles.CellEntryChanged += UpdateTerrainCell;
|
||||||
|
world.Map.CustomTerrain.CellEntryChanged += UpdateTerrainCell;
|
||||||
|
|
||||||
|
IsInitialized = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<int, int> this[MPos uv]
|
||||||
|
{
|
||||||
|
get { return terrainColor[uv]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<int, int> GetColor(Map map, MPos uv)
|
||||||
|
{
|
||||||
|
var custom = map.CustomTerrain[uv];
|
||||||
|
int leftColor, rightColor;
|
||||||
|
if (custom == byte.MaxValue)
|
||||||
|
{
|
||||||
|
var type = map.Rules.TileSet.GetTileInfo(map.Tiles[uv]);
|
||||||
|
leftColor = type != null ? type.LeftColor.ToArgb() : Color.Black.ToArgb();
|
||||||
|
rightColor = type != null ? type.RightColor.ToArgb() : Color.Black.ToArgb();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
leftColor = rightColor = map.Rules.TileSet[custom].Color.ToArgb();
|
||||||
|
|
||||||
|
return Pair.New(leftColor, rightColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,6 +57,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
Sprite actorSprite;
|
Sprite actorSprite;
|
||||||
Sprite shroudSprite;
|
Sprite shroudSprite;
|
||||||
Shroud renderShroud;
|
Shroud renderShroud;
|
||||||
|
PlayerRadarTerrain playerRadarTerrain;
|
||||||
|
Player currentPlayer;
|
||||||
|
|
||||||
public string SoundUp { get; private set; }
|
public string SoundUp { get; private set; }
|
||||||
public string SoundDown { get; private set; }
|
public string SoundDown { get; private set; }
|
||||||
@@ -66,7 +68,9 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
|
|
||||||
radarPings = world.WorldActor.TraitOrDefault<RadarPings>();
|
radarPings = world.WorldActor.TraitOrDefault<RadarPings>();
|
||||||
|
MarkShroudDirty(world.Map.AllCells.MapCoords.Select(uv => (PPos)uv));
|
||||||
|
|
||||||
isRectangularIsometric = world.Map.Grid.Type == MapGridType.RectangularIsometric;
|
isRectangularIsometric = world.Map.Grid.Type == MapGridType.RectangularIsometric;
|
||||||
cellWidth = isRectangularIsometric ? 2 : 1;
|
cellWidth = isRectangularIsometric ? 2 : 1;
|
||||||
@@ -76,6 +80,11 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
previewWidth = 2 * previewWidth - 1;
|
previewWidth = 2 * previewWidth - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CellTerrainColorChanged(MPos puv)
|
||||||
|
{
|
||||||
|
UpdateTerrainColor(puv);
|
||||||
|
}
|
||||||
|
|
||||||
public override void Initialize(WidgetArgs args)
|
public override void Initialize(WidgetArgs args)
|
||||||
{
|
{
|
||||||
base.Initialize(args);
|
base.Initialize(args);
|
||||||
@@ -87,12 +96,72 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
MapBoundsChanged();
|
MapBoundsChanged();
|
||||||
|
|
||||||
// Set initial terrain data
|
if (world.Type == WorldType.Regular)
|
||||||
foreach (var cell in world.Map.AllCells)
|
SetPlayer(world.LocalPlayer ?? world.RenderPlayer);
|
||||||
UpdateTerrainCell(cell);
|
else
|
||||||
|
{
|
||||||
|
// Set initial terrain data
|
||||||
|
foreach (var uv in world.Map.AllCells.MapCoords)
|
||||||
|
UpdateTerrainColor(uv);
|
||||||
|
|
||||||
world.Map.Tiles.CellEntryChanged += UpdateTerrainCell;
|
world.Map.Tiles.CellEntryChanged += UpdateTerrainCell;
|
||||||
world.Map.CustomTerrain.CellEntryChanged += UpdateTerrainCell;
|
world.Map.CustomTerrain.CellEntryChanged += UpdateTerrainCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.RenderPlayerChanged += WorldOnRenderPlayerChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTerrainCell(CPos cell)
|
||||||
|
{
|
||||||
|
var uv = cell.ToMPos(world.Map);
|
||||||
|
|
||||||
|
UpdateTerrainColor(uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldOnRenderPlayerChanged(Player player)
|
||||||
|
{
|
||||||
|
SetPlayer(player);
|
||||||
|
|
||||||
|
// Set initial terrain data
|
||||||
|
foreach (var uv in world.Map.AllCells.MapCoords)
|
||||||
|
UpdateTerrainColor(uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPlayer(Player player)
|
||||||
|
{
|
||||||
|
currentPlayer = player;
|
||||||
|
|
||||||
|
var newRenderShroud = player != null ? player.Shroud : null;
|
||||||
|
if (newRenderShroud != renderShroud)
|
||||||
|
{
|
||||||
|
if (renderShroud != null)
|
||||||
|
renderShroud.CellsChanged -= MarkShroudDirty;
|
||||||
|
|
||||||
|
if (newRenderShroud != null)
|
||||||
|
{
|
||||||
|
// Redraw the full shroud sprite
|
||||||
|
MarkShroudDirty(world.Map.AllCells.MapCoords.Select(uv => (PPos)uv));
|
||||||
|
|
||||||
|
// Update the notification binding
|
||||||
|
newRenderShroud.CellsChanged += MarkShroudDirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderShroud = newRenderShroud;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newPlayerRadarTerrain =
|
||||||
|
currentPlayer != null ? currentPlayer.PlayerActor.TraitOrDefault<PlayerRadarTerrain>() : null;
|
||||||
|
|
||||||
|
if (newPlayerRadarTerrain != playerRadarTerrain)
|
||||||
|
{
|
||||||
|
if (playerRadarTerrain != null)
|
||||||
|
playerRadarTerrain.CellTerrainColorChanged -= CellTerrainColorChanged;
|
||||||
|
|
||||||
|
if (newPlayerRadarTerrain != null)
|
||||||
|
newPlayerRadarTerrain.CellTerrainColorChanged += CellTerrainColorChanged;
|
||||||
|
|
||||||
|
playerRadarTerrain = newPlayerRadarTerrain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapBoundsChanged()
|
void MapBoundsChanged()
|
||||||
@@ -132,23 +201,11 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
actorSprite = new Sprite(radarSheet, new Rectangle(b.Location + new Size(0, previewHeight), b.Size), TextureChannel.RGBA);
|
actorSprite = new Sprite(radarSheet, new Rectangle(b.Location + new Size(0, previewHeight), b.Size), TextureChannel.RGBA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateTerrainCell(CPos cell)
|
void UpdateTerrainColor(MPos uv)
|
||||||
{
|
{
|
||||||
var uv = cell.ToMPos(world.Map);
|
var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ? playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, uv);
|
||||||
|
var leftColor = colorPair.First;
|
||||||
if (!world.Map.CustomTerrain.Contains(uv))
|
var rightColor = colorPair.Second;
|
||||||
return;
|
|
||||||
|
|
||||||
var custom = world.Map.CustomTerrain[uv];
|
|
||||||
int leftColor, rightColor;
|
|
||||||
if (custom == byte.MaxValue)
|
|
||||||
{
|
|
||||||
var type = world.Map.Rules.TileSet.GetTileInfo(world.Map.Tiles[uv]);
|
|
||||||
leftColor = type != null ? type.LeftColor.ToArgb() : Color.Black.ToArgb();
|
|
||||||
rightColor = type != null ? type.RightColor.ToArgb() : Color.Black.ToArgb();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
leftColor = rightColor = world.Map.Rules.TileSet[custom].Color.ToArgb();
|
|
||||||
|
|
||||||
var stride = radarSheet.Size.Width;
|
var stride = radarSheet.Size.Width;
|
||||||
|
|
||||||
@@ -341,25 +398,6 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
var rp = world.RenderPlayer;
|
|
||||||
var newRenderShroud = rp != null ? rp.Shroud : null;
|
|
||||||
if (newRenderShroud != renderShroud)
|
|
||||||
{
|
|
||||||
if (renderShroud != null)
|
|
||||||
renderShroud.CellsChanged -= MarkShroudDirty;
|
|
||||||
|
|
||||||
if (newRenderShroud != null)
|
|
||||||
{
|
|
||||||
// Redraw the full shroud sprite
|
|
||||||
MarkShroudDirty(world.Map.AllCells.MapCoords.Select(uv => (PPos)uv));
|
|
||||||
|
|
||||||
// Update the notification binding
|
|
||||||
newRenderShroud.CellsChanged += MarkShroudDirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderShroud = newRenderShroud;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The actor layer is updated every tick
|
// The actor layer is updated every tick
|
||||||
var stride = radarSheet.Size.Width;
|
var stride = radarSheet.Size.Width;
|
||||||
Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride);
|
Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride);
|
||||||
@@ -451,8 +489,11 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
public override void Removed()
|
public override void Removed()
|
||||||
{
|
{
|
||||||
base.Removed();
|
base.Removed();
|
||||||
world.Map.Tiles.CellEntryChanged -= UpdateTerrainCell;
|
|
||||||
world.Map.CustomTerrain.CellEntryChanged -= UpdateTerrainCell;
|
if (playerRadarTerrain != null)
|
||||||
|
playerRadarTerrain.CellTerrainColorChanged -= CellTerrainColorChanged;
|
||||||
|
|
||||||
|
world.RenderPlayerChanged -= WorldOnRenderPlayerChanged;
|
||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,3 +60,4 @@ Player:
|
|||||||
PlayerExperience:
|
PlayerExperience:
|
||||||
ConditionManager:
|
ConditionManager:
|
||||||
GameSaveViewportManager:
|
GameSaveViewportManager:
|
||||||
|
PlayerRadarTerrain:
|
||||||
|
|||||||
@@ -152,3 +152,4 @@ Player:
|
|||||||
PlayerExperience:
|
PlayerExperience:
|
||||||
ConditionManager:
|
ConditionManager:
|
||||||
GameSaveViewportManager:
|
GameSaveViewportManager:
|
||||||
|
PlayerRadarTerrain:
|
||||||
|
|||||||
@@ -151,3 +151,4 @@ Player:
|
|||||||
PlayerExperience:
|
PlayerExperience:
|
||||||
ConditionManager:
|
ConditionManager:
|
||||||
GameSaveViewportManager:
|
GameSaveViewportManager:
|
||||||
|
PlayerRadarTerrain:
|
||||||
|
|||||||
@@ -124,3 +124,4 @@ Player:
|
|||||||
PlayerExperience:
|
PlayerExperience:
|
||||||
ConditionManager:
|
ConditionManager:
|
||||||
GameSaveViewportManager:
|
GameSaveViewportManager:
|
||||||
|
PlayerRadarTerrain:
|
||||||
|
|||||||
Reference in New Issue
Block a user