Move the core of OpenRA.Mods.RA.Scripting to OpenRA.Mods.Common.Scripting

This commit is contained in:
atlimit8
2014-11-25 20:14:03 -06:00
parent 60cf2d2cae
commit 91b5ac5070
26 changed files with 93 additions and 75 deletions

View File

@@ -0,0 +1,82 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using Eluant;
using OpenRA.Primitives;
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Actor")]
public class ActorGlobal : ScriptGlobal
{
public ActorGlobal(ScriptContext context) : base(context) { }
[Desc("Create a new actor. initTable specifies a list of key-value pairs that defines the initial parameters for the actor's traits.")]
public Actor Create(string type, bool addToWorld, LuaTable initTable)
{
var initDict = new TypeDictionary();
// Convert table entries into ActorInits
foreach (var kv in initTable)
{
// Find the requested type
var typeName = kv.Key.ToString();
var initType = Game.modData.ObjectCreator.FindType(typeName + "Init");
if (initType == null)
throw new LuaException("Unknown initializer type '{0}'".F(typeName));
// Cast it up to an IActorInit<T>
var genericType = initType.GetInterfaces()
.First(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IActorInit<>));
var innerType = genericType.GetGenericArguments().First();
var valueType = innerType.IsEnum ? typeof(int) : innerType;
// Try and coerce the table value to the required type
object value;
if (!kv.Value.TryGetClrValue(valueType, out value))
throw new LuaException("Invalid data type for '{0}' (expected '{1}')".F(typeName, valueType.Name));
// Construct the ActorInit. Phew!
var test = initType.GetConstructor(new[] { innerType }).Invoke(new[] { value });
initDict.Add(test);
}
// The actor must be added to the world at the end of the tick
var a = context.World.CreateActor(false, type, initDict);
if (addToWorld)
context.World.AddFrameEndTask(w => w.Add(a));
return a;
}
[Desc("Returns the build time (in ticks) of the requested unit type.")]
public int BuildTime(string type)
{
ActorInfo ai;
if (!context.World.Map.Rules.Actors.TryGetValue(type, out ai))
throw new LuaException("Unknown actor type '{0}'".F(type));
return ai.GetBuildTime();
}
[Desc("Returns the cruise altitude of the requested unit type (zero if it is ground-based).")]
public int CruiseAltitude(string type)
{
ActorInfo ai;
if (!context.World.Map.Rules.Actors.TryGetValue(type, out ai))
throw new LuaException("Unknown actor type '{0}'".F(type));
var pi = ai.Traits.GetOrDefault<ICruiseAltitudeInfo>();
return pi != null ? pi.GetCruiseAltitude().Range : 0;
}
}
}

View File

@@ -0,0 +1,28 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Camera")]
public class CameraGlobal : ScriptGlobal
{
public CameraGlobal(ScriptContext context)
: base(context) { }
[Desc("The center of the visible viewport.")]
public WPos Position
{
get { return context.WorldRenderer.Viewport.CenterPosition; }
set { context.WorldRenderer.Viewport.Center(value); }
}
}
}

View File

@@ -0,0 +1,73 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("CPos")]
public class CPosGlobal : ScriptGlobal
{
public CPosGlobal(ScriptContext context) : base(context) { }
[Desc("Create a new CPos with the specified coordinates.")]
public CPos New(int x, int y) { return new CPos(x, y); }
[Desc("The cell coordinate origin.")]
public CPos Zero { get { return CPos.Zero; } }
}
[ScriptGlobal("CVec")]
public class CVecGlobal : ScriptGlobal
{
public CVecGlobal(ScriptContext context) : base(context) { }
[Desc("Create a new CVec with the specified coordinates.")]
public CVec New(int x, int y) { return new CVec(x, y); }
[Desc("The cell zero-vector.")]
public CVec Zero { get { return CVec.Zero; } }
}
[ScriptGlobal("WPos")]
public class WPosGlobal : ScriptGlobal
{
public WPosGlobal(ScriptContext context) : base(context) { }
[Desc("Create a new WPos with the specified coordinates.")]
public WPos New(int x, int y, int z) { return new WPos(x, y, z); }
[Desc("The world coordinate origin.")]
public WPos Zero { get { return WPos.Zero; } }
}
[ScriptGlobal("WVec")]
public class WVecGlobal : ScriptGlobal
{
public WVecGlobal(ScriptContext context) : base(context) { }
[Desc("Create a new WVec with the specified coordinates.")]
public WVec New(int x, int y, int z) { return new WVec(x, y, z); }
[Desc("The world zero-vector.")]
public WVec Zero { get { return WVec.Zero; } }
}
[ScriptGlobal("WRange")]
public class WRangeGlobal : ScriptGlobal
{
public WRangeGlobal(ScriptContext context) : base(context) { }
[Desc("Create a new WRange.")]
public WRange New(int r) { return new WRange(r); }
[Desc("Create a new WRange by cell distance")]
public WRange FromCells(int numCells) { return WRange.FromCells(numCells); }
}
}

