Move ShroudPalette, ShroudRenderer and StartGameNotification to Common

Move World into Traits folder
This commit is contained in:
reaperrr
2014-11-09 16:04:23 +01:00
parent 3372914216
commit 41f3ee1080
15 changed files with 17 additions and 16 deletions

View File

@@ -1,97 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Network;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
[Desc("Attach this to the world actor.")]
public class CreateMPPlayersInfo : TraitInfo<CreateMPPlayers> { }
public class CreateMPPlayers : ICreatePlayers
{
public void CreatePlayers(World w)
{
// create the unplayable map players -- neutral, shellmap, scripted, etc.
foreach (var kv in w.Map.Players.Where(p => !p.Value.Playable))
{
var player = new Player(w, null, null, kv.Value);
w.AddPlayer(player);
if (kv.Value.OwnsWorld)
w.WorldActor.Owner = player;
}
// create the players which are bound through slots.
foreach (var kv in w.LobbyInfo.Slots)
{
var client = w.LobbyInfo.ClientInSlot(kv.Key);
if (client == null)
continue;
var player = new Player(w, client, kv.Value, w.Map.Players[kv.Value.PlayerReference]);
w.AddPlayer(player);
if (client.Index == Game.LocalClientId)
w.SetLocalPlayer(player.InternalName);
}
// create a player that is allied with everyone for shared observer shroud
w.AddPlayer(new Player(w, null, null, new PlayerReference
{
Name = "Everyone",
NonCombatant = true,
Spectating = true,
Allies = w.Players.Where(p => !p.NonCombatant && p.Playable).Select(p => p.InternalName).ToArray()
}));
foreach (var p in w.Players)
foreach (var q in w.Players)
if (!p.Stances.ContainsKey(q))
p.Stances[q] = ChooseInitialStance(p, q);
}
static Stance ChooseInitialStance(Player p, Player q)
{
if (p == q)
return Stance.Ally;
if (q.Spectating && !p.NonCombatant && p.Playable)
return Stance.Ally;
// Stances set via PlayerReference
if (p.PlayerReference.Allies.Contains(q.InternalName))
return Stance.Ally;
if (p.PlayerReference.Enemies.Contains(q.InternalName))
return Stance.Enemy;
// HACK: Map players share a ClientID with the host, so would
// otherwise take the host's team stance instead of being neutral
if (p.PlayerReference.Playable && q.PlayerReference.Playable)
{
// Stances set via lobby teams
var pc = GetClientForPlayer(p);
var qc = GetClientForPlayer(q);
if (pc != null && qc != null)
return pc.Team != 0 && pc.Team == qc.Team
? Stance.Ally : Stance.Enemy;
}
// Otherwise, default to neutral
return Stance.Neutral;
}
static Session.Client GetClientForPlayer(Player p)
{
return p.World.LobbyInfo.ClientWithIndex(p.ClientIndex);
}
}
}

View File

@@ -1,89 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
public class MPStartLocationsInfo : TraitInfo<MPStartLocations>
{
public readonly WRange InitialExploreRange = WRange.FromCells(5);
}
public class MPStartLocations : IWorldLoaded
{
public Dictionary<Player, CPos> Start = new Dictionary<Player, CPos>();
public void WorldLoaded(World world, WorldRenderer wr)
{
var spawns = world.Map.GetSpawnPoints().ToList();
var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != null)
.Select(c => spawns[c.SpawnPoint-1]).ToList();
var available = spawns.Except(taken).ToList();
// Set spawn
foreach (var kv in world.LobbyInfo.Slots)
{
var player = FindPlayerInSlot(world, kv.Key);
if (player == null) continue;
var client = world.LobbyInfo.ClientInSlot(kv.Key);
var spid = (client == null || client.SpawnPoint == 0)
? ChooseSpawnPoint(world, available, taken)
: spawns[client.SpawnPoint-1];
Start.Add(player, spid);
player.SpawnPoint = (client == null || client.SpawnPoint == 0)
? spawns.IndexOf(spid) + 1
: client.SpawnPoint;
}
// Explore allied shroud
var explore = world.WorldActor.Info.Traits.Get<MPStartLocationsInfo>().InitialExploreRange;
foreach (var p in Start.Keys)
foreach (var q in world.Players)
if (p.IsAlliedWith(q))
q.Shroud.Explore(world, Start[p], explore);
// Set viewport
if (world.LocalPlayer != null && Start.ContainsKey(world.LocalPlayer))
wr.Viewport.Center(world.Map.CenterOfCell(Start[world.LocalPlayer]));
}
static Player FindPlayerInSlot(World world, string pr)
{
return world.Players.FirstOrDefault(p => p.PlayerReference.Name == pr);
}
static CPos ChooseSpawnPoint(World world, List<CPos> available, List<CPos> taken)
{
if (available.Count == 0)
throw new InvalidOperationException("No free spawnpoint.");
var n = taken.Count == 0
? world.SharedRandom.Next(available.Count)
: available // pick the most distant spawnpoint from everyone else
.Select((k, i) => Pair.New(k, i))
.MaxBy(a => taken.Sum(t => (t - a.First).LengthSquared)).Second;
var sp = available[n];
available.RemoveAt(n);
taken.Add(sp);
return sp;
}
}
}

