From 8a56e14d7a6980325551953c9dbc4bdee776e2ac Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Tue, 13 Aug 2024 20:24:24 +0100 Subject: [PATCH] Allow SpawnStartingUnits to have an immovable BaseActor Fixes a regression from 2c435c050628be41f91f44b2b05104d4059ec617 - where the support actors must be able to path to the base actor in order to prevent them from spawning in isolated areas. If the base actor is immovable, they cannot path onto it because the base actor blocks them, so no support actors will spawn. Fix this by allowing the support actors to path back to any cell adjacent to an immovable base actor, rather than requiring them to be able to path to its location directly. --- .../Traits/World/SpawnStartingUnits.cs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs b/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs index a016bea376..8418de7ce9 100644 --- a/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs +++ b/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs @@ -86,10 +86,11 @@ namespace OpenRA.Mods.Common.Traits if (unitGroup == null) throw new InvalidOperationException($"No starting units defined for faction {p.Faction.InternalName} with class {spawnClass}"); + CPos[] homeLocations; if (unitGroup.BaseActor != null) { var facing = unitGroup.BaseActorFacing ?? new WAngle(w.SharedRandom.Next(1024)); - w.CreateActor(unitGroup.BaseActor.ToLowerInvariant(), new TypeDictionary + var baseActor = w.CreateActor(unitGroup.BaseActor.ToLowerInvariant(), new TypeDictionary { new LocationInit(p.HomeLocation + unitGroup.BaseActorOffset), new OwnerInit(p), @@ -97,6 +98,25 @@ namespace OpenRA.Mods.Common.Traits new FacingInit(facing), new SpawnedByMapInit(), }); + var baseActorIsMovable = + baseActor.OccupiesSpace is Mobile mobile && !mobile.IsTraitDisabled && !mobile.IsTraitPaused && !mobile.IsImmovable; + if (baseActorIsMovable) + { + // If the base is movable, we want support actors to be able to path to its location. + homeLocations = new[] { baseActor.Location }; + } + else + { + // For an immovable base, we want support actors to be able to path adjacent to it. + // They won't to able to path to its location, because it is immovable and blocks them. + var occupiedCells = baseActor.OccupiesSpace.OccupiedCells().Select(p => p.Cell).ToArray(); + homeLocations = Util.ExpandFootprint(occupiedCells, true).Except(occupiedCells).ToArray(); + } + } + else + { + // If there is no base actor, we want support actors to be able to path to the home location. + homeLocations = new[] { p.HomeLocation }; } if (unitGroup.SupportActors.Length == 0) @@ -121,7 +141,7 @@ namespace OpenRA.Mods.Common.Traits if (locomotor != null) validCells = validCells - .Where(c => pathFinder.PathMightExistForLocomotorBlockedByImmovable(locomotor, c, p.HomeLocation + unitGroup.BaseActorOffset)); + .Where(c => homeLocations.Any(h => pathFinder.PathMightExistForLocomotorBlockedByImmovable(locomotor, c, h))); } var validCell = validCells.RandomOrDefault(w.SharedRandom);