New types for cell and pixel coordinate position/vectors.

This commit is contained in:
James Dunne
2012-06-20 23:22:27 -05:00
parent 0b98a8ce5e
commit 9c49143534
162 changed files with 1291 additions and 865 deletions

3
.gitignore vendored
View File

@@ -10,6 +10,9 @@ obj
*.manifest *.manifest
mods/*/*.dll mods/*/*.dll
# ReSharper crap
_ReSharper.*/
# Red Alert binary files # Red Alert binary files
mods/*/packages/*.[mM][iI][xX] mods/*/packages/*.[mM][iI][xX]

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Editor
for (var u = 0; u < template.Size.X; u++) for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++) for (var v = 0; v < template.Size.Y; v++)
{ {
if (surface.Map.IsInMap(new int2(u, v) + pos)) if (surface.Map.IsInMap(new CVec(u, v) + pos))
{ {
var z = u + v * template.Size.X; var z = u + v * template.Size.X;
if (tile.TileBitmapBytes[z] != null) if (tile.TileBitmapBytes[z] != null)
@@ -69,17 +69,17 @@ namespace OpenRA.Editor
Brush.Bitmap.Height * surface.Zoom); Brush.Bitmap.Height * surface.Zoom);
} }
void FloodFillWithBrush(Surface s, int2 pos) void FloodFillWithBrush(Surface s, CPos pos)
{ {
var queue = new Queue<int2>(); var queue = new Queue<CPos>();
var replace = s.Map.MapTiles.Value[pos.X, pos.Y]; var replace = s.Map.MapTiles.Value[pos.X, pos.Y];
var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y]; var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y];
Action<int, int> MaybeEnqueue = (x, y) => Action<int, int> maybeEnqueue = (x, y) =>
{ {
if (s.Map.IsInMap(x, y) && !touched[x, y]) if (s.Map.IsInMap(x, y) && !touched[x, y])
{ {
queue.Enqueue(new int2(x, y)); queue.Enqueue(new CPos(x, y));
touched[x, y] = true; touched[x, y] = true;
} }
}; };
@@ -91,16 +91,16 @@ namespace OpenRA.Editor
if (!s.Map.MapTiles.Value[p.X, p.Y].Equals(replace)) if (!s.Map.MapTiles.Value[p.X, p.Y].Equals(replace))
continue; continue;
var a = FindEdge(s, p, new int2(-1, 0), replace); var a = FindEdge(s, p, new CVec(-1, 0), replace);
var b = FindEdge(s, p, new int2(1, 0), replace); var b = FindEdge(s, p, new CVec(1, 0), replace);
for (var x = a.X; x <= b.X; x++) for (var x = a.X; x <= b.X; x++)
{ {
s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, index = (byte)0 }; s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, index = (byte)0 };
if (s.Map.MapTiles.Value[x, p.Y - 1].Equals(replace)) if (s.Map.MapTiles.Value[x, p.Y - 1].Equals(replace))
MaybeEnqueue(x, p.Y - 1); maybeEnqueue(x, p.Y - 1);
if (s.Map.MapTiles.Value[x, p.Y + 1].Equals(replace)) if (s.Map.MapTiles.Value[x, p.Y + 1].Equals(replace))
MaybeEnqueue(x, p.Y + 1); maybeEnqueue(x, p.Y + 1);
} }
} }
@@ -109,7 +109,7 @@ namespace OpenRA.Editor
s.Chunks.Clear(); s.Chunks.Clear();
} }
int2 FindEdge(Surface s, int2 p, int2 d, TileReference<ushort, byte> replace) CPos FindEdge(Surface s, CPos p, CVec d, TileReference<ushort, byte> replace)
{ {
for (; ; ) for (; ; )
{ {

View File

@@ -175,7 +175,7 @@ namespace OpenRA.Editor
foreach( var kv in wps ) foreach( var kv in wps )
{ {
var a = new ActorReference("mpspawn"); var a = new ActorReference("mpspawn");
a.Add(new LocationInit(kv.Second)); a.Add(new LocationInit((CPos)kv.Second));
a.Add(new OwnerInit("Neutral")); a.Add(new OwnerInit("Neutral"));
Map.Actors.Value.Add("spawn" + kv.First, a); Map.Actors.Value.Add("spawn" + kv.First, a);
} }
@@ -276,7 +276,7 @@ namespace OpenRA.Editor
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(overlayActorMapping[raOverlayNames[o]]) new ActorReference(overlayActorMapping[raOverlayNames[o]])
{ {
new LocationInit( new int2(i, j) ), new LocationInit( new CPos(i, j) ),
new OwnerInit( "Neutral" ) new OwnerInit( "Neutral" )
}); });
} }
@@ -294,7 +294,7 @@ namespace OpenRA.Editor
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(kv.Value.ToLowerInvariant()) new ActorReference(kv.Value.ToLowerInvariant())
{ {
new LocationInit(new int2(loc % MapSize, loc / MapSize)), new LocationInit(new CPos(loc % MapSize, loc / MapSize)),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}); });
} }
@@ -323,7 +323,7 @@ namespace OpenRA.Editor
foreach (KeyValuePair<string, string> kv in overlay) foreach (KeyValuePair<string, string> kv in overlay)
{ {
var loc = int.Parse(kv.Key); var loc = int.Parse(kv.Key);
var cell = new int2(loc % MapSize, loc / MapSize); var cell = new CPos(loc % MapSize, loc / MapSize);
var res = Pair.New((byte)0, (byte)0); var res = Pair.New((byte)0, (byte)0);
if (overlayResourceMapping.ContainsKey(kv.Value.ToLower())) if (overlayResourceMapping.ContainsKey(kv.Value.ToLower()))
@@ -353,7 +353,7 @@ namespace OpenRA.Editor
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant()) new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
{ {
new LocationInit(new int2(loc % MapSize, loc / MapSize)), new LocationInit(new CPos(loc % MapSize, loc / MapSize)),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}); });
} }
@@ -380,7 +380,7 @@ namespace OpenRA.Editor
var actor = new ActorReference(parts[1].ToLowerInvariant()) var actor = new ActorReference(parts[1].ToLowerInvariant())
{ {
new LocationInit(new int2(loc % MapSize, loc / MapSize)), new LocationInit(new CPos(loc % MapSize, loc / MapSize)),
new OwnerInit(parts[0]), new OwnerInit(parts[0]),
new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256), new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256),
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])), new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
@@ -432,7 +432,7 @@ namespace OpenRA.Editor
(byte)(color.Second.GetBrightness() * 255)) (byte)(color.Second.GetBrightness() * 255))
}; };
var Neutral = new [] {"Neutral"}; var neutral = new [] {"Neutral"};
foreach (var s in file.GetSection(section, true)) foreach (var s in file.GetSection(section, true))
{ {
Console.WriteLine(s.Key); Console.WriteLine(s.Key);
@@ -442,8 +442,8 @@ namespace OpenRA.Editor
pr.InitialCash = int.Parse(s.Value); pr.InitialCash = int.Parse(s.Value);
break; break;
case "Allies": case "Allies":
pr.Allies = s.Value.Split(',').Intersect(Players).Except(Neutral).ToArray(); pr.Allies = s.Value.Split(',').Intersect(Players).Except(neutral).ToArray();
pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(Neutral).ToArray(); pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(neutral).ToArray();
break; break;
} }
} }

View File

@@ -157,23 +157,23 @@ namespace OpenRA.Editor
void Erase() void Erase()
{ {
// Crash preventing // Crash preventing
var BrushLocation = GetBrushLocation(); var brushLocation = GetBrushLocation();
if (Map == null || BrushLocation.X >= Map.MapSize.X || if (Map == null || brushLocation.X >= Map.MapSize.X ||
BrushLocation.Y >= Map.MapSize.Y || brushLocation.Y >= Map.MapSize.Y ||
BrushLocation.X < 0 || brushLocation.X < 0 ||
BrushLocation.Y < 0) brushLocation.Y < 0)
return; return;
Tool = null; Tool = null;
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == BrushLocation); var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == brushLocation);
if (key.Key != null) Map.Actors.Value.Remove(key.Key); if (key.Key != null) Map.Actors.Value.Remove(key.Key);
if (Map.MapResources.Value[BrushLocation.X, BrushLocation.Y].type != 0) if (Map.MapResources.Value[brushLocation.X, brushLocation.Y].type != 0)
{ {
Map.MapResources.Value[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>(); Map.MapResources.Value[brushLocation.X, brushLocation.Y] = new TileReference<byte, byte>();
var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize); var ch = new int2((brushLocation.X) / ChunkSize, (brushLocation.Y) / ChunkSize);
if (Chunks.ContainsKey(ch)) if (Chunks.ContainsKey(ch))
{ {
Chunks[ch].Dispose(); Chunks[ch].Dispose();
@@ -267,31 +267,31 @@ namespace OpenRA.Editor
return bitmap; return bitmap;
} }
public int2 GetBrushLocation() public CPos GetBrushLocation()
{ {
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom); var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom); var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize); return new CPos(vX / TileSet.TileSize, vY / TileSet.TileSize);
} }
public void DrawActor(SGraphics g, int2 p, ActorTemplate t, ColorPalette cp) public void DrawActor(SGraphics g, CPos p, ActorTemplate t, ColorPalette cp)
{ {
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft; var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
DrawImage(g, t.Bitmap, p, centered, cp); DrawImage(g, t.Bitmap, p, centered, cp);
} }
float2 GetDrawPosition(int2 location, Bitmap bmp, bool centered) float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered)
{ {
float OffsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0; float offsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0;
float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX; float drawX = TileSet.TileSize * location.X * Zoom + Offset.X - offsetX;
float OffsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0; float offsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0;
float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY; float drawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - offsetY;
return new float2(DrawX, DrawY); return new float2(drawX, drawY);
} }
public void DrawImage(SGraphics g, Bitmap bmp, int2 location, bool centered, ColorPalette cp) public void DrawImage(SGraphics g, Bitmap bmp, CPos location, bool centered, ColorPalette cp)
{ {
var drawPos = GetDrawPosition(location, bmp, centered); var drawPos = GetDrawPosition(location, bmp, centered);
@@ -304,7 +304,7 @@ namespace OpenRA.Editor
if (cp != null) bmp.Palette = restorePalette; if (cp != null) bmp.Palette = restorePalette;
} }
void DrawActorBorder(SGraphics g, int2 p, ActorTemplate t) void DrawActorBorder(SGraphics g, CPos p, ActorTemplate t)
{ {
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft; var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
var drawPos = GetDrawPosition(p, t.Bitmap, centered); var drawPos = GetDrawPosition(p, t.Bitmap, centered);
@@ -399,9 +399,9 @@ namespace OpenRA.Editor
static class ActorReferenceExts static class ActorReferenceExts
{ {
public static int2 Location(this ActorReference ar) public static CPos Location(this ActorReference ar)
{ {
return ar.InitDict.Get<LocationInit>().value; return (CPos)ar.InitDict.Get<LocationInit>().value;
} }
public static void DrawStringContrast(this SGraphics g, Font f, string s, int x, int y, Brush fg, Brush bg) public static void DrawStringContrast(this SGraphics g, Font f, string s, int x, int y, Brush fg, Brush bg)

View File

@@ -32,9 +32,9 @@ namespace OpenRA
public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } } public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } }
public int2 Location { get { return occupySpace.Value.TopLeft; } } public CPos Location { get { return occupySpace.Value.TopLeft; } }
public int2 CenterLocation public PPos CenterLocation
{ {
get get
{ {
@@ -123,22 +123,30 @@ namespace OpenRA
// at its current altitude // at its current altitude
Rectangle CalculateBounds(bool useAltitude) Rectangle CalculateBounds(bool useAltitude)
{ {
var size = Size.Value; var size = (PVecInt)(Size.Value);
var loc = CenterLocation - size / 2; var loc = CenterLocation - size / 2;
var si = Info.Traits.GetOrDefault<SelectableInfo>(); var si = Info.Traits.GetOrDefault<SelectableInfo>();
if (si != null && si.Bounds != null && si.Bounds.Length > 2) if (si != null && si.Bounds != null && si.Bounds.Length > 2)
{ {
#if true
loc += new PVecInt(si.Bounds[2], si.Bounds[3]);
#else
loc.X += si.Bounds[2]; loc.X += si.Bounds[2];
loc.Y += si.Bounds[3]; loc.Y += si.Bounds[3];
#endif
} }
var move = Move.Value; var move = Move.Value;
if (move != null) if (move != null)
{ {
#if true
loc -= new PVecInt(0, move.Altitude);
#else
loc.Y -= move.Altitude; loc.Y -= move.Altitude;
#endif
if (useAltitude) if (useAltitude)
size = new int2(size.X, size.Y + move.Altitude); size = new PVecInt(size.X, size.Y + move.Altitude);
} }
return new Rectangle(loc.X, loc.Y, size.X, size.Y); return new Rectangle(loc.X, loc.Y, size.X, size.Y);

View File

@@ -62,12 +62,12 @@ namespace OpenRA
public int Value( World world ) { return value; } public int Value( World world ) { return value; }
} }
public class LocationInit : IActorInit<int2> public class LocationInit : IActorInit<CPos>
{ {
[FieldFromYamlKey] public readonly int2 value = int2.Zero; [FieldFromYamlKey] public readonly int2 value = int2.Zero;
public LocationInit() { } public LocationInit() { }
public LocationInit( int2 init ) { value = init; } public LocationInit( CPos init ) { value = init.ToInt2(); }
public int2 Value( World world ) { return value; } public CPos Value(World world) { return (CPos)value; }
} }
public class SubCellInit : IActorInit<SubCell> public class SubCellInit : IActorInit<SubCell>
@@ -78,12 +78,12 @@ namespace OpenRA
public SubCell Value(World world) { return (SubCell)value; } public SubCell Value(World world) { return (SubCell)value; }
} }
public class CenterLocationInit : IActorInit<int2> public class CenterLocationInit : IActorInit<PPos>
{ {
[FieldFromYamlKey] public readonly int2 value = int2.Zero; [FieldFromYamlKey] public readonly int2 value = int2.Zero;
public CenterLocationInit() { } public CenterLocationInit() { }
public CenterLocationInit( int2 init ) { value = init; } public CenterLocationInit(PPos init) { value = init.ToInt2(); }
public int2 Value( World world ) { return value; } public PPos Value(World world) { return (PPos)value; }
} }
public class OwnerInit : IActorInit<Player> public class OwnerInit : IActorInit<Player>

View File

@@ -37,7 +37,7 @@ namespace OpenRA
world.ActorRemoved += a => Remove( a, a.OccupiesSpace ); world.ActorRemoved += a => Remove( a, a.OccupiesSpace );
} }
public IEnumerable<Actor> GetUnitsAt( int2 a ) public IEnumerable<Actor> GetUnitsAt(CPos a)
{ {
if (!map.IsInMap(a)) yield break; if (!map.IsInMap(a)) yield break;
@@ -46,7 +46,7 @@ namespace OpenRA
yield return i.actor; yield return i.actor;
} }
public IEnumerable<Actor> GetUnitsAt( int2 a, SubCell sub ) public IEnumerable<Actor> GetUnitsAt(CPos a, SubCell sub)
{ {
if (!map.IsInMap(a)) yield break; if (!map.IsInMap(a)) yield break;
@@ -55,7 +55,7 @@ namespace OpenRA
yield return i.actor; yield return i.actor;
} }
public bool HasFreeSubCell(int2 a) public bool HasFreeSubCell(CPos a)
{ {
if (!AnyUnitsAt(a)) if (!AnyUnitsAt(a))
return true; return true;
@@ -64,12 +64,12 @@ namespace OpenRA
SubCell.BottomLeft, SubCell.BottomRight }.Any(b => !AnyUnitsAt(a,b)); SubCell.BottomLeft, SubCell.BottomRight }.Any(b => !AnyUnitsAt(a,b));
} }
public bool AnyUnitsAt(int2 a) public bool AnyUnitsAt(CPos a)
{ {
return influence[ a.X, a.Y ] != null; return influence[ a.X, a.Y ] != null;
} }
public bool AnyUnitsAt(int2 a, SubCell sub) public bool AnyUnitsAt(CPos a, SubCell sub)
{ {
for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next ) for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next )
if (i.subCell == sub || i.subCell == SubCell.FullCell) if (i.subCell == sub || i.subCell == SubCell.FullCell)

71
OpenRA.Game/CPos.cs Normal file
View File

@@ -0,0 +1,71 @@
#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;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Cell coordinate position in the world (coarse).
/// </summary>
public struct CPos
{
public readonly int X, Y;
public CPos(int x, int y) { X = x; Y = y; }
public static readonly CPos Zero = new CPos(0, 0);
public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); }
public static CPos operator +(CVec a, CPos b) { return new CPos(a.X + b.X, a.Y + b.Y); }
public static CPos operator +(CPos a, CVec b) { return new CPos(a.X + b.X, a.Y + b.Y); }
public static CPos operator -(CPos a, CVec b) { return new CPos(a.X - b.X, a.Y - b.Y); }
public static CVec operator -(CPos a, CPos b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(CPos me, CPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(CPos me, CPos other) { return !(me == other); }
public static CPos Max(CPos a, CPos b) { return new CPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CPos Min(CPos a, CPos b) { return new CPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PPos ToPPos() { return new PPos(Game.CellSize * X, Game.CellSize * Y); }
public CPos Clamp(Rectangle r)
{
return new CPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
CPos o = (CPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
public static class RectangleExtensions
{
public static CPos TopLeftAsCPos(this Rectangle r) { return new CPos(r.Left, r.Top); }
public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); }
}
}

76
OpenRA.Game/CVec.cs Normal file
View File

@@ -0,0 +1,76 @@
#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;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Cell coordinate vector (coarse).
/// </summary>
public struct CVec
{
public readonly int X, Y;
public CVec(int x, int y) { X = x; Y = y; }
public CVec(Size p) { X = p.Width; Y = p.Height; }
public static readonly CVec Zero = new CVec(0, 0);
public static explicit operator CVec(int2 a) { return new CVec(a.X, a.Y); }
public static explicit operator CVec(float2 a) { return new CVec((int)a.X, (int)a.Y); }
public static CVec operator +(CVec a, CVec b) { return new CVec(a.X + b.X, a.Y + b.Y); }
public static CVec operator -(CVec a, CVec b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static CVec operator *(int a, CVec b) { return new CVec(a * b.X, a * b.Y); }
public static CVec operator *(CVec b, int a) { return new CVec(a * b.X, a * b.Y); }
public static CVec operator /(CVec a, int b) { return new CVec(a.X / b, a.Y / b); }
public static CVec operator -(CVec a) { return new CVec(-a.X, -a.Y); }
public static bool operator ==(CVec me, CVec other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(CVec me, CVec other) { return !(me == other); }
public static CVec Max(CVec a, CVec b) { return new CVec(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CVec Min(CVec a, CVec b) { return new CVec(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(CVec a, CVec b) { return a.X * b.X + a.Y * b.Y; }
public CVec Sign() { return new CVec(Math.Sign(X), Math.Sign(Y)); }
public CVec Abs() { return new CVec(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CVec Clamp(Rectangle r)
{
return new CVec(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
CVec o = (CVec)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

View File

@@ -72,11 +72,11 @@ namespace OpenRA.GameRules
{ {
public WeaponInfo weapon; public WeaponInfo weapon;
public Actor firedBy; public Actor firedBy;
public int2 src; public PPos src;
public int srcAltitude; public int srcAltitude;
public int facing; public int facing;
public Target target; public Target target;
public int2 dest; public PPos dest;
public int destAltitude; public int destAltitude;
public float firepowerModifier = 1.0f; public float firepowerModifier = 1.0f;
} }

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Graphics
public Renderable Image(Actor self, string pal) public Renderable Image(Actor self, string pal)
{ {
var p = self.CenterLocation; var p = self.CenterLocation;
var loc = p - 0.5f * Animation.Image.size var loc = p.ToFloat2() - 0.5f * Animation.Image.size
+ (OffsetFunc != null ? OffsetFunc() : float2.Zero); + (OffsetFunc != null ? OffsetFunc() : float2.Zero);
var r = new Renderable(Animation.Image, loc, pal, p.Y); var r = new Renderable(Animation.Image, loc, pal, p.Y);

View File

@@ -149,18 +149,18 @@ namespace OpenRA.Graphics
} }
// Convert from viewport coords to cell coords (not px) // Convert from viewport coords to cell coords (not px)
public float2 ViewToWorld(MouseInput mi) { return ViewToWorld(mi.Location); } public CPos ViewToWorld(MouseInput mi) { return ViewToWorld(mi.Location); }
public float2 ViewToWorld(int2 loc) public CPos ViewToWorld(int2 loc)
{ {
return (1f / Game.CellSize) * (1f/Zoom*loc.ToFloat2() + Location); return (CPos)( (1f / Game.CellSize) * (1f/Zoom*loc.ToFloat2() + Location) ).ToInt2();
} }
public int2 ViewToWorldPx(int2 loc) { return (1f/Zoom*loc.ToFloat2() + Location).ToInt2(); } public PPos ViewToWorldPx(int2 loc) { return (PPos)(1f/Zoom*loc.ToFloat2() + Location).ToInt2(); }
public int2 ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); } public PPos ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); }
public void Center(float2 loc) public void Center(float2 loc)
{ {
scrollPosition = NormalizeScrollPosition((Game.CellSize*loc - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2()); scrollPosition = NormalizeScrollPosition((Game.CellSize * loc - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
} }
public void Center(IEnumerable<Actor> actors) public void Center(IEnumerable<Actor> actors)
@@ -168,9 +168,9 @@ namespace OpenRA.Graphics
if (!actors.Any()) return; if (!actors.Any()) return;
var avgPos = actors var avgPos = actors
.Select(a => a.CenterLocation) .Select(a => (PVecInt)a.CenterLocation)
.Aggregate((a, b) => a + b) / actors.Count(); .Aggregate((a, b) => a + b) / actors.Count();
scrollPosition = NormalizeScrollPosition((avgPos - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2()); scrollPosition = NormalizeScrollPosition(((PVecFloat)avgPos - (PVecFloat)(1f / (2 * Zoom) * screenSize.ToFloat2())).ToInt2());
} }
// Rectangle (in viewport coords) that contains things to be drawn // Rectangle (in viewport coords) that contains things to be drawn

View File

@@ -53,8 +53,9 @@ namespace OpenRA.Graphics
var comparer = new SpriteComparer(); var comparer = new SpriteComparer();
var actors = world.FindUnits( var actors = world.FindUnits(
new int2(Game.CellSize*bounds.Left, Game.CellSize*bounds.Top), bounds.TopLeftAsCPos().ToPPos(),
new int2(Game.CellSize*bounds.Right, Game.CellSize*bounds.Bottom)); bounds.BottomRightAsCPos().ToPPos()
);
var renderables = actors.SelectMany(a => a.Render()) var renderables = actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer); .OrderBy(r => r, comparer);
@@ -140,25 +141,21 @@ namespace OpenRA.Graphics
selectable.DrawRollover(this, unit); selectable.DrawRollover(this, unit);
} }
public void DrawLocus(Color c, int2[] cells) public void DrawLocus(Color c, CPos[] cells)
{ {
var dict = cells.ToDictionary(a => a, a => 0); var dict = cells.ToDictionary(a => a, a => 0);
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
foreach (var t in dict.Keys) foreach (var t in dict.Keys)
{ {
if (!dict.ContainsKey(t + new int2(-1, 0))) if (!dict.ContainsKey(t + new CVec(-1, 0)))
wlr.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)), wlr.DrawLine(t.ToPPos().ToFloat2(), (t + new CVec(0, 1)).ToPPos().ToFloat2(), c, c);
c, c); if (!dict.ContainsKey(t + new CVec(1, 0)))
if (!dict.ContainsKey(t + new int2(1, 0))) wlr.DrawLine((t + new CVec(1, 0)).ToPPos().ToFloat2(), (t + new CVec(1, 1)).ToPPos().ToFloat2(), c, c);
wlr.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)), if (!dict.ContainsKey(t + new CVec(0, -1)))
c, c); wlr.DrawLine(t.ToPPos().ToFloat2(), (t + new CVec(1, 0)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new int2(0, -1))) if (!dict.ContainsKey(t + new CVec(0, 1)))
wlr.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)), wlr.DrawLine((t + new CVec(0, 1)).ToPPos().ToFloat2(), (t + new CVec(1, 1)).ToPPos().ToFloat2(), c, c);
c, c);
if (!dict.ContainsKey(t + new int2(0, 1)))
wlr.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)),
c, c);
} }
} }

View File

@@ -338,7 +338,7 @@ namespace OpenRA
return dataStream.ToArray(); return dataStream.ToArray();
} }
public bool IsInMap(int2 xy) { return IsInMap(xy.X, xy.Y); } public bool IsInMap(CPos xy) { return IsInMap(xy.X, xy.Y); }
public bool IsInMap(int x, int y) { return Bounds.Contains(x,y); } public bool IsInMap(int x, int y) { return Bounds.Contains(x,y); }
static T[,] ResizeArray<T>(T[,] ts, T t, int width, int height) static T[,] ResizeArray<T>(T[,] ts, T t, int width, int height)

View File

@@ -39,15 +39,15 @@ namespace OpenRA
public readonly Actor Subject; public readonly Actor Subject;
public readonly bool Queued; public readonly bool Queued;
public Actor TargetActor; public Actor TargetActor;
public int2 TargetLocation; public CPos TargetLocation;
public string TargetString; public string TargetString;
public int2 ExtraLocation; public CPos ExtraLocation;
public bool IsImmediate; public bool IsImmediate;
public Player Player { get { return Subject.Owner; } } public Player Player { get { return Subject.Owner; } }
Order(string orderString, Actor subject, Order(string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString, bool queued, int2 extraLocation) Actor targetActor, CPos targetLocation, string targetString, bool queued, CPos extraLocation)
{ {
this.OrderString = orderString; this.OrderString = orderString;
this.Subject = subject; this.Subject = subject;
@@ -60,10 +60,10 @@ namespace OpenRA
// For scripting special powers // For scripting special powers
public Order() public Order()
: this(null, null, null, int2.Zero, null, false, int2.Zero) { } : this(null, null, null, CPos.Zero, null, false, CPos.Zero) { }
public Order(string orderString, Actor subject, bool queued) public Order(string orderString, Actor subject, bool queued)
: this(orderString, subject, null, int2.Zero, null, queued, int2.Zero) { } : this(orderString, subject, null, CPos.Zero, null, queued, CPos.Zero) { }
public Order(string orderstring, Order order) public Order(string orderstring, Order order)
: this(orderstring, order.Subject, order.TargetActor, order.TargetLocation, : this(orderstring, order.Subject, order.TargetActor, order.TargetLocation,
@@ -98,21 +98,21 @@ namespace OpenRA
OrderFields fields = 0; OrderFields fields = 0;
if (TargetActor != null) fields |= OrderFields.TargetActor; if (TargetActor != null) fields |= OrderFields.TargetActor;
if (TargetLocation != int2.Zero) fields |= OrderFields.TargetLocation; if (TargetLocation != CPos.Zero) fields |= OrderFields.TargetLocation;
if (TargetString != null) fields |= OrderFields.TargetString; if (TargetString != null) fields |= OrderFields.TargetString;
if (Queued) fields |= OrderFields.Queued; if (Queued) fields |= OrderFields.Queued;
if (ExtraLocation != int2.Zero) fields |= OrderFields.ExtraLocation; if (ExtraLocation != CPos.Zero) fields |= OrderFields.ExtraLocation;
w.Write((byte)fields); w.Write((byte)fields);
if (TargetActor != null) if (TargetActor != null)
w.Write(UIntFromActor(TargetActor)); w.Write(UIntFromActor(TargetActor));
if (TargetLocation != int2.Zero) if (TargetLocation != CPos.Zero)
w.Write(TargetLocation); w.Write(TargetLocation.ToInt2());
if (TargetString != null) if (TargetString != null)
w.Write(TargetString); w.Write(TargetString);
if (ExtraLocation != int2.Zero) if (ExtraLocation != CPos.Zero)
w.Write(ExtraLocation); w.Write(ExtraLocation.ToInt2());
return ret.ToArray(); return ret.ToArray();
} }
@@ -130,10 +130,10 @@ namespace OpenRA
var flags = (OrderFields)r.ReadByte(); var flags = (OrderFields)r.ReadByte();
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff; var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff;
var targetLocation = flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero; var targetLocation = (CPos)( flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero );
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null; var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued); var queued = flags.HasField(OrderFields.Queued);
var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero; var extraLocation = (CPos)(flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero);
Actor subject, targetActor; Actor subject, targetActor;
if( !TryGetActorFromUInt( world, subjectId, out subject ) || !TryGetActorFromUInt( world, targetActorId, out targetActor ) ) if( !TryGetActorFromUInt( world, subjectId, out subject ) || !TryGetActorFromUInt( world, targetActorId, out targetActor ) )
@@ -218,17 +218,17 @@ namespace OpenRA
public static Order StartProduction(Actor subject, string item, int count) public static Order StartProduction(Actor subject, string item, int count)
{ {
return new Order("StartProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item }; return new Order("StartProduction", subject, false) { TargetLocation = new CPos(count, 0), TargetString = item };
} }
public static Order PauseProduction(Actor subject, string item, bool pause) public static Order PauseProduction(Actor subject, string item, bool pause)
{ {
return new Order("PauseProduction", subject, false) { TargetLocation = new int2(pause ? 1 : 0, 0), TargetString = item }; return new Order("PauseProduction", subject, false) { TargetLocation = new CPos(pause ? 1 : 0, 0), TargetString = item };
} }
public static Order CancelProduction(Actor subject, string item, int count) public static Order CancelProduction(Actor subject, string item, int count)
{ {
return new Order("CancelProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item }; return new Order("CancelProduction", subject, false) { TargetLocation = new CPos(count, 0), TargetString = item };
} }
} }
} }

View File

@@ -78,6 +78,9 @@
<Compile Include="ActorInitializer.cs" /> <Compile Include="ActorInitializer.cs" />
<Compile Include="ActorMap.cs" /> <Compile Include="ActorMap.cs" />
<Compile Include="ActorReference.cs" /> <Compile Include="ActorReference.cs" />
<Compile Include="PVecInt.cs" />
<Compile Include="PVecFloat.cs" />
<Compile Include="PPos.cs" />
<Compile Include="Download.cs" /> <Compile Include="Download.cs" />
<Compile Include="Effects\DelayedAction.cs" /> <Compile Include="Effects\DelayedAction.cs" />
<Compile Include="Effects\FlashTarget.cs" /> <Compile Include="Effects\FlashTarget.cs" />
@@ -114,6 +117,8 @@
<Compile Include="Graphics\WorldRenderer.cs" /> <Compile Include="Graphics\WorldRenderer.cs" />
<Compile Include="Group.cs" /> <Compile Include="Group.cs" />
<Compile Include="InputHandler.cs" /> <Compile Include="InputHandler.cs" />
<Compile Include="CVec.cs" />
<Compile Include="CPos.cs" />
<Compile Include="Map.cs" /> <Compile Include="Map.cs" />
<Compile Include="ModData.cs" /> <Compile Include="ModData.cs" />
<Compile Include="Network\Connection.cs" /> <Compile Include="Network\Connection.cs" />

View File

@@ -48,14 +48,14 @@ namespace OpenRA.Orders
} }
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi) public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{ {
if (mi.Button != expectedButton) if (mi.Button != expectedButton)
world.CancelInputMode(); world.CancelInputMode();
return OrderInner(world, xy, mi); return OrderInner(world, xy, mi);
} }
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi) IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
{ {
if (mi.Button == expectedButton && world.Map.IsInMap(xy)) if (mi.Button == expectedButton && world.Map.IsInMap(xy))
{ {
@@ -68,6 +68,6 @@ namespace OpenRA.Orders
public virtual void Tick(World world) { } public virtual void Tick(World world) { }
public void RenderBeforeWorld(WorldRenderer wr, World world) { } public void RenderBeforeWorld(WorldRenderer wr, World world) { }
public void RenderAfterWorld(WorldRenderer wr, World world) { } public void RenderAfterWorld(WorldRenderer wr, World world) { }
public string GetCursor(World world, int2 xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; } public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; }
} }
} }

View File

@@ -15,10 +15,10 @@ namespace OpenRA
{ {
public interface IOrderGenerator public interface IOrderGenerator
{ {
IEnumerable<Order> Order(World world, int2 xy, MouseInput mi); IEnumerable<Order> Order(World world, CPos xy, MouseInput mi);
void Tick(World world); void Tick(World world);
void RenderBeforeWorld(WorldRenderer wr, World world); void RenderBeforeWorld(WorldRenderer wr, World world);
void RenderAfterWorld(WorldRenderer wr, World world); void RenderAfterWorld(WorldRenderer wr, World world);
string GetCursor(World world, int2 xy, MouseInput mi); string GetCursor(World world, CPos xy, MouseInput mi);
} }
} }

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Orders
{ {
class UnitOrderGenerator : IOrderGenerator class UnitOrderGenerator : IOrderGenerator
{ {
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi ) public IEnumerable<Order> Order( World world, CPos xy, MouseInput mi )
{ {
var underCursor = world.FindUnitsAtMouse(mi.Location) var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>()) .Where(a => a.HasTrait<ITargetable>())
@@ -45,7 +45,7 @@ namespace OpenRA.Orders
public void RenderBeforeWorld( WorldRenderer wr, World world ) { } public void RenderBeforeWorld( WorldRenderer wr, World world ) { }
public void RenderAfterWorld( WorldRenderer wr, World world ) { } public void RenderAfterWorld( WorldRenderer wr, World world ) { }
public string GetCursor( World world, int2 xy, MouseInput mi ) public string GetCursor(World world, CPos xy, MouseInput mi)
{ {
bool useSelect = false; bool useSelect = false;
@@ -68,7 +68,7 @@ namespace OpenRA.Orders
return orders[0].cursor ?? ((useSelect) ? "select" : "default"); return orders[0].cursor ?? ((useSelect) ? "select" : "default");
} }
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor ) static UnitOrderResult OrderForUnit(Actor self, CPos xy, MouseInput mi, Actor underCursor)
{ {
if (self.Owner != self.World.LocalPlayer) if (self.Owner != self.World.LocalPlayer)
return null; return null;

70
OpenRA.Game/PPos.cs Normal file
View File

@@ -0,0 +1,70 @@
#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;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate position in the world (fine).
/// </summary>
public struct PPos
{
public readonly int X, Y;
public PPos(int x, int y) { X = x; Y = y; }
public static readonly PPos Zero = new PPos(0, 0);
public static explicit operator PPos(int2 a) { return new PPos(a.X, a.Y); }
public static explicit operator PVecInt(PPos a) { return new PVecInt(a.X, a.Y); }
public static explicit operator PVecFloat(PPos a) { return new PVecFloat(a.X, a.Y); }
public static PPos operator +(PPos a, PVecInt b) { return new PPos(a.X + b.X, a.Y + b.Y); }
public static PVecInt operator -(PPos a, PPos b) { return new PVecInt(a.X - b.X, a.Y - b.Y); }
public static PPos operator -(PPos a, PVecInt b) { return new PPos(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(PPos me, PPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PPos me, PPos other) { return !(me == other); }
public static PPos Max(PPos a, PPos b) { return new PPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PPos Min(PPos a, PPos b) { return new PPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static PPos Lerp(PPos a, PPos b, int mul, int div)
{
return a + ((PVecInt)(b - a) * mul / div);
}
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CPos ToCPos() { return new CPos((int)(1f / Game.CellSize * X), (int)(1f / Game.CellSize * Y)); }
public PPos Clamp(Rectangle r)
{
return new PPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PPos o = (PPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

97
OpenRA.Game/PVecFloat.cs Normal file
View File

@@ -0,0 +1,97 @@
#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;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate vector (fine; float)
/// </summary>
public struct PVecFloat
{
public readonly float X, Y;
public PVecFloat(float x, float y) { X = x; Y = y; }
public PVecFloat(Size p) { X = p.Width; Y = p.Height; }
public static readonly PVecFloat Zero = new PVecFloat(0, 0);
public static explicit operator PVecInt(PVecFloat a) { return new PVecInt((int)a.X, (int)a.Y); }
public static explicit operator PVecFloat(float2 a) { return new PVecFloat(a.X, a.Y); }
public static PVecFloat operator +(PVecFloat a, PVecFloat b) { return new PVecFloat(a.X + b.X, a.Y + b.Y); }
public static PVecFloat operator -(PVecFloat a, PVecFloat b) { return new PVecFloat(a.X - b.X, a.Y - b.Y); }
public static PVecFloat operator *(float a, PVecFloat b) { return new PVecFloat(a * b.X, a * b.Y); }
public static PVecFloat operator *(PVecFloat b, float a) { return new PVecFloat(a * b.X, a * b.Y); }
public static PVecFloat operator /(PVecFloat a, float b) { return new PVecFloat(a.X / b, a.Y / b); }
public static PVecFloat operator -(PVecFloat a) { return new PVecFloat(-a.X, -a.Y); }
public static bool operator ==(PVecFloat me, PVecFloat other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PVecFloat me, PVecFloat other) { return !(me == other); }
public static PVecFloat Max(PVecFloat a, PVecFloat b) { return new PVecFloat(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PVecFloat Min(PVecFloat a, PVecFloat b) { return new PVecFloat(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static float Dot(PVecFloat a, PVecFloat b) { return a.X * b.X + a.Y * b.Y; }
public static PVecFloat FromAngle(float a) { return new PVecFloat((float)Math.Sin(a), (float)Math.Cos(a)); }
public static PVecFloat Lerp(PVecFloat a, PVecFloat b, float t)
{
return new PVecFloat(
float2.Lerp(a.X, b.X, t),
float2.Lerp(a.Y, b.Y, t)
);
}
public static PVecFloat Lerp(PVecFloat a, PVecFloat b, PVecFloat t)
{
return new PVecFloat(
float2.Lerp(a.X, b.X, t.X),
float2.Lerp(a.Y, b.Y, t.Y)
);
}
public PVecFloat Sign() { return new PVecFloat(Math.Sign(X), Math.Sign(Y)); }
public PVecFloat Abs() { return new PVecFloat(Math.Abs(X), Math.Abs(Y)); }
public PVecFloat Round() { return new PVecFloat((float)Math.Round(X), (float)Math.Round(Y)); }
public float LengthSquared { get { return X * X + Y * Y; } }
public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2((int)X, (int)Y); }
static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; }
public PVecFloat Constrain(PVecFloat min, PVecFloat max)
{
return new PVecFloat(
Constrain(X, min.X, max.X),
Constrain(Y, min.Y, max.Y)
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PVecFloat o = (PVecFloat)obj;
return o == this;
}
public override string ToString() { return "({0},{1})".F(X, Y); }
}
}

79
OpenRA.Game/PVecInt.cs Normal file
View File

@@ -0,0 +1,79 @@
#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;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate vector (fine; integer)
/// </summary>
public struct PVecInt
{
public readonly int X, Y;
public PVecInt(int x, int y) { X = x; Y = y; }
public PVecInt(Size p) { X = p.Width; Y = p.Height; }
public static readonly PVecInt Zero = new PVecInt(0, 0);
public static PVecInt OneCell { get { return new PVecInt(Game.CellSize, Game.CellSize); } }
public static implicit operator PVecFloat(PVecInt a) { return new PVecFloat((float)a.X, (float)a.Y); }
public static explicit operator PVecInt(int2 a) { return new PVecInt(a.X, a.Y); }
public static PVecInt FromRadius(int r) { return new PVecInt(r, r); }
public static PVecInt operator +(PVecInt a, PVecInt b) { return new PVecInt(a.X + b.X, a.Y + b.Y); }
public static PVecInt operator -(PVecInt a, PVecInt b) { return new PVecInt(a.X - b.X, a.Y - b.Y); }
public static PVecInt operator *(int a, PVecInt b) { return new PVecInt(a * b.X, a * b.Y); }
public static PVecInt operator *(PVecInt b, int a) { return new PVecInt(a * b.X, a * b.Y); }
public static PVecInt operator /(PVecInt a, int b) { return new PVecInt(a.X / b, a.Y / b); }
public static PVecInt operator -(PVecInt a) { return new PVecInt(-a.X, -a.Y); }
public static bool operator ==(PVecInt me, PVecInt other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PVecInt me, PVecInt other) { return !(me == other); }
public static PVecInt Max(PVecInt a, PVecInt b) { return new PVecInt(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PVecInt Min(PVecInt a, PVecInt b) { return new PVecInt(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(PVecInt a, PVecInt b) { return a.X * b.X + a.Y * b.Y; }
public PVecInt Sign() { return new PVecInt(Math.Sign(X), Math.Sign(Y)); }
public PVecInt Abs() { return new PVecInt(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PVecInt Clamp(Rectangle r)
{
return new PVecInt(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PVecInt o = (PVecInt)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

View File

@@ -64,7 +64,7 @@ namespace OpenRA
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); } public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
static ISound Play(Player player, string name, bool headRelative, float2 pos, float volumeModifier) static ISound Play(Player player, string name, bool headRelative, PPos pos, float volumeModifier)
{ {
if (player != null && player != player.World.LocalPlayer) if (player != null && player != player.World.LocalPlayer)
return null; return null;
@@ -72,16 +72,16 @@ namespace OpenRA
return null; return null;
return soundEngine.Play2D(sounds[name], return soundEngine.Play2D(sounds[name],
false, headRelative, pos, false, headRelative, pos.ToFloat2(),
InternalSoundVolume * volumeModifier); InternalSoundVolume * volumeModifier);
} }
public static ISound Play(string name) { return Play(null, name, true, float2.Zero, 1); } public static ISound Play(string name) { return Play(null, name, true, PPos.Zero, 1); }
public static ISound Play(string name, float2 pos) { return Play(null, name, false, pos, 1); } public static ISound Play(string name, PPos pos) { return Play(null, name, false, pos, 1); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, float2.Zero, volumeModifier); } public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, PPos.Zero, volumeModifier); }
public static ISound Play(string name, float2 pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); } public static ISound Play(string name, PPos pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play( player, name, true, float2.Zero, 1); } public static ISound PlayToPlayer(Player player, string name) { return Play(player, name, true, PPos.Zero, 1); }
public static ISound PlayToPlayer(Player player, string name, float2 pos) { return Play(player, name, false, pos, 1); } public static ISound PlayToPlayer(Player player, string name, PPos pos) { return Play(player, name, false, pos, 1); }
public static void PlayVideo(byte[] raw) public static void PlayVideo(byte[] raw)
{ {

View File

@@ -50,6 +50,26 @@ namespace OpenRA
il.EmitCall(OpCodes.Call, ((Func<int2, int>)hash_int2).Method, null); il.EmitCall(OpCodes.Call, ((Func<int2, int>)hash_int2).Method, null);
il.Emit(OpCodes.Xor); il.Emit(OpCodes.Xor);
} }
else if (type == typeof(CPos))
{
il.EmitCall(OpCodes.Call, ((Func<CPos, int>)hash_CPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(CVec))
{
il.EmitCall(OpCodes.Call, ((Func<CVec, int>)hash_CVec).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PPos))
{
il.EmitCall(OpCodes.Call, ((Func<PPos, int>)hash_PPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PVecInt))
{
il.EmitCall(OpCodes.Call, ((Func<PVecInt, int>)hash_PVecInt).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(TypeDictionary)) else if (type == typeof(TypeDictionary))
{ {
il.EmitCall(OpCodes.Call, ((Func<TypeDictionary, int>)hash_tdict).Method, null); il.EmitCall(OpCodes.Call, ((Func<TypeDictionary, int>)hash_tdict).Method, null);
@@ -110,6 +130,26 @@ namespace OpenRA
return ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4; return ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4;
} }
public static int hash_CPos( CPos i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_CVec( CVec i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PPos( PPos i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PVecInt( PVecInt i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_tdict( TypeDictionary d ) public static int hash_tdict( TypeDictionary d )
{ {
int ret = 0; int ret = 0;

View File

@@ -52,12 +52,12 @@ namespace OpenRA.Traits
return; return;
var move = self.TraitOrDefault<IMove>(); var move = self.TraitOrDefault<IMove>();
var origin = move != null ? self.CenterLocation - new int2(0, move.Altitude) : self.CenterLocation; var origin = (move != null ? self.CenterLocation - new PVecInt(0, move.Altitude) : self.CenterLocation).ToFloat2();
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(origin, target.CenterLocation, c, c); wlr.DrawLine(origin, target.CenterLocation.ToFloat2(), c, c);
DrawTargetMarker(wlr, target.CenterLocation); DrawTargetMarker(wlr, target.CenterLocation.ToFloat2());
DrawTargetMarker(wlr, origin); DrawTargetMarker(wlr, origin);
} }

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Traits
class RevealsShroud : ITick class RevealsShroud : ITick
{ {
RevealsShroudInfo Info; RevealsShroudInfo Info;
int2 previousLocation; CPos previousLocation;
public RevealsShroud(RevealsShroudInfo info) public RevealsShroud(RevealsShroudInfo info)
{ {

View File

@@ -146,12 +146,12 @@ namespace OpenRA.Traits
{ {
var alt = new float2(0, -mobile.Altitude); var alt = new float2(0, -mobile.Altitude);
var targets = activity.GetTargets(self); var targets = activity.GetTargets(self);
var start = self.CenterLocation + alt; var start = self.CenterLocation.ToFloat2() + alt;
var c = Color.Green; var c = Color.Green;
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
foreach (var step in targets.Select(p => p.CenterLocation)) foreach (var step in targets.Select(p => p.CenterLocation.ToFloat2()))
{ {
var stp = step + alt; var stp = step + alt;
wlr.DrawLine(stp + new float2(-1, -1), stp + new float2(-1, 1), c, c); wlr.DrawLine(stp + new float2(-1, -1), stp + new float2(-1, 1), c, c);

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Traits
Actor actor; Actor actor;
Player owner; Player owner;
int2 pos; PPos pos;
bool valid; bool valid;
public static Target FromActor(Actor a) public static Target FromActor(Actor a)
@@ -28,8 +28,8 @@ namespace OpenRA.Traits
owner = (a != null) ? a.Owner : null owner = (a != null) ? a.Owner : null
}; };
} }
public static Target FromPos(int2 p) { return new Target { pos = p, valid = true }; } public static Target FromPos(PPos p) { return new Target { pos = p, valid = true }; }
public static Target FromCell(int2 c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; } public static Target FromCell(CPos c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; }
public static Target FromOrder(Order o) public static Target FromOrder(Order o)
{ {
return o.TargetActor != null return o.TargetActor != null
@@ -40,8 +40,8 @@ namespace OpenRA.Traits
public static readonly Target None = new Target(); public static readonly Target None = new Target();
public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && actor.Owner == owner)); } } public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && actor.Owner == owner)); } }
public int2 PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } } public PPos PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } }
public int2 CenterLocation { get { return PxPosition; } } public PPos CenterLocation { get { return PxPosition; } }
public Actor Actor { get { return IsActor ? actor : null; } } public Actor Actor { get { return IsActor ? actor : null; } }
public bool IsActor { get { return actor != null && !actor.Destroyed; } } public bool IsActor { get { return actor != null && !actor.Destroyed; } }

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Traits
string OrderID { get; } string OrderID { get; }
int OrderPriority { get; } int OrderPriority { get; }
bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueue, ref string cursor); bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueue, ref string cursor);
bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor); bool CanTargetLocation(Actor self, CPos location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor);
bool IsQueued { get; } bool IsQueued { get; }
} }
@@ -60,7 +60,7 @@ namespace OpenRA.Traits
public interface INotifyKilled { void Killed(Actor self, AttackInfo e); } public interface INotifyKilled { void Killed(Actor self, AttackInfo e); }
public interface INotifyAppliedDamage { void AppliedDamage(Actor self, Actor damaged, AttackInfo e); } public interface INotifyAppliedDamage { void AppliedDamage(Actor self, Actor damaged, AttackInfo e); }
public interface INotifyBuildComplete { void BuildingComplete(Actor self); } public interface INotifyBuildComplete { void BuildingComplete(Actor self); }
public interface INotifyProduction { void UnitProduced(Actor self, Actor other, int2 exit); } public interface INotifyProduction { void UnitProduced(Actor self, Actor other, CPos exit); }
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); }
public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); }
public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); } public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); }
@@ -79,23 +79,23 @@ namespace OpenRA.Traits
public interface IRadarSignature public interface IRadarSignature
{ {
IEnumerable<int2> RadarSignatureCells(Actor self); IEnumerable<CPos> RadarSignatureCells(Actor self);
Color RadarSignatureColor(Actor self); Color RadarSignatureColor(Actor self);
} }
public interface IVisibilityModifier { bool IsVisible(Actor self); } public interface IVisibilityModifier { bool IsVisible(Actor self); }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); } public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
public interface IHasLocation { int2 PxPosition { get; } } public interface IHasLocation { PPos PxPosition { get; } }
public interface IOccupySpace : IHasLocation public interface IOccupySpace : IHasLocation
{ {
int2 TopLeft { get; } CPos TopLeft { get; }
IEnumerable<Pair<int2, SubCell>> OccupiedCells(); IEnumerable<Pair<CPos, SubCell>> OccupiedCells();
} }
public static class IOccupySpaceExts public static class IOccupySpaceExts
{ {
public static int2 NearestCellTo(this IOccupySpace ios, int2 other) public static CPos NearestCellTo(this IOccupySpace ios, CPos other)
{ {
var nearest = ios.TopLeft; var nearest = ios.TopLeft;
var nearestDistance = int.MaxValue; var nearestDistance = int.MaxValue;
@@ -125,10 +125,10 @@ namespace OpenRA.Traits
public interface ITeleportable : IHasLocation /* crap name! */ public interface ITeleportable : IHasLocation /* crap name! */
{ {
bool CanEnterCell(int2 location); bool CanEnterCell(CPos location);
void SetPosition(Actor self, int2 cell); void SetPosition(Actor self, CPos cell);
void SetPxPosition(Actor self, int2 px); void SetPxPosition(Actor self, PPos px);
void AdjustPxPosition(Actor self, int2 px); /* works like SetPxPosition, but visual only */ void AdjustPxPosition(Actor self, PPos px); /* works like SetPxPosition, but visual only */
} }
public interface IMove : ITeleportable { int Altitude { get; set; } } public interface IMove : ITeleportable { int Altitude { get; set; } }
@@ -212,7 +212,7 @@ namespace OpenRA.Traits
public interface ITargetable public interface ITargetable
{ {
string[] TargetTypes { get; } string[] TargetTypes { get; }
IEnumerable<int2> TargetableCells(Actor self); IEnumerable<CPos> TargetableCells(Actor self);
bool TargetableBy(Actor self, Actor byActor); bool TargetableBy(Actor self, Actor byActor);
} }