View File

@@ -0,0 +1,47 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using Eluant;
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("DateTime")]
public class DateGlobal : ScriptGlobal
{
public DateGlobal(ScriptContext context)
: base(context) { }
[Desc("True on the 31st of October.")]
public bool IsHalloween
{
get { return DateTime.Today.Month == 10 && DateTime.Today.Day == 31; }
}
[Desc("Get the current game time (in ticks)")]
public int GameTime
{
get { return context.World.WorldTick; }
}
[Desc("Converts the number of seconds into game time (ticks).")]
public int Seconds(int seconds)
{
return seconds * 25;
}
[Desc("Converts the number of minutes into game time (ticks).")]
public int Minutes(int minutes)
{
return Seconds(minutes * 60);
}
}
}

View File

@@ -0,0 +1,125 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using Eluant;
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Map")]
public class MapGlobal : ScriptGlobal
{
SpawnMapActors sma;
public MapGlobal(ScriptContext context) : base(context)
{
sma = context.World.WorldActor.Trait<SpawnMapActors>();
// Register map actors as globals (yuck!)
foreach (var kv in sma.Actors)
context.RegisterMapActor(kv.Key, kv.Value);
}
[Desc("Returns a table of all actors within the requested region, filtered using the specified function.")]
public Actor[] ActorsInCircle(WPos location, WRange radius, LuaFunction filter = null)
{
var actors = context.World.FindActorsInCircle(location, radius);
if (filter != null)
{
actors = actors.Where(a =>
{
using (var f = filter.Call(a.ToLuaValue(context)))
return f.First().ToBoolean();
});
}
return actors.ToArray();
}
[Desc("Returns a table of all actors within the requested rectangle, filtered using the specified function.")]
public Actor[] ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null)
{
var actors = context.World.ActorMap.ActorsInBox(topLeft, bottomRight);
if (filter != null)
{
actors = actors.Where(a =>
{
using (var f = filter.Call(a.ToLuaValue(context)))
return f.First().ToBoolean();
});
}
return actors.ToArray();
}
[Desc("Returns the location of the top-left corner of the map.")]
public WPos TopLeft
{
get { return new WPos(context.World.Map.Bounds.Left * 1024, context.World.Map.Bounds.Top * 1024, 0); }
}
[Desc("Returns the location of the bottom-right corner of the map.")]
public WPos BottomRight
{
get { return new WPos(context.World.Map.Bounds.Right * 1024, context.World.Map.Bounds.Bottom * 1024, 0); }
}
[Desc("Returns a random cell inside the visible region of the map.")]
public CPos RandomCell()
{
return context.World.Map.ChooseRandomCell(context.World.SharedRandom);
}
[Desc("Returns a random cell on the visible border of the map.")]
public CPos RandomEdgeCell()
{
return context.World.Map.ChooseRandomEdgeCell(context.World.SharedRandom);
}
[Desc("Returns the center of a cell in world coordinates.")]
public WPos CenterOfCell(CPos cell)
{
return context.World.Map.CenterOfCell(cell);
}
[Desc("Returns true if there is only one human player.")]
public bool IsSinglePlayer { get { return context.World.LobbyInfo.IsSinglePlayer; } }
[Desc("Returns the difficulty selected by the player before starting the mission.")]
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 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).")]
public Actor NamedActor(string actorName)
{
Actor ret;
if (!sma.Actors.TryGetValue(actorName, out ret))
return null;
if (ret.Destroyed)
return null;
return ret;
}
[Desc("Returns true if actor was originally specified in the map file.")]
public bool IsNamedActor(Actor actor)
{
return actor.ActorID <= sma.LastMapActorID && actor.ActorID > sma.LastMapActorID - sma.Actors.Count;
}
}
}

