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