View File

@@ -30,6 +30,16 @@ namespace OpenRA.Traits
return ( facing - rot ) & 0xFF; return ( facing - rot ) & 0xFF;
} }
public static int GetFacing(PVecInt d, int currentFacing)
{
return GetFacing(d.ToInt2(), currentFacing);
}
public static int GetFacing(CVec d, int currentFacing)
{
return GetFacing(d.ToInt2(), currentFacing);
}
public static int GetFacing( int2 d, int currentFacing ) public static int GetFacing( int2 d, int currentFacing )
{ {
if (d == int2.Zero) if (d == int2.Zero)
@@ -80,14 +90,14 @@ namespace OpenRA.Traits
ecc * (cosAngle * v.Y - sinAngle * v.X)); ecc * (cosAngle * v.Y - sinAngle * v.X));
} }
public static int2 CenterOfCell(int2 loc) public static PPos CenterOfCell(CPos loc)
{ {
return new int2( Game.CellSize / 2, Game.CellSize / 2 ) + Game.CellSize * loc; return loc.ToPPos() + new PVecInt(Game.CellSize / 2, Game.CellSize / 2);
} }
public static int2 BetweenCells(int2 from, int2 to) public static PPos BetweenCells(CPos from, CPos to)
{ {
return int2.Lerp( CenterOfCell( from ), CenterOfCell( to ), 1, 2 ); return PPos.Lerp(CenterOfCell(from), CenterOfCell(to), 1, 2);
} }
public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); } public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); }
@@ -120,6 +130,7 @@ namespace OpenRA.Traits
public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); } public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); }
[Obsolete("Use ToCPos() method", true)]
public static int2 CellContaining(float2 pos) { return (1f / Game.CellSize * pos).ToInt2(); } public static int2 CellContaining(float2 pos) { return (1f / Game.CellSize * pos).ToInt2(); }
/* pretty crap */ /* pretty crap */
@@ -134,39 +145,39 @@ namespace OpenRA.Traits
} }
} }
static IEnumerable<int2> Neighbours(int2 c, bool allowDiagonal) static IEnumerable<CPos> Neighbours(CPos c, bool allowDiagonal)
{ {
yield return c; yield return c;
yield return new int2(c.X - 1, c.Y); yield return new CPos(c.X - 1, c.Y);
yield return new int2(c.X + 1, c.Y); yield return new CPos(c.X + 1, c.Y);
yield return new int2(c.X, c.Y - 1); yield return new CPos(c.X, c.Y - 1);
yield return new int2(c.X, c.Y + 1); yield return new CPos(c.X, c.Y + 1);
if (allowDiagonal) if (allowDiagonal)
{ {
yield return new int2(c.X - 1, c.Y - 1); yield return new CPos(c.X - 1, c.Y - 1);
yield return new int2(c.X + 1, c.Y - 1); yield return new CPos(c.X + 1, c.Y - 1);
yield return new int2(c.X - 1, c.Y + 1); yield return new CPos(c.X - 1, c.Y + 1);
yield return new int2(c.X + 1, c.Y + 1); yield return new CPos(c.X + 1, c.Y + 1);
} }
} }
public static IEnumerable<int2> ExpandFootprint(IEnumerable<int2> cells, bool allowDiagonal) public static IEnumerable<CPos> ExpandFootprint(IEnumerable<CPos> cells, bool allowDiagonal)
{ {
var result = new Dictionary<int2, bool>(); var result = new Dictionary<CPos, bool>();
foreach (var c in cells.SelectMany(c => Neighbours(c, allowDiagonal))) foreach (var c in cells.SelectMany(c => Neighbours(c, allowDiagonal)))
result[c] = true; result[c] = true;
return result.Keys; return result.Keys;
} }
public static IEnumerable<int2> AdjacentCells( Target target ) public static IEnumerable<CPos> AdjacentCells(Target target)
{ {
var cells = target.IsActor var cells = target.IsActor
? target.Actor.OccupiesSpace.OccupiedCells().Select(c => c.First).ToArray() ? target.Actor.OccupiesSpace.OccupiedCells().Select(c => c.First).ToArray()
: new int2[] {}; : new CPos[] {};
if (cells.Length == 0) if (cells.Length == 0)
cells = new [] { Util.CellContaining(target.CenterLocation) }; cells = new CPos[] { target.CenterLocation.ToCPos() };
return Util.ExpandFootprint(cells, true); return Util.ExpandFootprint(cells, true);
} }