View File

@@ -0,0 +1,73 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
using Eluant;
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Media")]
public class MediaGlobal : ScriptGlobal
{
World world;
public MediaGlobal(ScriptContext context) : base(context)
{
world = context.World;
}
[Desc("Play an announcer voice listed in notifications.yaml")]
public void PlaySpeechNotification(Player player, string notification)
{
Sound.PlayNotification(world.Map.Rules, player, "Speech", notification, player != null ? player.Country.Race : null);
}
[Desc("Play a sound listed in notifications.yaml")]
public void PlaySoundNotification(Player player, string notification)
{
Sound.PlayNotification(world.Map.Rules, player, "Sounds", notification, player != null ? player.Country.Race : null);
}
Action onComplete;
[Desc("Play a VQA video including the file extension.")]
public void PlayMovieFullscreen(string movie, LuaFunction func = null)
{
if (func != null)
{
var f = func.CopyReference() as LuaFunction;
onComplete = () =>
{
try
{
using (f)
f.Call();
}
catch (LuaException e)
{
context.FatalError(e.Message);
}
};
}
else
onComplete = () => { };
Media.PlayFMVFullscreen(world, movie, onComplete);
}
[Desc("Display a text message to the player.")]
public void DisplayMessage(string text, string prefix = "Mission") // TODO: expose HSLColor to Lua and add as parameter
{
if (string.IsNullOrEmpty(text))
return;
Game.AddChatLine(Color.White, prefix, text);
}
}
}

View File

@@ -0,0 +1,39 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using Eluant;
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Player")]
public class PlayerGlobal : ScriptGlobal
{
public PlayerGlobal(ScriptContext context) : base(context) { }
[Desc("Returns the player with the specified internal name, or nil if a match is not found.")]
public Player GetPlayer(string name)
{
return context.World.Players.FirstOrDefault(p => p.InternalName == name);
}
[Desc("Returns a table of players filtered by the specified function.")]
public Player[] GetPlayers(LuaFunction filter)
{
return context.World.Players
.Where(p =>
{
using (var f = filter.Call(p.ToLuaValue(context)))
return f.First().ToBoolean();
}).ToArray();
}
}
}

View File

