Rewrite Enter and related activities.

The unit will now path to the nearest adjacent cell, drag inside, do the inner activity, then (if still alive) drag back to its original
location.

This fixes:
 - Mismatch in logic between Enter and MoveAdjacentTo,
   which causes an infinite loop.
 - Building capturing failing from certain directions.
 - Being unable to enter buildings on unpathable tiles.
 - Units being stranded inside a building if the requirements
   for the inner order aren't met.
This commit is contained in:
Paul Chote
2013-04-15 01:50:19 +12:00
parent 8676562d47
commit e76c746b61
10 changed files with 87 additions and 82 deletions

View File

@@ -16,37 +16,35 @@ namespace OpenRA.Mods.RA.Activities
{
class Demolish : Activity
{
Actor target;
Target target;
int delay;
public Demolish( Actor target, int delay )
public Demolish(Actor target, int delay)
{
this.target = target;
this.target = Target.FromActor(target);
this.delay = delay;
}
public override Activity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if( !target.OccupiesSpace.OccupiedCells().Any( x => x.First == self.Location ) )
if (IsCanceled || !target.IsValid)
return NextActivity;
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(delay, () =>
{
// Can't demolish an already dead actor
if (target.IsDead())
if (!target.IsValid)
return;
// Invulnerable actors can't be demolished
var modifier = (float)target.TraitsImplementing<IDamageModifier>()
var modifier = (float)target.Actor.TraitsImplementing<IDamageModifier>()
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
.Select(t => t.GetDamageModifier(self, null)).Product();
if (target.IsInWorld && modifier > 0)
target.Kill(self);
if (modifier > 0)
target.Actor.Kill(self);
})));
return NextActivity;
}
}