View File

@@ -20,16 +20,16 @@ namespace OpenRA.Traits
class Waypoint : IOccupySpace, ISync class Waypoint : IOccupySpace, ISync
{ {
[Sync] int2 location; [Sync] CPos location;
public Waypoint(ActorInitializer init) public Waypoint(ActorInitializer init)
{ {
this.location = init.Get<LocationInit,int2>(); this.location = init.Get<LocationInit, CPos>();
} }
public int2 TopLeft { get { return location; } } public CPos TopLeft { get { return location; } }
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield break; } public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { yield break; }
public int2 PxPosition { get { return Util.CenterOfCell( location ); } } public PPos PxPosition { get { return Util.CenterOfCell(location); } }
} }
} }

View File

@@ -39,13 +39,13 @@ namespace OpenRA.Traits
for (int x = clip.Left; x < clip.Right; x++) for (int x = clip.Left; x < clip.Right; x++)
for (int y = clip.Top; y < clip.Bottom; y++) for (int y = clip.Top; y < clip.Bottom; y++)
{ {
if (!world.LocalShroud.IsExplored(new int2(x, y))) if (!world.LocalShroud.IsExplored(new CPos(x, y)))
continue; continue;
var c = content[x, y]; var c = content[x, y];
if (c.image != null) if (c.image != null)
c.image[c.density].DrawAt( c.image[c.density].DrawAt(
Game.CellSize * new int2(x, y), new CPos(x, y).ToPPos().ToFloat2(),
c.type.info.PaletteIndex); c.type.info.PaletteIndex);
} }
} }
@@ -70,7 +70,7 @@ namespace OpenRA.Traits
if (type == null) if (type == null)
continue; continue;
if (!AllowResourceAt(type, new int2(x,y))) if (!AllowResourceAt(type, new CPos(x,y)))
continue; continue;
content[x, y].type = type; content[x, y].type = type;
@@ -86,7 +86,7 @@ namespace OpenRA.Traits
} }
} }
public bool AllowResourceAt(ResourceType rt, int2 a) public bool AllowResourceAt(ResourceType rt, CPos a)
{ {
if (!world.Map.IsInMap(a.X, a.Y)) return false; if (!world.Map.IsInMap(a.X, a.Y)) return false;
if (!rt.info.AllowedTerrainTypes.Contains(world.GetTerrainInfo(a).Type)) return false; if (!rt.info.AllowedTerrainTypes.Contains(world.GetTerrainInfo(a).Type)) return false;
@@ -136,7 +136,7 @@ namespace OpenRA.Traits
public bool IsFull(int i, int j) { return content[i, j].density == content[i, j].image.Length - 1; } public bool IsFull(int i, int j) { return content[i, j].density == content[i, j].image.Length - 1; }
public ResourceType Harvest(int2 p) public ResourceType Harvest(CPos p)
{ {
var type = content[p.X,p.Y].type; var type = content[p.X,p.Y].type;
if (type == null) return null; if (type == null) return null;
@@ -150,7 +150,7 @@ namespace OpenRA.Traits
return type; return type;
} }
public void Destroy(int2 p) public void Destroy(CPos p)
{ {
// Don't break other users of CustomTerrain if there are no resources // Don't break other users of CustomTerrain if there are no resources
if (content[p.X, p.Y].type == null) if (content[p.X, p.Y].type == null)
@@ -162,7 +162,7 @@ namespace OpenRA.Traits
world.Map.CustomTerrain[p.X, p.Y] = null; world.Map.CustomTerrain[p.X, p.Y] = null;
} }
public ResourceType GetResource(int2 p) { return content[p.X, p.Y].type; } public ResourceType GetResource(CPos p) { return content[p.X, p.Y].type; }
public struct CellContents public struct CellContents
{ {

View File

@@ -54,22 +54,22 @@ namespace OpenRA.Traits
// cache of positions that were added, so no matter what crazy trait code does, it // cache of positions that were added, so no matter what crazy trait code does, it
// can't make us invalid. // can't make us invalid.
class ActorVisibility { public int range; public int2[] vis; } class ActorVisibility { public int range; public CPos[] vis; }
Dictionary<Actor, ActorVisibility> vis = new Dictionary<Actor, ActorVisibility>(); Dictionary<Actor, ActorVisibility> vis = new Dictionary<Actor, ActorVisibility>();
static IEnumerable<int2> FindVisibleTiles(World world, int2 a, int r) static IEnumerable<CPos> FindVisibleTiles(World world, CPos a, int r)
{ {
var min = a - new int2(r, r); var min = a - new CVec(r, r);
var max = a + new int2(r, r); var max = a + new CVec(r, r);
if (min.X < world.Map.Bounds.Left - 1) min.X = world.Map.Bounds.Left - 1; if (min.X < world.Map.Bounds.Left - 1) min = new CPos(world.Map.Bounds.Left - 1, min.Y);
if (min.Y < world.Map.Bounds.Top - 1) min.Y = world.Map.Bounds.Top - 1; if (min.Y < world.Map.Bounds.Top - 1) min = new CPos(min.X, world.Map.Bounds.Top - 1);
if (max.X > world.Map.Bounds.Right) max.X = world.Map.Bounds.Right; if (max.X > world.Map.Bounds.Right) max = new CPos(world.Map.Bounds.Right, max.Y);
if (max.Y > world.Map.Bounds.Bottom) max.Y = world.Map.Bounds.Bottom; if (max.Y > world.Map.Bounds.Bottom) max = new CPos(max.X, world.Map.Bounds.Bottom);
for (var j = min.Y; j <= max.Y; j++) for (var j = min.Y; j <= max.Y; j++)
for (var i = min.X; i <= max.X; i++) for (var i = min.X; i <= max.X; i++)
if (r * r >= (new int2(i, j) - a).LengthSquared) if (r * r >= (new CPos(i, j) - a).LengthSquared)
yield return new int2(i, j); yield return new CPos(i, j);
} }
void AddActor(Actor a) void AddActor(Actor a)
@@ -148,7 +148,7 @@ namespace OpenRA.Traits
AddActor(a); AddActor(a);
} }
public static IEnumerable<int2> GetVisOrigins(Actor a) public static IEnumerable<CPos> GetVisOrigins(Actor a)
{ {
var ios = a.OccupiesSpace; var ios = a.OccupiesSpace;
if (ios != null) if (ios != null)
@@ -157,7 +157,7 @@ namespace OpenRA.Traits
if (cells.Any()) return cells.Select(c => c.First); if (cells.Any()) return cells.Select(c => c.First);
} }
return new[] { a.CenterLocation / Game.CellSize }; return new[] { a.CenterLocation.ToCPos() };
} }
void RemoveActor(Actor a) void RemoveActor(Actor a)
@@ -183,7 +183,7 @@ namespace OpenRA.Traits
RemoveActor(a); AddActor(a); RemoveActor(a); AddActor(a);
} }
public void Explore(World world, int2 center, int range) public void Explore(World world, CPos center, int range)
{ {
foreach (var q in FindVisibleTiles(world, center, range)) foreach (var q in FindVisibleTiles(world, center, range))
exploredCells[q.X, q.Y] = true; exploredCells[q.X, q.Y] = true;
@@ -216,7 +216,7 @@ namespace OpenRA.Traits
Dirty(); Dirty();
} }
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); } public bool IsExplored(CPos xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(int x, int y) public bool IsExplored(int x, int y)
{ {
if (!map.IsInMap(x, y)) if (!map.IsInMap(x, y))
@@ -228,7 +228,7 @@ namespace OpenRA.Traits
return exploredCells[x,y]; return exploredCells[x,y];
} }
public bool IsVisible(int2 xy) { return IsVisible(xy.X, xy.Y); } public bool IsVisible(CPos xy) { return IsVisible(xy.X, xy.Y); }
public bool IsVisible(int x, int y) public bool IsVisible(int x, int y)
{ {
if (Disabled) if (Disabled)

View File

@@ -75,7 +75,7 @@ namespace OpenRA.Traits
yield return a; yield return a;
} }
public IEnumerable<Actor> ActorsInBox(int2 a, int2 b) public IEnumerable<Actor> ActorsInBox(PPos a, PPos b)
{ {
var r = Rectangle.FromLTRB(a.X, a.Y, b.X, b.Y); var r = Rectangle.FromLTRB(a.X, a.Y, b.X, b.Y);

View File

@@ -42,12 +42,12 @@ namespace OpenRA.Widgets
return; return;
} }
Game.Renderer.WorldLineRenderer.DrawRect(selbox.Value.First, selbox.Value.Second, Color.White); Game.Renderer.WorldLineRenderer.DrawRect(selbox.Value.First.ToFloat2(), selbox.Value.Second.ToFloat2(), Color.White);
foreach (var u in SelectActorsInBox(world, selbox.Value.First, selbox.Value.Second, _ => true)) foreach (var u in SelectActorsInBox(world, selbox.Value.First, selbox.Value.Second, _ => true))
worldRenderer.DrawRollover(u); worldRenderer.DrawRollover(u);
} }
int2 dragStart, dragEnd; PPos dragStart, dragEnd;
public override bool HandleMouseInput(MouseInput mi) public override bool HandleMouseInput(MouseInput mi)
{ {
@@ -101,7 +101,7 @@ namespace OpenRA.Widgets
return true; return true;
} }
public Pair<int2, int2>? SelectionBox public Pair<PPos, PPos>? SelectionBox
{ {
get get
{ {
@@ -110,11 +110,11 @@ namespace OpenRA.Widgets
} }
} }
public void ApplyOrders(World world, int2 xy, MouseInput mi) public void ApplyOrders(World world, PPos xy, MouseInput mi)
{ {
if (world.OrderGenerator == null) return; if (world.OrderGenerator == null) return;
var orders = world.OrderGenerator.Order(world, Traits.Util.CellContaining(xy), mi).ToArray(); var orders = world.OrderGenerator.Order(world, xy.ToCPos(), mi).ToArray();
orders.Do( o => world.IssueOrder( o ) ); orders.Do( o => world.IssueOrder( o ) );
world.PlayVoiceForOrders(orders); world.PlayVoiceForOrders(orders);
@@ -135,7 +135,7 @@ namespace OpenRA.Widgets
}; };
// TODO: fix this up. // TODO: fix this up.
return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi).ToInt2(), mi ); return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi), mi );
} ); } );
} }
@@ -161,7 +161,7 @@ namespace OpenRA.Widgets
} }
static readonly Actor[] NoActors = {}; static readonly Actor[] NoActors = {};
IEnumerable<Actor> SelectActorsInBox(World world, int2 a, int2 b, Func<Actor, bool> cond) IEnumerable<Actor> SelectActorsInBox(World world, PPos a, PPos b, Func<Actor, bool> cond)
{ {
return world.FindUnits(a, b) return world.FindUnits(a, b)
.Where( x => x.HasTrait<Selectable>() && world.LocalShroud.IsVisible(x) && cond(x) ) .Where( x => x.HasTrait<Selectable>() && world.LocalShroud.IsVisible(x) && cond(x) )

View File

@@ -27,24 +27,24 @@ namespace OpenRA
return FindUnits(world, loc, loc).Where(a => world.LocalShroud.IsVisible(a)); return FindUnits(world, loc, loc).Where(a => world.LocalShroud.IsVisible(a));
} }
public static IEnumerable<Actor> FindUnits(this World world, int2 a, int2 b) public static IEnumerable<Actor> FindUnits(this World world, PPos a, PPos b)
{ {
var u = float2.Min(a, b).ToInt2(); var u = PPos.Min(a, b);
var v = float2.Max(a, b).ToInt2(); var v = PPos.Max(a, b);
return world.WorldActor.Trait<SpatialBins>().ActorsInBox(u,v); return world.WorldActor.Trait<SpatialBins>().ActorsInBox(u,v);
} }
public static Actor ClosestTo( this IEnumerable<Actor> actors, int2 px ) public static Actor ClosestTo(this IEnumerable<Actor> actors, PPos px)
{ {
return actors.OrderBy( a => (a.CenterLocation - px).LengthSquared ).FirstOrDefault(); return actors.OrderBy( a => (a.CenterLocation - px).LengthSquared ).FirstOrDefault();
} }
public static IEnumerable<Actor> FindUnitsInCircle(this World world, int2 a, int r) public static IEnumerable<Actor> FindUnitsInCircle(this World world, PPos a, int r)
{ {
using (new PerfSample("FindUnitsInCircle")) using (new PerfSample("FindUnitsInCircle"))
{ {
var min = a - new int2(r, r); var min = a - PVecInt.FromRadius(r);
var max = a + new int2(r, r); var max = a + PVecInt.FromRadius(r);
var actors = world.FindUnits(min, max); var actors = world.FindUnits(min, max);
@@ -56,48 +56,48 @@ namespace OpenRA
} }
} }
public static IEnumerable<int2> FindTilesInCircle(this World world, int2 a, int r) public static IEnumerable<CPos> FindTilesInCircle(this World world, CPos a, int r)
{ {
var min = world.ClampToWorld(a - new int2(r, r)); var min = world.ClampToWorld(a - new CVec(r, r));
var max = world.ClampToWorld(a + new int2(r, r)); var max = world.ClampToWorld(a + new CVec(r, r));
for (var j = min.Y; j <= max.Y; j++) for (var j = min.Y; j <= max.Y; j++)
for (var i = min.X; i <= max.X; i++) for (var i = min.X; i <= max.X; i++)
if (r * r >= (new int2(i, j) - a).LengthSquared) if (r * r >= (new CPos(i, j) - a).LengthSquared)
yield return new int2(i, j); yield return new CPos(i, j);
} }
public static string GetTerrainType(this World world, int2 cell) public static string GetTerrainType(this World world, CPos cell)
{ {
var custom = world.Map.CustomTerrain[cell.X, cell.Y]; var custom = world.Map.CustomTerrain[cell.X, cell.Y];
return custom != null ? custom : world.TileSet.GetTerrainType(world.Map.MapTiles.Value[cell.X, cell.Y]); return custom != null ? custom : world.TileSet.GetTerrainType(world.Map.MapTiles.Value[cell.X, cell.Y]);
} }
public static TerrainTypeInfo GetTerrainInfo(this World world, int2 cell) public static TerrainTypeInfo GetTerrainInfo(this World world, CPos cell)
{ {
return world.TileSet.Terrain[world.GetTerrainType(cell)]; return world.TileSet.Terrain[world.GetTerrainType(cell)];
} }
public static int2 ClampToWorld( this World world, int2 xy ) public static CPos ClampToWorld(this World world, CPos xy)
{ {
var r = world.Map.Bounds; var r = world.Map.Bounds;
return xy.Clamp(new Rectangle(r.X,r.Y,r.Width-1, r.Height-1)); return xy.Clamp(new Rectangle(r.X,r.Y,r.Width-1, r.Height-1));
} }
public static int2 ChooseRandomEdgeCell(this World w) public static CPos ChooseRandomEdgeCell(this World w)
{ {
var isX = w.SharedRandom.Next(2) == 0; var isX = w.SharedRandom.Next(2) == 0;
var edge = w.SharedRandom.Next(2) == 0; var edge = w.SharedRandom.Next(2) == 0;
return new int2( return new CPos(
isX ? w.SharedRandom.Next(w.Map.Bounds.Left, w.Map.Bounds.Right) isX ? w.SharedRandom.Next(w.Map.Bounds.Left, w.Map.Bounds.Right)
: (edge ? w.Map.Bounds.Left : w.Map.Bounds.Right), : (edge ? w.Map.Bounds.Left : w.Map.Bounds.Right),
!isX ? w.SharedRandom.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom) !isX ? w.SharedRandom.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom)
: (edge ? w.Map.Bounds.Top : w.Map.Bounds.Bottom)); : (edge ? w.Map.Bounds.Top : w.Map.Bounds.Bottom));
} }
public static int2 ChooseRandomCell(this World w, Thirdparty.Random r) public static CPos ChooseRandomCell(this World w, Thirdparty.Random r)
{ {
return new int2( return new CPos(
r.Next(w.Map.Bounds.Left, w.Map.Bounds.Right), r.Next(w.Map.Bounds.Left, w.Map.Bounds.Right),
r.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom)); r.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom));
} }

