diff --git a/OpenRA.Mods.Common/Activities/Resupply.cs b/OpenRA.Mods.Common/Activities/Resupply.cs index 1965fa23b1..919c736bda 100644 --- a/OpenRA.Mods.Common/Activities/Resupply.cs +++ b/OpenRA.Mods.Common/Activities/Resupply.cs @@ -187,7 +187,7 @@ namespace OpenRA.Mods.Common.Activities { if (wasRepaired || isHostInvalid || (!stayOnResupplier && aircraft.Info.TakeOffOnResupply)) { - if (self.CurrentActivity.NextActivity == null && rp != null) + if (self.CurrentActivity.NextActivity == null && rp != null && rp.Path.Count > 0) foreach (var cell in rp.Path) QueueChild(move.MoveTo(cell, 1, ignoreActor: repairableNear != null ? null : host.Actor, targetLineColor: Color.Green)); else @@ -208,7 +208,7 @@ namespace OpenRA.Mods.Common.Activities // If there's a next activity and we're not RepairableNear, first leave host if the next activity is not a Move. if (self.CurrentActivity.NextActivity == null) { - if (rp != null) + if (rp != null && rp.Path.Count > 0) foreach (var cell in rp.Path) QueueChild(move.MoveTo(cell, 1, repairableNear != null ? null : host.Actor, true)); else if (repairableNear == null) diff --git a/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs b/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs index d510b37911..56d950004a 100644 --- a/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs +++ b/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs @@ -73,6 +73,9 @@ namespace OpenRA.Mods.Common.Effects foreach (var c in cachedLocations) targetLineNodes.Add(world.Map.CenterOfCell(c)); + if (targetLineNodes.Count == 0) + return; + var exitPos = building.CenterPosition; // Find closest exit diff --git a/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs index d90cf68ca6..eb02f93b78 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs @@ -79,8 +79,21 @@ namespace OpenRA.Mods.Common.Scripting [Desc("Query or set a factory's rally point.")] public CPos RallyPoint { - get { return rp.Path.Last(); } - set { rp.Path = new List { value }; } + get + { + if (rp.Path.Count > 0) + return rp.Path.Last(); + + var exit = Self.FirstExitOrDefault(); + if (exit != null) + return Self.Location + exit.Info.ExitCell; + + return Self.Location; + } + set + { + rp.Path = new List { value }; + } } } diff --git a/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs b/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs index aa11fbca96..0c4fb16ac6 100644 --- a/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs +++ b/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs @@ -228,8 +228,10 @@ namespace OpenRA.Mods.Common.Traits { foreach (var rp in world.ActorsWithTrait()) { - if (rp.Actor.Owner == player && - !IsRallyPointValid(rp.Trait.Path[0], rp.Actor.Info.TraitInfoOrDefault())) + if (rp.Actor.Owner != player) + continue; + + if (rp.Trait.Path.Count == 0 || !IsRallyPointValid(rp.Trait.Path[0], rp.Actor.Info.TraitInfoOrDefault())) { bot.QueueOrder(new Order("SetRallyPoint", rp.Actor, Target.FromCell(world, ChooseRallyLocationNear(rp.Actor)), false) { diff --git a/OpenRA.Mods.Common/Traits/Buildings/RallyPoint.cs b/OpenRA.Mods.Common/Traits/Buildings/RallyPoint.cs index c2b1311b36..e71dd62807 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/RallyPoint.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/RallyPoint.cs @@ -39,7 +39,8 @@ namespace OpenRA.Mods.Common.Traits [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = true; - public readonly CVec Offset = new CVec(1, 3); + [Desc("A list of 0 or more offsets defining the initial rally point path.")] + public readonly CVec[] Path = { new CVec(1, 3) }; public object Create(ActorInitializer init) { return new RallyPoint(init.Self, this); } } @@ -57,7 +58,7 @@ namespace OpenRA.Mods.Common.Traits public void ResetPath(Actor self) { - Path = new List { self.Location + Info.Offset }; + Path = Info.Path.Select(p => self.Location + p).ToList(); } public RallyPoint(Actor self, RallyPointInfo info) diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index a810d93431..4efba7cdaf 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits initialFacing = delta.Yaw.Facing; } - exitLocations = rp.Value != null ? rp.Value.Path : new List { exit }; + exitLocations = rp.Value != null && rp.Value.Path.Count > 0 ? rp.Value.Path : new List { exit }; td.Add(new LocationInit(exit)); td.Add(new CenterPositionInit(spawn)); diff --git a/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs b/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs index a1078142f2..db598b9c64 100644 --- a/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs +++ b/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Traits var aircraftInfo = producee.TraitInfoOrDefault(); var mobileInfo = producee.TraitInfoOrDefault(); - var destinations = rp != null ? rp.Path : new List { self.Location }; + var destinations = rp != null && rp.Path.Count > 0 ? rp.Path : new List { self.Location }; var location = spawnLocation; if (!location.HasValue) diff --git a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs index c7cf1da3da..4ad9a09d0b 100644 --- a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs +++ b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs @@ -123,7 +123,7 @@ namespace OpenRA.Mods.Common.Traits var initialFacing = exitinfo.Facing < 0 ? (to - spawn).Yaw.Facing : exitinfo.Facing; - exitLocations = rp.Value != null ? rp.Value.Path : new List { exit }; + exitLocations = rp.Value != null && rp.Value.Path.Count > 0 ? rp.Value.Path : new List { exit }; td.Add(new LocationInit(exit)); td.Add(new CenterPositionInit(spawn)); diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20191117/RenameRallyPointPath.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20191117/RenameRallyPointPath.cs new file mode 100644 index 0000000000..0f293ddde4 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20191117/RenameRallyPointPath.cs @@ -0,0 +1,35 @@ +#region Copyright & License Information +/* + * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) + * 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; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + class RenameRallyPointPath : UpdateRule + { + public override string Name { get { return "Renamed RallyPoint Offset to Path"; } } + public override string Description + { + get + { + return "The RallyPoint Offset property has been renamed to Path and now accepts multiple (or no) values."; + } + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + foreach (var rp in actorNode.ChildrenMatching("RallyPoint")) + rp.RenameChildrenMatching("Offset", "Path"); + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index f1ca2fe625..6626ef3723 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -98,6 +98,7 @@ namespace OpenRA.Mods.Common.UpdateRules new ReformatChromeProvider(), new RenameSpins(), new CreateScreenShakeWarhead(), + new RenameRallyPointPath(), }) }; diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 2341c3df80..16153ad3ad 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -376,7 +376,7 @@ HAND: Range: 5c0 WithBuildingBib: RallyPoint: - Offset: 1,2 + Path: 1,2 Exit@1: SpawnOffset: 512,1024,0 ExitCell: 1,2 @@ -432,7 +432,7 @@ AFLD: RevealsShroud: Range: 7c0 RallyPoint: - Offset: 4,2 + Path: 4,2 Exit@1: SpawnOffset: -1024,0,0 ExitCell: 3,1 @@ -497,7 +497,7 @@ WEAP: RequiresCondition: !build-incomplete Sequence: build-top RallyPoint: - Offset: 0,2 + Path: 0,2 Exit@1: SpawnOffset: -512,-512,0 ExitCell: 0,1 diff --git a/mods/cnc/rules/tech.yaml b/mods/cnc/rules/tech.yaml index 09ce3870df..5f7c543f47 100644 --- a/mods/cnc/rules/tech.yaml +++ b/mods/cnc/rules/tech.yaml @@ -106,7 +106,7 @@ BIO: ProductionBar: ProductionType: Biolab RallyPoint: - Offset: -1,-1 + Path: -1,-1 SpawnActorOnDeath: Actor: BIO.Husk ProvidesPrerequisite@buildingname: diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index c628186be8..1f7533dc9b 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -202,7 +202,7 @@ barracks: RevealsShroud: Range: 3c768 RallyPoint: - Offset: 1,2 + Path: 1,2 Exit@1: SpawnOffset: 352,576,0 ExitCell: 0,2 @@ -418,7 +418,7 @@ light_factory: Queues: Vehicle Sequence: production-welding RallyPoint: - Offset: 2,2 + Path: 2,2 Exit@1: SpawnOffset: 544,-224,0 ExitCell: 2,1 @@ -500,7 +500,7 @@ heavy_factory: RevealsShroud: Range: 4c768 RallyPoint: - Offset: 0,3 + Path: 0,3 Exit@1: SpawnOffset: 256,192,0 ExitCell: 0,2 @@ -652,7 +652,7 @@ starport: RevealsShroud: Range: 3c768 RallyPoint: - Offset: 1,3 + Path: 1,3 Exit@1: SpawnOffset: 0,-480,0 ExitCell: 2,2 @@ -907,7 +907,7 @@ repair_pad: FinishRepairingNotification: UnitRepaired PlayerExperience: 15 RallyPoint: - Offset: 1,3 + Path: 1,3 RenderSprites: Image: repair_pad.ordos FactionImages: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 4f8a6a0173..cf414b419a 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -1814,7 +1814,7 @@ KENN: WithBuildingBib: HasMinibib: True RallyPoint: - Offset: 0,2 + Path: 0,2 Exit@0: RequiresCondition: !being-captured SpawnOffset: -280,400,0 diff --git a/mods/ts/rules/gdi-structures.yaml b/mods/ts/rules/gdi-structures.yaml index e46f2874fe..0babe3aa1e 100644 --- a/mods/ts/rules/gdi-structures.yaml +++ b/mods/ts/rules/gdi-structures.yaml @@ -96,7 +96,7 @@ GAPILE: Range: 5c0 MaxHeightDelta: 3 RallyPoint: - Offset: 2,3 + Path: 2,3 Palette: mouse IsPlayerPalette: false LineWidth: 2 @@ -196,7 +196,7 @@ GAWEAP: Armor: Type: Heavy RallyPoint: - Offset: 4,1 + Path: 4,1 Palette: mouse IsPlayerPalette: false LineWidth: 2 diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index ce0846625e..ae5cf554be 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -150,7 +150,7 @@ NAHAND: ExitCell: 0,2 ExitsDebugOverlay: RallyPoint: - Offset: 3,3 + Path: 3,3 Palette: mouse IsPlayerPalette: false LineWidth: 2 @@ -208,7 +208,7 @@ NAWEAP: Range: 4c0 MaxHeightDelta: 3 RallyPoint: - Offset: 4,1 + Path: 4,1 Palette: mouse IsPlayerPalette: false LineWidth: 2