diff --git a/OpenRA.Mods.Common/Traits/Pluggable.cs b/OpenRA.Mods.Common/Traits/Pluggable.cs index d5f7ecc218..8f5a8e58c3 100644 --- a/OpenRA.Mods.Common/Traits/Pluggable.cs +++ b/OpenRA.Mods.Common/Traits/Pluggable.cs @@ -16,7 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class PluggableInfo : TraitInfo + public class PluggableInfo : TraitInfo, IEditorActorOptions { [Desc("Footprint cell offset where a plug can be placed.")] public readonly CVec Offset = CVec.Zero; @@ -32,6 +32,17 @@ namespace OpenRA.Mods.Common.Traits "Value is the condition expression defining the requirements to place the plug.")] public readonly Dictionary Requirements = new Dictionary(); + [Desc("Options to display in the map editor.", + "Key is the plug type that the requirements applies to.", + "Value is the label that is displayed in the actor editor dropdown.")] + public readonly Dictionary EditorOptions = new Dictionary(); + + [Desc("Label to use for an empty plug socket.")] + public readonly string EmptyOption = "Empty"; + + [Desc("Display order for the dropdown in the map editor")] + public readonly int EditorDisplayOrder = 5; + [GrantedConditionReference] public IEnumerable LinterConditions { get { return Conditions.Values; } } @@ -41,6 +52,28 @@ namespace OpenRA.Mods.Common.Traits get { return Requirements.Values.SelectMany(r => r.Variables).Distinct(); } } + IEnumerable IEditorActorOptions.ActorOptions(ActorInfo ai, World world) + { + if (!EditorOptions.Any()) + yield break; + + // Make sure the no-plug option is always available + EditorOptions[""] = EmptyOption; + yield return new EditorActorDropdown("Plug", EditorDisplayOrder, EditorOptions, + actor => + { + var init = actor.GetInitOrDefault(this); + return init != null ? init.Value : ""; + }, + (actor, value) => + { + if (string.IsNullOrEmpty(value)) + actor.RemoveInit(this); + else + actor.ReplaceInit(new PlugInit(this, value), this); + }); + } + public override object Create(ActorInitializer init) { return new Pluggable(init, this); } } @@ -58,9 +91,10 @@ namespace OpenRA.Mods.Common.Traits { Info = info; - var plugInit = init.GetValue>(info, new Dictionary()); - if (plugInit.ContainsKey(Info.Offset)) - initialPlug = plugInit[Info.Offset]; + initialPlug = init.GetValue(info, null); + var plugsInit = init.GetValue>(new Dictionary()); + if (plugsInit.ContainsKey(Info.Offset)) + initialPlug = plugsInit[Info.Offset]; if (info.Requirements.Count > 0) { @@ -125,4 +159,10 @@ namespace OpenRA.Mods.Common.Traits public PlugsInit(Dictionary value) : base(value) { } } + + public class PlugInit : ValueActorInit + { + public PlugInit(TraitInfo info, string value) + : base(info, value) { } + } } diff --git a/mods/ts/maps/fields-of-green/map.yaml b/mods/ts/maps/fields-of-green/map.yaml index 4525808e02..aed4066239 100644 --- a/mods/ts/maps/fields-of-green/map.yaml +++ b/mods/ts/maps/fields-of-green/map.yaml @@ -208,14 +208,12 @@ Actors: Location: 84,-1 TurretFacing: 92 Facing: 60 - Plugs: - 0,0: tower.vulcan + Plug: tower.vulcan Actor56: gactwr Owner: GDI Location: 80,-3 Facing: 60 - Plugs: - 0,0: tower.vulcan + Plug: tower.vulcan Actor57: gawall Owner: GDI Location: 79,-3 @@ -247,8 +245,7 @@ Actors: Owner: GDI Location: 84,-4 Facing: 60 - Plugs: - 0,0: tower.rocket + Plug: tower.rocket Actor67: gawall Owner: GDI Location: 88,-1 @@ -295,21 +292,18 @@ Actors: Owner: GDI Location: 86,-3 Facing: 60 - Plugs: - 0,1: powrup - 1,1: powrup + Plug@pluga: powrup + Plug@plugb: powrup Actor82: gapowr Owner: GDI Location: 86,-5 - Plugs: - 0,1: powrup - 1,1: powrup + Plug@pluga: powrup + Plug@plugb: powrup Actor91: gactwr Owner: GDI Location: 85,-11 Facing: -40 - Plugs: - 0,0: tower.vulcan + Plug: tower.vulcan Actor90: gasilo Owner: GDI Location: 79,-10 @@ -326,8 +320,7 @@ Actors: Owner: GDI Location: 81,-11 Facing: -40 - Plugs: - 0,0: tower.vulcan + Plug: tower.vulcan Actor89: gagate_a Owner: GDI Location: 82,-11 diff --git a/mods/ts/rules/gdi-structures.yaml b/mods/ts/rules/gdi-structures.yaml index 45f4533dc3..3f9fa32680 100644 --- a/mods/ts/rules/gdi-structures.yaml +++ b/mods/ts/rules/gdi-structures.yaml @@ -42,6 +42,8 @@ GAPOWR: powrup: powrup.a Requirements: powrup: !build-incomplete && !powrup.a + EditorOptions: + powrup: Power Turbine Power@pluga: RequiresCondition: !empdisable && powrup.a Amount: 50 @@ -55,6 +57,8 @@ GAPOWR: powrup: powrup.b Requirements: powrup: !build-incomplete && !powrup.b + EditorOptions: + powrup: Power Turbine WithIdleOverlay@plugb: RequiresCondition: !build-incomplete && powrup.b PauseOnCondition: empdisable @@ -508,6 +512,9 @@ GAPLUG: Requirements: plug.ioncannon: !build-incomplete && !plug.ioncannonb && !plug.ioncannona && !plug.hunterseekera plug.hunterseeker: !build-incomplete && !plug.hunterseekerb && !plug.ioncannona && !plug.hunterseekera + EditorOptions: + plug.ioncannon: Ion Cannon + plug.hunterseeker: Hunter Seeker WithIdleOverlay@ioncannona: RequiresCondition: !build-incomplete && plug.ioncannona PauseOnCondition: disabled @@ -524,6 +531,9 @@ GAPLUG: Requirements: plug.ioncannon: !build-incomplete && !plug.ioncannona && !plug.ioncannonb && !plug.hunterseekerb plug.hunterseeker: !build-incomplete && !plug.hunterseekera && !plug.ioncannonb && !plug.hunterseekerb + EditorOptions: + plug.ioncannon: Ion Cannon + plug.hunterseeker: Hunter Seeker WithIdleOverlay@ioncannonb: RequiresCondition: !build-incomplete && plug.ioncannonb PauseOnCondition: disabled diff --git a/mods/ts/rules/gdi-support.yaml b/mods/ts/rules/gdi-support.yaml index 26e4c3a069..3131c5c679 100644 --- a/mods/ts/rules/gdi-support.yaml +++ b/mods/ts/rules/gdi-support.yaml @@ -138,6 +138,10 @@ GACTWR: tower.vulcan: !build-incomplete && !tower.vulcan && !tower.rocket && !tower.sam tower.rocket: !build-incomplete && !tower.rocket && !tower.vulcan && !tower.sam tower.sam: !build-incomplete && !tower.vulcan && !tower.rocket && !tower.sam + EditorOptions: + tower.vulcan: Vulcan Tower + tower.rocket: RPG Upgrade + tower.sam: SAM Upgrade ProvidesPrerequisite@buildingname: ProvidesPrerequisite@pluggable: RequiresCondition: !build-incomplete && !tower.vulcan && !tower.rocket && !tower.sam