View File

@@ -27,8 +27,8 @@ namespace OpenRA.Mods.Cnc
readonly RenderUnit ru; readonly RenderUnit ru;
State state; State state;
int2 startDock; PPos startDock;
int2 endDock; PPos endDock;
public HarvesterDockSequence(Actor self, Actor proc) public HarvesterDockSequence(Actor self, Actor proc)
{ {
this.proc = proc; this.proc = proc;
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Cnc
harv = self.Trait<Harvester>(); harv = self.Trait<Harvester>();
ru = self.Trait<RenderUnit>(); ru = self.Trait<RenderUnit>();
startDock = self.Trait<IHasLocation>().PxPosition; startDock = self.Trait<IHasLocation>().PxPosition;
endDock = proc.Trait<IHasLocation>().PxPosition + new int2(-15,8); endDock = proc.Trait<IHasLocation>().PxPosition + new PVecInt(-15,8);
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Cnc.Effects
Animation anim; Animation anim;
Actor firedBy; Actor firedBy;
public IonCannon(Actor firedBy, World world, int2 location) public IonCannon(Actor firedBy, World world, CPos location)
{ {
this.firedBy = firedBy; this.firedBy = firedBy;
target = Target.FromCell(location); target = Target.FromCell(location);
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Cnc.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
yield return new Renderable(anim.Image, yield return new Renderable(anim.Image,
target.CenterLocation - new float2(.5f * anim.Image.size.X, anim.Image.size.Y - Game.CellSize), target.CenterLocation.ToFloat2() - new float2(.5f * anim.Image.size.X, anim.Image.size.Y - Game.CellSize),
"effect", (int)target.CenterLocation.Y); "effect", (int)target.CenterLocation.Y);
} }

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc
{ {
self.World.AddFrameEndTask(w => self.World.AddFrameEndTask(w =>
{ {
Sound.Play(Info.LaunchSound, Game.CellSize * order.TargetLocation.ToFloat2()); Sound.Play(Info.LaunchSound, order.TargetLocation.ToPPos());
w.Add(new IonCannon(self, w, order.TargetLocation)); w.Add(new IonCannon(self, w, order.TargetLocation));
}); });
} }

View File

@@ -22,13 +22,13 @@ namespace OpenRA.Mods.RA
class CncShellmapScript: IWorldLoaded, ITick class CncShellmapScript: IWorldLoaded, ITick
{ {
Dictionary<string, Actor> Actors; Dictionary<string, Actor> Actors;
static int2 ViewportOrigin; static CPos ViewportOrigin;
public void WorldLoaded(World w) public void WorldLoaded(World w)
{ {
var b = w.Map.Bounds; var b = w.Map.Bounds;
ViewportOrigin = new int2(b.Left + b.Width/2, b.Top + b.Height/2); ViewportOrigin = new CPos(b.Left + b.Width/2, b.Top + b.Height/2);
Game.MoveViewport(ViewportOrigin); Game.MoveViewport(ViewportOrigin.ToFloat2());
Actors = w.WorldActor.Trait<SpawnMapActors>().Actors; Actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA
void SetViewport() void SetViewport()
{ {
var t = (ticks + 45) % (360f * speed) * (Math.PI / 180) * 1f / speed; var t = (ticks + 45) % (360f * speed) * (Math.PI / 180) * 1f / speed;
var loc = ViewportOrigin + new float2(-15,4) * float2.FromAngle( (float)t ); var loc = ViewportOrigin.ToFloat2() + (new float2(-15,4) * float2.FromAngle( (float)t ));
Game.viewport.Center(loc); Game.viewport.Center(loc);
} }
@@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA
})); }));
} }
void LoopTrack(Actor self, int2 left, int2 right) void LoopTrack(Actor self, CPos left, CPos right)
{ {
var mobile = self.Trait<Mobile>(); var mobile = self.Trait<Mobile>();
self.QueueActivity(mobile.ScriptedMove(left)); self.QueueActivity(mobile.ScriptedMove(left));

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc
Players = w.Players.ToDictionary(p => p.InternalName); Players = w.Players.ToDictionary(p => p.InternalName);
Actors = w.WorldActor.Trait<SpawnMapActors>().Actors; Actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
var b = w.Map.Bounds; var b = w.Map.Bounds;
Game.MoveViewport(new int2(b.Left + b.Width/2, b.Top + b.Height/2)); Game.MoveViewport(new CPos(b.Left + b.Width/2, b.Top + b.Height/2).ToFloat2());
Scripting.Media.PlayFMVFullscreen(w, "gdi1.vqa", Scripting.Media.PlayFMVFullscreen(w, "gdi1.vqa",
() => Scripting.Media.PlayFMVFullscreen(w, "landing.vqa", () => () => Scripting.Media.PlayFMVFullscreen(w, "landing.vqa", () =>
@@ -130,7 +130,7 @@ namespace OpenRA.Mods.Cnc
ReinforceFromSea(self.World, ReinforceFromSea(self.World,
Actors["lstStart"].Location, Actors["lstStart"].Location,
Actors["lstEnd"].Location, Actors["lstEnd"].Location,
new int2(53,53), new CPos(53, 53),
new string[] {"e1","e1","e1"}, new string[] {"e1","e1","e1"},
Players["GoodGuy"]); Players["GoodGuy"]);
} }
@@ -140,7 +140,7 @@ namespace OpenRA.Mods.Cnc
ReinforceFromSea(self.World, ReinforceFromSea(self.World,
Actors["lstStart"].Location, Actors["lstStart"].Location,
Actors["lstEnd"].Location, Actors["lstEnd"].Location,
new int2(53,53), new CPos(53, 53),
new string[] {"e1","e1","e1"}, new string[] {"e1","e1","e1"},
Players["GoodGuy"]); Players["GoodGuy"]);
} }
@@ -150,7 +150,7 @@ namespace OpenRA.Mods.Cnc
ReinforceFromSea(self.World, ReinforceFromSea(self.World,
Actors["lstStart"].Location, Actors["lstStart"].Location,
Actors["lstEnd"].Location, Actors["lstEnd"].Location,
new int2(53,53), new CPos(53, 53),
new string[] {"jeep"}, new string[] {"jeep"},
Players["GoodGuy"]); Players["GoodGuy"]);
} }
@@ -160,7 +160,7 @@ namespace OpenRA.Mods.Cnc
ReinforceFromSea(self.World, ReinforceFromSea(self.World,
Actors["lstStart"].Location, Actors["lstStart"].Location,
Actors["lstEnd"].Location, Actors["lstEnd"].Location,
new int2(53,53), new CPos(53, 53),
new string[] {"jeep"}, new string[] {"jeep"},
Players["GoodGuy"]); Players["GoodGuy"]);
} }
@@ -177,7 +177,7 @@ namespace OpenRA.Mods.Cnc
self.QueueActivity(new CallFunc(() => SetGunboatPath())); self.QueueActivity(new CallFunc(() => SetGunboatPath()));
} }
void ReinforceFromSea(World world, int2 startPos, int2 endPos, int2 unload, string[] items, Player player) void ReinforceFromSea(World world, CPos startPos, CPos endPos, CPos unload, string[] items, Player player)
{ {
world.AddFrameEndTask(w => world.AddFrameEndTask(w =>
{ {

View File

@@ -36,8 +36,8 @@ namespace OpenRA.Mods.Cnc
// Start a fixed distance away: the width of the map. // Start a fixed distance away: the width of the map.
// This makes the production timing independent of spawnpoint // This makes the production timing independent of spawnpoint
var startPos = self.Location + new int2(owner.World.Map.Bounds.Width, 0); var startPos = self.Location + new CVec(owner.World.Map.Bounds.Width, 0);
var endPos = new int2(owner.World.Map.Bounds.Left - 5, self.Location.Y); var endPos = new CPos(owner.World.Map.Bounds.Left - 5, self.Location.Y);
// Assume a single exit point for simplicity // Assume a single exit point for simplicity
var exit = self.Info.Traits.WithInterface<ExitInfo>().First(); var exit = self.Info.Traits.WithInterface<ExitInfo>().First();
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.Cnc
new AltitudeInit( Rules.Info[actorType].Traits.Get<PlaneInfo>().CruiseAltitude ), new AltitudeInit( Rules.Info[actorType].Traits.Get<PlaneInfo>().CruiseAltitude ),
}); });
a.QueueActivity(Fly.ToCell(self.Location + new int2(6,0))); a.QueueActivity(Fly.ToCell(self.Location + new CVec(6, 0)));
a.QueueActivity(new Land(Target.FromActor(self))); a.QueueActivity(new Land(Target.FromActor(self)));
a.QueueActivity(new CallFunc(() => a.QueueActivity(new CallFunc(() =>
{ {

View File

@@ -62,7 +62,7 @@ namespace OpenRA.Mods.Cnc.Widgets
public void UpdateMouseover() public void UpdateMouseover()
{ {
TooltipType = WorldTooltipType.None; TooltipType = WorldTooltipType.None;
var cell = Game.viewport.ViewToWorld(Viewport.LastMousePos).ToInt2(); var cell = Game.viewport.ViewToWorld(Viewport.LastMousePos);
if (!world.Map.IsInMap(cell)) if (!world.Map.IsInMap(cell))
return; return;

View File

@@ -72,7 +72,7 @@ namespace OpenRA.Mods.RA.AI
readonly HackyAIInfo Info; readonly HackyAIInfo Info;
Cache<Player,Enemy> aggro = new Cache<Player, Enemy>( _ => new Enemy() ); Cache<Player,Enemy> aggro = new Cache<Player, Enemy>( _ => new Enemy() );
int2 baseCenter; CPos baseCenter;
XRandom random = new XRandom(); //we do not use the synced random number generator. XRandom random = new XRandom(); //we do not use the synced random number generator.
BaseBuilder[] builders; BaseBuilder[] builders;
@@ -116,7 +116,7 @@ namespace OpenRA.Mods.RA.AI
ActorInfo ChooseRandomUnitToBuild(ProductionQueue queue) ActorInfo ChooseRandomUnitToBuild(ProductionQueue queue)
{ {
var buildableThings = queue.BuildableItems(); var buildableThings = queue.BuildableItems();
if (buildableThings.Count() == 0) return null; if (!buildableThings.Any()) return null;
return buildableThings.ElementAtOrDefault(random.Next(buildableThings.Count())); return buildableThings.ElementAtOrDefault(random.Next(buildableThings.Count()));
} }
@@ -154,13 +154,13 @@ namespace OpenRA.Mods.RA.AI
return null; return null;
} }
bool NoBuildingsUnder(IEnumerable<int2> cells) bool NoBuildingsUnder(IEnumerable<CPos> cells)
{ {
var bi = world.WorldActor.Trait<BuildingInfluence>(); var bi = world.WorldActor.Trait<BuildingInfluence>();
return cells.All(c => bi.GetBuildingAt(c) == null); return cells.All(c => bi.GetBuildingAt(c) == null);
} }
public int2? ChooseBuildLocation(string actorType) public CPos? ChooseBuildLocation(string actorType)
{ {
var bi = Rules.Info[actorType].Traits.Get<BuildingInfo>(); var bi = Rules.Info[actorType].Traits.Get<BuildingInfo>();
@@ -200,12 +200,12 @@ namespace OpenRA.Mods.RA.AI
//A bunch of hardcoded lists to keep track of which units are doing what. //A bunch of hardcoded lists to keep track of which units are doing what.
List<Actor> unitsHangingAroundTheBase = new List<Actor>(); List<Actor> unitsHangingAroundTheBase = new List<Actor>();
List<Actor> attackForce = new List<Actor>(); List<Actor> attackForce = new List<Actor>();
int2? attackTarget; CPos? attackTarget;
//Units that the ai already knows about. Any unit not on this list needs to be given a role. //Units that the ai already knows about. Any unit not on this list needs to be given a role.
List<Actor> activeUnits = new List<Actor>(); List<Actor> activeUnits = new List<Actor>();
int2? ChooseEnemyTarget() CPos? ChooseEnemyTarget()
{ {
var liveEnemies = world.Players var liveEnemies = world.Players
.Where(q => p != q && p.Stances[q] == Stance.Enemy) .Where(q => p != q && p.Stances[q] == Stance.Enemy)
@@ -219,14 +219,14 @@ namespace OpenRA.Mods.RA.AI
if (leastLikedEnemies == null) if (leastLikedEnemies == null)
return null; return null;
var enemy = leastLikedEnemies != null ? leastLikedEnemies.Random(random) : null; var enemy = leastLikedEnemies.Random(random);
/* pick something worth attacking owned by that player */ /* pick something worth attacking owned by that player */
var targets = world.Actors var targets = world.Actors
.Where(a => a.Owner == enemy && a.HasTrait<IOccupySpace>()); .Where(a => a.Owner == enemy && a.HasTrait<IOccupySpace>());
Actor target=null; Actor target = null;
if (targets.Count()>0) if (targets.Any())
target = targets.Random(random); target = targets.Random(random);
if (target == null) if (target == null)
@@ -346,7 +346,7 @@ namespace OpenRA.Mods.RA.AI
} }
} }
bool IsRallyPointValid(int2 x) bool IsRallyPointValid(CPos x)
{ {
// this is actually WRONG as soon as HackyAI is building units with a variety of // this is actually WRONG as soon as HackyAI is building units with a variety of
// movement capabilities. (has always been wrong) // movement capabilities. (has always been wrong)
@@ -363,16 +363,15 @@ namespace OpenRA.Mods.RA.AI
BotDebug("Bot {0} needs to find rallypoints for {1} buildings.", BotDebug("Bot {0} needs to find rallypoints for {1} buildings.",
p.PlayerName, buildings.Length); p.PlayerName, buildings.Length);
foreach (var a in buildings) foreach (var a in buildings)
{ {
int2 newRallyPoint = ChooseRallyLocationNear(a.Actor.Location); CPos newRallyPoint = ChooseRallyLocationNear(a.Actor.Location);
world.IssueOrder(new Order("SetRallyPoint", a.Actor, false) { TargetLocation = newRallyPoint }); world.IssueOrder(new Order("SetRallyPoint", a.Actor, false) { TargetLocation = newRallyPoint });
} }
} }
//won't work for shipyards... //won't work for shipyards...
int2 ChooseRallyLocationNear(int2 startPos) CPos ChooseRallyLocationNear(CPos startPos)
{ {
var possibleRallyPoints = world.FindTilesInCircle(startPos, 8).Where(IsRallyPointValid).ToArray(); var possibleRallyPoints = world.FindTilesInCircle(startPos, 8).Where(IsRallyPointValid).ToArray();
if (possibleRallyPoints.Length == 0) if (possibleRallyPoints.Length == 0)
@@ -384,18 +383,18 @@ namespace OpenRA.Mods.RA.AI
return possibleRallyPoints.Random(random); return possibleRallyPoints.Random(random);
} }
int2? ChooseDestinationNear(Actor a, int2 desiredMoveTarget) CPos? ChooseDestinationNear(Actor a, CPos desiredMoveTarget)
{ {
var move = a.TraitOrDefault<IMove>(); var move = a.TraitOrDefault<IMove>();
if (move == null) return null; if (move == null) return null;
int2 xy; CPos xy;
int loopCount = 0; //avoid infinite loops. int loopCount = 0; //avoid infinite loops.
int range = 2; int range = 2;
do do
{ {
//loop until we find a valid move location //loop until we find a valid move location
xy = new int2(desiredMoveTarget.X + random.Next(-range, range), desiredMoveTarget.Y + random.Next(-range, range)); xy = new CPos(desiredMoveTarget.X + random.Next(-range, range), desiredMoveTarget.Y + random.Next(-range, range));
loopCount++; loopCount++;
range = Math.Max(range, loopCount / 2); range = Math.Max(range, loopCount / 2);
if (loopCount > 10) return null; if (loopCount > 10) return null;
@@ -406,7 +405,7 @@ namespace OpenRA.Mods.RA.AI
//try very hard to find a valid move destination near the target. //try very hard to find a valid move destination near the target.
//(Don't accept a move onto the subject's current position. maybe this is already not allowed? ) //(Don't accept a move onto the subject's current position. maybe this is already not allowed? )
bool TryToMove(Actor a, int2 desiredMoveTarget, bool attackMove) bool TryToMove(Actor a, CPos desiredMoveTarget, bool attackMove)
{ {
var xy = ChooseDestinationNear(a, desiredMoveTarget); var xy = ChooseDestinationNear(a, desiredMoveTarget);
if (xy == null) if (xy == null)

View File

@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA.Activities
public override IEnumerable<Target> GetTargets(Actor self) public override IEnumerable<Target> GetTargets(Actor self)
{ {
yield return Target.FromPos(self.Location); yield return Target.FromCell(self.Location);
} }
} }

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA.Activities
if (IsCanceled) return NextActivity; if (IsCanceled) return NextActivity;
if (!Target.IsValid) return NextActivity; if (!Target.IsValid) return NextActivity;
var inRange = ( Util.CellContaining( Target.CenterLocation ) - self.Location ).LengthSquared < Range * Range; var inRange = ( Target.CenterLocation.ToCPos() - self.Location ).LengthSquared < Range * Range;
if( inRange ) return this; if( inRange ) return this;
if (--nextPathTime > 0) return this; if (--nextPathTime > 0) return this;

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Activities
return Util.SequenceActivities( return Util.SequenceActivities(
new MoveAdjacentTo(Target.FromActor(rearmTarget)), new MoveAdjacentTo(Target.FromActor(rearmTarget)),
mobile.MoveTo(Traits.Util.CellContaining(rearmTarget.CenterLocation), rearmTarget), mobile.MoveTo(rearmTarget.CenterLocation.ToCPos(), rearmTarget),
new Rearm(self), new Rearm(self),
new Repair(rearmTarget), new Repair(rearmTarget),
this ); this );
@@ -65,11 +65,10 @@ namespace OpenRA.Mods.RA.Activities
return new Wait(20); // nothing to do here return new Wait(20); // nothing to do here
} }
bool ShouldLayMine(Actor self, int2 p) bool ShouldLayMine(Actor self, CPos p)
{ {
// if there is no unit (other than me) here, we want to place a mine here // if there is no unit (other than me) here, we want to place a mine here
return !self.World.ActorMap return !self.World.ActorMap.GetUnitsAt(p).Any(a => a != self);
.GetUnitsAt(p).Any(a => a != self);
} }
void LayMine(Actor self) void LayMine(Actor self)

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA.Activities
class Leap : Activity class Leap : Activity
{ {
Target target; Target target;
int2 initialLocation; PPos initialLocation;
int moveFraction; int moveFraction;
const int delay = 6; const int delay = 6;
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
public Leap(Actor self, Target target) public Leap(Actor self, Target target)
{ {
this.target = target; this.target = target;
initialLocation = self.Trait<Mobile>().PxPosition; initialLocation = (PPos) self.Trait<Mobile>().PxPosition;
self.Trait<RenderInfantry>().Attacking(self, target); self.Trait<RenderInfantry>().Attacking(self, target);
Sound.Play("dogg5p.aud", self.CenterLocation); Sound.Play("dogg5p.aud", self.CenterLocation);
@@ -41,12 +41,12 @@ namespace OpenRA.Mods.RA.Activities
var mobile = self.Trait<Mobile>(); var mobile = self.Trait<Mobile>();
++moveFraction; ++moveFraction;
mobile.PxPosition = int2.Lerp(initialLocation, target.PxPosition, moveFraction, delay); mobile.PxPosition = PPos.Lerp(initialLocation, target.PxPosition, moveFraction, delay);
if (moveFraction >= delay) if (moveFraction >= delay)
{ {
self.TraitsImplementing<IMove>().FirstOrDefault() self.TraitsImplementing<IMove>().FirstOrDefault()
.SetPosition(self, Util.CellContaining(target.CenterLocation)); .SetPosition(self, target.CenterLocation.ToCPos());
if (target.IsActor) if (target.IsActor)
target.Actor.Kill(self); target.Actor.Kill(self);

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Activities
ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell ); ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );
var ps2 = PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, Util.CellContaining(target.CenterLocation), true ); var ps2 = PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, target.CenterLocation.ToCPos(), true );
var ret = self.World.WorldActor.Trait<PathFinder>().FindBidiPath( ps1, ps2 ); var ret = self.World.WorldActor.Trait<PathFinder>().FindBidiPath( ps1, ps2 );
return Util.SequenceActivities( mobile.MoveTo( () => ret ), this ); return Util.SequenceActivities( mobile.MoveTo( () => ret ), this );

View File

@@ -15,9 +15,9 @@ namespace OpenRA.Mods.RA.Activities
{ {
public class Teleport : Activity public class Teleport : Activity
{ {
int2 destination; CPos destination;
public Teleport(int2 destination) public Teleport(CPos destination)
{ {
this.destination = destination; this.destination = destination;
} }

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.RA.Activities
class Transform : Activity class Transform : Activity
{ {
public readonly string ToActor = null; public readonly string ToActor = null;
public int2 Offset = new int2(0,0); public CVec Offset = new CVec(0, 0);
public int Facing = 96; public int Facing = 96;
public string[] Sounds = {}; public string[] Sounds = {};
public int ForceHealthPercentage = 0; public int ForceHealthPercentage = 0;

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA.Activities
{ {
public class UnloadCargo : Activity public class UnloadCargo : Activity
{ {
int2? ChooseExitTile(Actor self, Actor cargo) CPos? ChooseExitTile(Actor self, Actor cargo)
{ {
// is anyone still hogging this tile? // is anyone still hogging this tile?
if (self.World.ActorMap.GetUnitsAt(self.Location).Count() > 1) if (self.World.ActorMap.GetUnitsAt(self.Location).Count() > 1)
@@ -29,8 +29,8 @@ namespace OpenRA.Mods.RA.Activities
for (var i = -1; i < 2; i++) for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++) for (var j = -1; j < 2; j++)
if ((i != 0 || j != 0) && if ((i != 0 || j != 0) &&
mobile.CanEnterCell(self.Location + new int2(i, j))) mobile.CanEnterCell(self.Location + new CVec(i, j)))
return self.Location + new int2(i, j); return self.Location + new CVec(i, j);
return null; return null;
} }
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA.Activities
if (actor.Destroyed) return; if (actor.Destroyed) return;
var mobile = actor.Trait<Mobile>(); var mobile = actor.Trait<Mobile>();
mobile.Facing = Util.GetFacing( exitPx - currentPx, mobile.Facing ); mobile.Facing = Util.GetFacing( (exitPx - currentPx).ToInt2(), mobile.Facing );
mobile.SetPosition(actor, exitTile.Value); mobile.SetPosition(actor, exitTile.Value);
mobile.AdjustPxPosition(actor, currentPx); mobile.AdjustPxPosition(actor, currentPx);
var speed = mobile.MovementSpeedForCell(actor, exitTile.Value); var speed = mobile.MovementSpeedForCell(actor, exitTile.Value);

View File

@@ -108,8 +108,8 @@ namespace OpenRA.Mods.RA.Air
public int Altitude { get; set; } public int Altitude { get; set; }
[Sync] [Sync]
public int2 SubPxPosition; public int2 SubPxPosition;
public int2 PxPosition { get { return new int2( SubPxPosition.X / 1024, SubPxPosition.Y / 1024 ); } } public PPos PxPosition { get { return new PPos( SubPxPosition.X / 1024, SubPxPosition.Y / 1024 ); } }
public int2 TopLeft { get { return Util.CellContaining( PxPosition ); } } public CPos TopLeft { get { return PxPosition.ToCPos(); } }
readonly AircraftInfo Info; readonly AircraftInfo Info;
@@ -117,7 +117,7 @@ namespace OpenRA.Mods.RA.Air
{ {
this.self = init.self; this.self = init.self;
if( init.Contains<LocationInit>() ) if( init.Contains<LocationInit>() )
this.SubPxPosition = 1024 * Util.CenterOfCell( init.Get<LocationInit, int2>() ); this.SubPxPosition = 1024 * Util.CenterOfCell( init.Get<LocationInit, CPos>() ).ToInt2();
this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing; this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing;
this.Altitude = init.Contains<AltitudeInit>() ? init.Get<AltitudeInit,int>() : 0; this.Altitude = init.Contains<AltitudeInit>() ? init.Get<AltitudeInit,int>() : 0;
@@ -151,17 +151,17 @@ namespace OpenRA.Mods.RA.Air
public int InitialFacing { get { return Info.InitialFacing; } } public int InitialFacing { get { return Info.InitialFacing; } }
public void SetPosition(Actor self, int2 cell) public void SetPosition(Actor self, CPos cell)
{ {
SetPxPosition( self, Util.CenterOfCell( cell ) ); SetPxPosition( self, Util.CenterOfCell( cell ) );
} }
public void SetPxPosition( Actor self, int2 px ) public void SetPxPosition( Actor self, PPos px )
{ {
SubPxPosition = px * 1024; SubPxPosition = px.ToInt2() * 1024;
} }
public void AdjustPxPosition(Actor self, int2 px) { SetPxPosition(self, px); } public void AdjustPxPosition(Actor self, PPos px) { SetPxPosition(self, px); }
public bool AircraftCanEnter(Actor a) public bool AircraftCanEnter(Actor a)
{ {
@@ -170,7 +170,7 @@ namespace OpenRA.Mods.RA.Air
|| Info.RepairBuildings.Contains( a.Info.Name ); || Info.RepairBuildings.Contains( a.Info.Name );
} }
public bool CanEnterCell(int2 location) { return true; } public bool CanEnterCell(CPos location) { return true; }
public int MovementSpeed public int MovementSpeed
{ {
@@ -183,8 +183,8 @@ namespace OpenRA.Mods.RA.Air
} }
} }
Pair<int2, SubCell>[] noCells = new Pair<int2, SubCell>[] { }; Pair<CPos, SubCell>[] noCells = new Pair<CPos, SubCell>[] { };
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { return noCells; } public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { return noCells; }
public void TickMove( int speed, int facing ) public void TickMove( int speed, int facing )
{ {
@@ -192,7 +192,7 @@ namespace OpenRA.Mods.RA.Air
SubPxPosition += rawspeed * -Util.SubPxVector[facing]; SubPxPosition += rawspeed * -Util.SubPxVector[facing];
} }
public bool CanLand(int2 cell) public bool CanLand(CPos cell)
{ {
if (!self.World.Map.IsInMap(cell)) if (!self.World.Map.IsInMap(cell))
return false; return false;
@@ -230,7 +230,7 @@ namespace OpenRA.Mods.RA.Air
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
if (order.OrderID == "Move") if (order.OrderID == "Move")
return new Order(order.OrderID, self, queued) { TargetLocation = Util.CellContaining(target.CenterLocation) }; return new Order(order.OrderID, self, queued) { TargetLocation = target.CenterLocation.ToCPos() };
return null; return null;
} }
@@ -273,7 +273,7 @@ namespace OpenRA.Mods.RA.Air
return false; return false;
} }
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) public bool CanTargetLocation(Actor self, CPos location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor)
{ {
IsQueued = forceQueued; IsQueued = forceQueued;
cursor = self.World.Map.IsInMap(location) ? "move" : "move-blocked"; cursor = self.World.Map.IsInMap(location) ? "move" : "move-blocked";

View File

@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA
{ {
self.World.AddFrameEndTask(w => w.Add( self.World.AddFrameEndTask(w => w.Add(
new Parachute(pilot.Owner, new Parachute(pilot.Owner,
Util.CenterOfCell(Util.CellContaining(self.CenterLocation)), Util.CenterOfCell(self.CenterLocation.ToCPos()),
aircraft.Altitude, pilot))); aircraft.Altitude, pilot)));
Sound.Play(info.ChuteSound, self.CenterLocation); Sound.Play(info.ChuteSound, self.CenterLocation);
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA
pilot.Destroy(); pilot.Destroy();
} }
bool IsSuitableCell(Actor actorToDrop, int2 p) bool IsSuitableCell(Actor actorToDrop, CPos p)
{ {
return actorToDrop.Trait<ITeleportable>().CanEnterCell(p); return actorToDrop.Trait<ITeleportable>().CanEnterCell(p);
} }

View File

@@ -16,12 +16,12 @@ namespace OpenRA.Mods.RA.Air
{ {
public class Fly : Activity public class Fly : Activity
{ {
public readonly int2 Pos; public readonly PPos Pos;
Fly( int2 px ) { Pos = px; } Fly(PPos px) { Pos = px; }
public static Fly ToPx( int2 px ) { return new Fly( px ); } public static Fly ToPx( PPos px ) { return new Fly( px ); }
public static Fly ToCell( int2 pos ) { return new Fly( Util.CenterOfCell( pos ) ); } public static Fly ToCell(CPos pos) { return new Fly(Util.CenterOfCell(pos)); }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Air
var aircraft = self.Trait<Aircraft>(); var aircraft = self.Trait<Aircraft>();
var desiredFacing = Util.GetFacing(d, aircraft.Facing); var desiredFacing = Util.GetFacing(d.ToInt2(), aircraft.Facing);
if (aircraft.Altitude == cruiseAltitude) if (aircraft.Altitude == cruiseAltitude)
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);

View File

@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA.Air
var desiredFacing = Util.GetFacing(dist, aircraft.Facing); var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
if( !float2.WithinEpsilon( float2.Zero, dist, range * Game.CellSize ) ) if( !float2.WithinEpsilon( float2.Zero, dist.ToFloat2(), range * Game.CellSize ) )
aircraft.TickMove( 1024 * aircraft.MovementSpeed, desiredFacing ); aircraft.TickMove( 1024 * aircraft.MovementSpeed, desiredFacing );
attack.DoAttack( self, target ); attack.DoAttack( self, target );

View File

@@ -16,8 +16,8 @@ namespace OpenRA.Mods.RA.Air
{ {
class HeliFly : Activity class HeliFly : Activity
{ {
public readonly int2 Dest; public readonly PPos Dest;
public HeliFly(int2 dest) public HeliFly(PPos dest)
{ {
Dest = dest; Dest = dest;
} }
@@ -36,9 +36,9 @@ namespace OpenRA.Mods.RA.Air
} }
var dist = Dest - aircraft.PxPosition; var dist = Dest - aircraft.PxPosition;
if (float2.WithinEpsilon(float2.Zero, dist, 2)) if (float2.WithinEpsilon(float2.Zero, dist.ToFloat2(), 2))
{ {
aircraft.SubPxPosition = Dest * 1024; aircraft.SubPxPosition = (Dest.ToInt2() * 1024);
return NextActivity; return NextActivity;
} }

View File

@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Air
heli.reservation = res.Reserve(dest, self, heli); heli.reservation = res.Reserve(dest, self, heli);
var exit = dest.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault(); var exit = dest.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = exit != null ? exit.SpawnOffset : int2.Zero; var offset = exit != null ? exit.SpawnOffsetVector : PVecInt.Zero;
return Util.SequenceActivities( return Util.SequenceActivities(
new HeliFly(dest.Trait<IHasLocation>().PxPosition + offset), new HeliFly(dest.Trait<IHasLocation>().PxPosition + offset),

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA.Air
reservation = res.Reserve(order.TargetActor, self, this); reservation = res.Reserve(order.TargetActor, self, this);
var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault(); var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = exit != null ? exit.SpawnOffset : int2.Zero; var offset = exit != null ? exit.SpawnOffsetVector : PVecInt.Zero;
self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green); self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green);
@@ -118,9 +118,9 @@ namespace OpenRA.Mods.RA.Air
.Select(h => GetRepulseForce(self, h)) .Select(h => GetRepulseForce(self, h))
.Aggregate(int2.Zero, (a, b) => a + b); .Aggregate(int2.Zero, (a, b) => a + b);
int RepulsionFacing = Util.GetFacing( f, -1 ); int repulsionFacing = Util.GetFacing( f, -1 );
if( RepulsionFacing != -1 ) if( repulsionFacing != -1 )
TickMove( 1024 * MovementSpeed, RepulsionFacing ); TickMove( 1024 * MovementSpeed, repulsionFacing );
} }
// Returns an int2 in subPx units // Returns an int2 in subPx units
@@ -137,7 +137,7 @@ namespace OpenRA.Mods.RA.Air
if (d.LengthSquared < 1) if (d.LengthSquared < 1)
return Util.SubPxVector[self.World.SharedRandom.Next(255)]; return Util.SubPxVector[self.World.SharedRandom.Next(255)];
return (5120 / d.LengthSquared) * d; return (5120 / d.LengthSquared) * d.ToInt2();
} }
} }
} }

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA.Air
public class Plane : Aircraft, IResolveOrder, ITick, ISync public class Plane : Aircraft, IResolveOrder, ITick, ISync
{ {
[Sync] public int2 RTBPathHash; [Sync] public PVecInt RTBPathHash;
public Plane( ActorInitializer init, PlaneInfo info ) public Plane( ActorInitializer init, PlaneInfo info )
: base( init, info ) { } : base( init, info ) { }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Air
bool isCalculated; bool isCalculated;
Actor dest; Actor dest;
int2 w1, w2, w3; /* tangent points to turn circles */ PPos w1, w2, w3; /* tangent points to turn circles */
public static Actor ChooseAirfield(Actor self) public static Actor ChooseAirfield(Actor self)
{ {
@@ -52,19 +52,18 @@ namespace OpenRA.Mods.RA.Air
var speed = .2f * aircraft.MovementSpeed; var speed = .2f * aircraft.MovementSpeed;
var approachStart = landPos - new float2(aircraft.Altitude * speed, 0); var approachStart = landPos.ToFloat2() - new float2(aircraft.Altitude * speed, 0);
var turnRadius = (128f / self.Info.Traits.Get<AircraftInfo>().ROT) * speed / (float)Math.PI; var turnRadius = (128f / self.Info.Traits.Get<AircraftInfo>().ROT) * speed / (float)Math.PI;
/* work out the center points */ /* work out the center points */
var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI); var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI);
var side = new float2(-fwd.Y, fwd.X); /* rotate */ var side = new float2(-fwd.Y, fwd.X); /* rotate */
var sideTowardBase = new[] { side, -side } var sideTowardBase = new[] { side, -side }
.OrderBy(a => float2.Dot(a, self.CenterLocation - approachStart)) .OrderBy(a => float2.Dot(a, self.CenterLocation.ToFloat2() - approachStart))
.First(); .First();
var c1 = self.CenterLocation + turnRadius * sideTowardBase; var c1 = self.CenterLocation.ToFloat2() + turnRadius * sideTowardBase;
var c2 = approachStart + new float2(0, var c2 = approachStart + new float2(0, turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point
turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point
/* work out tangent points */ /* work out tangent points */
var d = c2 - c1; var d = c2 - c1;
@@ -75,10 +74,10 @@ namespace OpenRA.Mods.RA.Air
if (f.X > 0) f = -f; if (f.X > 0) f = -f;
w1 = (c1 + f).ToInt2(); w1 = (PPos)(c1 + f).ToInt2();
w2 = (c2 + f).ToInt2(); w2 = (PPos)(c2 + f).ToInt2();
w3 = (approachStart).ToInt2(); w3 = (PPos)(approachStart).ToInt2();
plane.RTBPathHash = w1 + w2 + w3; plane.RTBPathHash = (PVecInt)w1 + (PVecInt)w2 + (PVecInt)w3;
isCalculated = true; isCalculated = true;
} }

View File

@@ -28,10 +28,10 @@ namespace OpenRA.Mods.RA
public AppearsOnRadar(AppearsOnRadarInfo info) { this.info = info; } public AppearsOnRadar(AppearsOnRadarInfo info) { this.info = info; }
public IEnumerable<int2> RadarSignatureCells(Actor self) public IEnumerable<CPos> RadarSignatureCells(Actor self)
{ {
if (info.UseLocation) if (info.UseLocation)
return new int2[] { self.Location }; return new CPos[] { self.Location };
else else
return self.OccupiesSpace.OccupiedCells().Select(c => c.First); return self.OccupiesSpace.OccupiedCells().Select(c => c.First);
} }

View File

@@ -149,7 +149,7 @@ namespace OpenRA.Mods.RA
if( target.IsActor ) if( target.IsActor )
return new Order("Attack", self, queued) { TargetActor = target.Actor }; return new Order("Attack", self, queued) { TargetActor = target.Actor };
else else
return new Order( "Attack", self, queued ) { TargetLocation = Util.CellContaining( target.CenterLocation ) }; return new Order( "Attack", self, queued ) { TargetLocation = target.CenterLocation.ToCPos() };
} }
return null; return null;
} }
@@ -217,7 +217,7 @@ namespace OpenRA.Mods.RA
return self.Owner.Stances[ target.Owner ] == targetableRelationship; return self.Owner.Stances[ target.Owner ] == targetableRelationship;
} }
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) public bool CanTargetLocation(Actor self, CPos location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor)
{ {
if (!self.World.Map.IsInMap(location)) if (!self.World.Map.IsInMap(location))
return false; return false;

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
public void TickIdle(Actor self) public void TickIdle(Actor self)
{ {
var target = Util.SubPxVector[self.World.SharedRandom.Next(255)]* Info.MoveRadius / 1024 + self.Location; var target = (CVec)( Util.SubPxVector[self.World.SharedRandom.Next(255)] * Info.MoveRadius / 1024) + self.Location;
self.Trait<AttackMove>().ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = target }); self.Trait<AttackMove>().ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = target });
} }
} }

View File

@@ -23,8 +23,8 @@ namespace OpenRA.Mods.RA
class AttackMove : IResolveOrder, IOrderVoice, INotifyIdle, ISync class AttackMove : IResolveOrder, IOrderVoice, INotifyIdle, ISync
{ {
[Sync] public int2 _targetLocation { get { return TargetLocation.HasValue ? TargetLocation.Value : int2.Zero; } } [Sync] public CPos _targetLocation { get { return TargetLocation.HasValue ? TargetLocation.Value : CPos.Zero; } }
public int2? TargetLocation = null; public CPos? TargetLocation = null;
readonly Mobile mobile; readonly Mobile mobile;
readonly AttackMoveInfo Info; readonly AttackMoveInfo Info;

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Mods.RA
static string cachedTileset; static string cachedTileset;
static Cache<TileReference<ushort,byte>, Sprite> sprites; static Cache<TileReference<ushort,byte>, Sprite> sprites;
Dictionary<ushort, Dictionary<int2, Sprite>> TileSprites = new Dictionary<ushort, Dictionary<int2, Sprite>>(); Dictionary<ushort, Dictionary<CPos, Sprite>> TileSprites = new Dictionary<ushort, Dictionary<CPos, Sprite>>();
Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>(); Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
ushort currentTemplate; ushort currentTemplate;
@@ -86,7 +86,7 @@ namespace OpenRA.Mods.RA
this.Type = self.Info.Name; this.Type = self.Info.Name;
} }
public void Create(ushort template, Dictionary<int2, byte> subtiles) public void Create(ushort template, Dictionary<CPos, byte> subtiles)
{ {
currentTemplate = template; currentTemplate = template;
@@ -103,7 +103,7 @@ namespace OpenRA.Mods.RA
foreach (var t in Info.Templates) foreach (var t in Info.Templates)
{ {
Templates.Add(t.First,self.World.TileSet.Templates[t.First]); Templates.Add(t.First,self.World.TileSet.Templates[t.First]);
TileSprites.Add(t.First,subtiles.ToDictionary( TileSprites.Add(t.First, subtiles.ToDictionary(
a => a.Key, a => a.Key,
a => sprites[new TileReference<ushort,byte>(t.First, (byte)a.Value)])); a => sprites[new TileReference<ushort,byte>(t.First, (byte)a.Value)]));
} }
@@ -113,10 +113,10 @@ namespace OpenRA.Mods.RA
self.World.Map.CustomTerrain[c.X, c.Y] = GetTerrainType(c); self.World.Map.CustomTerrain[c.X, c.Y] = GetTerrainType(c);
} }
public string GetTerrainType(int2 cell) public string GetTerrainType(CPos cell)
{ {
var dx = cell - self.Location; var dx = cell - self.Location;
var index = dx.X + Templates[currentTemplate].Size.X*dx.Y; var index = dx.X + Templates[currentTemplate].Size.X * dx.Y;
return self.World.TileSet.GetTerrainType(new TileReference<ushort, byte>(currentTemplate,(byte)index)); return self.World.TileSet.GetTerrainType(new TileReference<ushort, byte>(currentTemplate,(byte)index));
} }
@@ -132,13 +132,13 @@ namespace OpenRA.Mods.RA
public Bridge GetNeighbor(int[] offset, BridgeLayer bridges) public Bridge GetNeighbor(int[] offset, BridgeLayer bridges)
{ {
if (offset == null) return null; if (offset == null) return null;
return bridges.GetBridge(self.Location + new int2(offset[0], offset[1])); return bridges.GetBridge(self.Location + new CVec(offset[0], offset[1]));
} }
public IEnumerable<Renderable> RenderAsTerrain(Actor self) public IEnumerable<Renderable> RenderAsTerrain(Actor self)
{ {
foreach (var t in TileSprites[currentTemplate]) foreach (var t in TileSprites[currentTemplate])
yield return new Renderable(t.Value, Game.CellSize * t.Key, "terrain", Game.CellSize * t.Key.Y); yield return new Renderable(t.Value, t.Key.ToPPos().ToFloat2(), "terrain", Game.CellSize * t.Key.Y);
} }
bool IsIntact(Bridge b) bool IsIntact(Bridge b)

View File

@@ -75,12 +75,12 @@ namespace OpenRA.Mods.RA
// Create a new actor for this bridge and keep track of which subtiles this bridge includes // Create a new actor for this bridge and keep track of which subtiles this bridge includes
var bridge = w.CreateActor(BridgeTypes[tile].First, new TypeDictionary var bridge = w.CreateActor(BridgeTypes[tile].First, new TypeDictionary
{ {
new LocationInit( new int2(ni, nj) ), new LocationInit( new CPos(ni, nj) ),
new OwnerInit( w.WorldActor.Owner ), new OwnerInit( w.WorldActor.Owner ),
new HealthInit( BridgeTypes[tile].Second ), new HealthInit( BridgeTypes[tile].Second ),
}).Trait<Bridge>(); }).Trait<Bridge>();
Dictionary<int2, byte> subTiles = new Dictionary<int2, byte>(); var subTiles = new Dictionary<CPos, byte>();
// For each subtile in the template // For each subtile in the template
for (byte ind = 0; ind < template.Size.X*template.Size.Y; ind++) for (byte ind = 0; ind < template.Size.X*template.Size.Y; ind++)
@@ -97,16 +97,16 @@ namespace OpenRA.Mods.RA
if (!w.Map.IsInMap(x, y) || w.Map.MapTiles.Value[x, y].index != ind) if (!w.Map.IsInMap(x, y) || w.Map.MapTiles.Value[x, y].index != ind)
continue; continue;
subTiles.Add(new int2(x,y),ind); subTiles.Add(new CPos(x, y), ind);
Bridges[x,y] = bridge; Bridges[x,y] = bridge;
} }
bridge.Create(tile, subTiles); bridge.Create(tile, subTiles);
} }
// Used to check for neighbouring bridges // Used to check for neighbouring bridges
public Bridge GetBridge(int2 cell) public Bridge GetBridge(CPos cell)
{ {
if (!world.Map.IsInMap(cell.X, cell.Y)) if (!world.Map.IsInMap(cell))
return null; return null;
return Bridges[ cell.X, cell.Y ]; return Bridges[ cell.X, cell.Y ];

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Buildings
{ {
World world; World world;
BibLayerInfo info; BibLayerInfo info;
Dictionary<int2, TileReference<byte, byte>> tiles; Dictionary<CPos, TileReference<byte, byte>> tiles;
Sprite[][] bibSprites; Sprite[][] bibSprites;
public BibLayer(Actor self, BibLayerInfo info) public BibLayer(Actor self, BibLayerInfo info)
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Buildings
public void WorldLoaded(World w) public void WorldLoaded(World w)
{ {
world = w; world = w;
tiles = new Dictionary<int2, TileReference<byte, byte>>(); tiles = new Dictionary<CPos, TileReference<byte, byte>>();
} }
public void DoBib(Actor b, bool isAdd) public void DoBib(Actor b, bool isAdd)
@@ -63,9 +63,9 @@ namespace OpenRA.Mods.RA.Buildings
for (int i = 0; i < 2 * size; i++) for (int i = 0; i < 2 * size; i++)
{ {
var p = b.Location + new int2(i % size, i / size + bibOffset); var p = b.Location + new CVec(i % size, i / size + bibOffset);
if (isAdd) if (isAdd)
tiles[p] = new TileReference<byte, byte>((byte)((isAdd) ? bib + 1 : 0), (byte)i); tiles[p] = new TileReference<byte, byte>((byte)(bib + 1), (byte)i);
else else
tiles.Remove(p); tiles.Remove(p);
} }
@@ -81,8 +81,7 @@ namespace OpenRA.Mods.RA.Buildings
if (!world.LocalShroud.IsExplored(kv.Key)) if (!world.LocalShroud.IsExplored(kv.Key))
continue; continue;
bibSprites[kv.Value.type - 1][kv.Value.index].DrawAt( wr, bibSprites[kv.Value.type - 1][kv.Value.index].DrawAt(wr, kv.Key.ToPPos().ToFloat2(), "terrain");
Game.CellSize * kv.Key, "terrain");
} }
} }
} }

View File

@@ -32,28 +32,28 @@ namespace OpenRA.Mods.RA.Buildings
public object Create(ActorInitializer init) { return new Building(init, this); } public object Create(ActorInitializer init) { return new Building(init, this); }
public bool IsCloseEnoughToBase(World world, Player p, string buildingName, int2 topLeft) public bool IsCloseEnoughToBase(World world, Player p, string buildingName, CPos topLeft)
{ {
if (p.PlayerActor.Trait<DeveloperMode>().BuildAnywhere) if (p.PlayerActor.Trait<DeveloperMode>().BuildAnywhere)
return true; return true;
var buildingMaxBounds = Dimensions; var buildingMaxBounds = (CVec)Dimensions;
if( Rules.Info[ buildingName ].Traits.Contains<BibInfo>() ) if( Rules.Info[ buildingName ].Traits.Contains<BibInfo>() )
buildingMaxBounds.Y += 1; buildingMaxBounds += new CVec(0, 1);
var scanStart = world.ClampToWorld( topLeft - new int2( Adjacent, Adjacent ) ); var scanStart = world.ClampToWorld( topLeft - new CVec( Adjacent, Adjacent ) );
var scanEnd = world.ClampToWorld( topLeft + buildingMaxBounds + new int2( Adjacent, Adjacent ) ); var scanEnd = world.ClampToWorld(topLeft + buildingMaxBounds + new CVec(Adjacent, Adjacent));
var nearnessCandidates = new List<int2>(); var nearnessCandidates = new List<CPos>();
var bi = world.WorldActor.Trait<BuildingInfluence>(); var bi = world.WorldActor.Trait<BuildingInfluence>();
for( int y = scanStart.Y ; y < scanEnd.Y ; y++ ) for( int y = scanStart.Y ; y < scanEnd.Y ; y++ )
for( int x = scanStart.X ; x < scanEnd.X ; x++ ) for( int x = scanStart.X ; x < scanEnd.X ; x++ )
{ {
var at = bi.GetBuildingAt( new int2( x, y ) ); var at = bi.GetBuildingAt( new CPos( x, y ) );
if( at != null && at.Owner.Stances[ p ] == Stance.Ally && at.HasTrait<GivesBuildableArea>() ) if( at != null && at.Owner.Stances[ p ] == Stance.Ally && at.HasTrait<GivesBuildableArea>() )
nearnessCandidates.Add( new int2( x, y ) ); nearnessCandidates.Add( new CPos( x, y ) );
} }
var buildingTiles = FootprintUtils.Tiles( buildingName, this, topLeft ).ToList(); var buildingTiles = FootprintUtils.Tiles( buildingName, this, topLeft ).ToList();
@@ -68,27 +68,26 @@ namespace OpenRA.Mods.RA.Buildings
{ {
readonly Actor self; readonly Actor self;
public readonly BuildingInfo Info; public readonly BuildingInfo Info;
[Sync] [Sync] readonly CPos topLeft;
readonly int2 topLeft;
PowerManager PlayerPower; PowerManager PlayerPower;
int2 pxPosition; PPos pxPosition;
public int2 TopLeft { get { return topLeft; } } public CPos TopLeft { get { return topLeft; } }
public int2 PxPosition { get { return pxPosition; } } public PPos PxPosition { get { return pxPosition; } }
public IEnumerable<string> ProvidesPrerequisites { get { yield return self.Info.Name; } } public IEnumerable<string> ProvidesPrerequisites { get { yield return self.Info.Name; } }
public Building(ActorInitializer init, BuildingInfo info) public Building(ActorInitializer init, BuildingInfo info)
{ {
this.self = init.self; this.self = init.self;
this.topLeft = init.Get<LocationInit,int2>(); this.topLeft = init.Get<LocationInit, CPos>();
this.Info = info; this.Info = info;
this.PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>(); this.PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>();
occupiedCells = FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ) occupiedCells = FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft )
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); .Select(c => Pair.New(c, SubCell.FullCell)).ToArray();
pxPosition = ( 2 * topLeft + Info.Dimensions ) * Game.CellSize / 2; pxPosition = (PPos) (( 2 * topLeft.ToInt2() + Info.Dimensions ) * Game.CellSize / 2);
} }
public int GetPowerUsage() public int GetPowerUsage()
@@ -107,8 +106,8 @@ namespace OpenRA.Mods.RA.Buildings
PlayerPower.UpdateActor(self, GetPowerUsage()); PlayerPower.UpdateActor(self, GetPowerUsage());
} }
Pair<int2,SubCell>[] occupiedCells; Pair<CPos, SubCell>[] occupiedCells;
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { return occupiedCells; } public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { return occupiedCells; }
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner) public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{ {

View File

@@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA.Buildings
influence[ u.X, u.Y ] = isAdd ? a : null; influence[ u.X, u.Y ] = isAdd ? a : null;
} }
public Actor GetBuildingAt(int2 cell) public Actor GetBuildingAt(CPos cell)
{ {
if (!map.IsInMap(cell)) return null; if (!map.IsInMap(cell)) return null;
return influence[cell.X, cell.Y]; return influence[cell.X, cell.Y];

View File

@@ -16,34 +16,34 @@ namespace OpenRA.Mods.RA.Buildings
{ {
public static class FootprintUtils public static class FootprintUtils
{ {
public static IEnumerable<int2> Tiles( string name, BuildingInfo buildingInfo, int2 topLeft ) public static IEnumerable<CPos> Tiles(string name, BuildingInfo buildingInfo, CPos topLeft)
{ {
var dim = buildingInfo.Dimensions; var dim = (CVec)buildingInfo.Dimensions;
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x)); var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
if (Rules.Info[ name ].Traits.Contains<BibInfo>()) if (Rules.Info[ name ].Traits.Contains<BibInfo>())
{ {
dim.Y += 1; dim += new CVec(0, 1);
footprint = footprint.Concat(new char[dim.X]); footprint = footprint.Concat(new char[dim.X]);
} }
return TilesWhere( name, dim, footprint.ToArray(), a => a != '_' ).Select( t => t + topLeft ); return TilesWhere( name, dim, footprint.ToArray(), a => a != '_' ).Select( t => t + topLeft );
} }
public static IEnumerable<int2> Tiles(Actor a) public static IEnumerable<CPos> Tiles(Actor a)
{ {
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ); return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location );
} }
public static IEnumerable<int2> UnpathableTiles( string name, BuildingInfo buildingInfo, int2 position ) public static IEnumerable<CPos> UnpathableTiles(string name, BuildingInfo buildingInfo, CPos position)
{ {
var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray(); var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray();
foreach( var tile in TilesWhere( name, buildingInfo.Dimensions, footprint, a => a == 'x' ) ) foreach( var tile in TilesWhere( name, (CVec)buildingInfo.Dimensions, footprint, a => a == 'x' ) )
yield return tile + position; yield return tile + position;
} }
static IEnumerable<int2> TilesWhere( string name, int2 dim, char[] footprint, Func<char, bool> cond ) static IEnumerable<CVec> TilesWhere(string name, CVec dim, char[] footprint, Func<char, bool> cond)
{ {
if( footprint.Length != dim.X * dim.Y ) if( footprint.Length != dim.X * dim.Y )
throw new InvalidOperationException( "Invalid footprint for " + name ); throw new InvalidOperationException( "Invalid footprint for " + name );
@@ -52,13 +52,13 @@ namespace OpenRA.Mods.RA.Buildings
for( int y = 0 ; y < dim.Y ; y++ ) for( int y = 0 ; y < dim.Y ; y++ )
for( int x = 0 ; x < dim.X ; x++ ) for( int x = 0 ; x < dim.X ; x++ )
if( cond( footprint[ index++ ] ) ) if( cond( footprint[ index++ ] ) )
yield return new int2( x, y ); yield return new CVec(x, y);
} }
public static int2 AdjustForBuildingSize( BuildingInfo buildingInfo ) public static CVec AdjustForBuildingSize( BuildingInfo buildingInfo )
{ {
var dim = buildingInfo.Dimensions; var dim = buildingInfo.Dimensions;
return new int2( dim.X / 2, dim.Y > 1 ? ( dim.Y + 1 ) / 2 : 0 ); return new CVec(dim.X / 2, dim.Y > 1 ? (dim.Y + 1) / 2 : 0);
} }
} }
} }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Buildings
public void Killed(Actor self, AttackInfo e) public void Killed(Actor self, AttackInfo e)
{ {
self.World.WorldActor.Trait<ScreenShaker>().AddEffect(Info.Intensity, self.CenterLocation, 1); self.World.WorldActor.Trait<ScreenShaker>().AddEffect(Info.Intensity, self.CenterLocation.ToFloat2(), 1);
} }
} }
} }

