Fix subcell crushing properly.
This commit is contained in:
@@ -51,6 +51,15 @@ namespace OpenRA.Traits
|
|||||||
yield return i.actor;
|
yield return i.actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Actor> GetUnitsAt( int2 a, SubCell sub )
|
||||||
|
{
|
||||||
|
if (!map.IsInMap(a)) yield break;
|
||||||
|
|
||||||
|
for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next )
|
||||||
|
if (!i.actor.Destroyed && (i.subCell == sub || i.subCell == SubCell.FullCell))
|
||||||
|
yield return i.actor;
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasFreeSubCell(int2 a)
|
public bool HasFreeSubCell(int2 a)
|
||||||
{
|
{
|
||||||
if (!AnyUnitsAt(a))
|
if (!AnyUnitsAt(a))
|
||||||
@@ -60,29 +69,6 @@ namespace OpenRA.Traits
|
|||||||
SubCell.BottomLeft, SubCell.BottomRight}.Any(b => !AnyUnitsAt(a,b));
|
SubCell.BottomLeft, SubCell.BottomRight}.Any(b => !AnyUnitsAt(a,b));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only used inside Move, when we *know* that we can enter the cell.
|
|
||||||
// If the cell contains something crushable, a naive check of 'is it empty' will fail.
|
|
||||||
// Infantry can currently only crush crates/mines which take a whole cell, so we will ignore
|
|
||||||
// the SubCell.FullCell case and hope that someone doesn't introduce subcell units
|
|
||||||
// crushing other subcell units in the future.
|
|
||||||
public SubCell GetFreeSubcell(int2 a, SubCell preferred)
|
|
||||||
{
|
|
||||||
if (preferred == SubCell.FullCell)
|
|
||||||
return preferred;
|
|
||||||
|
|
||||||
return new[]{ preferred, SubCell.TopLeft, SubCell.TopRight, SubCell.Center,
|
|
||||||
SubCell.BottomLeft, SubCell.BottomRight}.First(b =>
|
|
||||||
{
|
|
||||||
var node = influence[ a.X, a.Y ];
|
|
||||||
while (node != null)
|
|
||||||
{
|
|
||||||
if (node.subCell == b) return false;
|
|
||||||
node = node.next;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AnyUnitsAt(int2 a)
|
public bool AnyUnitsAt(int2 a)
|
||||||
{
|
{
|
||||||
return influence[ a.X, a.Y ] != null;
|
return influence[ a.X, a.Y ] != null;
|
||||||
@@ -90,12 +76,10 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public bool AnyUnitsAt(int2 a, SubCell sub)
|
public bool AnyUnitsAt(int2 a, SubCell sub)
|
||||||
{
|
{
|
||||||
var node = influence[ a.X, a.Y ];
|
for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next )
|
||||||
while (node != null)
|
if (i.subCell == sub || i.subCell == SubCell.FullCell)
|
||||||
{
|
return true;
|
||||||
if (node.subCell == sub || node.subCell == SubCell.FullCell) return true;
|
|
||||||
node = node.next;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -308,6 +308,30 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SubCell GetDesiredSubcell(int2 a)
|
||||||
|
{
|
||||||
|
if (!Info.SharesCell)
|
||||||
|
return SubCell.FullCell;
|
||||||
|
|
||||||
|
// Prioritise the current subcell
|
||||||
|
return new[]{ __fromSubCell, SubCell.TopLeft, SubCell.TopRight, SubCell.Center,
|
||||||
|
SubCell.BottomLeft, SubCell.BottomRight}.First(b =>
|
||||||
|
{
|
||||||
|
var blockingActors = uim.GetUnitsAt(a,b);
|
||||||
|
if (blockingActors.Count() > 0)
|
||||||
|
{
|
||||||
|
// Non-sharable unit can enter a cell with shareable units only if it can crush all of them
|
||||||
|
if (Info.Crushes == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (blockingActors.Any(c => !(c.HasTrait<ICrushable>() &&
|
||||||
|
c.TraitsImplementing<ICrushable>().Any(d => d.CrushClasses.Intersect(Info.Crushes).Any()))))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanEnterCell(int2 p)
|
public bool CanEnterCell(int2 p)
|
||||||
{
|
{
|
||||||
return CanEnterCell(p, null, true);
|
return CanEnterCell(p, null, true);
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
hasWaited = false;
|
hasWaited = false;
|
||||||
path.RemoveAt( path.Count - 1 );
|
path.RemoveAt( path.Count - 1 );
|
||||||
|
|
||||||
var subCell = self.World.WorldActor.Trait<UnitInfluence>().GetFreeSubcell(nextCell, mobile.__fromSubCell);
|
var subCell = mobile.GetDesiredSubcell(nextCell);
|
||||||
return Pair.New(nextCell, subCell);
|
return Pair.New(nextCell, subCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user