diff --git a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs index 69345ff428..f47ee46e0b 100644 --- a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs +++ b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Collections; using System.Linq; using NLua; using OpenRA.Effects; @@ -49,6 +50,7 @@ namespace OpenRA.Mods.RA.Scripting context.Lua["WorldRenderer"] = wr; context.RegisterObject(this, "Internal", false); context.RegisterType(typeof(WVec), "WVec", true); + context.RegisterType(typeof(CVec), "CVec", true); context.RegisterType(typeof(WPos), "WPos", true); context.RegisterType(typeof(CPos), "CPos", true); context.RegisterType(typeof(WRot), "WRot", true); @@ -146,6 +148,19 @@ namespace OpenRA.Mods.RA.Scripting return ret != null; } + [LuaGlobal] + public object[] ActorsWithTrait(string className) + { + var type = Game.modData.ObjectCreator.FindType(className); + if (type == null) + throw new InvalidOperationException("Cannot locate type: {0}".F(className)); + + var method = typeof(World).GetMethod("ActorsWithTrait"); + var genericMethod = method.MakeGenericMethod(type); + var result = ((IEnumerable)genericMethod.Invoke(world, null)).Cast().ToArray(); + return result; + } + [LuaGlobal] public object TraitInfoOrDefault(string actorType, string className) { @@ -273,5 +288,32 @@ namespace OpenRA.Mods.RA.Scripting { return world.ActorsWithTrait().All(p => p.Actor.Owner != player); } + + [LuaGlobal] + public void AttackMove(Actor actor, CPos location) + { + if (actor.HasTrait()) + actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, new Move.Move(location, 0))); + else + actor.QueueActivity(new Move.Move(location, 0)); + } + + [LuaGlobal] + public int GetRandomInteger(double low, double high) + { + return world.SharedRandom.Next((int)low, (int)high); + } + + [LuaGlobal] + public CPos GetRandomCell() + { + return world.ChooseRandomCell(world.SharedRandom); + } + + [LuaGlobal] + public CPos GetRandomEdgeCell() + { + return world.ChooseRandomEdgeCell(); + } } } diff --git a/mods/cnc/maps/shellmap/shellmap.lua b/mods/cnc/maps/shellmap/shellmap.lua index d47573a29e..ba266799b2 100644 --- a/mods/cnc/maps/shellmap/shellmap.lua +++ b/mods/cnc/maps/shellmap/shellmap.lua @@ -5,7 +5,7 @@ speed = 5 Tick = function() ticks = ticks + 1 local t = (ticks + 45) % (360 * speed) * (math.pi / 180) / speed; - OpenRA.SetViewportCenterPosition(WPos.op_Addition(viewportOrigin, MakeVec(-15360 * math.sin(t), 4096 * math.cos(t)))) + OpenRA.SetViewportCenterPosition(WPos.op_Addition(viewportOrigin, WVec.New(-15360 * math.sin(t), 4096 * math.cos(t)))) end WorldLoaded = function() @@ -16,7 +16,7 @@ WorldLoaded = function() local units = { boat1, boat2, boat3, boat4, lst1, lst2, lst3} for i, unit in ipairs(units) do - LoopTrack(unit, MakePos(8, unit.Location.Y), MakePos(87, unit.Location.Y)) + LoopTrack(unit, CPos.New(8, unit.Location.Y), CPos.New(87, unit.Location.Y)) end end @@ -34,13 +34,4 @@ CreateUnitsInTransport = function(transport, passengerNames) for i, passengerName in ipairs(passengerNames) do cargo:Load(transport, Actor.Create(passengerName, { AddToWorld = false, Owner = owner, Facing = { facing, "Int32" } })) end -end - --- TODO: The standard library should expose CPos.New() etc -MakePos = function(x, y) - return OpenRA.New("CPos", { {x, "Int32"}, {y, "Int32"} }) -end - -MakeVec = function(x, y) - return OpenRA.New("WVec", { {x, "Int32"}, {y, "Int32"}, {0, "Int32"} }) end \ No newline at end of file diff --git a/mods/ra/lua/actor.lua b/mods/ra/lua/actor.lua index 4e50e923b9..328b62bafc 100644 --- a/mods/ra/lua/actor.lua +++ b/mods/ra/lua/actor.lua @@ -24,7 +24,7 @@ Actor.Move = function(actor, location) end Actor.MoveNear = function(actor, location, nearEnough) - actor:QueueActivity(OpenRA.New("Move", { location, Map.GetWRangeFromCells(nearEnough) })) + actor:QueueActivity(OpenRA.New("Move", { location, WRange.FromCells(nearEnough) })) end Actor.ScriptedMove = function(actor, location) @@ -35,6 +35,10 @@ Actor.Teleport = function(actor, location) actor:QueueActivity(OpenRA.New("SimpleTeleport", { location })) end +Actor.AttackMove = function(actor, location) + Internal.AttackMove(actor, location) +end + Actor.HeliFly = function(actor, position) actor:QueueActivity(OpenRA.New("HeliFly", { position })) end @@ -119,6 +123,10 @@ Actor.Facing = function(actor) return Actor.Trait(actor, "IFacing"):get_Facing() end +Actor.IsIdle = function(actor) + return actor.IsIdle +end + Actor.SetStance = function(actor, stance) Internal.SetUnitStance(actor, stance) end @@ -135,6 +143,14 @@ Actor.OnRemovedFromWorld = function(actor, eh) Actor.Trait(actor, "LuaScriptEvents").OnRemovedFromWorld:Add(eh) end +Actor.ActorsWithTrait = function(className) + local ret = { } + for item in Utils.Enumerate(Internal.ActorsWithTrait(className)) do + table.insert(ret, item.Actor) + end + return ret +end + Actor.HasTrait = function(actor, className) return Internal.HasTrait(actor, className) end diff --git a/mods/ra/lua/map.lua b/mods/ra/lua/map.lua index 39ed982234..ae53c5fcd2 100644 --- a/mods/ra/lua/map.lua +++ b/mods/ra/lua/map.lua @@ -4,6 +4,44 @@ Map.GetFacing = function(vec, currentFacing) return Internal.GetFacing(vec, currentFacing) end -Map.GetWRangeFromCells = function(cells) - return Internal.GetWRangeFromCells(cells) -end \ No newline at end of file +Map.GetRandomCell = function() + return Internal.GetRandomCell() +end + +Map.GetRandomEdgeCell = function() + return Internal.GetRandomEdgeCell() +end + +CPos.New = function(x, y) + return OpenRA.New("CPos", { { x, "Int32" }, { y, "Int32" } }) +end + +WPos.New = function(x, y, z) + if z == nil then + z = 0 + end + return OpenRA.New("WPos", { { x, "Int32" }, { y, "Int32" }, { z, "Int32" } }) +end + +WPos.FromCPos = function(location) + return WPos.New(location.X * 1024, location.Y * 1024, 0) +end + +CVec.New = function(x, y) + return OpenRA.New("CVec", { { x, "Int32" }, { y, "Int32" } }) +end + +WVec.New = function(x, y, z) + if z == nil then + z = 0 + end + return OpenRA.New("WVec", { { x, "Int32" }, { y, "Int32" }, { z, "Int32" } }) +end + +WRange.New = function(r) + return OpenRA.New("WRange", { { r, "Int32" } }) +end + +WRange.FromCells = function(cells) + return WRange.New(cells * 1024) +end diff --git a/mods/ra/lua/mission.lua b/mods/ra/lua/mission.lua index 94fca80214..ae942766ea 100644 --- a/mods/ra/lua/mission.lua +++ b/mods/ra/lua/mission.lua @@ -23,8 +23,8 @@ Mission.MissionOver = function(winners, losers, setWinStates) end Mission.GetGroundAttackersOf = function(player) - return Utils.EnumerableWhere(World.Actors, function(actor) - return not Actor.IsDead(actor) and Actor.IsInWorld(actor) and Actor.Owner(actor) == player and Actor.HasTrait(actor, "AttackBase") and Actor.HasTrait(actor, "Mobile") + return Utils.Where(Actor.ActorsWithTrait("AttackBase"), function(actor) + return not Actor.IsDead(actor) and Actor.IsInWorld(actor) and Actor.Owner(actor) == player and Actor.HasTrait(actor, "Mobile") end) end diff --git a/mods/ra/lua/openra.lua b/mods/ra/lua/openra.lua index 64589a1ba1..16f1e02671 100644 --- a/mods/ra/lua/openra.lua +++ b/mods/ra/lua/openra.lua @@ -33,10 +33,18 @@ OpenRA.GetPlayer = function(internalName) return Utils.EnumerableFirstOrNil(World.Players, function(p) return p.InternalName == internalName end) end +OpenRA.GetPlayers = function(func) + return Utils.EnumerableWhere(World.Players, func) +end + OpenRA.SetWinState = function(player, winState) Internal.SetWinState(player, winState) end +OpenRA.GetRandomInteger = function(low, high) + return Internal.GetRandomInteger(low, high) +end + OpenRA.TakeOre = function(player, amount) Actor.Trait(player.PlayerActor, "PlayerResources"):TakeOre(amount) end @@ -67,4 +75,4 @@ end OpenRA.GetCash = function(player) return Actor.Trait(player.PlayerActor, "PlayerResources").Cash -end \ No newline at end of file +end diff --git a/mods/ra/lua/team.lua b/mods/ra/lua/team.lua index f77a0733ed..f81fed4bcc 100644 --- a/mods/ra/lua/team.lua +++ b/mods/ra/lua/team.lua @@ -1,6 +1,6 @@ Team = { } -Team.Create = function(actors) +Team.New = function(actors) local team = { } team.Actors = actors team.OnAllKilled = { } diff --git a/mods/ra/maps/allies-01-classic/mission.lua b/mods/ra/maps/allies-01-classic/mission.lua index c52bf6be7b..86e0198865 100644 --- a/mods/ra/maps/allies-01-classic/mission.lua +++ b/mods/ra/maps/allies-01-classic/mission.lua @@ -134,10 +134,10 @@ WorldLoaded = function() Actor.OnKilled(Lab, LabDestroyed) Actor.OnKilled(OilPump, OilPumpDestroyed) - labGuardsTeam = Team.Create({ LabGuard1, LabGuard2, LabGuard3 }) + labGuardsTeam = Team.New({ LabGuard1, LabGuard2, LabGuard3 }) Team.AddEventHandler(labGuardsTeam.OnAllKilled, LabGuardsKilled) - civiliansTeam = Team.Create({ Civilian1, Civilian2 }) + civiliansTeam = Team.New({ Civilian1, Civilian2 }) RunInitialActivities() diff --git a/mods/ra/maps/allies-02-classic/mission.lua b/mods/ra/maps/allies-02-classic/mission.lua index 1c2ae5d54d..4b5a237368 100644 --- a/mods/ra/maps/allies-02-classic/mission.lua +++ b/mods/ra/maps/allies-02-classic/mission.lua @@ -54,7 +54,7 @@ SendTrucks = function() Actor.Move(truck, TruckExitPoint.Location) Actor.RemoveSelf(truck) end) - local trucksTeam = Team.Create(trucks) + local trucksTeam = Team.New(trucks) Team.AddEventHandler(trucksTeam.OnAllRemovedFromWorld, MissionAccomplished) Team.AddEventHandler(trucksTeam.OnAnyKilled, MissionFailed) end)