Skip to content

Commit

Permalink
Fix subcell crushing properly.
Browse files Browse the repository at this point in the history
  • Loading branch information
pchote committed Feb 4, 2011
1 parent 639a7e3 commit afcb724
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 31 deletions.
42 changes: 13 additions & 29 deletions OpenRA.Game/Traits/World/UnitInfluence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public IEnumerable<Actor> GetUnitsAt( int2 a )
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)
{
if (!AnyUnitsAt(a))
Expand All @@ -59,29 +68,6 @@ public bool HasFreeSubCell(int2 a)
return new[]{SubCell.TopLeft, SubCell.TopRight, SubCell.Center,
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)
{
Expand All @@ -90,12 +76,10 @@ public bool AnyUnitsAt(int2 a)

public bool AnyUnitsAt(int2 a, SubCell sub)
{
var node = influence[ a.X, a.Y ];
while (node != null)
{
if (node.subCell == sub || node.subCell == SubCell.FullCell) return true;
node = node.next;
}
for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next )
if (i.subCell == sub || i.subCell == SubCell.FullCell)
return true;

return false;
}

Expand Down
26 changes: 25 additions & 1 deletion OpenRA.Mods.RA/Move/Mobile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,31 @@ public IEnumerable<Pair<int2, SubCell>> OccupiedCells()
yield return Pair.New(toCell, __toSubCell);
}
}


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)
{
return CanEnterCell(p, null, true);
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.RA/Move/Move.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ void NudgeBlocker(Actor self, int2 nextCell)
hasWaited = false;
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);
}

Expand Down

0 comments on commit afcb724

Please sign in to comment.