diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 7f0ace144d..4a2f5fae3e 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -736,6 +736,7 @@
+
diff --git a/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs
index 7f6c4fa2ca..59074f8e3c 100644
--- a/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs
+++ b/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs
@@ -9,6 +9,7 @@
*/
#endregion
+using System.Collections.Generic;
using System.Linq;
using Eluant;
using OpenRA.Mods.Common.Traits;
@@ -113,5 +114,11 @@ namespace OpenRA.Mods.Common.Scripting
{
return actor.ActorID <= sma.LastMapActorID && actor.ActorID > sma.LastMapActorID - sma.Actors.Count;
}
+
+ [Desc("Returns a table of all actors tagged with the given string.")]
+ public Actor[] ActorsWithTag(string tag)
+ {
+ return Context.World.ActorsHavingTrait(t => t.HasTag(tag)).ToArray();
+ }
}
}
diff --git a/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs
index d228fc5e6e..c0e8269b46 100644
--- a/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs
+++ b/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs
@@ -79,12 +79,14 @@ namespace OpenRA.Mods.Common.Scripting
{
readonly IFacing facing;
readonly AutoTarget autotarget;
+ readonly ScriptTags scriptTags;
public GeneralProperties(ScriptContext context, Actor self)
: base(context, self)
{
facing = self.TraitOrDefault();
autotarget = self.TraitOrDefault();
+ scriptTags = self.TraitOrDefault();
}
[Desc("The actor position in cell coordinates.")]
@@ -162,5 +164,26 @@ namespace OpenRA.Mods.Common.Scripting
autotarget.Stance = stance;
}
}
+
+ [Desc("Specifies whether or not the actor supports 'tags'.")]
+ public bool IsTaggable { get { return scriptTags != null; } }
+
+ [Desc("Add a tag to the actor. Returns true on success, false otherwise (for example the actor may already have the given tag).")]
+ public bool AddTag(string tag)
+ {
+ return IsTaggable && scriptTags.AddTag(tag);
+ }
+
+ [Desc("Remove a tag from the actor. Returns true on success, false otherwise (tag was not present).")]
+ public bool RemoveTag(string tag)
+ {
+ return IsTaggable && scriptTags.RemoveTag(tag);
+ }
+
+ [Desc("Specifies whether or not the actor has a particular tag.")]
+ public bool HasTag(string tag)
+ {
+ return IsTaggable && scriptTags.HasTag(tag);
+ }
}
}
diff --git a/OpenRA.Mods.Common/Traits/ScriptTags.cs b/OpenRA.Mods.Common/Traits/ScriptTags.cs
new file mode 100644
index 0000000000..b692203d43
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/ScriptTags.cs
@@ -0,0 +1,58 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2016 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
+{
+ [Desc("Allows this actor to be 'tagged' with arbitrary strings. Tags must be unique or they will be rejected.")]
+ public class ScriptTagsInfo : UsesInit
+ {
+ object ITraitInfo.Create(ActorInitializer init) { return new ScriptTags(init, this); }
+ }
+
+ public class ScriptTags
+ {
+ readonly HashSet tags = new HashSet();
+
+ public ScriptTags(ActorInitializer init, ScriptTagsInfo info)
+ {
+ if (init.Contains())
+ foreach (var tag in init.Get())
+ tags.Add(tag);
+ }
+
+ public bool AddTag(string tag)
+ {
+ return tags.Add(tag);
+ }
+
+ public bool RemoveTag(string tag)
+ {
+ return tags.Remove(tag);
+ }
+
+ public bool HasTag(string tag)
+ {
+ return tags.Contains(tag);
+ }
+ }
+
+ /// Allows mappers to 'tag' actors with arbitrary strings that may have meaning in their scripts.
+ public class ScriptTagsInit : IActorInit
+ {
+ [FieldFromYamlKey] readonly string[] value = new string[0];
+ public ScriptTagsInit() { }
+ public ScriptTagsInit(string[] init) { value = init; }
+ public string[] Value(World world) { return value; }
+ }
+}
\ No newline at end of file