Rework paradrop logic to be more robust.

This commit is contained in:
Paul Chote
2019-05-26 22:19:46 +00:00
committed by reaperrr
parent 829b8cd2e1
commit e2b27328bd
5 changed files with 94 additions and 91 deletions

View File

@@ -22,6 +22,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Distance around the drop-point to unload troops.")]
public readonly WDist DropRange = WDist.FromCells(4);
[Desc("Wait at least this many ticks between each drop.")]
public readonly int DropInterval = 5;
[Desc("Sound to play when dropping.")]
public readonly string ChuteSound = null;
@@ -33,7 +36,6 @@ namespace OpenRA.Mods.Common.Traits
readonly ParaDropInfo info;
readonly Actor self;
readonly Cargo cargo;
readonly HashSet<CPos> droppedAt = new HashSet<CPos>();
public event Action<Actor> OnRemovedFromWorld = self => { };
public event Action<Actor> OnEnteredDropRange = self => { };
@@ -45,6 +47,9 @@ namespace OpenRA.Mods.Common.Traits
[Sync]
Target target;
[Sync]
int dropDelay;
bool checkForSuitableCell;
public ParaDrop(Actor self, ParaDropInfo info)
@@ -56,13 +61,18 @@ namespace OpenRA.Mods.Common.Traits
public void SetLZ(CPos lz, bool checkLandingCell)
{
droppedAt.Clear();
target = Target.FromCell(self.World, lz);
checkForSuitableCell = checkLandingCell;
}
void ITick.Tick(Actor self)
{
if (dropDelay > 0)
{
dropDelay--;
return;
}
var wasInDropRange = inDropRange;
inDropRange = target.IsInRange(self.CenterPosition, info.DropRange);
@@ -73,30 +83,38 @@ namespace OpenRA.Mods.Common.Traits
OnExitedDropRange(self);
// Are we able to drop the next trooper?
if (!inDropRange || cargo.IsEmpty(self))
if (!inDropRange || cargo.IsEmpty(self) || !self.World.Map.Contains(self.Location))
return;
if (droppedAt.Contains(self.Location) || (checkForSuitableCell && !IsSuitableCell(cargo.Peek(self), self.Location)))
return;
var dropActor = cargo.Peek(self);
var dropPositionable = dropActor.Trait<IPositionable>();
var dropCell = self.Location;
var dropSubCell = dropPositionable.GetAvailableSubCell(dropCell);
if (dropSubCell == SubCell.Invalid)
{
if (checkForSuitableCell)
return;
if (!self.World.Map.Contains(self.Location))
return;
dropSubCell = SubCell.Any;
}
// unload a dude here
droppedAt.Add(self.Location);
// Unload here
if (cargo.Unload(self) != dropActor)
throw new InvalidOperationException("Peeked cargo was not unloaded!");
var a = cargo.Unload(self);
self.World.AddFrameEndTask(w =>
{
w.Add(a);
a.QueueActivity(new Parachute(a, self.CenterPosition));
});
Game.Sound.Play(SoundType.World, info.ChuteSound, self.CenterPosition);
}
dropPositionable.SetPosition(dropActor, dropCell, dropSubCell);
w.Add(dropActor);
static bool IsSuitableCell(Actor actorToDrop, CPos p)
{
return actorToDrop.Trait<IPositionable>().CanEnterCell(p);
var dropPosition = dropActor.CenterPosition + new WVec(0, 0, self.CenterPosition.Z - dropActor.CenterPosition.Z);
dropPositionable.SetVisualPosition(dropActor, dropPosition);
dropActor.QueueActivity(new Parachute(dropActor));
});
Game.Sound.Play(SoundType.World, info.ChuteSound, self.CenterPosition);
dropDelay = info.DropInterval;
}
void INotifyRemovedFromWorld.RemovedFromWorld(Actor self)