diff --git a/OpenRA.Mods.Cnc/Traits/MadTank.cs b/OpenRA.Mods.Cnc/Traits/MadTank.cs index 00368292bc..66847f5734 100644 --- a/OpenRA.Mods.Cnc/Traits/MadTank.cs +++ b/OpenRA.Mods.Cnc/Traits/MadTank.cs @@ -249,7 +249,7 @@ namespace OpenRA.Mods.Cnc.Traits new LocationInit(self.Location), new OwnerInit(self.Owner) }); - driver.TraitOrDefault()?.Nudge(driver); + driver.QueueActivity(false, new Nudge(driver)); } } } diff --git a/OpenRA.Mods.Common/Activities/Move/Nudge.cs b/OpenRA.Mods.Common/Activities/Move/Nudge.cs new file mode 100644 index 0000000000..0fb90b01af --- /dev/null +++ b/OpenRA.Mods.Common/Activities/Move/Nudge.cs @@ -0,0 +1,66 @@ +#region Copyright & License Information +/* + * Copyright (c) The OpenRA Developers and Contributors + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using OpenRA.Activities; +using OpenRA.Mods.Common.Activities; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class Nudge : Activity + { + readonly Actor nudger; + public Nudge(Actor nudger) + { + this.nudger = nudger; + } + + protected override void OnFirstRun(Actor self) + { + var move = self.Trait(); + if (move is Mobile mobile) + { + if (mobile.IsTraitDisabled || mobile.IsTraitPaused || mobile.IsImmovable) + return; + + var cell = mobile.GetAdjacentCell(nudger.Location); + if (cell != null) + QueueChild(mobile.MoveTo(cell.Value, 0, targetLineColor: mobile.Info.TargetLineColor)); + } + else if (move is Aircraft aircraft) + { + if (aircraft.IsTraitDisabled || aircraft.IsTraitPaused || aircraft.RequireForceMove) + return; + + // Disable nudging if the aircraft is outside the map. + if (!self.World.Map.Contains(self.Location)) + return; + + var offset = new WVec(0, -self.World.SharedRandom.Next(512, 2048), 0) + .Rotate(WRot.FromFacing(self.World.SharedRandom.Next(256))); + + var target = Target.FromPos(self.CenterPosition + offset); + QueueChild(new Fly(self, target, targetLineColor: aircraft.Info.TargetLineColor)); + aircraft.UnReserve(); + } + } + + public override IEnumerable TargetLineNodes(Actor self) + { + if (ChildActivity != null) + foreach (var n in ChildActivity.TargetLineNodes(self)) + yield return n; + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs index 453192c458..894fdef432 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Scripting [Desc("Leave the current position in a random direction.")] public void Scatter() { - mobile.Nudge(Self); + Self.QueueActivity(false, new Nudge(Self)); } [ScriptActorPropertyActivity] diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 7988f8cc08..780d08dda8 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -283,7 +283,7 @@ namespace OpenRA.Mods.Common.Traits public bool ForceLanding { get; private set; } (CPos, SubCell)[] landingCells = Array.Empty<(CPos, SubCell)>(); - bool requireForceMove; + public bool RequireForceMove; readonly int creationActivityDelay; @@ -354,7 +354,7 @@ namespace OpenRA.Mods.Common.Traits void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary conditions) { - requireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions); + RequireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions); } protected override void Created(Actor self) @@ -586,7 +586,7 @@ namespace OpenRA.Mods.Common.Traits bool AircraftCanEnter(Actor a, TargetModifiers modifiers) { - if (requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove)) + if (RequireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove)) return false; return AircraftCanEnter(a); @@ -1144,29 +1144,14 @@ namespace OpenRA.Mods.Common.Traits self.ShowTargetLines(); } else if (orderString == "Scatter") - Nudge(self); + { + self.QueueActivity(order.Queued, new Nudge(self)); + self.ShowTargetLines(); + } } #endregion - void Nudge(Actor self) - { - if (IsTraitDisabled || IsTraitPaused || requireForceMove) - return; - - // Disable nudging if the aircraft is outside the map - if (!self.World.Map.Contains(self.Location)) - return; - - var offset = new WVec(0, -self.World.SharedRandom.Next(512, 2048), 0) - .Rotate(WRot.FromFacing(self.World.SharedRandom.Next(256))); - var target = Target.FromPos(self.CenterPosition + offset); - - self.QueueActivity(false, new Fly(self, target)); - self.ShowTargetLines(); - UnReserve(); - } - #region Airborne conditions void OnAirborneAltitudeReached() @@ -1295,7 +1280,7 @@ namespace OpenRA.Mods.Common.Traits public virtual bool CanTarget(Actor self, in Target target, ref TargetModifiers modifiers, ref string cursor) { - if (target.Type != TargetType.Terrain || (aircraft.requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))) + if (target.Type != TargetType.Terrain || (aircraft.RequireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))) return false; var location = self.World.Map.CellContaining(target.CenterPosition); diff --git a/OpenRA.Mods.Common/Traits/Crushable.cs b/OpenRA.Mods.Common/Traits/Crushable.cs index 7b0023e979..579c4b6baa 100644 --- a/OpenRA.Mods.Common/Traits/Crushable.cs +++ b/OpenRA.Mods.Common/Traits/Crushable.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits var mobile = self.TraitOrDefault(); if (mobile != null && self.World.SharedRandom.Next(100) <= Info.WarnProbability) - mobile.Nudge(crusher); + self.QueueActivity(false, new Nudge(crusher)); } void INotifyCrushed.OnCrush(Actor self, Actor crusher, BitSet crushClasses) diff --git a/OpenRA.Mods.Common/Traits/EjectOnDeath.cs b/OpenRA.Mods.Common/Traits/EjectOnDeath.cs index dffc13a1ce..68ea2678c0 100644 --- a/OpenRA.Mods.Common/Traits/EjectOnDeath.cs +++ b/OpenRA.Mods.Common/Traits/EjectOnDeath.cs @@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Traits var pilot = self.World.CreateActor(true, Info.PilotActor.ToLowerInvariant(), td); if (!inAir) - pilot.TraitOrDefault()?.Nudge(pilot); + pilot.QueueActivity(false, new Nudge(pilot)); else Game.Sound.Play(SoundType.World, Info.ChuteSound, cp); }); diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 9a9c74cc2d..2a6f71ad95 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -367,16 +367,6 @@ namespace OpenRA.Mods.Common.Traits #region Local misc stuff - public void Nudge(Actor nudger) - { - if (IsTraitDisabled || IsTraitPaused || IsImmovable) - return; - - var cell = GetAdjacentCell(nudger.Location); - if (cell != null) - self.QueueActivity(false, MoveTo(cell.Value, 0)); - } - public CPos? GetAdjacentCell(CPos nextCell, Func preferToAvoid = null) { var availCells = new List(); @@ -873,7 +863,7 @@ namespace OpenRA.Mods.Common.Traits if (self.IsIdle) { - Nudge(blocking); + self.QueueActivity(false, new Nudge(blocking)); return; } @@ -942,7 +932,10 @@ namespace OpenRA.Mods.Common.Traits else if (order.OrderString == "Stop") self.CancelActivity(); else if (order.OrderString == "Scatter") - Nudge(self); + { + self.QueueActivity(order.Queued, new Nudge(self)); + self.ShowTargetLines(); + } } string IOrderVoice.VoicePhraseForOrder(Actor self, Order order) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs index 6889540ac4..3bb4fe70ae 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs @@ -142,7 +142,8 @@ namespace OpenRA.Mods.Common.Widgets if (highlightOnButtonPress) scatterHighlighted = 2; - PerformKeyboardOrderOnSelection(a => new Order("Scatter", a, false)); + var queued = Game.GetModifierKeys().HasModifier(Modifiers.Shift); + PerformKeyboardOrderOnSelection(a => new Order("Scatter", a, queued)); }; scatterButton.OnKeyPress = ki => { scatterHighlighted = 2; scatterButton.OnClick(); }; @@ -211,7 +212,7 @@ namespace OpenRA.Mods.Common.Widgets var keyOverrides = widget.GetOrNull("MODIFIER_OVERRIDES"); if (keyOverrides != null) { - var noShiftButtons = new[] { guardButton, deployButton, attackMoveButton }; + var noShiftButtons = new[] { guardButton, deployButton, scatterButton, attackMoveButton }; var keyUpButtons = new[] { guardButton, attackMoveButton }; keyOverrides.AddHandler(e => {