diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 9243e8d516..a10b6e5f8e 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -480,6 +480,8 @@ + + diff --git a/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs b/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs index edde98d1fe..223c86b9c9 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs @@ -22,10 +22,21 @@ namespace OpenRA.Mods.Common.Traits if (!world.Map.Contains(cell)) return false; - if (world.WorldActor.Trait().GetBuildingAt(cell) != null) - return false; + var building = world.WorldActor.Trait().GetBuildingAt(cell); + if (building != null) + { + if (ai == null) + return false; - if (!bi.AllowInvalidPlacement && world.ActorMap.GetActorsAt(cell).Any(a => a != toIgnore)) + var replacementInfo = ai.TraitInfoOrDefault(); + if (replacementInfo == null) + return false; + + if (!building.TraitsImplementing().Any(p => !p.IsTraitDisabled && + p.Info.Types.Overlaps(replacementInfo.ReplaceableTypes))) + return false; + } + else if (!bi.AllowInvalidPlacement && world.ActorMap.GetActorsAt(cell).Any(a => a != toIgnore)) return false; var tile = world.Map.Tiles[cell]; diff --git a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs index b424c8c4f8..d0d6ef9f08 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs @@ -136,6 +136,18 @@ namespace OpenRA.Mods.Common.Traits || !buildingInfo.IsCloseEnoughToBase(self.World, order.Player, actorInfo, order.TargetLocation)) return; + var replacementInfo = actorInfo.TraitInfoOrDefault(); + if (replacementInfo != null) + { + var buildingInfluence = self.World.WorldActor.Trait(); + foreach (var t in buildingInfo.Tiles(order.TargetLocation)) + { + var host = buildingInfluence.GetBuildingAt(t); + if (host != null) + host.World.Remove(host); + } + } + var building = w.CreateActor(order.TargetString, new TypeDictionary { new LocationInit(order.TargetLocation), diff --git a/OpenRA.Mods.Common/Traits/Replaceable.cs b/OpenRA.Mods.Common/Traits/Replaceable.cs new file mode 100644 index 0000000000..4d2f0f122c --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Replaceable.cs @@ -0,0 +1,31 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 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; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class ReplaceableInfo : ConditionalTraitInfo, ITraitInfo + { + [FieldLoader.Require] + [Desc("Replacement types this Relpaceable actor accepts.")] + public readonly HashSet Types = new HashSet(); + + public override object Create(ActorInitializer init) { return new Replaceable(init, this); } + } + + public class Replaceable : ConditionalTrait + { + public Replaceable(ActorInitializer init, ReplaceableInfo info) + : base(info) { } + } +} diff --git a/OpenRA.Mods.Common/Traits/Replacement.cs b/OpenRA.Mods.Common/Traits/Replacement.cs new file mode 100644 index 0000000000..5edc764dea --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Replacement.cs @@ -0,0 +1,25 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 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; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class ReplacementInfo : TraitInfo + { + [FieldLoader.Require] + [Desc("Replacement type (matched against Conditions in Replaceable).")] + public readonly HashSet ReplaceableTypes = new HashSet(); + } + + public class Replacement { } +}