Merge pull request #4912 from pchote/exits
Clean up mobile world insertion.
This commit is contained in:
@@ -161,6 +161,8 @@ namespace OpenRA.Traits
|
|||||||
Activity MoveTo(CPos cell, Actor ignoredActor);
|
Activity MoveTo(CPos cell, Actor ignoredActor);
|
||||||
Activity MoveWithinRange(Target target, WRange range);
|
Activity MoveWithinRange(Target target, WRange range);
|
||||||
Activity MoveFollow(Actor self, Target target, WRange range);
|
Activity MoveFollow(Actor self, Target target, WRange range);
|
||||||
|
Activity MoveIntoWorld(Actor self, CPos cell);
|
||||||
|
Activity VisualMove(Actor self, WPos fromPos, WPos toPos);
|
||||||
CPos NearestMoveableCell(CPos target);
|
CPos NearestMoveableCell(CPos target);
|
||||||
bool IsMoving { get; set; }
|
bool IsMoving { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,18 +37,11 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
return Util.SequenceActivities(new MoveAdjacentTo(self, target), this);
|
return Util.SequenceActivities(new MoveAdjacentTo(self, target), this);
|
||||||
|
|
||||||
// Move to the middle of the target, ignoring impassable tiles
|
// Move to the middle of the target, ignoring impassable tiles
|
||||||
var mobile = self.Trait<Mobile>();
|
var move = self.Trait<IMove>();
|
||||||
var to = target.CenterPosition;
|
|
||||||
var from = self.CenterPosition;
|
|
||||||
var speed = mobile.MovementSpeedForCell(self, self.Location);
|
|
||||||
var length = speed > 0 ? (to - from).Length / speed : 0;
|
|
||||||
|
|
||||||
return Util.SequenceActivities(
|
return Util.SequenceActivities(
|
||||||
new Turn(Util.GetFacing(to - from, mobile.Facing)),
|
move.VisualMove(self, self.CenterPosition, target.CenterPosition),
|
||||||
new Drag(from, to, length),
|
|
||||||
inner,
|
inner,
|
||||||
new Turn(Util.GetFacing(from - to, mobile.Facing)),
|
move.VisualMove(self, target.CenterPosition, self.CenterPosition),
|
||||||
new Drag(to, from, length),
|
|
||||||
NextActivity
|
NextActivity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,20 +33,21 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public CPos? ChooseExitCell(Actor passenger)
|
public CPos? ChooseExitCell(Actor passenger)
|
||||||
{
|
{
|
||||||
var mobile = passenger.Trait<Mobile>();
|
var pos = passenger.Trait<IPositionable>();
|
||||||
|
|
||||||
return cargo.CurrentAdjacentCells
|
return cargo.CurrentAdjacentCells
|
||||||
.Shuffle(self.World.SharedRandom)
|
.Shuffle(self.World.SharedRandom)
|
||||||
.Cast<CPos?>()
|
.Cast<CPos?>()
|
||||||
.FirstOrDefault(c => mobile.CanEnterCell(c.Value));
|
.FirstOrDefault(c => pos.CanEnterCell(c.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<CPos> BlockedExitCells(Actor passenger)
|
IEnumerable<CPos> BlockedExitCells(Actor passenger)
|
||||||
{
|
{
|
||||||
var mobile = passenger.Trait<Mobile>();
|
var pos = passenger.Trait<IPositionable>();
|
||||||
|
|
||||||
|
// Find the cells that are blocked by transient actors
|
||||||
return cargo.CurrentAdjacentCells
|
return cargo.CurrentAdjacentCells
|
||||||
.Where(c => mobile.MovementSpeedForCell(passenger, c) != int.MaxValue && !mobile.CanEnterCell(c));
|
.Where(c => pos.CanEnterCell(c, null, true) != pos.CanEnterCell(c, null, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Activity Tick(Actor self)
|
public override Activity Tick(Actor self)
|
||||||
@@ -58,6 +59,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
cloak.Uncloak();
|
cloak.Uncloak();
|
||||||
|
|
||||||
var actor = cargo.Peek(self);
|
var actor = cargo.Peek(self);
|
||||||
|
var spawn = self.CenterPosition;
|
||||||
|
|
||||||
var exitCell = ChooseExitCell(actor);
|
var exitCell = ChooseExitCell(actor);
|
||||||
if (exitCell == null)
|
if (exitCell == null)
|
||||||
@@ -71,33 +73,18 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
}
|
}
|
||||||
|
|
||||||
cargo.Unload(self);
|
cargo.Unload(self);
|
||||||
|
|
||||||
self.World.AddFrameEndTask(w =>
|
self.World.AddFrameEndTask(w =>
|
||||||
{
|
{
|
||||||
if (actor.Destroyed)
|
if (actor.Destroyed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var mobile = actor.Trait<Mobile>();
|
var move = actor.Trait<IMove>();
|
||||||
|
var pos = actor.Trait<IPositionable>();
|
||||||
var exitSubcell = mobile.GetDesiredSubcell(exitCell.Value, null);
|
|
||||||
|
|
||||||
mobile.fromSubCell = exitSubcell; // these settings make sure that the below Set* calls
|
|
||||||
mobile.toSubCell = exitSubcell; // and the above GetDesiredSubcell call pick a good free subcell for later units being unloaded
|
|
||||||
|
|
||||||
var exit = exitCell.Value.CenterPosition + MobileInfo.SubCellOffsets[exitSubcell];
|
|
||||||
var current = self.Location.CenterPosition + MobileInfo.SubCellOffsets[exitSubcell];
|
|
||||||
|
|
||||||
mobile.Facing = Util.GetFacing(exit - current, mobile.Facing);
|
|
||||||
mobile.SetPosition(actor, exitCell.Value);
|
|
||||||
mobile.SetVisualPosition(actor, current);
|
|
||||||
var speed = mobile.MovementSpeedForCell(actor, exitCell.Value);
|
|
||||||
var length = speed > 0 ? (exit - current).Length / speed : 0;
|
|
||||||
|
|
||||||
w.Add(actor);
|
w.Add(actor);
|
||||||
actor.CancelActivity();
|
actor.CancelActivity();
|
||||||
actor.QueueActivity(new Drag(current, exit, length));
|
pos.SetVisualPosition(actor, spawn);
|
||||||
actor.QueueActivity(mobile.MoveTo(exitCell.Value, 0));
|
actor.QueueActivity(move.MoveIntoWorld(actor, exitCell.Value));
|
||||||
|
|
||||||
actor.SetTargetLine(Target.FromCell(exitCell.Value), Color.Green, false);
|
actor.SetTargetLine(Target.FromCell(exitCell.Value), Color.Green, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -159,5 +159,16 @@ namespace OpenRA.Mods.RA.Air
|
|||||||
public Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange) { return new HeliFly(self, target, minRange, maxRange); }
|
public Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange) { return new HeliFly(self, target, minRange, maxRange); }
|
||||||
public Activity MoveFollow(Actor self, Target target, WRange range) { return new Follow(self, target, range); }
|
public Activity MoveFollow(Actor self, Target target, WRange range) { return new Follow(self, target, range); }
|
||||||
public CPos NearestMoveableCell(CPos cell) { return cell; }
|
public CPos NearestMoveableCell(CPos cell) { return cell; }
|
||||||
|
|
||||||
|
public Activity MoveIntoWorld(Actor self, CPos cell)
|
||||||
|
{
|
||||||
|
return new HeliFly(self, Target.FromCell(cell));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Activity VisualMove(Actor self, WPos fromPos, WPos toPos)
|
||||||
|
{
|
||||||
|
// TODO: Ignore repulsion when moving
|
||||||
|
return Util.SequenceActivities(new CallFunc(() => SetVisualPosition(self, fromPos)), new HeliFly(self, Target.FromPos(toPos)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,5 +100,8 @@ namespace OpenRA.Mods.RA.Air
|
|||||||
public Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange) { return Util.SequenceActivities(new Fly(self, target, minRange, maxRange), new FlyCircle()); }
|
public Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange) { return Util.SequenceActivities(new Fly(self, target, minRange, maxRange), new FlyCircle()); }
|
||||||
public Activity MoveFollow(Actor self, Target target, WRange range) { return new FlyFollow(self, target, range); }
|
public Activity MoveFollow(Actor self, Target target, WRange range) { return new FlyFollow(self, target, range); }
|
||||||
public CPos NearestMoveableCell(CPos cell) { return cell; }
|
public CPos NearestMoveableCell(CPos cell) { return cell; }
|
||||||
|
|
||||||
|
public Activity MoveIntoWorld(Actor self, CPos cell) { return new Fly(self, Target.FromCell(cell)); }
|
||||||
|
public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) { return Util.SequenceActivities(new CallFunc(() => SetVisualPosition(self, fromPos)), new Fly(self, Target.FromPos(toPos))); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -548,5 +548,31 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
if (self.IsIdle && self.AppearsFriendlyTo(blocking))
|
if (self.IsIdle && self.AppearsFriendlyTo(blocking))
|
||||||
Nudge(self, blocking, true);
|
Nudge(self, blocking, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Activity MoveIntoWorld(Actor self, CPos cell)
|
||||||
|
{
|
||||||
|
var pos = self.CenterPosition;
|
||||||
|
|
||||||
|
// Reserve the exit cell
|
||||||
|
SetPosition(self, cell);
|
||||||
|
SetVisualPosition(self, pos);
|
||||||
|
|
||||||
|
// Animate transition
|
||||||
|
var to = cell.CenterPosition;
|
||||||
|
var speed = MovementSpeedForCell(self, cell);
|
||||||
|
var length = speed > 0 ? (to - pos).Length / speed : 0;
|
||||||
|
|
||||||
|
var facing = Util.GetFacing(to - pos, Facing);
|
||||||
|
return Util.SequenceActivities(new Turn(facing), new Drag(pos, to, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Activity VisualMove(Actor self, WPos fromPos, WPos toPos)
|
||||||
|
{
|
||||||
|
var speed = MovementSpeedForCell(self, self.Location);
|
||||||
|
var length = speed > 0 ? (toPos - fromPos).Length / speed : 0;
|
||||||
|
|
||||||
|
var facing = Util.GetFacing(toPos - fromPos, Facing);
|
||||||
|
return Util.SequenceActivities(new Turn(facing), new Drag(fromPos, toPos, length));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace OpenRA.Mods.RA
|
|||||||
[Desc("Cell offset where the exiting actor enters the ActorMap")]
|
[Desc("Cell offset where the exiting actor enters the ActorMap")]
|
||||||
public readonly CVec ExitCell = CVec.Zero;
|
public readonly CVec ExitCell = CVec.Zero;
|
||||||
public readonly int Facing = -1;
|
public readonly int Facing = -1;
|
||||||
|
public readonly bool MoveIntoWorld = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Exit { }
|
public class Exit { }
|
||||||
@@ -58,28 +59,15 @@ namespace OpenRA.Mods.RA
|
|||||||
var newUnit = self.World.CreateActor(producee.Name, new TypeDictionary
|
var newUnit = self.World.CreateActor(producee.Name, new TypeDictionary
|
||||||
{
|
{
|
||||||
new OwnerInit(self.Owner),
|
new OwnerInit(self.Owner),
|
||||||
new LocationInit(exit),
|
new CenterPositionInit(spawn),
|
||||||
new FacingInit(initialFacing)
|
new FacingInit(initialFacing)
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Move this into an *Init
|
var move = newUnit.Trait<IMove>();
|
||||||
// TODO: We should be adjusting the actual position for aircraft, not just visuals.
|
if (exitinfo.MoveIntoWorld)
|
||||||
var teleportable = newUnit.Trait<IPositionable>();
|
newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
|
||||||
teleportable.SetVisualPosition(newUnit, spawn);
|
|
||||||
|
|
||||||
// TODO: Generalize this for non-mobile (e.g. aircraft) too
|
|
||||||
// Remember to update the Enter activity too
|
|
||||||
var mobile = newUnit.TraitOrDefault<Mobile>();
|
|
||||||
if (mobile != null)
|
|
||||||
{
|
|
||||||
// Animate the spawn -> exit transition
|
|
||||||
var speed = mobile.MovementSpeedForCell(newUnit, exit);
|
|
||||||
var length = speed > 0 ? (to - spawn).Length / speed : 0;
|
|
||||||
newUnit.QueueActivity(new Drag(spawn, to, length));
|
|
||||||
}
|
|
||||||
|
|
||||||
var target = MoveToRallyPoint(self, newUnit, exit);
|
var target = MoveToRallyPoint(self, newUnit, exit);
|
||||||
|
|
||||||
newUnit.SetTargetLine(Target.FromCell(target), Color.Green, false);
|
newUnit.SetTargetLine(Target.FromCell(target), Color.Green, false);
|
||||||
foreach (var t in self.TraitsImplementing<INotifyProduction>())
|
foreach (var t in self.TraitsImplementing<INotifyProduction>())
|
||||||
t.UnitProduced(self, newUnit, exit);
|
t.UnitProduced(self, newUnit, exit);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA.Render
|
namespace OpenRA.Mods.RA.Render
|
||||||
{
|
{
|
||||||
public class RenderInfantryInfo : RenderSimpleInfo, Requires<MobileInfo>
|
public class RenderInfantryInfo : RenderSimpleInfo, Requires<IMoveInfo>
|
||||||
{
|
{
|
||||||
public readonly int MinIdleWaitTicks = 30;
|
public readonly int MinIdleWaitTicks = 30;
|
||||||
public readonly int MaxIdleWaitTicks = 110;
|
public readonly int MaxIdleWaitTicks = 110;
|
||||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
IdleAnimating
|
IdleAnimating
|
||||||
}
|
}
|
||||||
|
|
||||||
Mobile mobile;
|
IMove move;
|
||||||
RenderInfantryInfo info;
|
RenderInfantryInfo info;
|
||||||
public bool IsMoving { get; set; }
|
public bool IsMoving { get; set; }
|
||||||
protected bool dirty = false;
|
protected bool dirty = false;
|
||||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
this.info = info;
|
this.info = info;
|
||||||
anim.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandAnimations.Random(Game.CosmeticRandom)), () => 0);
|
anim.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandAnimations.Random(Game.CosmeticRandom)), () => 0);
|
||||||
State = AnimationState.Waiting;
|
State = AnimationState.Waiting;
|
||||||
mobile = self.Trait<Mobile>();
|
move = self.Trait<IMove>();
|
||||||
|
|
||||||
self.Trait<IBodyOrientation>().SetAutodetectedFacings(anim.CurrentSequence.Facings);
|
self.Trait<IBodyOrientation>().SetAutodetectedFacings(anim.CurrentSequence.Facings);
|
||||||
}
|
}
|
||||||
@@ -83,12 +83,12 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
{
|
{
|
||||||
base.Tick(self);
|
base.Tick(self);
|
||||||
|
|
||||||
if ((State == AnimationState.Moving || dirty) && !mobile.IsMoving)
|
if ((State == AnimationState.Moving || dirty) && !move.IsMoving)
|
||||||
{
|
{
|
||||||
State = AnimationState.Waiting;
|
State = AnimationState.Waiting;
|
||||||
anim.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandAnimations.Random(Game.CosmeticRandom)), () => 0);
|
anim.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandAnimations.Random(Game.CosmeticRandom)), () => 0);
|
||||||
}
|
}
|
||||||
else if ((State != AnimationState.Moving || dirty) && mobile.IsMoving)
|
else if ((State != AnimationState.Moving || dirty) && move.IsMoving)
|
||||||
{
|
{
|
||||||
State = AnimationState.Moving;
|
State = AnimationState.Moving;
|
||||||
anim.PlayRepeating(NormalizeInfantrySequence(self, "run"));
|
anim.PlayRepeating(NormalizeInfantrySequence(self, "run"));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using OpenRA.Mods.RA.Move;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA.Render
|
namespace OpenRA.Mods.RA.Render
|
||||||
{
|
{
|
||||||
public class RenderLandingCraftInfo : RenderUnitInfo
|
public class RenderLandingCraftInfo : RenderUnitInfo, Requires<IMoveInfo>
|
||||||
{
|
{
|
||||||
public readonly string[] OpenTerrainTypes = { "Clear" };
|
public readonly string[] OpenTerrainTypes = { "Clear" };
|
||||||
public readonly string OpenAnim = "open";
|
public readonly string OpenAnim = "open";
|
||||||
@@ -25,26 +25,24 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
|
|
||||||
public class RenderLandingCraft : RenderUnit
|
public class RenderLandingCraft : RenderUnit
|
||||||
{
|
{
|
||||||
|
readonly RenderLandingCraftInfo info;
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
readonly Cargo cargo;
|
readonly Cargo cargo;
|
||||||
readonly RenderLandingCraftInfo info;
|
readonly IMove move;
|
||||||
bool open;
|
bool open;
|
||||||
|
|
||||||
public RenderLandingCraft(Actor self, RenderLandingCraftInfo info)
|
public RenderLandingCraft(Actor self, RenderLandingCraftInfo info)
|
||||||
: base(self)
|
: base(self)
|
||||||
{
|
{
|
||||||
|
this.info = info;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
cargo = self.Trait<Cargo>();
|
cargo = self.Trait<Cargo>();
|
||||||
this.info = info;
|
move = self.Trait<IMove>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldBeOpen()
|
public bool ShouldBeOpen()
|
||||||
{
|
{
|
||||||
var mobile = self.TraitOrDefault<Mobile>();
|
if (self.CenterPosition.Z > 0 || move.IsMoving)
|
||||||
if (mobile == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (self.CenterPosition.Z > 0 || mobile.IsMoving)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return cargo.CurrentAdjacentCells
|
return cargo.CurrentAdjacentCells
|
||||||
|
|||||||
@@ -1025,6 +1025,7 @@ HPAD:
|
|||||||
Exit@1:
|
Exit@1:
|
||||||
SpawnOffset: 0,-256,0
|
SpawnOffset: 0,-256,0
|
||||||
ExitCell: 0,0
|
ExitCell: 0,0
|
||||||
|
MoveIntoWorld: false
|
||||||
Production:
|
Production:
|
||||||
Produces: Helicopter
|
Produces: Helicopter
|
||||||
Reservable:
|
Reservable:
|
||||||
@@ -1059,6 +1060,7 @@ AFLD:
|
|||||||
SpawnOffset: 0,170,0
|
SpawnOffset: 0,170,0
|
||||||
ExitCell: 1,1
|
ExitCell: 1,1
|
||||||
Facing: 192
|
Facing: 192
|
||||||
|
MoveIntoWorld: false
|
||||||
Production:
|
Production:
|
||||||
Produces: Plane
|
Produces: Plane
|
||||||
Reservable:
|
Reservable:
|
||||||
|
|||||||
Reference in New Issue
Block a user