diff --git a/OpenRA.Mods.Cnc/Traits/TDGunboat.cs b/OpenRA.Mods.Cnc/Traits/TDGunboat.cs index 6b1d84bd68..73857b9d18 100644 --- a/OpenRA.Mods.Cnc/Traits/TDGunboat.cs +++ b/OpenRA.Mods.Cnc/Traits/TDGunboat.cs @@ -191,7 +191,7 @@ namespace OpenRA.Mods.Cnc.Traits WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange, WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } - public Activity MoveIntoWorld(Actor self, int delay = 0) { return null; } + public Activity ReturnToCell(Actor self) { return null; } public Activity MoveToTarget(Actor self, Target target, WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } public Activity MoveIntoTarget(Actor self, Target target) { return null; } diff --git a/OpenRA.Mods.Common/Activities/Enter.cs b/OpenRA.Mods.Common/Activities/Enter.cs index 08449dc15e..718e439527 100644 --- a/OpenRA.Mods.Common/Activities/Enter.cs +++ b/OpenRA.Mods.Common/Activities/Enter.cs @@ -138,7 +138,7 @@ namespace OpenRA.Mods.Common.Activities case EnterState.Exiting: { - QueueChild(move.MoveIntoWorld(self)); + QueueChild(move.ReturnToCell(self)); lastState = EnterState.Finished; return false; } diff --git a/OpenRA.Mods.Common/ActorInitializer.cs b/OpenRA.Mods.Common/ActorInitializer.cs index 9726050fdd..02208d69e0 100644 --- a/OpenRA.Mods.Common/ActorInitializer.cs +++ b/OpenRA.Mods.Common/ActorInitializer.cs @@ -24,13 +24,13 @@ namespace OpenRA.Mods.Common public int Value(World world) { return value; } } - public class MoveIntoWorldDelayInit : IActorInit + public class CreationActivityDelayInit : IActorInit { [FieldFromYamlKey] readonly int value = 0; - public MoveIntoWorldDelayInit() { } - public MoveIntoWorldDelayInit(int init) { value = init; } + public CreationActivityDelayInit() { } + public CreationActivityDelayInit(int init) { value = init; } public int Value(World world) { return value; } } diff --git a/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs index af240e1214..a6446562c0 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Scripting var pos = Self.CenterPosition; mobile.SetPosition(Self, cell); mobile.SetVisualPosition(Self, pos); - Self.QueueActivity(mobile.MoveIntoWorld(Self)); + Self.QueueActivity(mobile.ReturnToCell(Self)); } [ScriptActorPropertyActivity] diff --git a/OpenRA.Mods.Common/Scripting/Properties/TransportProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/TransportProperties.cs index bf27ac1d40..61dad8c4f3 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/TransportProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/TransportProperties.cs @@ -10,6 +10,7 @@ #endregion using System.Linq; +using Eluant; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Traits; using OpenRA.Scripting; @@ -35,7 +36,13 @@ namespace OpenRA.Mods.Common.Scripting public int PassengerCount { get { return cargo.Passengers.Count(); } } [Desc("Teleport an existing actor inside this transport.")] - public void LoadPassenger(Actor a) { cargo.Load(Self, a); } + public void LoadPassenger(Actor a) + { + if (!a.IsIdle) + throw new LuaException("LoadPassenger requires the passenger to be idle."); + + cargo.Load(Self, a); + } [Desc("Remove the first actor from the transport. This actor is not added to the world.")] public Actor UnloadPassenger() { return cargo.Unload(Self); } diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 12d897558b..bfb20e2088 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -220,7 +220,7 @@ namespace OpenRA.Mods.Common.Traits IEnumerable landingCells = Enumerable.Empty(); bool requireForceMove; - int moveIntoWorldDelay; + int creationActivityDelay; public static WPos GroundPosition(Actor self) { @@ -251,7 +251,9 @@ namespace OpenRA.Mods.Common.Traits SetPosition(self, init.Get()); Facing = init.Contains() ? init.Get() : Info.InitialFacing; - moveIntoWorldDelay = init.Contains() ? init.Get() : 0; + + if (init.Contains()) + creationActivityDelay = init.Get(); } public WDist LandAltitude @@ -841,18 +843,15 @@ namespace OpenRA.Mods.Common.Traits initialTargetPosition, targetLineColor); } - public Activity MoveIntoWorld(Actor self, int delay = 0) - { - return new MoveIntoWorldActivity(self, delay); - } + public Activity ReturnToCell(Actor self) { return null; } - class MoveIntoWorldActivity : Activity + class AssociateWithAirfieldActivity : Activity { readonly Actor self; readonly Aircraft aircraft; readonly int delay; - public MoveIntoWorldActivity(Actor self, int delay = 0) + public AssociateWithAirfieldActivity(Actor self, int delay = 0) { this.self = self; aircraft = self.Trait(); @@ -1164,7 +1163,7 @@ namespace OpenRA.Mods.Common.Traits Activity ICreationActivity.GetCreationActivity() { - return MoveIntoWorld(self, moveIntoWorldDelay); + return new AssociateWithAirfieldActivity(self, creationActivityDelay); } public class AircraftMoveOrderTargeter : IOrderTargeter diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 8cfdbff5b0..7347dbc921 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -406,11 +406,11 @@ namespace OpenRA.Mods.Common.Traits // If not initialized then this will be notified in the first tick if (initialized) { - foreach (var npe in self.TraitsImplementing()) - npe.OnPassengerEntered(self, a); - foreach (var nec in a.TraitsImplementing()) nec.OnEnteredCargo(a, self); + + foreach (var npe in self.TraitsImplementing()) + npe.OnPassengerEntered(self, a); } var p = a.Trait(); @@ -507,11 +507,11 @@ namespace OpenRA.Mods.Common.Traits { c.Trait().Transport = self; - foreach (var npe in self.TraitsImplementing()) - npe.OnPassengerEntered(self, c); - foreach (var nec in c.TraitsImplementing()) nec.OnEnteredCargo(c, self); + + foreach (var npe in self.TraitsImplementing()) + npe.OnPassengerEntered(self, c); } initialized = true; diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 8b3a722bc7..59cc3eb59c 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -143,7 +143,10 @@ namespace OpenRA.Mods.Common.Traits { readonly Actor self; readonly Lazy> speedModifiers; - readonly int moveIntoWorldDelay; + + readonly bool returnToCellOnCreation; + readonly bool returnToCellOnCreationRecalculateSubCell = true; + readonly int creationActivityDelay; #region IMove CurrentMovementTypes MovementType movementTypes; @@ -228,7 +231,10 @@ namespace OpenRA.Mods.Common.Traits ToSubCell = FromSubCell = info.LocomotorInfo.SharesCell ? init.World.Map.Grid.DefaultSubCell : SubCell.FullCell; if (init.Contains()) + { FromSubCell = ToSubCell = init.Get(); + returnToCellOnCreationRecalculateSubCell = false; + } if (init.Contains()) { @@ -238,12 +244,16 @@ namespace OpenRA.Mods.Common.Traits Facing = init.Contains() ? init.Get() : info.InitialFacing; - // Sets the visual position to WPos accuracy - // Use LocationInit if you want to insert the actor into the ActorMap! + // Sets the initial visual position + // Unit will move into the cell grid (defined by LocationInit) as its initial activity if (init.Contains()) + { SetVisualPosition(self, init.Get()); + returnToCellOnCreation = true; + } - moveIntoWorldDelay = init.Contains() ? init.Get() : 0; + if (init.Contains()) + creationActivityDelay = init.Get(); } protected override void Created(Actor self) @@ -568,27 +578,27 @@ namespace OpenRA.Mods.Common.Traits return WrapMove(new Follow(self, target, minRange, maxRange, initialTargetPosition, targetLineColor)); } - public Activity MoveIntoWorld(Actor self, int delay = 0) + public Activity ReturnToCell(Actor self) { - return new MoveIntoWorldActivity(self, delay); + return new ReturnToCellActivity(self); } - class MoveIntoWorldActivity : Activity + class ReturnToCellActivity : Activity { - readonly Actor self; readonly Mobile mobile; + readonly bool recalculateSubCell; CPos cell; SubCell subCell; WPos pos; int delay; - public MoveIntoWorldActivity(Actor self, int delay = 0) + public ReturnToCellActivity(Actor self, int delay = 0, bool recalculateSubCell = false) { - this.self = self; mobile = self.Trait(); IsInterruptible = false; this.delay = delay; + this.recalculateSubCell = recalculateSubCell; } protected override void OnFirstRun(Actor self) @@ -604,7 +614,7 @@ namespace OpenRA.Mods.Common.Traits cell = mobile.ToCell; subCell = mobile.ToSubCell; - if (subCell == SubCell.Any) + if (recalculateSubCell) subCell = mobile.Info.LocomotorInfo.SharesCell ? self.World.ActorMap.FreeSubCell(cell, subCell) : SubCell.FullCell; // TODO: solve/reduce cell is full problem @@ -898,7 +908,7 @@ namespace OpenRA.Mods.Common.Traits Activity ICreationActivity.GetCreationActivity() { - return MoveIntoWorld(self, moveIntoWorldDelay); + return returnToCellOnCreation ? new ReturnToCellActivity(self, creationActivityDelay, returnToCellOnCreationRecalculateSubCell) : null; } class MoveOrderTargeter : IOrderTargeter diff --git a/OpenRA.Mods.Common/Traits/Passenger.cs b/OpenRA.Mods.Common/Traits/Passenger.cs index 1ca8ae6666..da9a431861 100644 --- a/OpenRA.Mods.Common/Traits/Passenger.cs +++ b/OpenRA.Mods.Common/Traits/Passenger.cs @@ -131,6 +131,16 @@ namespace OpenRA.Mods.Common.Traits if (specificCargoToken == ConditionManager.InvalidConditionToken && Info.CargoConditions.TryGetValue(cargo.Info.Name, out specificCargoCondition)) specificCargoToken = conditionManager.GrantCondition(self, specificCargoCondition); } + + // Allow scripted / initial actors to move from the unload point back into the cell grid on unload + // This is handled by the RideTransport activity for player-loaded cargo + if (self.IsIdle) + { + // IMove is not used anywhere else in this trait, there is no benefit to caching it from Created. + var move = self.TraitOrDefault(); + if (move != null) + self.QueueActivity(move.ReturnToCell(self)); + } } void INotifyExitedCargo.OnExitedCargo(Actor self, Actor cargo) diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index 8a67915bc5..c8b4f7a295 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.Traits td.Add(new CenterPositionInit(spawn)); td.Add(new FacingInit(initialFacing)); if (exitinfo != null) - td.Add(new MoveIntoWorldDelayInit(exitinfo.ExitDelay)); + td.Add(new CreationActivityDelayInit(exitinfo.ExitDelay)); } self.World.AddFrameEndTask(w => diff --git a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs index d249c6d4c6..caba158fa2 100644 --- a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs +++ b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs @@ -127,7 +127,7 @@ namespace OpenRA.Mods.Common.Traits td.Add(new LocationInit(exit)); td.Add(new CenterPositionInit(spawn)); td.Add(new FacingInit(initialFacing)); - td.Add(new MoveIntoWorldDelayInit(exitinfo.ExitDelay)); + td.Add(new CreationActivityDelayInit(exitinfo.ExitDelay)); } self.World.AddFrameEndTask(w => diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 929ec5410b..65bc255700 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -435,7 +435,7 @@ namespace OpenRA.Mods.Common.Traits WPos? initialTargetPosition = null, Color? targetLineColor = null); Activity MoveToTarget(Actor self, Target target, WPos? initialTargetPosition = null, Color? targetLineColor = null); - Activity MoveIntoWorld(Actor self, int delay = 0); + Activity ReturnToCell(Actor self); Activity MoveIntoTarget(Actor self, Target target); Activity VisualMove(Actor self, WPos fromPos, WPos toPos); int EstimatedMoveDuration(Actor self, WPos fromPos, WPos toPos);