View File

@@ -1,41 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
[Desc("Used by SpawnMPUnits. Attach these to the world actor. You can have multiple variants by adding @suffixes.")]
public class MPStartUnitsInfo : TraitInfo<MPStartUnits>
{
[Desc("Internal class ID.")]
public readonly string Class = "none";
[Desc("Exposed via the UI to the player.")]
public readonly string ClassName = "Unlabeled";
[Desc("Only available when selecting this faction.", "Leave empty for no restrictions.")]
public readonly string[] Races = { };
[Desc("The mobile construction vehicle.")]
public readonly string BaseActor = null;
[Desc("A group of units ready to defend or scout.")]
public readonly string[] SupportActors = { };
[Desc("Inner radius for spawning support actors")]
public readonly int InnerSupportRadius = 2;
[Desc("Outer radius for spawning support actors")]
public readonly int OuterSupportRadius = 4;
}
public class MPStartUnits { }
}

View File

@@ -1,51 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
class PlayMusicOnMapLoadInfo : ITraitInfo
{
public readonly string Music = null;
public readonly bool Loop = false;
public object Create(ActorInitializer init) { return new PlayMusicOnMapLoad(init.world, this); }
}
class PlayMusicOnMapLoad : IWorldLoaded
{
readonly PlayMusicOnMapLoadInfo info;
readonly World world;
public PlayMusicOnMapLoad(World world, PlayMusicOnMapLoadInfo info)
{
this.world = world;
this.info = info;
}
public void WorldLoaded(World world, WorldRenderer wr)
{
PlayMusic();
}
void PlayMusic()
{
var onComplete = info.Loop ? (Action)PlayMusic : () => {};
if (Game.Settings.Sound.MapMusic &&
world.Map.Rules.Music.ContainsKey(info.Music))
Sound.PlayMusicThen(world.Map.Rules.Music[info.Music], onComplete);
}
}
}

View File

@@ -1,113 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
public class RadarPingsInfo : ITraitInfo
{
public readonly int FromRadius = 200;
public readonly int ToRadius = 15;
public readonly int ShrinkSpeed = 4;
public readonly float RotationSpeed = 0.12f;
public object Create(ActorInitializer init) { return new RadarPings(this); }
}
public class RadarPings : ITick
{
public readonly List<RadarPing> Pings = new List<RadarPing>();
readonly RadarPingsInfo info;
public WPos? LastPingPosition;
public RadarPings(RadarPingsInfo info)
{
this.info = info;
}
public void Tick(Actor self)
{
foreach (var ping in Pings.ToArray())
if (!ping.Tick())
Pings.Remove(ping);
}
public RadarPing Add(Func<bool> isVisible, WPos position, Color color, int duration)
{
var ping = new RadarPing(isVisible, position, color, duration,
info.FromRadius, info.ToRadius, info.ShrinkSpeed, info.RotationSpeed);
if (ping.IsVisible())
LastPingPosition = ping.Position;
Pings.Add(ping);
return ping;
}
public void Remove(RadarPing ping)
{
Pings.Remove(ping);
}
}
public class RadarPing
{
public Func<bool> IsVisible;
public WPos Position;
public Color Color;
public int Duration;
public int FromRadius;
public int ToRadius;
public int ShrinkSpeed;
public float RotationSpeed;
int radius;
float angle;
int tick;
public RadarPing(Func<bool> isVisible, WPos position, Color color, int duration,
int fromRadius, int toRadius, int shrinkSpeed, float rotationSpeed)
{
IsVisible = isVisible;
Position = position;
Color = color;
Duration = duration;
FromRadius = fromRadius;
ToRadius = toRadius;
ShrinkSpeed = shrinkSpeed;
RotationSpeed = rotationSpeed;
radius = fromRadius;
}
public bool Tick()
{
if (++tick == Duration)
return false;
radius = Math.Max(radius - ShrinkSpeed, ToRadius);
angle -= RotationSpeed;
return true;
}
public IEnumerable<float2> Points(float2 center)
{
yield return center + radius * float2.FromAngle(angle);
yield return center + radius * float2.FromAngle((float)(angle + 2 * Math.PI / 3));
yield return center + radius * float2.FromAngle((float)(angle + 4 * Math.PI / 3));
}
}
}

