From 9500a1168999c85107d26cd53c4994d52cc29276 Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Sun, 26 Jan 2014 12:53:52 +0100 Subject: [PATCH 1/8] Add Actor.ReturnToBase --- mods/common/lua/actor.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/common/lua/actor.lua b/mods/common/lua/actor.lua index a676f16db2..ba750c06de 100644 --- a/mods/common/lua/actor.lua +++ b/mods/common/lua/actor.lua @@ -178,3 +178,7 @@ end Actor.Trait = function(actor, className) return Internal.Trait(actor, className) end + +Actor.ReturnToBase = function(actor, airfield) + actor:QueueActivity(OpenRA.New("ReturnToBase", { actor, airfield })) +end From 43e386a48d6e2dab26c18fc6ccad028364f17af7 Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Tue, 28 Jan 2014 20:54:19 +0100 Subject: [PATCH 2/8] Add Utils.Seconds and Utils.Minutes --- mods/common/lua/utils.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mods/common/lua/utils.lua b/mods/common/lua/utils.lua index eab8cbe6d7..15c376da1c 100644 --- a/mods/common/lua/utils.lua +++ b/mods/common/lua/utils.lua @@ -74,4 +74,13 @@ end Utils.TableToArray = function(luaTable) return Internal.TableToArray(luaTable) -end \ No newline at end of file +end + +Utils.Seconds = function(seconds) + local TicksPerSecond = 25 + return seconds * TicksPerSecond +end + +Utils.Minutes = function(minutes) + return Utils.Seconds(minutes * 60) +end From 5322096dc45ea59ac753342f41b12f591aac99ca Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Tue, 28 Jan 2014 23:06:25 +0100 Subject: [PATCH 3/8] Add Team.Patrol and Actor.Patrol. Fixes #4491. --- .../Scripting/LuaScriptInterface.cs | 6 ++--- mods/common/lua/actor.lua | 22 +++++++++++++++++-- mods/common/lua/team.lua | 12 ++++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs index 56b8671d15..8a6a7f72da 100644 --- a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs +++ b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs @@ -299,12 +299,12 @@ namespace OpenRA.Mods.RA.Scripting } [LuaGlobal] - public void AttackMove(Actor actor, CPos location) + public void AttackMove(Actor actor, CPos location, double nearEnough) { if (actor.HasTrait()) - actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, new Move.Move(location, 0))); + actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, new Move.Move(location, (int)nearEnough))); else - actor.QueueActivity(new Move.Move(location, 0)); + actor.QueueActivity(new Move.Move(location, (int)nearEnough)); } [LuaGlobal] diff --git a/mods/common/lua/actor.lua b/mods/common/lua/actor.lua index ba750c06de..7eb9e650c7 100644 --- a/mods/common/lua/actor.lua +++ b/mods/common/lua/actor.lua @@ -47,8 +47,8 @@ Actor.Teleport = function(actor, location) actor:QueueActivity(OpenRA.New("SimpleTeleport", { location })) end -Actor.AttackMove = function(actor, location) - Internal.AttackMove(actor, location) +Actor.AttackMove = function(actor, location, nearEnough) + Internal.AttackMove(actor, location, nearEnough or 0) end Actor.HeliFly = function(actor, position) @@ -182,3 +182,21 @@ end Actor.ReturnToBase = function(actor, airfield) actor:QueueActivity(OpenRA.New("ReturnToBase", { actor, airfield })) end + +Actor.Patrol = function(actor, waypoints, wait, loop) + Utils.Do(waypoints, function(wpt) + Actor.AttackMove(actor, wpt.Location, 3) + Actor.Wait(actor, wait or 0) + end) + if loop or loop == nil then + Actor.CallFunc(actor, function() Actor.Patrol(actor, waypoints, wait, loop) end) + end +end + +Actor.PatrolUntil = function(actor, waypoints, wait, func) + if func == nil then error("No function specified", 2) end + Actor.Patrol(actor, waypoints, wait, false) + if not func(actor) then + Actor.CallFunc(actor, function() Actor.PatrolUntil(actor, waypoints, wait, func) end) + end +end diff --git a/mods/common/lua/team.lua b/mods/common/lua/team.lua index 6d41af2d23..074e02c076 100644 --- a/mods/common/lua/team.lua +++ b/mods/common/lua/team.lua @@ -18,7 +18,7 @@ Team.AddActorEventHandlers = function(team) Team.InvokeHandlers(team.OnAnyKilled) if Team.AllAreDead(team) then Team.InvokeHandlers(team.OnAllKilled) end end) - + Actor.OnRemovedFromWorld(actor, function() Team.InvokeHandlers(team.OnAnyRemovedFromWorld) if not Team.AnyAreInWorld(team) then Team.InvokeHandlers(team.OnAllRemovedFromWorld) end @@ -58,4 +58,12 @@ end Team.Do = function(team, func) Utils.Do(team.Actors, func) -end \ No newline at end of file +end + +Team.Patrol = function(team, waypoints, wait, loop) + Team.Do(team, function(a) Actor.Patrol(a, waypoints, wait, loop) end) +end + +Team.PatrolUntil = function(team, waypoints, wait, func) + Team.Do(team, function(a) Actor.PatrolUntil(a, waypoints, wait, func) end) +end From b3323869cb18d6b18ea6794d008ae3dab8491e14 Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Mon, 27 Jan 2014 23:27:40 +0100 Subject: [PATCH 4/8] Add Map.FindActorsInCircle and ...InBox, plus related shortcuts --- .../Scripting/LuaScriptInterface.cs | 12 ++++++ mods/common/lua/map.lua | 42 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs index 8a6a7f72da..cf20e6d650 100644 --- a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs +++ b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs @@ -330,5 +330,17 @@ namespace OpenRA.Mods.RA.Scripting { return mapActors[actorName]; } + + [LuaGlobal] + public Actor[] FindActorsInBox(WPos topLeft, WPos bottomRight) + { + return world.FindActorsInBox(topLeft, bottomRight).ToArray(); + } + + [LuaGlobal] + public Actor[] FindActorsInCircle(WPos location, WRange radius) + { + return world.FindActorsInCircle(location, radius).ToArray(); + } } } diff --git a/mods/common/lua/map.lua b/mods/common/lua/map.lua index 1b587cf780..48f4194540 100644 --- a/mods/common/lua/map.lua +++ b/mods/common/lua/map.lua @@ -16,6 +16,48 @@ Map.GetNamedActor = function(actorName) return Internal.GetNamedActor(actorName) end +Map.FindActorsInCircle = function(location, radius, func) + local actors = Internal.FindActorsInCircle(location.CenterPosition, WRange.FromCells(radius)) + return Utils.EnumerableWhere(actors, func) +end + +Map.FindActorsInBox = function(topLeft, bottomRight, func) + local actors = Internal.FindActorsInBox(topLeft.CenterPosition, bottomRight.CenterPosition) + return Utils.EnumerableWhere(actors, func) +end + +Map.__FilterByTrait = function(a, player, trait) + return Actor.Owner(a) == player and Actor.HasTrait(a, trait) +end + +Map.__FilterByTraitAndIdle = function(a, player, trait) + return Map.__FilterByTrait(a, player, trait) and Actor.IsIdle(a) +end + +Map.FindUnitsInCircle = function(player, location, radius) + return Map.FindActorsInCircle(location, radius, function(a) return Map.__FilterByTrait(a, player, "Mobile") end) +end + +Map.FindUnitsInBox = function(player, topLeft, bottomRight) + return Map.FindActorsInBox(topLeft, bottomRight, function(a) return Map.__FilterByTrait(a, player, "Mobile") end) +end + +Map.FindStructuresInCircle = function(player, location, radius) + return Map.FindActorsInCircle(location, radius, function(a) return Map.__FilterByTrait(a, player, "Building") end) +end + +Map.FindStructuresInBox = function(player, topLeft, bottomRight) + return Map.FindActorsInBox(topLeft, bottomRight, function(a) return Map.__FilterByTrait(a, player, "Building") end) +end + +Map.FindIdleUnitsInCircle = function(player, location, radius) + return Map.FindActorsInCircle(location, radius, function(a) return Map.__FilterByTraitAndIdle(a, player, "Mobile") end) +end + +Map.FindIdleUnitsInBox = function(player, topLeft, bottomRight) + return Map.FindActorsInBox(topLeft, bottomRight, function(a) return Map.__FilterByTraitAndIdle(a, player, "Mobile") end) +end + CPos.New = function(x, y) return OpenRA.New("CPos", { { x, "Int32" }, { y, "Int32" } }) end From 42532efd8f87fba5c54446b6519afd4b944aac7d Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Thu, 30 Jan 2014 22:23:09 +0100 Subject: [PATCH 5/8] Replace Lua's for loops with Utils.Do/Team.Do Besides fitting in better with the OpenRA coding style, this also gets rid of some weird timing-related errors I have seen when creating teams with a larger number (6+) of members. (The script would just print 'Error: function' in Team.AddActorEventHandlers. Adding a strategically placed print statement fixed that. Replacing the original for loop with Team.Do did as well) --- mods/common/lua/team.lua | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mods/common/lua/team.lua b/mods/common/lua/team.lua index 074e02c076..f0f9da15c8 100644 --- a/mods/common/lua/team.lua +++ b/mods/common/lua/team.lua @@ -12,7 +12,7 @@ Team.New = function(actors) end Team.AddActorEventHandlers = function(team) - for i, actor in ipairs(team.Actors) do + Team.Do(team, function(actor) Actor.OnKilled(actor, function() Team.InvokeHandlers(team.OnAnyKilled) @@ -23,13 +23,11 @@ Team.AddActorEventHandlers = function(team) Team.InvokeHandlers(team.OnAnyRemovedFromWorld) if not Team.AnyAreInWorld(team) then Team.InvokeHandlers(team.OnAllRemovedFromWorld) end end) - end + end) end Team.InvokeHandlers = function(event) - for i, handler in ipairs(event) do - handler() - end + Utils.Do(event, function(handler) handler() end) end Team.AllAreDead = function(team) From 886efd0b978a33df613f2299bfd38823087d73bc Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Fri, 31 Jan 2014 20:41:47 +0100 Subject: [PATCH 6/8] Add production-related Lua functions --- .../Scripting/LuaScriptInterface.cs | 30 +++++++++++++++++++ mods/cnc/mod.yaml | 1 + mods/common/lua/production.lua | 17 +++++++++++ mods/d2k/mod.yaml | 1 + mods/ra/mod.yaml | 1 + mods/ts/mod.yaml | 1 + 6 files changed, 51 insertions(+) create mode 100644 mods/common/lua/production.lua diff --git a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs index cf20e6d650..1861c770cb 100644 --- a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs +++ b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs @@ -342,5 +342,35 @@ namespace OpenRA.Mods.RA.Scripting { return world.FindActorsInCircle(location, radius).ToArray(); } + + [LuaGlobal] + public void BuildWithSharedQueue(Player player, string unit, double amount) + { + var ri = Rules.Info[unit]; + if (ri == null || !ri.Traits.Contains()) + return; + + var category = ri.Traits.Get().Queue; + + var queue = world.ActorsWithTrait() + .Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category) + .Select(a => a.Trait).FirstOrDefault(); + + if (queue != null) + queue.ResolveOrder(queue.self, Order.StartProduction(queue.self, unit, (int)amount)); + } + + [LuaGlobal] + public void BuildWithPerFactoryQueue(Actor factory, string unit, double amount) + { + if (!factory.HasTrait()) + return; + + var ri = Rules.Info[unit]; + if (ri == null || !ri.Traits.Contains()) + return; + + factory.Trait().ResolveOrder(factory, Order.StartProduction(factory, unit, (int)amount)); + } } } diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index d8deb3b629..82a28d7449 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -180,3 +180,4 @@ LuaScripts: mods/common/lua/reinforcements.lua mods/common/lua/supportpowers.lua mods/common/lua/rules.lua + mods/common/lua/production.lua diff --git a/mods/common/lua/production.lua b/mods/common/lua/production.lua new file mode 100644 index 0000000000..9acef2b6c5 --- /dev/null +++ b/mods/common/lua/production.lua @@ -0,0 +1,17 @@ +Production = { } + +Production.BuildWithSharedQueue = function(player, unit, amount) + Internal.BuildWithSharedQueue(player, unit, amount or 1) +end + +Production.BuildWithPerFactoryQueue = function(factory, unit, amount) + Internal.BuildWithPerFactoryQueue(factory, unit, amount or 1) +end + +Production.SetRallyPoint = function(factory, location) + Actor.Trait(factory, "RallyPoint").rallyPoint = location.Location +end + +Production.SetPrimaryBuilding = function(factory) + Actor.Trait(factory, "PrimaryBuilding"):SetPrimaryProducer(factory, true) +end diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 3615116d7e..2173f2b60a 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -161,3 +161,4 @@ LuaScripts: mods/common/lua/reinforcements.lua mods/common/lua/supportpowers.lua mods/common/lua/rules.lua + mods/common/lua/production.lua diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 99105ce6fe..acf490c4e3 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -177,3 +177,4 @@ LuaScripts: mods/common/lua/reinforcements.lua mods/common/lua/supportpowers.lua mods/common/lua/rules.lua + mods/common/lua/production.lua diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 09bc97b964..6d339fdc35 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -199,3 +199,4 @@ LuaScripts: mods/common/lua/reinforcements.lua mods/common/lua/supportpowers.lua mods/common/lua/rules.lua + mods/common/lua/production.lua From 6be0a263535ab68fbe0f287333e40d52a96e53f6 Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Fri, 31 Jan 2014 23:58:40 +0100 Subject: [PATCH 7/8] Fix OpenRA.RunAfterDelay queuing a null action. Fixes #4512. --- mods/common/lua/openra.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/common/lua/openra.lua b/mods/common/lua/openra.lua index 16f1e02671..9d20c03ff2 100644 --- a/mods/common/lua/openra.lua +++ b/mods/common/lua/openra.lua @@ -10,6 +10,7 @@ OpenRA.New = function(className, args) end OpenRA.RunAfterDelay = function(delay, func) + if func == nil then error("No function specified", 2) end Internal.RunAfterDelay(delay, func) end From 2f9b1459a8217581c566561a3b09c0a4a01f8d02 Mon Sep 17 00:00:00 2001 From: Oliver Brakmann Date: Sat, 1 Feb 2014 00:04:24 +0100 Subject: [PATCH 8/8] Fix OpenRA.GetRandomInteger crashing under certain circumstances OpenRA.GetRandomInteger crashes when the supplied high value is less or equal to the low value. A situation where this might occur is when you try to get a random member of a dynamically generated array that happens to have only a single member. --- mods/common/lua/openra.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mods/common/lua/openra.lua b/mods/common/lua/openra.lua index 9d20c03ff2..1b8b9d9bab 100644 --- a/mods/common/lua/openra.lua +++ b/mods/common/lua/openra.lua @@ -43,7 +43,11 @@ OpenRA.SetWinState = function(player, winState) end OpenRA.GetRandomInteger = function(low, high) - return Internal.GetRandomInteger(low, high) + if high <= low then + return low + else + return Internal.GetRandomInteger(low, high) + end end OpenRA.TakeOre = function(player, amount)