diff --git a/OpenRA.Game/Scripting/ScriptTypes.cs b/OpenRA.Game/Scripting/ScriptTypes.cs index 191ae0a183..f388140e26 100644 --- a/OpenRA.Game/Scripting/ScriptTypes.cs +++ b/OpenRA.Game/Scripting/ScriptTypes.cs @@ -164,14 +164,5 @@ namespace OpenRA.Scripting throw new InvalidOperationException("Cannot convert type '{0}' to Lua. Class must implement IScriptBindable.".F(obj.GetType())); } - - public static LuaTable ToLuaTable(this IEnumerable collection, ScriptContext context) - { - var i = 1; - var table = context.CreateTable(); - foreach (var x in collection) - table.Add(i++, x.ToLuaValue(context)); - return table; - } } } diff --git a/OpenRA.Mods.RA/Scripting/Global/MapGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/MapGlobal.cs index 6c874430b5..2714bce6bc 100644 --- a/OpenRA.Mods.RA/Scripting/Global/MapGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/MapGlobal.cs @@ -29,35 +29,37 @@ namespace OpenRA.Mods.RA.Scripting } [Desc("Returns a table of all actors within the requested region, filtered using the specified function.")] - public LuaTable ActorsInCircle(WPos location, WRange radius, LuaFunction filter = null) + public Actor[] ActorsInCircle(WPos location, WRange radius, LuaFunction filter = null) { - var actors = context.World.FindActorsInCircle(location, radius) - .Select(a => a.ToLuaValue(context)); + var actors = context.World.FindActorsInCircle(location, radius); if (filter != null) + { actors = actors.Where(a => { - using (var f = filter.Call(a)) + using (var f = filter.Call(a.ToLuaValue(context))) return f.First().ToBoolean(); }); + } - return actors.ToLuaTable(context); + return actors.ToArray(); } [Desc("Returns a table of all actors within the requested rectangle, filtered using the specified function.")] - public LuaTable ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null) + public Actor[] ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null) { - var actors = context.World.ActorMap.ActorsInBox(topLeft, bottomRight) - .Select(a => a.ToLuaValue(context)); + var actors = context.World.ActorMap.ActorsInBox(topLeft, bottomRight); if (filter != null) + { actors = actors.Where(a => { - using (var f = filter.Call(a)) + using (var f = filter.Call(a.ToLuaValue(context))) return f.First().ToBoolean(); }); + } - return actors.ToLuaTable(context); + return actors.ToArray(); } [Desc("Returns the location of the top-left corner of the map.")] @@ -91,13 +93,7 @@ namespace OpenRA.Mods.RA.Scripting public string Difficulty { get { return context.World.LobbyInfo.GlobalSettings.Difficulty; } } [Desc("Returns a table of all the actors that were specified in the map file.")] - public LuaTable NamedActors - { - get - { - return sma.Actors.Values.ToLuaTable(context); - } - } + public Actor[] NamedActors { get { return sma.Actors.Values.ToArray(); } } [Desc("Returns the actor that was specified with a given name in " + "the map file (or nil, if the actor is dead or not found).")] diff --git a/OpenRA.Mods.RA/Scripting/Global/PlayerGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/PlayerGlobal.cs index f834cfc355..92416040e0 100644 --- a/OpenRA.Mods.RA/Scripting/Global/PlayerGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/PlayerGlobal.cs @@ -25,17 +25,14 @@ namespace OpenRA.Scripting } [Desc("Returns a table of players filtered by the specified function.")] - public LuaTable GetPlayers(LuaFunction filter) + public Player[] GetPlayers(LuaFunction filter) { - var players = context.World.Players - .Select(p => p.ToLuaValue(context)) - .Where(a => + return context.World.Players + .Where(p => { - using (var f = filter.Call(a)) + using (var f = filter.Call(p.ToLuaValue(context))) return f.First().ToBoolean(); - }); - - return players.ToLuaTable(context); + }).ToArray(); } } } diff --git a/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs index 1f2994118e..814ff804c8 100644 --- a/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs @@ -72,51 +72,36 @@ namespace OpenRA.Mods.RA.Scripting "while the last one will be their destination. If actionFunc is given, " + "it will be executed once a unit has reached its destination. actionFunc " + "will be called as actionFunc(Actor actor)")] - public LuaTable Reinforce(Player owner, LuaTable actorTypes, LuaTable entryPath, int interval = 25, LuaFunction actionFunc = null) + public Actor[] Reinforce(Player owner, string[] actorTypes, CPos[] entryPath, int interval = 25, LuaFunction actionFunc = null) { var actors = new List(); - for (var i = 1; i <= actorTypes.Count; i++) + for (var i = 0; i < actorTypes.Length; i++) { - string actorType; - if (!(actorTypes[i].TryGetClrValue(out actorType))) - throw new LuaException("Invalid data in actorTypes array"); - - CPos entry, next = new CPos(); - if (!(entryPath[1].TryGetClrValue(out entry) - && (entryPath.Count < 2 || entryPath[2].TryGetClrValue(out next)))) - throw new LuaException("Invalid data in entryPath array"); - - var actor = CreateActor(owner, actorType, false, entry, entryPath.Count > 1 ? next : (CPos?)null); + var af = actionFunc != null ? actionFunc.CopyReference() as LuaFunction : null; + var actor = CreateActor(owner, actorTypes[i], false, entryPath[0], entryPath.Length > 1 ? entryPath[1] : (CPos?)null); actors.Add(actor); - var ep = entryPath.CopyReference() as LuaTable; - var af = actionFunc != null ? actionFunc.CopyReference() as LuaFunction : null; - - var actionDelay = (i - 1) * interval; + var actionDelay = i * interval; Action actorAction = () => { context.World.Add(actor); - for (var j = 2; j <= ep.Count; j++) - { - CPos wpt; - if (!(ep[j].TryGetClrValue(out wpt))) - throw new LuaException("Invalid data in entryPath array"); - - Move(actor, wpt); - } - ep.Dispose(); + for (var j = 1; j < entryPath.Length; j++) + Move(actor, entryPath[j]); if (af != null) + { actor.QueueActivity(new CallFunc(() => { af.Call(actor.ToLuaValue(context)); af.Dispose(); })); + } }; context.World.AddFrameEndTask(w => w.Add(new DelayedAction(actionDelay, actorAction))); } - return actors.Select(a => a.ToLuaValue(context)).ToLuaTable(context); + + return actors.ToArray(); } [Desc("Send reinforcements in a transport. A transport can be a ground unit (APC etc.), ships and aircraft. " + @@ -127,48 +112,32 @@ namespace OpenRA.Mods.RA.Scripting "been supplied. Afterwards, the transport will follow the exitPath and leave the map, " + "unless a custom exitFunc has been supplied. actionFunc will be called as " + "actionFunc(Actor transport, Actor[] cargo). exitFunc will be called as exitFunc(Actor transport).")] - public LuaTable ReinforceWithTransport(Player owner, string actorType, LuaTable cargoTypes, LuaTable entryPath, LuaTable exitPath = null, + public LuaTable ReinforceWithTransport(Player owner, string actorType, string[] cargoTypes, CPos[] entryPath, CPos[] exitPath = null, LuaFunction actionFunc = null, LuaFunction exitFunc = null) { - CPos entry, next = new CPos(); - if (!(entryPath[1].TryGetClrValue(out entry) - && (entryPath.Count < 2 || entryPath[2].TryGetClrValue(out next)))) - throw new LuaException("Invalid data in entryPath array"); - - var transport = CreateActor(owner, actorType, true, entry, entryPath.Count > 1 ? next : (CPos?)null); + var transport = CreateActor(owner, actorType, true, entryPath[0], entryPath.Length > 1 ? entryPath[1] : (CPos?)null); var cargo = transport.TraitOrDefault(); - var passengers = context.CreateTable(); - + var passengers = new List(); if (cargo != null && cargoTypes != null) { - for (var i = 1; i <= cargoTypes.Count; i++) + foreach (var cargoType in cargoTypes) { - string cargoType; - if (!(cargoTypes [i].TryGetClrValue(out cargoType))) - throw new LuaException("Invalid data in cargoTypes array"); - var passenger = CreateActor(owner, cargoType, false); - passengers.Add(passengers.Count + 1, passenger.ToLuaValue(context)); + passengers.Add(passenger); cargo.Load(transport, passenger); } } - for (var i = 2; i <= entryPath.Count; i++) - { - CPos wpt; - if (!(entryPath[i].TryGetClrValue(out wpt))) - throw new LuaException("Invalid data in entryPath array"); - - Move(transport, wpt); - } + for (var i = 1; i < entryPath.Length; i++) + Move(transport, entryPath[i]); if (actionFunc != null) { var af = actionFunc.CopyReference() as LuaFunction; transport.QueueActivity(new CallFunc(() => { - af.Call(transport.ToLuaValue(context), passengers); + af.Call(transport.ToLuaValue(context), passengers.ToArray().ToLuaValue(context)); af.Dispose(); })); } @@ -181,11 +150,13 @@ namespace OpenRA.Mods.RA.Scripting transport.QueueActivity(new HeliLand(true)); transport.QueueActivity(new Wait(15)); } + if (cargo != null) { transport.QueueActivity(new UnloadCargo(transport, true)); transport.QueueActivity(new WaitFor(() => cargo.IsEmpty(transport))); } + transport.QueueActivity(new Wait(heli != null ? 50 : 25)); } @@ -200,20 +171,15 @@ namespace OpenRA.Mods.RA.Scripting } else if (exitPath != null) { - for (var i = 1; i <= exitPath.Count; i++) - { - CPos wpt; - if (!(exitPath[i].TryGetClrValue(out wpt))) - throw new LuaException("Invalid data in exitPath array."); - + foreach (var wpt in exitPath) Move(transport, wpt); - } + transport.QueueActivity(new RemoveSelf()); } var ret = context.CreateTable(); ret.Add(1, transport.ToLuaValue(context)); - ret.Add(2, passengers); + ret.Add(2, passengers.ToArray().ToLuaValue(context)); return ret; } } diff --git a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs index b912d66db1..c4bd716d91 100644 --- a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs @@ -75,18 +75,9 @@ namespace OpenRA.Mods.RA.Scripting [Desc("Call a function when all of the actors in a group are killed. The callback " + "function will be called as func().")] - public void OnAllKilled(LuaTable actors, LuaFunction func) + public void OnAllKilled(Actor[] actors, LuaFunction func) { - var group = new List(); - foreach (var kv in actors) - { - Actor actor; - if (!kv.Value.TryGetClrValue(out actor)) - throw new LuaException("OnAllKilled requires a table of int,Actor pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name)); - - group.Add(actor); - } - + var group = actors.ToList(); var copy = (LuaFunction)func.CopyReference(); Action OnMemberKilled = m => { @@ -104,18 +95,8 @@ namespace OpenRA.Mods.RA.Scripting [Desc("Call a function when one of the actors in a group is killed. The callback " + "function will be called as func(Actor killed).")] - public void OnAnyKilled(LuaTable actors, LuaFunction func) + public void OnAnyKilled(Actor[] actors, LuaFunction func) { - var group = new List(); - foreach (var kv in actors) - { - Actor actor; - if (!kv.Value.TryGetClrValue(out actor)) - throw new LuaException("OnAnyKilled requires a table of int,Actor pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name)); - - group.Add(actor); - } - var called = false; var copy = (LuaFunction)func.CopyReference(); Action OnMemberKilled = m => @@ -130,7 +111,7 @@ namespace OpenRA.Mods.RA.Scripting called = true; }; - foreach (var a in group) + foreach (var a in actors) GetScriptTriggers(a).OnKilledInternal += OnMemberKilled; } @@ -197,25 +178,10 @@ namespace OpenRA.Mods.RA.Scripting GetScriptTriggers(a).RegisterCallback(Trigger.OnCapture, func, context); } - static CPos[] MakeCellFootprint(LuaTable table) - { - var cells = new List(); - foreach (var kv in table) - { - CPos cell; - if (!kv.Value.TryGetClrValue(out cell)) - throw new LuaException("Cell footprints must be specified as a table of int,Cell pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name)); - - cells.Add(cell); - } - - return cells.ToArray(); - } - [Desc("Call a function when a ground-based actor enters this cell footprint." + "Returns the trigger id for later removal using RemoveFootprintTrigger(int id)." + "The callback function will be called as func(Actor a, int id).")] - public int OnEnteredFootprint(LuaTable cells, LuaFunction func) + public int OnEnteredFootprint(CPos[] cells, LuaFunction func) { var triggerId = 0; var onEntry = (LuaFunction)func.CopyReference(); @@ -226,7 +192,7 @@ namespace OpenRA.Mods.RA.Scripting onEntry.Call(luaActor, id).Dispose(); }; - triggerId = context.World.ActorMap.AddCellTrigger(MakeCellFootprint(cells), invokeEntry, null); + triggerId = context.World.ActorMap.AddCellTrigger(cells, invokeEntry, null); return triggerId; } @@ -234,7 +200,7 @@ namespace OpenRA.Mods.RA.Scripting [Desc("Call a function when a ground-based actor leaves this cell footprint." + "Returns the trigger id for later removal using RemoveFootprintTrigger(int id)." + "The callback function will be called as func(Actor a, int id).")] - public int OnExitedFootprint(LuaTable cells, LuaFunction func) + public int OnExitedFootprint(CPos[] cells, LuaFunction func) { var triggerId = 0; var onExit = (LuaFunction)func.CopyReference(); @@ -245,7 +211,7 @@ namespace OpenRA.Mods.RA.Scripting onExit.Call(luaActor, id).Dispose(); }; - triggerId = context.World.ActorMap.AddCellTrigger(MakeCellFootprint(cells), null, invokeExit); + triggerId = context.World.ActorMap.AddCellTrigger(cells, null, invokeExit); return triggerId; } diff --git a/OpenRA.Mods.RA/Scripting/Global/UtilsGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/UtilsGlobal.cs index bfa1b49e8a..2b9056c40c 100644 --- a/OpenRA.Mods.RA/Scripting/Global/UtilsGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/UtilsGlobal.cs @@ -19,19 +19,19 @@ namespace OpenRA.Mods.RA.Scripting { public UtilsGlobal(ScriptContext context) : base(context) { } - [Desc("Calls a function on every value in table.")] - public void Do(LuaTable table, LuaFunction func) + [Desc("Calls a function on every element in a collection.")] + public void Do(LuaValue[] collection, LuaFunction func) { - foreach (var kv in table) - func.Call(kv.Value).Dispose(); + foreach (var c in collection) + func.Call(c).Dispose(); } - [Desc("Returns true if func returns true for any value in table.")] - public bool Any(LuaTable table, LuaFunction func) + [Desc("Returns true if func returns true for any element in a collection.")] + public bool Any(LuaValue[] collection, LuaFunction func) { - foreach (var kv in table) + foreach (var c in collection) { - using (var ret = func.Call(kv.Value)) + using (var ret = func.Call(c)) { var result = ret.FirstOrDefault(); if (result != null && result.ToBoolean()) @@ -42,12 +42,12 @@ namespace OpenRA.Mods.RA.Scripting return false; } - [Desc("Returns true if func returns true for all values in table.")] - public bool All(LuaTable table, LuaFunction func) + [Desc("Returns true if func returns true for all elements in a collection.")] + public bool All(LuaValue[] collection, LuaFunction func) { - foreach (var kv in table) + foreach (var c in collection) { - using (var ret = func.Call(kv.Value)) + using (var ret = func.Call(c)) { var result = ret.FirstOrDefault(); if (result == null || !result.ToBoolean()) @@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA.Scripting return true; } - [Desc("Skips over the first numElements members of the array and returns the rest.")] + [Desc("Skips over the first numElements members of a table and return the rest.")] public LuaTable Skip(LuaTable table, int numElements) { var t = context.CreateTable(); @@ -69,26 +69,16 @@ namespace OpenRA.Mods.RA.Scripting return t; } - [Desc("Returns a random value from table.")] - public LuaValue Random(LuaTable table) + [Desc("Returns a random value from a collection.")] + public LuaValue Random(LuaValue[] collection) { - return table.Values.Random(context.World.SharedRandom); + return collection.Random(context.World.SharedRandom); } [Desc("Expands the given footprint one step along the coordinate axes, and (if requested) diagonals.")] - public LuaTable ExpandFootprint(LuaTable cells, bool allowDiagonal) + public CPos[] ExpandFootprint(CPos[] footprint, bool allowDiagonal) { - var footprint = cells.Values.Select(c => - { - CPos cell; - if (!c.TryGetClrValue(out cell)) - throw new LuaException("ExpandFootprint only accepts a table of CPos"); - - return cell; - }); - - var expanded = Traits.Util.ExpandFootprint(footprint, allowDiagonal); - return expanded.ToLuaTable(context); + return Traits.Util.ExpandFootprint(footprint, allowDiagonal).ToArray(); } [Desc("Returns a random integer x in the range low <= x < high.")] diff --git a/OpenRA.Mods.RA/Scripting/Properties/PlayerProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/PlayerProperties.cs index ee1e52a064..b43ab9b491 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/PlayerProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/PlayerProperties.cs @@ -26,11 +26,11 @@ namespace OpenRA.Mods.RA.Scripting public string Name { get { return player.PlayerName; } } [Desc("Returns an array of actors representing all ground attack units of this player.")] - public LuaTable GetGroundAttackers() + public Actor[] GetGroundAttackers() { return player.World.ActorsWithTrait().Select(a => a.Actor) .Where(a => a.Owner == player && !a.IsDead() && a.IsInWorld && a.HasTrait()) - .Select(a => a.ToLuaValue(context)).ToLuaTable(context); + .ToArray(); } } }