View File

@@ -1,20 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
namespace OpenRA.Mods.Common
{
public sealed class ResourceClaim
{
public readonly Actor Claimer;
public CPos Cell;
public ResourceClaim(Actor claimer, CPos cell) { Claimer = claimer; Cell = cell; }
}
}

View File

@@ -1,128 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
[Desc("Allows harvesters to coordinate their operations. Attach this to the world actor.")]
public sealed class ResourceClaimLayerInfo : TraitInfo<ResourceClaimLayer> { }
public sealed class ResourceClaimLayer : IWorldLoaded
{
Dictionary<CPos, ResourceClaim> claimByCell;
Dictionary<Actor, ResourceClaim> claimByActor;
private void MakeClaim(Actor claimer, CPos cell)
{
UnclaimByActor(claimer);
UnclaimByCell(cell, claimer);
claimByActor[claimer] = claimByCell[cell] = new ResourceClaim(claimer, cell);
}
private void Unclaim(ResourceClaim claim, Actor claimer)
{
if (claimByActor.Remove(claim.Claimer) & claimByCell.Remove(claim.Cell))
{
if (claim.Claimer.Destroyed) return;
if (!claim.Claimer.IsInWorld) return;
if (claim.Claimer.IsDead()) return;
claim.Claimer.Trait<INotifyResourceClaimLost>().OnNotifyResourceClaimLost(claim.Claimer, claim, claimer);
}
}
public void WorldLoaded(World w, WorldRenderer wr)
{
// NOTE(jsd): 32 seems a sane default initial capacity for the total # of harvesters in a game. Purely a guesstimate.
claimByCell = new Dictionary<CPos, ResourceClaim>(32);
claimByActor = new Dictionary<Actor, ResourceClaim>(32);
}
/// <summary>
/// Attempt to claim the resource at the cell for the given actor.
/// </summary>
/// <param name="claimer"></param>
/// <param name="cell"></param>
/// <returns></returns>
public bool ClaimResource(Actor claimer, CPos cell)
{
// Has anyone else claimed this point?
ResourceClaim claim;
if (claimByCell.TryGetValue(cell, out claim))
{
// Same claimer:
if (claim.Claimer == claimer) return true;
// This is to prevent in-fighting amongst friendly harvesters:
if (claimer.Owner == claim.Claimer.Owner) return false;
if (claimer.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return false;
// If an enemy/neutral claimed this, don't respect that claim:
}
// Either nobody else claims this point or an enemy/neutral claims it:
MakeClaim(claimer, cell);
return true;
}
/// <summary>
/// Release the last resource claim made on this cell.
/// </summary>
/// <param name="cell"></param>
public void UnclaimByCell(CPos cell, Actor claimer)
{
ResourceClaim claim;
if (claimByCell.TryGetValue(cell, out claim))
Unclaim(claim, claimer);
}
/// <summary>
/// Release the last resource claim made by this actor.
/// </summary>
/// <param name="claimer"></param>
public void UnclaimByActor(Actor claimer)
{
ResourceClaim claim;
if (claimByActor.TryGetValue(claimer, out claim))
Unclaim(claim, claimer);
}
/// <summary>
/// Is the cell location <paramref name="cell"/> claimed for harvesting by any other actor?
/// </summary>
/// <param name="self"></param>
/// <param name="cell"></param>
/// <returns>true if already claimed by an ally that isn't <paramref name="self"/>; false otherwise.</returns>
public bool IsClaimedByAnyoneElse(Actor self, CPos cell, out ResourceClaim claim)
{
if (claimByCell.TryGetValue(cell, out claim))
{
// Same claimer:
if (claim.Claimer == self) return false;
// This is to prevent in-fighting amongst friendly harvesters:
if (self.Owner == claim.Claimer.Owner) return true;
if (self.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return true;
// If an enemy/neutral claimed this, don't respect that claim and fall through:
}
else
{
// No claim.
claim = null;
}
return false;
}
}
}

View File

@@ -1,145 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
[Desc("Attach this to the world actor.", "Order of the layers defines the Z sorting.")]
public class SmudgeLayerInfo : ITraitInfo
{
public readonly string Type = "Scorch";
[Desc("Sprite sequence name")]
public readonly string Sequence = "scorch";
public readonly int SmokePercentage = 25;
[Desc("Sprite sequence name")]
public readonly string SmokeType = "smoke_m";
public readonly string Palette = "terrain";
public object Create(ActorInitializer init) { return new SmudgeLayer(this); }
}
public class SmudgeLayer : IRenderOverlay, IWorldLoaded, ITickRender
{
struct Smudge
{
public string Type;
public int Depth;
public Sprite Sprite;
}
public SmudgeLayerInfo Info;
Dictionary<CPos, Smudge> tiles;
Dictionary<CPos, Smudge> dirty;
Dictionary<string, Sprite[]> smudges;
World world;
public SmudgeLayer(SmudgeLayerInfo info)
{
this.Info = info;
}
public void WorldLoaded(World w, WorldRenderer wr)
{
world = w;
tiles = new Dictionary<CPos, Smudge>();
dirty = new Dictionary<CPos, Smudge>();
smudges = new Dictionary<string, Sprite[]>();
var types = world.Map.SequenceProvider.Sequences(Info.Sequence);
foreach (var t in types)
{
var seq = world.Map.SequenceProvider.GetSequence(Info.Sequence, t);
var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x));
smudges.Add(t, sprites);
}
// Add map smudges
foreach (var s in w.Map.Smudges.Value.Where(s => smudges.Keys.Contains(s.Type)))
{
var smudge = new Smudge
{
Type = s.Type,
Depth = s.Depth,
Sprite = smudges[s.Type][s.Depth]
};
tiles.Add((CPos)s.Location, smudge);
}
}
public void AddSmudge(CPos loc)
{
if (Game.CosmeticRandom.Next(0, 100) <= Info.SmokePercentage)
world.AddFrameEndTask(w => w.Add(new Smoke(w, world.Map.CenterOfCell(loc), Info.SmokeType)));
if (!dirty.ContainsKey(loc) && !tiles.ContainsKey(loc))
{
// No smudge; create a new one
var st = smudges.Keys.Random(world.SharedRandom);
dirty[loc] = new Smudge { Type = st, Depth = 0, Sprite = smudges[st][0] };
}
else
{
// Existing smudge; make it deeper
var tile = dirty.ContainsKey(loc) ? dirty[loc] : tiles[loc];
var maxDepth = smudges[tile.Type].Length;
if (tile.Depth < maxDepth - 1)
{
tile.Depth++;
tile.Sprite = smudges[tile.Type][tile.Depth];
}
dirty[loc] = tile;
}
}
public void TickRender(WorldRenderer wr, Actor self)
{
var remove = new List<CPos>();
foreach (var kv in dirty)
{
if (!self.World.FogObscures(kv.Key))
{
tiles[kv.Key] = kv.Value;
remove.Add(kv.Key);
}
}
foreach (var r in remove)
dirty.Remove(r);
}
public void Render(WorldRenderer wr)
{
var pal = wr.Palette(Info.Palette);
foreach (var kv in tiles)
{
if (!wr.Viewport.VisibleCells.Contains(kv.Key))
continue;
if (world.ShroudObscures(kv.Key))
continue;
new SpriteRenderable(kv.Value.Sprite, world.Map.CenterOfCell(kv.Key),
WVec.Zero, -511, pal, 1f, true).Render(wr); // TODO ZOffset is ignored
}
}
}
}