View File

@@ -16,12 +16,12 @@ namespace OpenRA.Mods.RA.Buildings
{ {
public static class BuildingUtils public static class BuildingUtils
{ {
public static bool IsCellBuildable(this World world, int2 a, BuildingInfo bi) public static bool IsCellBuildable(this World world, CPos a, BuildingInfo bi)
{ {
return world.IsCellBuildable(a, bi, null); return world.IsCellBuildable(a, bi, null);
} }
public static bool IsCellBuildable(this World world, int2 a, BuildingInfo bi, Actor toIgnore) public static bool IsCellBuildable(this World world, CPos a, BuildingInfo bi, Actor toIgnore)
{ {
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(a) != null) return false; if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(a) != null) return false;
if (world.ActorMap.GetUnitsAt(a).Any(b => b != toIgnore)) return false; if (world.ActorMap.GetUnitsAt(a).Any(b => b != toIgnore)) return false;
@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Buildings
return world.Map.IsInMap(a) && bi.TerrainTypes.Contains(world.GetTerrainType(a)); return world.Map.IsInMap(a) && bi.TerrainTypes.Contains(world.GetTerrainType(a));
} }
public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, int2 topLeft, Actor toIgnore) public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, CPos topLeft, Actor toIgnore)
{ {
var res = world.WorldActor.Trait<ResourceLayer>(); var res = world.WorldActor.Trait<ResourceLayer>();
return FootprintUtils.Tiles(name, building, topLeft).All( return FootprintUtils.Tiles(name, building, topLeft).All(
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA.Buildings
world.IsCellBuildable(t, building, toIgnore)); world.IsCellBuildable(t, building, toIgnore));
} }
public static IEnumerable<int2> GetLineBuildCells(World world, int2 location, string name, BuildingInfo bi) public static IEnumerable<CPos> GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi)
{ {
int range = Rules.Info[name].Traits.Get<LineBuildInfo>().Range; int range = Rules.Info[name].Traits.Get<LineBuildInfo>().Range;
var topLeft = location; // 1x1 assumption! var topLeft = location; // 1x1 assumption!
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Buildings
// Start at place location, search outwards // Start at place location, search outwards
// TODO: First make it work, then make it nice // TODO: First make it work, then make it nice
var vecs = new[] { new int2(1, 0), new int2(0, 1), new int2(-1, 0), new int2(0, -1) }; var vecs = new[] { new CVec(1, 0), new CVec(0, 1), new CVec(-1, 0), new CVec(0, -1) };
int[] dirs = { 0, 0, 0, 0 }; int[] dirs = { 0, 0, 0, 0 };
for (int d = 0; d < 4; d++) for (int d = 0; d < 4; d++)
{ {
@@ -56,7 +56,7 @@ namespace OpenRA.Mods.RA.Buildings
if (dirs[d] != 0) if (dirs[d] != 0)
continue; continue;
int2 cell = topLeft + i * vecs[d]; CPos cell = topLeft + i * vecs[d];
if (world.IsCellBuildable(cell, bi)) if (world.IsCellBuildable(cell, bi))
continue; // Cell is empty; continue search continue; // Cell is empty; continue search

View File

@@ -24,8 +24,7 @@ namespace OpenRA.Mods.RA
class Burns : ITick, ISync class Burns : ITick, ISync
{ {
[Sync] [Sync] int ticks;
int ticks;
BurnsInfo Info; BurnsInfo Info;
public Burns(Actor self, BurnsInfo info) public Burns(Actor self, BurnsInfo info)

View File

@@ -22,16 +22,16 @@ namespace OpenRA.Mods.RA
class CarpetBomb : ITick // todo: maybe integrate this better with the normal weapons system? class CarpetBomb : ITick // todo: maybe integrate this better with the normal weapons system?
{ {
int2 Target; CPos Target;
int dropDelay; int dropDelay;
public void SetTarget(int2 targetCell) { Target = targetCell; } public void SetTarget(CPos targetCell) { Target = targetCell; }
public void Tick(Actor self) public void Tick(Actor self)
{ {
var info = self.Info.Traits.Get<CarpetBombInfo>(); var info = self.Info.Traits.Get<CarpetBombInfo>();
if( !Combat.IsInRange( self.CenterLocation, info.Range, Target * Game.CellSize ) ) if( !Combat.IsInRange( self.CenterLocation, info.Range, Target.ToPPos() ) )
return; return;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>(); var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();

View File

@@ -26,8 +26,7 @@ namespace OpenRA.Mods.RA
class CashTrickler : ITick, ISync class CashTrickler : ITick, ISync
{ {
[Sync] [Sync] int ticks;
int ticks;
CashTricklerInfo Info; CashTricklerInfo Info;
public CashTrickler(CashTricklerInfo info) public CashTrickler(CashTricklerInfo info)
{ {

View File

@@ -24,8 +24,7 @@ namespace OpenRA.Mods.RA
class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ITick, IPips, IOrderVoice, ISync class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ITick, IPips, IOrderVoice, ISync
{ {
// Recharge logic // Recharge logic
[Sync] [Sync] int chargeTick = 0; // How long until we can chronoshift again?
int chargeTick = 0; // How long until we can chronoshift again?
public void Tick(Actor self) public void Tick(Actor self)
{ {
@@ -60,7 +59,7 @@ namespace OpenRA.Mods.RA
self.CancelActivity(); self.CancelActivity();
self.QueueActivity(new Teleport(order.TargetLocation)); self.QueueActivity(new Teleport(order.TargetLocation));
Sound.Play("chrotnk1.aud", self.CenterLocation); Sound.Play("chrotnk1.aud", self.CenterLocation);
Sound.Play("chrotnk1.aud", Game.CellSize * order.TargetLocation.ToFloat2()); Sound.Play("chrotnk1.aud", order.TargetLocation.ToPPos());
chargeTick = 25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime; chargeTick = 25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime;
foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>()) foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>())

View File

@@ -18,10 +18,8 @@ namespace OpenRA.Mods.RA
public class Chronoshiftable : ITick, ISync public class Chronoshiftable : ITick, ISync
{ {
// Return-to-sender logic // Return-to-sender logic
[Sync] [Sync] CPos chronoshiftOrigin;
int2 chronoshiftOrigin; [Sync] int chronoshiftReturnTicks = 0;
[Sync]
int chronoshiftReturnTicks = 0;
public void Tick(Actor self) public void Tick(Actor self)
{ {
@@ -41,7 +39,7 @@ namespace OpenRA.Mods.RA
} }
// Can't be used in synced code, except with ignoreVis. // Can't be used in synced code, except with ignoreVis.
public virtual bool CanChronoshiftTo(Actor self, int2 targetLocation, bool ignoreVis) public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation, bool ignoreVis)
{ {
// Todo: Allow enemy units to be chronoshifted into bad terrain to kill them // Todo: Allow enemy units to be chronoshifted into bad terrain to kill them
return self.HasTrait<ITeleportable>() && return self.HasTrait<ITeleportable>() &&
@@ -49,7 +47,7 @@ namespace OpenRA.Mods.RA
(ignoreVis || self.World.LocalShroud.IsExplored(targetLocation)); (ignoreVis || self.World.LocalShroud.IsExplored(targetLocation));
} }
public virtual bool Teleport(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere) public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere)
{ {
/// Set up return-to-sender info /// Set up return-to-sender info
chronoshiftOrigin = self.Location; chronoshiftOrigin = self.Location;

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA
public static void DoImpact(WarheadInfo warhead, ProjectileArgs args) public static void DoImpact(WarheadInfo warhead, ProjectileArgs args)
{ {
var world = args.firedBy.World; var world = args.firedBy.World;
var targetTile = Util.CellContaining(args.dest); var targetTile = args.dest.ToCPos();
if (!world.Map.IsInMap(targetTile)) if (!world.Map.IsInMap(targetTile))
return; return;
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA
case DamageModel.PerCell: case DamageModel.PerCell:
{ {
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0])) foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new int2(1,1)))) foreach (var unit in world.FindUnits(t.ToPPos(), (t + new CVec(1,1)).ToPPos()))
unit.InflictDamage(args.firedBy, unit.InflictDamage(args.firedBy,
(int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead); (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
} break; } break;
@@ -103,16 +103,19 @@ namespace OpenRA.Mods.RA
{ {
foreach (var warhead in args.weapon.Warheads) foreach (var warhead in args.weapon.Warheads)
{ {
Action a = () => DoImpact(warhead, args); // NOTE(jsd): Fixed access to modified closure bug!
var warheadClosed = warhead;
Action a = () => DoImpact(warheadClosed, args);
if (warhead.Delay > 0) if (warhead.Delay > 0)
args.firedBy.World.AddFrameEndTask( args.firedBy.World.AddFrameEndTask(
w => w.Add(new DelayedAction(warhead.Delay, a))); w => w.Add(new DelayedAction(warheadClosed.Delay, a)));
else else
a(); a();
} }
} }
public static void DoExplosion(Actor attacker, string weapontype, int2 pos, int altitude) public static void DoExplosion(Actor attacker, string weapontype, PPos pos, int altitude)
{ {
var args = new ProjectileArgs var args = new ProjectileArgs
{ {
@@ -174,7 +177,7 @@ namespace OpenRA.Mods.RA
return true; return true;
} }
public static bool WeaponValidForTarget( WeaponInfo weapon, World world, int2 location ) public static bool WeaponValidForTarget( WeaponInfo weapon, World world, CPos location )
{ {
if( weapon.ValidTargets.Contains( "Ground" ) && world.GetTerrainType( location ) != "Water" ) return true; if( weapon.ValidTargets.Contains( "Ground" ) && world.GetTerrainType( location ) != "Water" ) return true;
if( weapon.ValidTargets.Contains( "Water" ) && world.GetTerrainType( location ) == "Water" ) return true; if( weapon.ValidTargets.Contains( "Water" ) && world.GetTerrainType( location ) == "Water" ) return true;
@@ -192,7 +195,7 @@ namespace OpenRA.Mods.RA
return Util.RotateVectorByFacing(localRecoil, facing, .7f); return Util.RotateVectorByFacing(localRecoil, facing, .7f);
} }
public static float2 GetTurretPosition(Actor self, IFacing facing, Turret turret) public static PVecInt GetTurretPosition(Actor self, IFacing facing, Turret turret)
{ {
if (facing == null) return turret.ScreenSpacePosition; /* things that don't have a rotating base don't need the turrets repositioned */ if (facing == null) return turret.ScreenSpacePosition; /* things that don't have a rotating base don't need the turrets repositioned */
@@ -201,41 +204,41 @@ namespace OpenRA.Mods.RA
var bodyFacing = facing.Facing; var bodyFacing = facing.Facing;
var quantizedFacing = Util.QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs); var quantizedFacing = Util.QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs);
return (Util.RotateVectorByFacing(turret.UnitSpacePosition, quantizedFacing, .7f) return (PVecInt) ((PVecFloat)(Util.RotateVectorByFacing(turret.UnitSpacePosition.ToFloat2(), quantizedFacing, .7f)
+ GetRecoil(self, turret.Recoil)) + GetRecoil(self, turret.Recoil))
+ turret.ScreenSpacePosition; + turret.ScreenSpacePosition);
} }
// gets the screen-space position of a barrel. // gets the screen-space position of a barrel.
public static float2 GetBarrelPosition(Actor self, IFacing facing, Turret turret, Barrel barrel) public static PVecInt GetBarrelPosition(Actor self, IFacing facing, Turret turret, Barrel barrel)
{ {
var turreted = self.TraitOrDefault<Turreted>(); var turreted = self.TraitOrDefault<Turreted>();
if (turreted == null && facing == null) if (turreted == null && facing == null)
return float2.Zero; return PVecInt.Zero;
var turretFacing = turreted != null ? turreted.turretFacing : facing.Facing; var turretFacing = turreted != null ? turreted.turretFacing : facing.Facing;
return GetTurretPosition(self, facing, turret) + barrel.ScreenSpaceOffset return GetTurretPosition(self, facing, turret) + barrel.ScreenSpaceOffset
+ Util.RotateVectorByFacing(barrel.TurretSpaceOffset, turretFacing, .7f); + (PVecInt)(PVecFloat)Util.RotateVectorByFacing(barrel.TurretSpaceOffset.ToFloat2(), turretFacing, .7f);
} }
public static bool IsInRange( float2 attackOrigin, float range, Actor target ) public static bool IsInRange( PPos attackOrigin, float range, Actor target )
{ {
var rsq = range * range * Game.CellSize * Game.CellSize; var rsq = range * range * Game.CellSize * Game.CellSize;
foreach( var cell in target.Trait<ITargetable>().TargetableCells( target ) ) foreach ( var cell in target.Trait<ITargetable>().TargetableCells( target ) )
if( ( attackOrigin - cell * Game.CellSize ).LengthSquared <= rsq ) if ( (attackOrigin - cell.ToPPos()).LengthSquared <= rsq )
return true; return true;
return false; return false;
} }
public static bool IsInRange( float2 attackOrigin, float range, float2 targetLocation ) public static bool IsInRange(PPos attackOrigin, float range, PPos targetLocation)
{ {
var rsq = range * range * Game.CellSize * Game.CellSize; var rsq = range * range * Game.CellSize * Game.CellSize;
return ( attackOrigin - targetLocation ).LengthSquared <= rsq; return ( attackOrigin - targetLocation ).LengthSquared <= rsq;
} }
public static bool IsInRange( float2 attackOrigin, float range, Target target ) public static bool IsInRange(PPos attackOrigin, float range, Target target)
{ {
if( !target.IsValid ) return false; if( !target.IsValid ) return false;
if( target.IsActor ) if( target.IsActor )

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA
{ {
readonly Actor self; readonly Actor self;
[Sync] int ticks; [Sync] int ticks;
[Sync] public int2 Location; [Sync] public CPos Location;
CrateInfo Info; CrateInfo Info;
public Crate(ActorInitializer init, CrateInfo info) public Crate(ActorInitializer init, CrateInfo info)
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA
this.self = init.self; this.self = init.self;
if (init.Contains<LocationInit>()) if (init.Contains<LocationInit>())
{ {
this.Location = init.Get<LocationInit, int2>(); this.Location = init.Get<LocationInit, CPos>();
PxPosition = Util.CenterOfCell(Location); PxPosition = Util.CenterOfCell(Location);
} }
this.Info = info; this.Info = info;
@@ -79,19 +79,19 @@ namespace OpenRA.Mods.RA
self.Destroy(); self.Destroy();
} }
public int2 TopLeft { get { return Location; } } public CPos TopLeft { get { return Location; } }
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); } public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); }
public int2 PxPosition { get; private set; } public PPos PxPosition { get; private set; }
public void SetPxPosition( Actor self, int2 px ) public void SetPxPosition(Actor self, PPos px)
{ {
SetPosition( self, Util.CellContaining( px ) ); SetPosition( self, px.ToCPos() );
} }
public void AdjustPxPosition(Actor self, int2 px) { SetPxPosition(self, px); } public void AdjustPxPosition(Actor self, PPos px) { SetPxPosition(self, px); }
public bool CanEnterCell(int2 cell) public bool CanEnterCell(CPos cell)
{ {
if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false; if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false;
var type = self.World.GetTerrainType(cell); var type = self.World.GetTerrainType(cell);
@@ -104,7 +104,7 @@ namespace OpenRA.Mods.RA
return true; return true;
} }
public void SetPosition(Actor self, int2 cell) public void SetPosition(Actor self, CPos cell)
{ {
if( self.IsInWorld ) if( self.IsInWorld )
self.World.ActorMap.Remove(self, this); self.World.ActorMap.Remove(self, this);

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA
} }
} }
int2? ChooseDropCell(Actor self, bool inWater, int maxTries) CPos? ChooseDropCell(Actor self, bool inWater, int maxTries)
{ {
for( var n = 0; n < maxTries; n++ ) for( var n = 0; n < maxTries; n++ )
{ {

View File

@@ -60,17 +60,17 @@ namespace OpenRA.Mods.RA.Crates
base.Activate(collector); base.Activate(collector);
} }
IEnumerable<int2> GetSuitableCells(int2 near) IEnumerable<CPos> GetSuitableCells(CPos near)
{ {
var mi = Rules.Info[Info.Unit].Traits.Get<MobileInfo>(); var mi = Rules.Info[Info.Unit].Traits.Get<MobileInfo>();
for (var i = -1; i < 2; i++) for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++) for (var j = -1; j < 2; j++)
if (mi.CanEnterCell(self.World, self.Owner, near + new int2(i, j), null, true)) if (mi.CanEnterCell(self.World, self.Owner, near + new CVec(i, j), null, true))
yield return near + new int2(i, j); yield return near + new CVec(i, j);
} }
int2? ChooseEmptyCellNear(Actor a) CPos? ChooseEmptyCellNear(Actor a)
{ {
var possibleCells = GetSuitableCells(a.Location).ToArray(); var possibleCells = GetSuitableCells(a.Location).ToArray();
if (possibleCells.Length == 0) if (possibleCells.Length == 0)

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.RA
class DemoTruck : Chronoshiftable, INotifyKilled class DemoTruck : Chronoshiftable, INotifyKilled
{ {
// Explode on chronoshift // Explode on chronoshift
public override bool Teleport(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere) public override bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere)
{ {
Detonate(self, chronosphere); Detonate(self, chronosphere);
return false; return false;

View File

@@ -57,8 +57,8 @@ namespace OpenRA.Mods.RA.Effects
if (info.Inaccuracy > 0) if (info.Inaccuracy > 0)
{ {
var factor = ((Args.dest - Args.src).Length / Game.CellSize) / args.weapon.Range; var factor = ((Args.dest - Args.src).Length / (float)Game.CellSize) / args.weapon.Range;
Args.dest += (info.Inaccuracy * factor * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2(); Args.dest += (PVecInt) (info.Inaccuracy * factor * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2();
} }
if (Info.Image != null) if (Info.Image != null)
@@ -110,7 +110,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
var at = (float)t / TotalTime(); var at = (float)t / TotalTime();
var altitude = float2.Lerp(Args.srcAltitude, Args.destAltitude, at); var altitude = float2.Lerp(Args.srcAltitude, Args.destAltitude, at);
var pos = float2.Lerp(Args.src, Args.dest, at) - new float2(0, altitude); var pos = float2.Lerp(Args.src.ToFloat2(), Args.dest.ToFloat2(), at) - new float2(0, altitude);
var highPos = (Info.High || Info.Angle > 0) var highPos = (Info.High || Info.Angle > 0)
? (pos - new float2(0, GetAltitude())) ? (pos - new float2(0, GetAltitude()))
@@ -119,24 +119,24 @@ namespace OpenRA.Mods.RA.Effects
if (Info.Trail != null && --ticksToNextSmoke < 0) if (Info.Trail != null && --ticksToNextSmoke < 0)
{ {
world.AddFrameEndTask(w => w.Add( world.AddFrameEndTask(w => w.Add(
new Smoke(w, highPos.ToInt2(), Info.Trail))); new Smoke(w, (PPos) highPos.ToInt2(), Info.Trail)));
ticksToNextSmoke = Info.TrailInterval; ticksToNextSmoke = Info.TrailInterval;
} }
if (Trail != null) if (Trail != null)
Trail.Tick(highPos); Trail.Tick((PPos)highPos.ToInt2());
} }
if (!Info.High) // check for hitting a wall if (!Info.High) // check for hitting a wall
{ {
var at = (float)t / TotalTime(); var at = (float)t / TotalTime();
var pos = float2.Lerp(Args.src, Args.dest, at); var pos = float2.Lerp(Args.src.ToFloat2(), Args.dest.ToFloat2(), at);
var cell = Traits.Util.CellContaining(pos); var cell = ((PPos) pos.ToInt2()).ToCPos();
if (world.ActorMap.GetUnitsAt(cell).Any( if (world.ActorMap.GetUnitsAt(cell).Any(
a => a.HasTrait<IBlocksBullets>())) a => a.HasTrait<IBlocksBullets>()))
{ {
Args.dest = pos.ToInt2(); Args.dest = (PPos) pos.ToInt2();
Explode(world); Explode(world);
} }
} }
@@ -151,9 +151,9 @@ namespace OpenRA.Mods.RA.Effects
var at = (float)t / TotalTime(); var at = (float)t / TotalTime();
var altitude = float2.Lerp(Args.srcAltitude, Args.destAltitude, at); var altitude = float2.Lerp(Args.srcAltitude, Args.destAltitude, at);
var pos = float2.Lerp(Args.src, Args.dest, at) - new float2(0, altitude); var pos = float2.Lerp(Args.src.ToFloat2(), Args.dest.ToFloat2(), at) - new float2(0, altitude);
if (Args.firedBy.World.LocalShroud.IsVisible(OpenRA.Traits.Util.CellContaining(pos))) if (Args.firedBy.World.LocalShroud.IsVisible(((PPos) pos.ToInt2()).ToCPos()))
{ {
if (Info.High || Info.Angle > 0) if (Info.High || Info.Angle > 0)
{ {

View File

@@ -18,19 +18,20 @@ namespace OpenRA.Mods.RA.Effects
{ {
class CashTick : IEffect class CashTick : IEffect
{ {
string s; readonly string s;
int remaining; int remaining;
int velocity; readonly int velocity;
float2 pos, offset; PPos pos;
Color color; readonly float2 offset;
SpriteFont font; readonly Color color;
readonly SpriteFont font;
static string FormatCashAmount(int x) { return "{0}${1}".F(x < 0 ? "-" : "+", x); } static string FormatCashAmount(int x) { return "{0}${1}".F(x < 0 ? "-" : "+", x); }
public CashTick(int value, int lifetime, int velocity, float2 pos, Color color) public CashTick(int value, int lifetime, int velocity, PPos pos, Color color)
: this( FormatCashAmount(value), lifetime, velocity, pos, color ) { } : this( FormatCashAmount(value), lifetime, velocity, pos, color ) { }
public CashTick(string value, int lifetime, int velocity, float2 pos, Color color) public CashTick(string value, int lifetime, int velocity, PPos pos, Color color)
{ {
this.color = color; this.color = color;
this.velocity = velocity; this.velocity = velocity;
@@ -45,12 +46,12 @@ namespace OpenRA.Mods.RA.Effects
{ {
if (--remaining <= 0) if (--remaining <= 0)
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
pos.Y -= velocity; pos -= new PVecInt(0, velocity);
} }
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
font.DrawTextWithContrast(s, Game.viewport.Zoom*(pos - Game.viewport.Location) - offset, color, Color.Black,1); font.DrawTextWithContrast(s, Game.viewport.Zoom*(pos.ToFloat2() - Game.viewport.Location) - offset, color, Color.Black,1);
yield break; yield break;
} }
} }

View File

@@ -45,8 +45,7 @@ namespace OpenRA.Mods.RA
public void Tick(Actor self) public void Tick(Actor self)
{ {
history.Tick(self.CenterLocation - new int2(0, move.Altitude) history.Tick(self.CenterLocation - new PVecInt(0, move.Altitude) - Combat.GetTurretPosition(self, facing, contrailTurret));
- Combat.GetTurretPosition(self, facing, contrailTurret));
} }
public void RenderAfterWorld(WorldRenderer wr, Actor self) { history.Render(self); } public void RenderAfterWorld(WorldRenderer wr, Actor self) { history.Render(self); }
@@ -54,7 +53,7 @@ namespace OpenRA.Mods.RA
class ContrailHistory class ContrailHistory
{ {
List<float2> positions = new List<float2>(); List<PPos> positions = new List<PPos>();
readonly int TrailLength; readonly int TrailLength;
readonly Color Color; readonly Color Color;
readonly int StartSkip; readonly int StartSkip;
@@ -75,7 +74,7 @@ namespace OpenRA.Mods.RA
this.StartSkip = startSkip; this.StartSkip = startSkip;
} }
public void Tick(float2 currentPos) public void Tick(PPos currentPos)
{ {
positions.Add(currentPos); positions.Add(currentPos);
if (positions.Count >= TrailLength) if (positions.Count >= TrailLength)
@@ -85,22 +84,20 @@ namespace OpenRA.Mods.RA
public void Render(Actor self) public void Render(Actor self)
{ {
Color trailStart = Color; Color trailStart = Color;
Color trailEnd = Color.FromArgb(trailStart.A - 255 / TrailLength, trailStart.R, Color trailEnd = Color.FromArgb(trailStart.A - 255 / TrailLength, trailStart.R, trailStart.G, trailStart.B);
trailStart.G, trailStart.B);
for (int i = positions.Count - 1 - StartSkip; i >= 1; --i) for (int i = positions.Count - 1 - StartSkip; i >= 1; --i)
{ {
var conPos = positions[i]; var conPos = positions[i];
var nextPos = positions[i - 1]; var nextPos = positions[i - 1];
if (self.World.LocalShroud.IsVisible(OpenRA.Traits.Util.CellContaining(conPos)) || if (self.World.LocalShroud.IsVisible(conPos.ToCPos()) ||
self.World.LocalShroud.IsVisible(OpenRA.Traits.Util.CellContaining(nextPos))) self.World.LocalShroud.IsVisible(nextPos.ToCPos()))
{ {
Game.Renderer.WorldLineRenderer.DrawLine(conPos, nextPos, trailStart, trailEnd); Game.Renderer.WorldLineRenderer.DrawLine(conPos.ToFloat2(), nextPos.ToFloat2(), trailStart, trailEnd);
trailStart = trailEnd; trailStart = trailEnd;
trailEnd = Color.FromArgb(trailStart.A - 255 / positions.Count, trailStart.R, trailEnd = Color.FromArgb(trailStart.A - 255 / positions.Count, trailStart.R, trailStart.G, trailStart.B);
trailStart.G, trailStart.B);
} }
} }
} }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Effects
anim.PlayThen(sequence, anim.PlayThen(sequence,
() => fromActor.World.AddFrameEndTask(w => w.Remove(this))); () => fromActor.World.AddFrameEndTask(w => w.Remove(this)));
pos = fromActor.CenterLocation; pos = fromActor.CenterLocation.ToFloat2();
} }
public void Tick( World world ) { anim.Tick(); } public void Tick( World world ) { anim.Tick(); }

View File

@@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
if (a.IsInWorld) if (a.IsInWorld)
yield return new Renderable(anim.Image, yield return new Renderable(anim.Image,
a.CenterLocation - .5f * anim.Image.size + offset, "effect", (int)a.CenterLocation.Y); a.CenterLocation.ToFloat2() - .5f * anim.Image.size + offset, "effect", (int)a.CenterLocation.Y);
} }
} }
} }

View File

@@ -18,10 +18,10 @@ namespace OpenRA.Mods.RA.Effects
public class Explosion : IEffect public class Explosion : IEffect
{ {
Animation anim; Animation anim;
int2 pos; PPos pos;
int altitude; int altitude;
public Explosion(World world, int2 pixelPos, string style, bool isWater, int altitude) public Explosion(World world, PPos pixelPos, string style, bool isWater, int altitude)
{ {
this.pos = pixelPos; this.pos = pixelPos;
this.altitude = altitude; this.altitude = altitude;
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
yield return new Renderable(anim.Image, yield return new Renderable(anim.Image,
pos - .5f * anim.Image.size - new int2(0,altitude), pos.ToFloat2() - .5f * anim.Image.size - new int2(0,altitude),
"effect", (int)pos.Y - altitude); "effect", (int)pos.Y - altitude);
} }

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA.Effects
if (show && !self.Destroyed) if (show && !self.Destroyed)
{ {
var p = self.CenterLocation; var p = self.CenterLocation;
yield return new Renderable(anim.Image, p - 0.5f * anim.Image.size, rs.Palette(self.Owner), p.Y) yield return new Renderable(anim.Image, p.ToFloat2() - 0.5f * anim.Image.size, rs.Palette(self.Owner), p.Y)
.WithScale(1.5f); .WithScale(1.5f);
} }
} }

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
yield return new Renderable(anim.Image, yield return new Renderable(anim.Image,
Args.dest - new int2(0, altitude) - .5f * anim.Image.size, "effect", Args.dest.Y); Args.dest.ToInt2() - new int2(0, altitude) - .5f * anim.Image.size, "effect", Args.dest.Y);
} }
} }
} }

View File

@@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
if (explosion != null) if (explosion != null)
yield return new Renderable(explosion.Image, yield return new Renderable(explosion.Image,
args.dest - .5f * explosion.Image.size, "effect", (int)args.dest.Y); args.dest.ToFloat2() - .5f * explosion.Image.size, "effect", (int)args.dest.Y);
if (ticks >= info.BeamDuration) if (ticks >= info.BeamDuration)
yield break; yield break;
@@ -87,7 +87,7 @@ namespace OpenRA.Mods.RA.Effects
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
wlr.LineWidth = info.BeamRadius * 2; wlr.LineWidth = info.BeamRadius * 2;
wlr.DrawLine(args.src, args.dest, rc, rc); wlr.DrawLine(args.src.ToFloat2(), args.dest.ToFloat2(), rc, rc);
wlr.Flush(); wlr.Flush();
wlr.LineWidth = 1f; wlr.LineWidth = 1f;
} }

View File

@@ -46,9 +46,9 @@ namespace OpenRA.Mods.RA.Effects
readonly MissileInfo Info; readonly MissileInfo Info;
readonly ProjectileArgs Args; readonly ProjectileArgs Args;
int2 offset; PVecInt offset;
public int2 SubPxPosition; public int2 SubPxPosition;
public int2 PxPosition { get { return new int2( SubPxPosition.X / 1024, SubPxPosition.Y / 1024 ); } } public PPos PxPosition { get { return new PPos(SubPxPosition.X / 1024, SubPxPosition.Y / 1024); } }
readonly Animation anim; readonly Animation anim;
int Facing; int Facing;
@@ -61,12 +61,12 @@ namespace OpenRA.Mods.RA.Effects
Info = info; Info = info;
Args = args; Args = args;
SubPxPosition = 1024 * Args.src; SubPxPosition = 1024 * Args.src.ToInt2();
Altitude = Args.srcAltitude; Altitude = Args.srcAltitude;
Facing = Args.facing; Facing = Args.facing;
if (info.Inaccuracy > 0) if (info.Inaccuracy > 0)
offset = (info.Inaccuracy * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2(); offset = (PVecInt)(info.Inaccuracy * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2();
if (Info.Image != null) if (Info.Image != null)
{ {
@@ -121,7 +121,7 @@ namespace OpenRA.Mods.RA.Effects
if (Info.Trail != null) if (Info.Trail != null)
{ {
var sp = (SubPxPosition - (move * 3) / 2) / 1024 - new int2(0, Altitude); var sp = (PPos)((SubPxPosition - (move * 3) / 2) / 1024) - new PVecInt(0, Altitude);
if (--ticksToNextSmoke < 0) if (--ticksToNextSmoke < 0)
{ {
@@ -135,14 +135,13 @@ namespace OpenRA.Mods.RA.Effects
if (!Info.High) // check for hitting a wall if (!Info.High) // check for hitting a wall
{ {
var cell = Traits.Util.CellContaining(PxPosition); var cell = PxPosition.ToCPos();
if (world.ActorMap.GetUnitsAt(cell).Any( if (world.ActorMap.GetUnitsAt(cell).Any(a => a.HasTrait<IBlocksBullets>()))
a => a.HasTrait<IBlocksBullets>()))
Explode(world); Explode(world);
} }
if (Trail != null) if (Trail != null)
Trail.Tick(PxPosition - new float2(0,Altitude)); Trail.Tick(PxPosition - new PVecInt(0, Altitude));
} }
void Explode(World world) void Explode(World world)
@@ -155,8 +154,8 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
if (Args.firedBy.World.LocalShroud.IsVisible(OpenRA.Traits.Util.CellContaining(PxPosition.ToFloat2()))) if (Args.firedBy.World.LocalShroud.IsVisible(PxPosition.ToCPos()))
yield return new Renderable(anim.Image,PxPosition.ToFloat2() - 0.5f * anim.Image.size - new float2(0, Altitude), yield return new Renderable(anim.Image, PxPosition.ToFloat2() - 0.5f * anim.Image.size - new float2(0, Altitude),
Args.weapon.Underwater ? "shadow" : "effect", PxPosition.Y); Args.weapon.Underwater ? "shadow" : "effect", PxPosition.Y);
if (Trail != null) if (Trail != null)

View File

@@ -19,13 +19,13 @@ namespace OpenRA.Mods.RA.Effects
{ {
readonly Player firedBy; readonly Player firedBy;
Animation anim; Animation anim;
int2 pos; PPos pos;
int2 targetLocation; CPos targetLocation;
int altitude; int altitude;
bool goingUp = true; bool goingUp = true;
string weapon; string weapon;
public NukeLaunch(Player firedBy, Actor silo, string weapon, int2 spawnOffset, int2 targetLocation) public NukeLaunch(Player firedBy, Actor silo, string weapon, PVecInt spawnOffset, CPos targetLocation)
{ {
this.firedBy = firedBy; this.firedBy = firedBy;
this.targetLocation = targetLocation; this.targetLocation = targetLocation;
@@ -71,7 +71,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
Combat.DoExplosion(firedBy.PlayerActor, weapon, pos, 0); Combat.DoExplosion(firedBy.PlayerActor, weapon, pos, 0);
world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5); world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos.ToFloat2(), 5);
foreach (var a in world.ActorsWithTrait<NukePaletteEffect>()) foreach (var a in world.ActorsWithTrait<NukePaletteEffect>())
a.Trait.Enable(); a.Trait.Enable();
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
yield return new Renderable(anim.Image, pos - 0.5f * anim.Image.size - new float2(0, altitude), yield return new Renderable(anim.Image, pos.ToFloat2() - 0.5f * anim.Image.size - new float2(0, altitude),
"effect", (int)pos.Y); "effect", (int)pos.Y);
} }
} }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Effects
readonly Animation anim; readonly Animation anim;
readonly string palette; readonly string palette;
readonly Animation paraAnim; readonly Animation paraAnim;
readonly float2 location; readonly PPos location;
readonly Actor cargo; readonly Actor cargo;
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Effects
float altitude; float altitude;
const float fallRate = .3f; const float fallRate = .3f;
public Parachute(Player owner, float2 location, int altitude, Actor cargo) public Parachute(Player owner, PPos location, int altitude, Actor cargo)
{ {
this.location = location; this.location = location;
this.altitude = altitude; this.altitude = altitude;
@@ -63,7 +63,7 @@ namespace OpenRA.Mods.RA.Effects
world.AddFrameEndTask(w => world.AddFrameEndTask(w =>
{ {
w.Remove(this); w.Remove(this);
var loc = Traits.Util.CellContaining(location); var loc = location.ToCPos();
cargo.CancelActivity(); cargo.CancelActivity();
cargo.Trait<ITeleportable>().SetPosition(cargo, loc); cargo.Trait<ITeleportable>().SetPosition(cargo, loc);
w.Add(cargo); w.Add(cargo);
@@ -72,8 +72,8 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
var pos = location - new float2(0, altitude); var pos = location.ToFloat2() - new float2(0, altitude);
yield return new Renderable(anim.Image, location - .5f * anim.Image.size, "shadow", 0); yield return new Renderable(anim.Image, location.ToFloat2() - .5f * anim.Image.size, "shadow", 0);
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, palette, 2); yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, palette, 2);
yield return new Renderable(paraAnim.Image, pos - .5f * paraAnim.Image.size + offset, palette, 3); yield return new Renderable(paraAnim.Image, pos - .5f * paraAnim.Image.size + offset, palette, 3);
} }

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
if (!a.Destroyed && (a.World.LocalPlayer == null || a.Owner.Stances[a.Owner.World.LocalPlayer] == Stance.Ally)) if (!a.Destroyed && (a.World.LocalPlayer == null || a.Owner.Stances[a.Owner.World.LocalPlayer] == Stance.Ally))
yield return new Renderable(anim.Image, yield return new Renderable(anim.Image,
a.CenterLocation - .5f * anim.Image.size, "chrome", (int)a.CenterLocation.Y); a.CenterLocation.ToFloat2() - .5f * anim.Image.size, "chrome", (int)a.CenterLocation.Y);
} }
} }
} }

View File

@@ -18,8 +18,8 @@ namespace OpenRA.Mods.RA.Effects
{ {
class RallyPoint : IEffect class RallyPoint : IEffect
{ {
Actor building; readonly Actor building;
RA.RallyPoint rp; readonly RA.RallyPoint rp;
public Animation flag = new Animation("rallypoint"); public Animation flag = new Animation("rallypoint");
public Animation circles = new Animation("rallypoint"); public Animation circles = new Animation("rallypoint");
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA.Effects
circles.Play("circles"); circles.Play("circles");
} }
int2 cachedLocation; CPos cachedLocation;
public void Tick( World world ) public void Tick( World world )
{ {
flag.Tick(); flag.Tick();
@@ -55,11 +55,11 @@ namespace OpenRA.Mods.RA.Effects
var palette = building.Trait<RenderSimple>().Palette(building.Owner); var palette = building.Trait<RenderSimple>().Palette(building.Owner);
yield return new Renderable(circles.Image, yield return new Renderable(circles.Image,
pos - .5f * circles.Image.size, pos.ToFloat2() - .5f * circles.Image.size,
palette, (int)pos.Y); palette, (int)pos.Y);
yield return new Renderable(flag.Image, yield return new Renderable(flag.Image,
pos + new float2(-1,-17), pos.ToFloat2() + new float2(-1,-17),
palette, (int)pos.Y); palette, (int)pos.Y);
} }
} }

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Effects
var palette = building.Trait<RenderSimple>().Palette(player); var palette = building.Trait<RenderSimple>().Palette(player);
yield return new Renderable(anim.Image, yield return new Renderable(anim.Image,
building.CenterLocation - .5f * anim.Image.size, palette, (int)building.CenterLocation.Y); building.CenterLocation.ToFloat2() - .5f * anim.Image.size, palette, (int)building.CenterLocation.Y);
} }
} }
} }

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA.Effects
doors.PlayThen("active", doors.PlayThen("active",
() => a.World.AddFrameEndTask(w => w.Remove(this))); () => a.World.AddFrameEndTask(w => w.Remove(this)));
pos = a.CenterLocation - .5f * doors.Image.size + doorOffset; pos = a.CenterLocation.ToFloat2() - .5f * doors.Image.size + doorOffset;
} }
public void Tick( World world ) public void Tick( World world )

View File

@@ -17,10 +17,10 @@ namespace OpenRA.Mods.RA.Effects
{ {
public class Smoke : IEffect public class Smoke : IEffect
{ {
readonly int2 pos; readonly PPos pos;
readonly Animation anim; readonly Animation anim;
public Smoke(World world, int2 pos, string trail) public Smoke(World world, PPos pos, string trail)
{ {
this.pos = pos; this.pos = pos;
anim = new Animation(trail); anim = new Animation(trail);
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "effect", (int)pos.Y); yield return new Renderable(anim.Image, pos.ToFloat2() - .5f * anim.Image.size, "effect", (int)pos.Y);
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More