@@ -0,0 +1,426 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using Eluant;
using OpenRA.Effects;
using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Trigger")]
public class TriggerGlobal : ScriptGlobal
{
public TriggerGlobal(ScriptContext context) : base(context) { }
public static ScriptTriggers GetScriptTriggers(Actor a)
{
var events = a.TraitOrDefault<ScriptTriggers>();
if (events == null)
throw new LuaException("Actor '{0}' requires the ScriptTriggers trait before attaching a trigger".F(a.Info.Name));
return events;
}
[Desc("Call a function after a specified delay. The callback function will be called as func().")]
public void AfterDelay(int delay, LuaFunction func)
{
var f = func.CopyReference() as LuaFunction;
Action doCall = () =>
{
try
{
using (f)
f.Call();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
context.World.AddFrameEndTask(w => w.Add(new DelayedAction(delay, doCall)));
}
[Desc("Call a function each tick that the actor is idle. " +
"The callback function will be called as func(Actor self).")]
public void OnIdle(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnIdle, func, context);
}
[Desc("Call a function when the actor is damaged. The callback " +
"function will be called as func(Actor self, Actor attacker).")]
public void OnDamaged(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnDamaged, func, context);
}
[Desc("Call a function when the actor is killed. The callback " +
"function will be called as func(Actor self, Actor killer).")]
public void OnKilled(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnKilled, func, context);
}
[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(Actor[] actors, LuaFunction func)
{
var group = actors.ToList();
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberKilled = m =>
{
try
{
group.Remove(m);
if (!group.Any())
{
copy.Call();
copy.Dispose();
}
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
foreach (var a in group)
GetScriptTriggers(a).OnKilledInternal += OnMemberKilled;
}
[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(Actor[] actors, LuaFunction func)
{
var called = false;
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberKilled = m =>
{
try
{
if (called)
return;
using (var killed = m.ToLuaValue(context))
copy.Call(killed).Dispose();
copy.Dispose();
called = true;
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
foreach (var a in actors)
GetScriptTriggers(a).OnKilledInternal += OnMemberKilled;
}
[Desc("Call a function when this actor produces another actor. " +
"The callback function will be called as func(Actor producer, Actor produced).")]
public void OnProduction(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnProduction, func, context);
}
[Desc("Call a function when this player completes all primary objectives. " +
"The callback function will be called as func(Player player).")]
public void OnPlayerWon(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerWon, func, context);
}
[Desc("Call a function when this player fails any primary objective. " +
"The callback function will be called as func(Player player).")]
public void OnPlayerLost(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerLost, func, context);
}
[Desc("Call a function when this player is assigned a new objective. " +
"The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveAdded(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveAdded, func, context);
}
[Desc("Call a function when this player completes an objective. " +
"The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveCompleted(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveCompleted, func, context);
}
[Desc("Call a function when this player fails an objective. " +
"The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveFailed(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveFailed, func, context);
}
[Desc("Call a function when this actor is added to the world. " +
"The callback function will be called as func(Actor self).")]
public void OnAddedToWorld(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnAddedToWorld, func, context);
}
[Desc("Call a function when this actor is removed from the world. " +
"The callback function will be called as func(Actor self).")]
public void OnRemovedFromWorld(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnRemovedFromWorld, func, context);
}
[Desc("Call a function when all of the actors in a group have been removed from the world. " +
"The callback function will be called as func().")]
public void OnAllRemovedFromWorld(Actor[] actors, LuaFunction func)
{
var group = actors.ToList();
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberRemoved = m =>
{
try
{
group.Remove(m);
if (!group.Any())
{
copy.Call().Dispose();
copy.Dispose();
}
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
foreach (var a in group)
GetScriptTriggers(a).OnRemovedInternal += OnMemberRemoved;
}
[Desc("Call a function when this actor is captured. The callback function " +
"will be called as func(Actor self, Actor captor, Player oldOwner, Player newOwner).")]
public void OnCapture(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnCapture, func, context);
}
[Desc("Call a function when this actor is killed or captured. " +
"The callback function will be called as func().")]
public void OnKilledOrCaptured(Actor a, LuaFunction func)
{
var called = false;
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnKilledOrCaptured = m =>
{
try
{
if (called)
return;
copy.Call().Dispose();
copy.Dispose();
called = true;
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
GetScriptTriggers(a).OnCapturedInternal += OnKilledOrCaptured;
GetScriptTriggers(a).OnKilledInternal += OnKilledOrCaptured;
}
[Desc("Call a function when all of the actors in a group have been killed or captured. " +
"The callback function will be called as func().")]
public void OnAllKilledOrCaptured(Actor[] actors, LuaFunction func)
{
var group = actors.ToList();
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberKilledOrCaptured = m =>
{
try
{
if (!group.Contains(m))
return;
group.Remove(m);
if (!group.Any())
{
copy.Call().Dispose();
copy.Dispose();
}
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
foreach (var a in group)
{
GetScriptTriggers(a).OnCapturedInternal += OnMemberKilledOrCaptured;
GetScriptTriggers(a).OnKilledInternal += OnMemberKilledOrCaptured;
}
}
[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(CPos[] cells, LuaFunction func)
{
var triggerId = 0;
var onEntry = (LuaFunction)func.CopyReference();
Action<Actor> invokeEntry = a =>
{
try
{
using (var luaActor = a.ToLuaValue(context))
using (var id = triggerId.ToLuaValue(context))
onEntry.Call(luaActor, id).Dispose();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
triggerId = context.World.ActorMap.AddCellTrigger(cells, invokeEntry, null);
return triggerId;
}
[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(CPos[] cells, LuaFunction func)
{
var triggerId = 0;
var onExit = (LuaFunction)func.CopyReference();
Action<Actor> invokeExit = a =>
{
try
{
using (var luaActor = a.ToLuaValue(context))
using (var id = triggerId.ToLuaValue(context))
onExit.Call(luaActor, id).Dispose();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
triggerId = context.World.ActorMap.AddCellTrigger(cells, null, invokeExit);
return triggerId;
}
[Desc("Removes a previously created footprint trigger.")]
public void RemoveFootprintTrigger(int id)
{
context.World.ActorMap.RemoveCellTrigger(id);
}
[Desc("Call a function when an actor enters this range." +
"Returns the trigger id for later removal using RemoveProximityTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
public int OnEnteredProximityTrigger(WPos pos, WRange range, LuaFunction func)
{
var triggerId = 0;
var onEntry = (LuaFunction)func.CopyReference();
Action<Actor> invokeEntry = a =>
{
try
{
using (var luaActor = a.ToLuaValue(context))
using (var id = triggerId.ToLuaValue(context))
onEntry.Call(luaActor, id).Dispose();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
triggerId = context.World.ActorMap.AddProximityTrigger(pos, range, invokeEntry, null);
return triggerId;
}
[Desc("Call a function when an actor leaves this range." +
"Returns the trigger id for later removal using RemoveProximityTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
public int OnExitedProximityTrigger(WPos pos, WRange range, LuaFunction func)
{
var triggerId = 0;
var onExit = (LuaFunction)func.CopyReference();
Action<Actor> invokeExit = a =>
{
try
{
using (var luaActor = a.ToLuaValue(context))
using (var id = triggerId.ToLuaValue(context))
onExit.Call(luaActor, id).Dispose();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
triggerId = context.World.ActorMap.AddProximityTrigger(pos, range, null, invokeExit);
return triggerId;
}
[Desc("Removes a previously created proximitry trigger.")]
public void RemoveProximityTrigger(int id)
{
context.World.ActorMap.RemoveProximityTrigger(id);
}
[Desc("Call a function when this actor is infiltrated. The callback function " +
"will be called as func(Actor self, Actor infiltrator).")]
public void OnInfiltrated(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnInfiltrated, func, context);
}
[Desc("Removes all triggers from this actor." +
"Note that the removal will only take effect at the end of a tick, " +
"so you must not add new triggers at the same time that you are calling this function.")]
public void ClearAll(Actor a)
{
GetScriptTriggers(a).ClearAll();
}
[Desc("Removes the specified trigger from this actor." +
"Note that the removal will only take effect at the end of a tick, " +
"so you must not add new triggers at the same time that you are calling this function.")]
public void Clear(Actor a, string triggerName)
{
var trigger = (Trigger)Enum.Parse(typeof(Trigger), triggerName);
GetScriptTriggers(a).Clear(trigger);
}
}
}

View File

@@ -0,0 +1,94 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using Eluant;
using OpenRA.Scripting;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Scripting
{
[ScriptGlobal("Utils")]
public class UtilsGlobal : ScriptGlobal
{
public UtilsGlobal(ScriptContext context) : base(context) { }
[Desc("Calls a function on every element in a collection.")]
public void Do(LuaValue[] collection, LuaFunction func)
{
foreach (var c in collection)
func.Call(c).Dispose();
}
[Desc("Returns true if func returns true for any element in a collection.")]
public bool Any(LuaValue[] collection, LuaFunction func)
{
foreach (var c in collection)
{
using (var ret = func.Call(c))
{
var result = ret.FirstOrDefault();
if (result != null && result.ToBoolean())
return true;
}
}
return false;
}
[Desc("Returns true if func returns true for all elements in a collection.")]
public bool All(LuaValue[] collection, LuaFunction func)
{
foreach (var c in collection)
{
using (var ret = func.Call(c))
{
var result = ret.FirstOrDefault();
if (result == null || !result.ToBoolean())
return false;
}
}
return true;
}
[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();
for (var i = numElements; i <= table.Count; i++)
t.Add(t.Count + 1, table[i]);
return t;
}
[Desc("Returns a random value from a collection.")]
public LuaValue Random(LuaValue[] collection)
{
return collection.Random(context.World.SharedRandom);
}
[Desc("Expands the given footprint one step along the coordinate axes, and (if requested) diagonals.")]
public CPos[] ExpandFootprint(CPos[] footprint, bool allowDiagonal)
{
return Util.ExpandFootprint(footprint, allowDiagonal).ToArray();
}
[Desc("Returns a random integer x in the range low &lt;= x &lt; high.")]
public int RandomInteger(int low, int high)
{
if (high <= low)
return low;
return context.World.SharedRandom.Next(low, high);
}
}
}