View File

@@ -1,44 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
public class SpawnMapActorsInfo : TraitInfo<SpawnMapActors> { }
public class SpawnMapActors : IWorldLoaded
{
public Dictionary<string, Actor> Actors = new Dictionary<string, Actor>();
public uint LastMapActorID { get; private set; }
public void WorldLoaded(World world, WorldRenderer wr)
{
foreach (var actorReference in world.Map.Actors.Value)
{
// if there is no real player associated, dont spawn it.
var ownerName = actorReference.Value.InitDict.Get<OwnerInit>().PlayerName;
if (!world.Players.Any(p => p.InternalName == ownerName))
continue;
var initDict = actorReference.Value.InitDict;
initDict.Add(new SkipMakeAnimsInit());
var actor = world.CreateActor(actorReference.Value.Type, initDict);
Actors[actorReference.Key] = actor;
LastMapActorID = actor.ActorID;
}
}
}
public class SkipMakeAnimsInit : IActorInit {}
}

View File

@@ -1,127 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Graphics;
namespace OpenRA.Mods.Common
{
[Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")]
public class TerrainGeometryOverlayInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new TerrainGeometryOverlay(init.self); }
}
public class TerrainGeometryOverlay : IRenderOverlay
{
readonly int[][] vertices = new int[][]
{
// Flat
new[] { 0, 0, 0, 0 },
// Slopes (two corners high)
new[] { 0, 0, 1, 1 },
new[] { 1, 0, 0, 1 },
new[] { 1, 1, 0, 0 },
new[] { 0, 1, 1, 0 },
// Slopes (one corner high)
new[] { 0, 0, 0, 1 },
new[] { 1, 0, 0, 0 },
new[] { 0, 1, 0, 0 },
new[] { 0, 0, 1, 0 },
// Slopes (three corners high)
new[] { 1, 0, 1, 1 },
new[] { 1, 1, 0, 1 },
new[] { 1, 1, 1, 0 },
new[] { 0, 1, 1, 1 },
// Slopes (two corners high, one corner double high)
new[] { 1, 0, 1, 2 },
new[] { 2, 1, 0, 1 },
new[] { 1, 2, 1, 0 },
new[] { 0, 1, 2, 1 },
// Slopes (two corners high, alternating)
new[] { 1, 0, 1, 0 },
new[] { 0, 1, 0, 1 },
new[] { 1, 0, 1, 0 },
new[] { 0, 1, 0, 1 }
};
readonly Lazy<DeveloperMode> devMode;
public TerrainGeometryOverlay(Actor self)
{
devMode = Exts.Lazy(() => self.World.LocalPlayer != null ? self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>() : null);
}
public void Render(WorldRenderer wr)
{
if (devMode.Value == null || !devMode.Value.ShowTerrainGeometry)
return;
var ts = wr.world.Map.TileShape;
var colors = wr.world.TileSet.HeightDebugColors;
var leftDelta = ts == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
var topDelta = ts == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
var rightDelta = ts == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
var bottomDelta = ts == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
foreach (var cell in wr.Viewport.VisibleCells)
{
var lr = Game.Renderer.WorldLineRenderer;
var pos = wr.world.Map.CenterOfCell(cell);
var height = (int)wr.world.Map.MapHeight.Value[cell];
var tile = wr.world.Map.MapTiles.Value[cell];
TerrainTileInfo tileInfo = null;
// TODO: This is a temporary workaround for our sloppy tileset definitions
// (ra/td templates omit Clear tiles from templates)
try
{
tileInfo = wr.world.TileSet.Templates[tile.Type][tile.Index];
}
catch (Exception) { }
if (tileInfo == null)
continue;
var leftHeight = vertices[tileInfo.RampType][0];
var topHeight = vertices[tileInfo.RampType][1];
var rightHeight = vertices[tileInfo.RampType][2];
var bottomHeight = vertices[tileInfo.RampType][3];
var leftColor = colors[height + leftHeight];
var topColor = colors[height + topHeight];
var rightColor = colors[height + rightHeight];
var bottomColor = colors[height + bottomHeight];
var left = wr.ScreenPxPosition(pos + leftDelta + new WVec(0, 0, 512 * leftHeight)).ToFloat2();
var top = wr.ScreenPxPosition(pos + topDelta + new WVec(0, 0, 512 * topHeight)).ToFloat2();
var right = wr.ScreenPxPosition(pos + rightDelta + new WVec(0, 0, 512 * rightHeight)).ToFloat2();
var bottom = wr.ScreenPxPosition(pos + bottomDelta + new WVec(0, 0, 512 * bottomHeight)).ToFloat2();
lr.DrawLine(left, top, leftColor, topColor);
lr.DrawLine(top, right, topColor, rightColor);
lr.DrawLine(right, bottom, rightColor, bottomColor);
lr.DrawLine(bottom, left, bottomColor, leftColor);
}
}
}
}