diff --git a/OpenRA.Game/Graphics/QuadRenderer.cs b/OpenRA.Game/Graphics/QuadRenderer.cs
new file mode 100644
index 0000000000..26ab90664d
--- /dev/null
+++ b/OpenRA.Game/Graphics/QuadRenderer.cs
@@ -0,0 +1,60 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2011 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.Drawing;
+using OpenRA.FileFormats.Graphics;
+
+namespace OpenRA.Graphics
+{
+ public class QuadRenderer : Renderer.IBatchRenderer
+ {
+ Renderer renderer;
+ IShader shader;
+
+ Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
+ int nv = 0;
+
+ public QuadRenderer(Renderer renderer, IShader shader)
+ {
+ this.renderer = renderer;
+ this.shader = shader;
+ }
+
+ public void Flush()
+ {
+ if (nv > 0)
+ {
+ shader.Render(() =>
+ {
+ var vb = renderer.GetTempVertexBuffer();
+ vb.SetData(vertices, nv);
+ renderer.DrawBatch(vb, 0, nv, PrimitiveType.QuadList);
+ });
+
+ nv = 0;
+ }
+ }
+
+ public void FillRect(RectangleF r, Color color)
+ {
+ Renderer.CurrentBatchRenderer = this;
+
+ if (nv + 4 > Renderer.TempBufferSize)
+ Flush();
+
+ vertices[nv] = new Vertex(new float2(r.Left, r.Top), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f));
+ vertices[nv + 1] = new Vertex(new float2(r.Right, r.Top), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f));
+ vertices[nv + 2] = new Vertex(new float2(r.Right, r.Bottom), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f));
+ vertices[nv + 3] = new Vertex(new float2(r.Left, r.Bottom), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f));
+
+ nv += 4;
+ }
+ }
+}
diff --git a/OpenRA.Game/Graphics/Renderer.cs b/OpenRA.Game/Graphics/Renderer.cs
index 8be5040802..d98ddecd9d 100644
--- a/OpenRA.Game/Graphics/Renderer.cs
+++ b/OpenRA.Game/Graphics/Renderer.cs
@@ -28,6 +28,7 @@ namespace OpenRA.Graphics
internal static int TempBufferCount;
public SpriteRenderer WorldSpriteRenderer { get; private set; }
+ public QuadRenderer WorldQuadRenderer { get; private set; }
public LineRenderer WorldLineRenderer { get; private set; }
public LineRenderer LineRenderer { get; private set; }
public SpriteRenderer RgbaSpriteRenderer { get; private set; }
@@ -48,6 +49,7 @@ namespace OpenRA.Graphics
WorldSpriteRenderer = new SpriteRenderer(this, device.CreateShader("shp"));
WorldLineRenderer = new LineRenderer(this, device.CreateShader("line"));
LineRenderer = new LineRenderer(this, device.CreateShader("line"));
+ WorldQuadRenderer = new QuadRenderer(this, device.CreateShader("line"));
RgbaSpriteRenderer = new SpriteRenderer(this, device.CreateShader("rgba"));
SpriteRenderer = new SpriteRenderer(this, device.CreateShader("shp"));
diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj
index 890b04c2ca..e1d4cc465c 100755
--- a/OpenRA.Game/OpenRA.Game.csproj
+++ b/OpenRA.Game/OpenRA.Game.csproj
@@ -80,6 +80,7 @@
+
diff --git a/OpenRA.Mods.RA/Move/PathFinder.cs b/OpenRA.Mods.RA/Move/PathFinder.cs
index 8705463283..2ef3f8f452 100755
--- a/OpenRA.Mods.RA/Move/PathFinder.cs
+++ b/OpenRA.Mods.RA/Move/PathFinder.cs
@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using OpenRA.FileFormats;
using OpenRA.Support;
using OpenRA.Traits;
@@ -125,21 +126,43 @@ namespace OpenRA.Mods.RA.Move
{
using (fromSrc)
using (fromDest)
+ {
+ List path = null;
+
while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
{
/* make some progress on the first search */
var p = fromSrc.Expand(world);
- if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
- return MakeBidiPath(fromSrc, fromDest, p);
+ if (fromDest.cellInfo[p.X, p.Y].Seen &&
+ fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
+ {
+ path = MakeBidiPath(fromSrc, fromDest, p);
+ break;
+ }
/* make some progress on the second search */
var q = fromDest.Expand(world);
- if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
- return MakeBidiPath(fromSrc, fromDest, q);
+ if (fromSrc.cellInfo[q.X, q.Y].Seen &&
+ fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
+ {
+ path = MakeBidiPath(fromSrc, fromDest, q);
+ break;
+ }
}
+ var dbg = world.WorldActor.TraitOrDefault();
+ if (dbg != null)
+ {
+ dbg.AddLayer(fromSrc.considered.Select(p => new Pair(p, fromSrc.cellInfo[p.X, p.Y].MinCost)), fromSrc.maxCost);
+ dbg.AddLayer(fromDest.considered.Select(p => new Pair(p, fromDest.cellInfo[p.X, p.Y].MinCost)), fromDest.maxCost);
+ }
+
+ if (path != null)
+ return path;
+ }
+
return new List(0);
}
}
diff --git a/OpenRA.Mods.RA/Move/PathSearch.cs b/OpenRA.Mods.RA/Move/PathSearch.cs
index 8261f807b7..be8b3d6d45 100755
--- a/OpenRA.Mods.RA/Move/PathSearch.cs
+++ b/OpenRA.Mods.RA/Move/PathSearch.cs
@@ -26,7 +26,8 @@ namespace OpenRA.Mods.RA.Move
public bool checkForBlocked;
public Actor ignoreBuilding;
public bool inReverse;
-
+ public HashSet considered;
+ public int maxCost;
MobileInfo mobileInfo;
Actor self;
public Player owner { get { return self.Owner; } }
@@ -39,6 +40,8 @@ namespace OpenRA.Mods.RA.Move
this.self = self;
customCost = null;
queue = new PriorityQueue();
+ considered = new HashSet();
+ maxCost = 0;
}
public PathSearch InReverse()
@@ -108,14 +111,20 @@ namespace OpenRA.Mods.RA.Move
return p.Location;
}
+ // This current cell is ok; check all immediate directions:
+ considered.Add(p.Location);
+
foreach( CVec d in directions )
{
CPos newHere = p.Location + d;
- if (!world.Map.IsInMap(newHere.X, newHere.Y)) continue;
+ // Is this direction flat-out unusable or already seen?
+ if (!world.Map.IsInMap(newHere.X, newHere.Y))
+ continue;
if (cellInfo[newHere.X, newHere.Y].Seen)
continue;
+ // Now we may seriously consider this direction using heuristics:
var costHere = mobileInfo.MovementCostForCell(world, newHere);
if (costHere == int.MaxValue)
@@ -134,8 +143,12 @@ namespace OpenRA.Mods.RA.Move
int cellCost = costHere;
if (d.X * d.Y != 0) cellCost = (cellCost * 34) / 24;
+ int userCost = 0;
if (customCost != null)
- cellCost += customCost(newHere);
+ {
+ userCost = customCost(newHere);
+ cellCost += userCost;
+ }
// directional bonuses for smoother flow!
if (LaneBias != 0)
@@ -151,6 +164,7 @@ namespace OpenRA.Mods.RA.Move
int newCost = cellInfo[p.Location.X, p.Location.Y].MinCost + cellCost;
+ // Cost is even higher; next direction:
if (newCost >= cellInfo[newHere.X, newHere.Y].MinCost)
continue;
@@ -158,7 +172,11 @@ namespace OpenRA.Mods.RA.Move
cellInfo[newHere.X, newHere.Y].MinCost = newCost;
queue.Add(new PathDistance(newCost + est, newHere));
+
+ if (newCost > maxCost) maxCost = newCost;
+ considered.Add(newHere);
}
+
return p.Location;
}
diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
index 00c0d47f48..735cae25ae 100644
--- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
+++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
@@ -403,6 +403,7 @@
+
diff --git a/OpenRA.Mods.RA/World/DebugOverlay.cs b/OpenRA.Mods.RA/World/DebugOverlay.cs
new file mode 100644
index 0000000000..4d1f1b8af0
--- /dev/null
+++ b/OpenRA.Mods.RA/World/DebugOverlay.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using OpenRA.FileFormats;
+using OpenRA.Graphics;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.RA
+{
+ class DebugOverlayInfo : Traits.TraitInfo
+ {
+ }
+
+ class DebugOverlay : IRenderOverlay, IWorldLoaded
+ {
+ int[,] layer;
+ int refreshTick;
+ World world;
+
+ public void WorldLoaded(World w)
+ {
+ this.world = w;
+ this.layer = new int[w.Map.MapSize.X, w.Map.MapSize.Y];
+ this.refreshTick = 0;
+ }
+
+ public void AddLayer(IEnumerable> cellWeights, int maxWeight)
+ {
+ if (maxWeight == 0) return;
+
+ foreach (var p in cellWeights)
+ layer[p.First.X, p.First.Y] = layer[p.First.X, p.First.Y] / 2 + (p.Second * 128 / maxWeight);
+ }
+
+ public void Render(WorldRenderer wr)
+ {
+ var qr = Game.Renderer.WorldQuadRenderer;
+ bool doSwap = refreshTick - world.FrameNumber <= 0;
+ if (doSwap) refreshTick = world.FrameNumber + 20;
+
+ for (int j = world.Map.Bounds.Top; j <= world.Map.Bounds.Bottom; ++j)
+ for (int i = world.Map.Bounds.Left; i <= world.Map.Bounds.Right; ++i)
+ {
+ if (!world.Map.IsInMap(i, j)) continue;
+
+ var cell = new CPos(i, j);
+ var pix = cell.ToPPos();
+
+ var w = Math.Max(0, Math.Min(layer[i, j], 224));
+ if (doSwap)
+ {
+ layer[i, j] = layer[i, j] * 4 / 5;
+ }
+ qr.FillRect(new RectangleF(pix.X, pix.Y, Game.CellSize, Game.CellSize), Color.FromArgb(w, Color.White));
+ }
+ }
+ }
+}
diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml
index 0999f4ce4e..6b2f3ae00b 100644
--- a/mods/ra/rules/system.yaml
+++ b/mods/ra/rules/system.yaml
@@ -455,7 +455,7 @@ Player:
BaseAttackNotifier:
PlayerStatistics:
-World:
+World:
OpenWidgetAtGameStart:
Widget: INGAME_ROOT
ObserverWidget: OBSERVER_ROOT
@@ -562,6 +562,7 @@ World:
Type:Crater
Types:cr1,cr2,cr3,cr4,cr5,cr6
Depths:5,5,5,5,5,5
+ DebugOverlay:
SpawnMapActors:
CreateMPPlayers:
MPStartLocations: