Move the core of OpenRA.Mods.RA.Scripting to OpenRA.Mods.Common.Scripting
This commit is contained in:
82
OpenRA.Mods.Common/Scripting/Global/ActorGlobal.cs
Normal file
82
OpenRA.Mods.Common/Scripting/Global/ActorGlobal.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
OpenRA.Mods.Common/Scripting/Global/CameraGlobal.cs
Normal file
28
OpenRA.Mods.Common/Scripting/Global/CameraGlobal.cs
Normal 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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
73
OpenRA.Mods.Common/Scripting/Global/CoordinateGlobals.cs
Normal file
73
OpenRA.Mods.Common/Scripting/Global/CoordinateGlobals.cs
Normal 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); }
|
||||
}
|
||||
}
|
||||
47
OpenRA.Mods.Common/Scripting/Global/DateTimeGlobal.cs
Normal file
47
OpenRA.Mods.Common/Scripting/Global/DateTimeGlobal.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
125
OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs
Normal file
125
OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs
Normal file
73
OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
OpenRA.Mods.Common/Scripting/Global/PlayerGlobal.cs
Normal file
39
OpenRA.Mods.Common/Scripting/Global/PlayerGlobal.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
426
OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs
Normal file
426
OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
OpenRA.Mods.Common/Scripting/Global/UtilsGlobal.cs
Normal file
94
OpenRA.Mods.Common/Scripting/Global/UtilsGlobal.cs
Normal 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 <= x < high.")]
|
||||
public int RandomInteger(int low, int high)
|
||||
{
|
||||
if (high <= low)
|
||||
return low;
|
||||
|
||||
return context.World.SharedRandom.Next(low, high);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user