Add a SubCell field to UIM. Allow UIM to query for units by subcell.
This commit is contained in:
@@ -82,10 +82,20 @@ namespace OpenRA.Traits
|
||||
int2 PxPosition { get; }
|
||||
}
|
||||
|
||||
public enum SubCell
|
||||
{
|
||||
FullCell,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
Center,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
}
|
||||
|
||||
public interface IOccupySpace : IHasLocation
|
||||
{
|
||||
int2 TopLeft { get; }
|
||||
IEnumerable<int2> OccupiedCells();
|
||||
IEnumerable<Pair<int2, SubCell>> OccupiedCells();
|
||||
}
|
||||
|
||||
public static class IOccupySpaceExts
|
||||
@@ -96,10 +106,10 @@ namespace OpenRA.Traits
|
||||
var nearestDistance = int.MaxValue;
|
||||
foreach( var cell in ios.OccupiedCells() )
|
||||
{
|
||||
var dist = ( other - cell ).LengthSquared;
|
||||
var dist = ( other - cell.First ).LengthSquared;
|
||||
if( dist < nearestDistance )
|
||||
{
|
||||
nearest = cell;
|
||||
nearest = cell.First;
|
||||
nearestDistance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace OpenRA.Traits
|
||||
if (ios != null)
|
||||
{
|
||||
var cells = ios.OccupiedCells();
|
||||
if (cells.Any()) return cells;
|
||||
if (cells.Any()) return cells.Select(c => c.First);
|
||||
}
|
||||
|
||||
return new[] { a.CenterLocation / Game.CellSize };
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace OpenRA.Traits
|
||||
class InfluenceNode
|
||||
{
|
||||
public InfluenceNode next;
|
||||
public SubCell subCell;
|
||||
public Actor actor;
|
||||
}
|
||||
|
||||
@@ -51,21 +52,32 @@ namespace OpenRA.Traits
|
||||
|
||||
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 )
|
||||
{
|
||||
if (unit != null)
|
||||
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 )
|
||||
{
|
||||
if (unit != null)
|
||||
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 )
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (target == null || !target.IsInWorld || target.IsDead()) 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;
|
||||
|
||||
// todo: clean this up
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (IsCanceled) 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;
|
||||
|
||||
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.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;
|
||||
|
||||
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace OpenRA.Mods.RA.Activities
|
||||
};
|
||||
foreach( var cell in target.Trait<IOccupySpace>().OccupiedCells() )
|
||||
{
|
||||
ps1.AddInitialCell( cell );
|
||||
if( ( mobile.toCell - cell ).LengthSquared <= 2 )
|
||||
ps1.AddInitialCell( cell.First );
|
||||
if( ( mobile.toCell - cell.First ).LengthSquared <= 2 )
|
||||
return NextActivity;
|
||||
}
|
||||
ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
{
|
||||
if (IsCanceled) 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;
|
||||
|
||||
var health = target.Trait<Health>();
|
||||
|
||||
@@ -12,6 +12,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Mods.RA.Air
|
||||
{
|
||||
@@ -135,8 +136,8 @@ namespace OpenRA.Mods.RA.Air
|
||||
}
|
||||
}
|
||||
|
||||
int2[] noCells = new int2[] { };
|
||||
public IEnumerable<int2> OccupiedCells() { return noCells; }
|
||||
Pair<int2, SubCell>[] noCells = new Pair<int2, SubCell>[] { };
|
||||
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { return noCells; }
|
||||
|
||||
public void TickMove( int speed, int facing )
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (Space == null)
|
||||
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.Linq;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Mods.RA.Buildings
|
||||
{
|
||||
@@ -110,9 +111,9 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
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)
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
@@ -36,7 +37,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
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 ); } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
@@ -53,7 +54,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
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 ); } }
|
||||
}
|
||||
|
||||
|
||||
@@ -271,13 +271,17 @@ namespace OpenRA.Mods.RA.Move
|
||||
|
||||
public int2 TopLeft { get { return toCell; } }
|
||||
|
||||
public IEnumerable<int2> OccupiedCells()
|
||||
public IEnumerable<Pair<int2, SubCell>> OccupiedCells()
|
||||
{
|
||||
return (fromCell == toCell)
|
||||
? new[] { fromCell }
|
||||
: CanEnterCell(toCell)
|
||||
? new[] { toCell }
|
||||
: new[] { fromCell, toCell };
|
||||
if (fromCell == toCell)
|
||||
yield return Pair.New(fromCell, SubCell.FullCell);
|
||||
else if (CanEnterCell(toCell))
|
||||
yield return Pair.New(toCell, SubCell.FullCell);
|
||||
else
|
||||
{
|
||||
yield return Pair.New(fromCell, SubCell.FullCell);
|
||||
yield return Pair.New(toCell, SubCell.FullCell);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanEnterCell(int2 p)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Traits;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
@@ -32,7 +33,7 @@ namespace OpenRA.Mods.RA
|
||||
public bool TargetableBy(Actor self, Actor byActor) { return true; }
|
||||
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