Add a SubCell field to UIM. Allow UIM to query for units by subcell.
This commit is contained in:
@@ -81,11 +81,21 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
int2 PxPosition { get; }
|
int2 PxPosition { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum SubCell
|
||||||
|
{
|
||||||
|
FullCell,
|
||||||
|
TopLeft,
|
||||||
|
TopRight,
|
||||||
|
Center,
|
||||||
|
BottomLeft,
|
||||||
|
BottomRight
|
||||||
|
}
|
||||||
|
|
||||||
public interface IOccupySpace : IHasLocation
|
public interface IOccupySpace : IHasLocation
|
||||||
{
|
{
|
||||||
int2 TopLeft { get; }
|
int2 TopLeft { get; }
|
||||||
IEnumerable<int2> OccupiedCells();
|
IEnumerable<Pair<int2, SubCell>> OccupiedCells();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IOccupySpaceExts
|
public static class IOccupySpaceExts
|
||||||
@@ -96,10 +106,10 @@ namespace OpenRA.Traits
|
|||||||
var nearestDistance = int.MaxValue;
|
var nearestDistance = int.MaxValue;
|
||||||
foreach( var cell in ios.OccupiedCells() )
|
foreach( var cell in ios.OccupiedCells() )
|
||||||
{
|
{
|
||||||
var dist = ( other - cell ).LengthSquared;
|
var dist = ( other - cell.First ).LengthSquared;
|
||||||
if( dist < nearestDistance )
|
if( dist < nearestDistance )
|
||||||
{
|
{
|
||||||
nearest = cell;
|
nearest = cell.First;
|
||||||
nearestDistance = dist;
|
nearestDistance = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ namespace OpenRA.Traits
|
|||||||
if (ios != null)
|
if (ios != null)
|
||||||
{
|
{
|
||||||
var cells = ios.OccupiedCells();
|
var cells = ios.OccupiedCells();
|
||||||
if (cells.Any()) return cells;
|
if (cells.Any()) return cells.Select(c => c.First);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new[] { a.CenterLocation / Game.CellSize };
|
return new[] { a.CenterLocation / Game.CellSize };
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ namespace OpenRA.Traits
|
|||||||
class InfluenceNode
|
class InfluenceNode
|
||||||
{
|
{
|
||||||
public InfluenceNode next;
|
public InfluenceNode next;
|
||||||
|
public SubCell subCell;
|
||||||
public Actor actor;
|
public Actor actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
InfluenceNode[,] influence;
|
InfluenceNode[,] influence;
|
||||||
Map map;
|
Map map;
|
||||||
|
|
||||||
@@ -51,21 +52,32 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public bool AnyUnitsAt(int2 a)
|
public bool AnyUnitsAt(int2 a)
|
||||||
{
|
{
|
||||||
return /*map.IsInMap(a) && */influence[ a.X, a.Y ] != null;
|
return influence[ a.X, a.Y ] != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AnyUnitsAt(int2 a, SubCell sub)
|
||||||
|
{
|
||||||
|
var node = influence[ a.X, a.Y ];
|
||||||
|
while (node != null)
|
||||||
|
{
|
||||||
|
if (node.subCell == sub) return true;
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add( Actor self, IOccupySpace unit )
|
public void Add( Actor self, IOccupySpace unit )
|
||||||
{
|
{
|
||||||
if (unit != null)
|
if (unit != null)
|
||||||
foreach( var c in unit.OccupiedCells() )
|
foreach( var c in unit.OccupiedCells() )
|
||||||
influence[ c.X, c.Y ] = new InfluenceNode { next = influence[ c.X, c.Y ], actor = self };
|
influence[ c.First.X, c.First.Y ] = new InfluenceNode { next = influence[ c.First.X, c.First.Y ], subCell = c.Second, actor = self };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove( Actor self, IOccupySpace unit )
|
public void Remove( Actor self, IOccupySpace unit )
|
||||||
{
|
{
|
||||||
if (unit != null)
|
if (unit != null)
|
||||||
foreach (var c in unit.OccupiedCells())
|
foreach (var c in unit.OccupiedCells())
|
||||||
RemoveInner( ref influence[ c.X, c.Y ], self );
|
RemoveInner( ref influence[ c.First.X, c.First.Y ], self );
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveInner( ref InfluenceNode influenceNode, Actor toRemove )
|
void RemoveInner( ref InfluenceNode influenceNode, Actor toRemove )
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
||||||
if (target.Owner == self.Owner) return NextActivity;
|
if (target.Owner == self.Owner) return NextActivity;
|
||||||
|
|
||||||
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x == self.Location ) )
|
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
// todo: clean this up
|
// todo: clean this up
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
if (IsCanceled) return NextActivity;
|
if (IsCanceled) return NextActivity;
|
||||||
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
||||||
|
|
||||||
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x == self.Location ) )
|
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(25 * 2,
|
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(25 * 2,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
||||||
if (target.Owner == self.Owner) return NextActivity;
|
if (target.Owner == self.Owner) return NextActivity;
|
||||||
|
|
||||||
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x == self.Location ) )
|
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
|
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
};
|
};
|
||||||
foreach( var cell in target.Trait<IOccupySpace>().OccupiedCells() )
|
foreach( var cell in target.Trait<IOccupySpace>().OccupiedCells() )
|
||||||
{
|
{
|
||||||
ps1.AddInitialCell( cell );
|
ps1.AddInitialCell( cell.First );
|
||||||
if( ( mobile.toCell - cell ).LengthSquared <= 2 )
|
if( ( mobile.toCell - cell.First ).LengthSquared <= 2 )
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );
|
ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
{
|
{
|
||||||
if (IsCanceled) return NextActivity;
|
if (IsCanceled) return NextActivity;
|
||||||
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
|
||||||
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x == self.Location ) )
|
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
var health = target.Trait<Health>();
|
var health = target.Trait<Health>();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA.Air
|
namespace OpenRA.Mods.RA.Air
|
||||||
{
|
{
|
||||||
@@ -135,8 +136,8 @@ namespace OpenRA.Mods.RA.Air
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int2[] noCells = new int2[] { };
|
Pair<int2, SubCell>[] noCells = new Pair<int2, SubCell>[] { };
|
||||||
public IEnumerable<int2> OccupiedCells() { return noCells; }
|
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { return noCells; }
|
||||||
|
|
||||||
public void TickMove( int speed, int facing )
|
public void TickMove( int speed, int facing )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
if (Space == null)
|
if (Space == null)
|
||||||
Space = self.Trait<IOccupySpace>();
|
Space = self.Trait<IOccupySpace>();
|
||||||
return Space.OccupiedCells();
|
return Space.OccupiedCells().Select(c => c.First);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA.Buildings
|
namespace OpenRA.Mods.RA.Buildings
|
||||||
{
|
{
|
||||||
@@ -110,9 +111,9 @@ namespace OpenRA.Mods.RA.Buildings
|
|||||||
get { return topLeft; }
|
get { return topLeft; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<int2> OccupiedCells()
|
public IEnumerable<Pair<int2, SubCell>> OccupiedCells()
|
||||||
{
|
{
|
||||||
return FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft );
|
return FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ).Select(c => Pair.New(c, SubCell.FullCell));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int2 TopLeft { get { return Location; } }
|
public int2 TopLeft { get { return Location; } }
|
||||||
public IEnumerable<int2> OccupiedCells() { return new int2[] { Location }; }
|
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); }
|
||||||
|
|
||||||
public int2 PxPosition { get; private set; }
|
public int2 PxPosition { get; private set; }
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
@@ -36,7 +37,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
public int2 TopLeft { get { return location; } }
|
public int2 TopLeft { get { return location; } }
|
||||||
|
|
||||||
public IEnumerable<int2> OccupiedCells() { yield return TopLeft; }
|
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); }
|
||||||
public int2 PxPosition { get { return Util.CenterOfCell( location ); } }
|
public int2 PxPosition { get { return Util.CenterOfCell( location ); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenRA.Mods.RA.Activities;
|
using OpenRA.Mods.RA.Activities;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
@@ -53,7 +54,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
public int2 TopLeft { get { return location; } }
|
public int2 TopLeft { get { return location; } }
|
||||||
|
|
||||||
public IEnumerable<int2> OccupiedCells() { yield return TopLeft; }
|
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); }
|
||||||
public int2 PxPosition { get { return Util.CenterOfCell( location ); } }
|
public int2 PxPosition { get { return Util.CenterOfCell( location ); } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -271,13 +271,17 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
public int2 TopLeft { get { return toCell; } }
|
public int2 TopLeft { get { return toCell; } }
|
||||||
|
|
||||||
public IEnumerable<int2> OccupiedCells()
|
public IEnumerable<Pair<int2, SubCell>> OccupiedCells()
|
||||||
{
|
{
|
||||||
return (fromCell == toCell)
|
if (fromCell == toCell)
|
||||||
? new[] { fromCell }
|
yield return Pair.New(fromCell, SubCell.FullCell);
|
||||||
: CanEnterCell(toCell)
|
else if (CanEnterCell(toCell))
|
||||||
? new[] { toCell }
|
yield return Pair.New(toCell, SubCell.FullCell);
|
||||||
: new[] { fromCell, toCell };
|
else
|
||||||
|
{
|
||||||
|
yield return Pair.New(fromCell, SubCell.FullCell);
|
||||||
|
yield return Pair.New(toCell, SubCell.FullCell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanEnterCell(int2 p)
|
public bool CanEnterCell(int2 p)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenRA.Mods.RA.Buildings;
|
using OpenRA.Mods.RA.Buildings;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA
|
namespace OpenRA.Mods.RA
|
||||||
{
|
{
|
||||||
@@ -32,7 +33,7 @@ namespace OpenRA.Mods.RA
|
|||||||
public bool TargetableBy(Actor self, Actor byActor) { return true; }
|
public bool TargetableBy(Actor self, Actor byActor) { return true; }
|
||||||
public IEnumerable<int2> TargetableCells( Actor self )
|
public IEnumerable<int2> TargetableCells( Actor self )
|
||||||
{
|
{
|
||||||
return self.Trait<Building>().OccupiedCells();
|
return self.Trait<Building>().OccupiedCells().Select(c => c.First);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user