Merge pull request #6284 from obrakmann/gdi01-touchup
More Lua API enhancements
This commit is contained in:
@@ -52,12 +52,6 @@ namespace OpenRA.Mods.RA
|
||||
mo.MarkCompleted(self.Owner, objectiveID);
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Surrender")
|
||||
mo.MarkFailed(self.Owner, objectiveID);
|
||||
}
|
||||
|
||||
public void OnPlayerLost(Player player)
|
||||
{
|
||||
Game.Debug("{0} is defeated.".F(player.PlayerName));
|
||||
|
||||
@@ -566,6 +566,7 @@
|
||||
<Compile Include="Warheads\HealthPercentageDamageWarhead.cs" />
|
||||
<Compile Include="Warheads\PerCellDamageWarhead.cs" />
|
||||
<Compile Include="Warheads\SpreadDamageWarhead.cs" />
|
||||
<Compile Include="Scripting\Global\ReinforcementsGlobal.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">
|
||||
@@ -611,4 +612,4 @@ copy "FuzzyLogicLibrary.dll" "$(SolutionDir)"
|
||||
cd "$(SolutionDir)"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace OpenRA.Mods.RA
|
||||
objectives.Insert(newID, new MissionObjective(type, description));
|
||||
|
||||
ObjectiveAdded(player);
|
||||
foreach (var imo in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
|
||||
imo.OnObjectiveAdded(player, newID);
|
||||
foreach (var inou in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
|
||||
inou.OnObjectiveAdded(player, newID);
|
||||
|
||||
return newID;
|
||||
}
|
||||
@@ -90,22 +90,23 @@ namespace OpenRA.Mods.RA
|
||||
if (objectiveID >= objectives.Count || objectives[objectiveID].State == ObjectiveState.Completed)
|
||||
return;
|
||||
|
||||
var inous = player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>();
|
||||
|
||||
objectives[objectiveID].State = ObjectiveState.Completed;
|
||||
foreach (var inou in inous)
|
||||
inou.OnObjectiveCompleted(player, objectiveID);
|
||||
|
||||
if (objectives[objectiveID].Type == ObjectiveType.Primary)
|
||||
{
|
||||
var playerWon = objectives.Where(o => o.Type == ObjectiveType.Primary).All(o => o.State == ObjectiveState.Completed);
|
||||
|
||||
foreach (var imo in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
|
||||
{
|
||||
imo.OnObjectiveCompleted(player, objectiveID);
|
||||
|
||||
if (playerWon)
|
||||
imo.OnPlayerWon(player);
|
||||
}
|
||||
|
||||
if (playerWon)
|
||||
{
|
||||
foreach (var inou in inous)
|
||||
inou.OnPlayerWon(player);
|
||||
|
||||
CheckIfGameIsOver(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,89 +115,118 @@ namespace OpenRA.Mods.RA
|
||||
if (objectiveID >= objectives.Count || objectives[objectiveID].State == ObjectiveState.Failed)
|
||||
return;
|
||||
|
||||
var inous = player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>();
|
||||
|
||||
objectives[objectiveID].State = ObjectiveState.Failed;
|
||||
foreach (var inou in inous)
|
||||
inou.OnObjectiveFailed(player, objectiveID);
|
||||
|
||||
if (objectives[objectiveID].Type == ObjectiveType.Primary)
|
||||
{
|
||||
var playerLost = objectives.Where(o => o.Type == ObjectiveType.Primary).Any(o => o.State == ObjectiveState.Failed);
|
||||
|
||||
foreach (var imo in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
|
||||
{
|
||||
imo.OnObjectiveFailed(player, objectiveID);
|
||||
|
||||
if (playerLost)
|
||||
imo.OnPlayerLost(player);
|
||||
}
|
||||
|
||||
if (playerLost)
|
||||
{
|
||||
foreach (var inou in inous)
|
||||
inou.OnPlayerLost(player);
|
||||
|
||||
CheckIfGameIsOver(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckIfGameIsOver(Player player)
|
||||
{
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
||||
|
||||
var gameOver = ((info.EarlyGameOver && !info.Cooperative && player.WinState != WinState.Undefined) ||
|
||||
(info.EarlyGameOver && info.Cooperative && allies.All(p => p.WinState != WinState.Undefined)) ||
|
||||
players.All(p => p.WinState != WinState.Undefined));
|
||||
|
||||
var gameOver = players.All(p => p.WinState != WinState.Undefined);
|
||||
if (gameOver)
|
||||
{
|
||||
Game.RunAfterDelay(info.GameOverDelay, () =>
|
||||
{
|
||||
player.World.EndGame();
|
||||
player.World.SetPauseState(true);
|
||||
player.World.PauseStateLocked = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPlayerWon(Player player)
|
||||
{
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var enemies = players.Where(p => !p.IsAlliedWith(player));
|
||||
|
||||
if (info.Cooperative)
|
||||
{
|
||||
WinStateCooperative = WinState.Won;
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
||||
|
||||
if (allies.All(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Won))
|
||||
{
|
||||
foreach (var p in allies)
|
||||
{
|
||||
p.WinState = WinState.Won;
|
||||
p.World.OnPlayerWinStateChanged(p);
|
||||
}
|
||||
|
||||
if (info.EarlyGameOver)
|
||||
foreach (var p in enemies)
|
||||
p.PlayerActor.Trait<MissionObjectives>().ForceDefeat(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.WinState = WinState.Won;
|
||||
player.World.OnPlayerWinStateChanged(player);
|
||||
|
||||
if (info.EarlyGameOver)
|
||||
foreach (var p in enemies)
|
||||
p.PlayerActor.Trait<MissionObjectives>().ForceDefeat(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPlayerLost(Player player)
|
||||
{
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var enemies = players.Where(p => !p.IsAlliedWith(player));
|
||||
|
||||
if (info.Cooperative)
|
||||
{
|
||||
WinStateCooperative = WinState.Lost;
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
||||
|
||||
if (allies.Any(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Lost))
|
||||
{
|
||||
foreach (var p in allies)
|
||||
{
|
||||
p.WinState = WinState.Lost;
|
||||
p.World.OnPlayerWinStateChanged(p);
|
||||
}
|
||||
|
||||
if (info.EarlyGameOver)
|
||||
foreach (var p in enemies)
|
||||
p.PlayerActor.Trait<MissionObjectives>().ForceDefeat(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.WinState = WinState.Lost;
|
||||
player.World.OnPlayerWinStateChanged(player);
|
||||
|
||||
if (info.EarlyGameOver)
|
||||
foreach (var p in enemies)
|
||||
{
|
||||
p.WinState = WinState.Won;
|
||||
p.World.OnPlayerWinStateChanged(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ForceDefeat(Player player)
|
||||
{
|
||||
for (var id = 0; id < Objectives.Count; id++)
|
||||
if (Objectives[id].State == ObjectiveState.Incomplete)
|
||||
MarkFailed(player, id);
|
||||
}
|
||||
|
||||
public event Action<Player> ObjectiveAdded = player => { };
|
||||
|
||||
public void OnObjectiveAdded(Player player, int id) {}
|
||||
@@ -206,8 +236,7 @@ namespace OpenRA.Mods.RA
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Surrender")
|
||||
for (var id = 0; id < objectives.Count; id++)
|
||||
MarkFailed(self.Owner, id);
|
||||
ForceDefeat(self.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,5 +65,8 @@ namespace OpenRA.Scripting
|
||||
|
||||
[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); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Eluant;
|
||||
using OpenRA.Scripting;
|
||||
@@ -43,6 +44,34 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
return actors.ToLuaTable(context);
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
var actors = context.World.ActorMap.ActorsInBox(topLeft, bottomRight)
|
||||
.Select(a => a.ToLuaValue(context));
|
||||
|
||||
if (filter != null)
|
||||
actors = actors.Where(a =>
|
||||
{
|
||||
using (var f = filter.Call(a))
|
||||
return f.First().ToBoolean();
|
||||
});
|
||||
|
||||
return actors.ToLuaTable(context);
|
||||
}
|
||||
|
||||
[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()
|
||||
{
|
||||
|
||||
220
OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs
Normal file
220
OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
#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 Eluant;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
|
||||
namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
[ScriptGlobal("Reinforcements")]
|
||||
public class ReinforcementsGlobal : ScriptGlobal
|
||||
{
|
||||
public ReinforcementsGlobal(ScriptContext context) : base(context) { }
|
||||
|
||||
Actor CreateActor(Player owner, string actorType, bool addToWorld, CPos? entryLocation = null, CPos? nextLocation = null)
|
||||
{
|
||||
ActorInfo ai;
|
||||
if (!context.World.Map.Rules.Actors.TryGetValue(actorType, out ai))
|
||||
throw new LuaException("Unknown actor type '{0}'".F(actorType));
|
||||
|
||||
var initDict = new TypeDictionary();
|
||||
|
||||
initDict.Add(new OwnerInit(owner));
|
||||
|
||||
if (entryLocation.HasValue)
|
||||
{
|
||||
var pi = ai.Traits.GetOrDefault<AircraftInfo>();
|
||||
initDict.Add(new CenterPositionInit(owner.World.Map.CenterOfCell(entryLocation.Value) + new WVec(0, 0, pi != null ? pi.CruiseAltitude.Range : 0)));
|
||||
initDict.Add(new LocationInit(entryLocation.Value));
|
||||
}
|
||||
|
||||
if (entryLocation.HasValue && nextLocation.HasValue)
|
||||
initDict.Add(new FacingInit(context.World.Map.FacingBetween(CPos.Zero, CPos.Zero + (nextLocation.Value - entryLocation.Value), 0)));
|
||||
|
||||
var actor = context.World.CreateActor(addToWorld, actorType, initDict);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
void Move(Actor actor, CPos dest)
|
||||
{
|
||||
if (actor.HasTrait<Aircraft>())
|
||||
{
|
||||
if (actor.HasTrait<Helicopter>())
|
||||
actor.QueueActivity(new HeliFly(actor, Target.FromCell(actor.World, dest)));
|
||||
else
|
||||
actor.QueueActivity(new Fly(actor, Target.FromCell(actor.World, dest)));
|
||||
}
|
||||
else
|
||||
{
|
||||
actor.QueueActivity(new Move.Move(dest, 2));
|
||||
}
|
||||
}
|
||||
|
||||
[Desc("Send reinforcements consisting of multiple units. Supports ground-based, naval and air units. " +
|
||||
"The first member of the 'entryPath' array will be the units' spawnpoint, " +
|
||||
"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)
|
||||
{
|
||||
var actors = new List<Actor>();
|
||||
for (var i = 1; i <= actorTypes.Count; i++)
|
||||
{
|
||||
string actorType;
|
||||
if (!(actorTypes[i].TryGetClrValue<String>(out actorType)))
|
||||
throw new LuaException("Invalid data in actorTypes array");
|
||||
|
||||
CPos entry, next = new CPos();
|
||||
if (!(entryPath[1].TryGetClrValue<CPos>(out entry)
|
||||
&& (entryPath.Count < 2 || entryPath[2].TryGetClrValue<CPos>(out next))))
|
||||
throw new LuaException("Invalid data in entryPath array");
|
||||
|
||||
var actor = CreateActor(owner, actorType, false, entry, entryPath.Count > 1 ? next : (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;
|
||||
Action actorAction = () =>
|
||||
{
|
||||
context.World.Add(actor);
|
||||
for (var j = 2; j <= ep.Count; j++)
|
||||
{
|
||||
CPos wpt;
|
||||
if (!(ep[j].TryGetClrValue<CPos>(out wpt)))
|
||||
throw new LuaException("Invalid data in entryPath array");
|
||||
|
||||
Move(actor, wpt);
|
||||
}
|
||||
ep.Dispose();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[Desc("Send reinforcements in a transport. A transport can be a ground unit (APC etc.), ships and aircraft. " +
|
||||
"The first member of the 'entryPath' array will be the spawnpoint for the transport, " +
|
||||
"while the last one will be its destination. The last member of the 'exitPath' array " +
|
||||
"is be the place where the transport will be removed from the game. When the transport " +
|
||||
"has reached the destination, it will unload its cargo unless a custom 'actionFunc' has " +
|
||||
"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,
|
||||
LuaFunction actionFunc = null, LuaFunction exitFunc = null)
|
||||
{
|
||||
CPos entry, next = new CPos();
|
||||
if (!(entryPath[1].TryGetClrValue<CPos>(out entry)
|
||||
&& (entryPath.Count < 2 || entryPath[2].TryGetClrValue<CPos>(out next))))
|
||||
throw new LuaException("Invalid data in entryPath array");
|
||||
|
||||
var transport = CreateActor(owner, actorType, true, entry, entryPath.Count > 1 ? next : (CPos?)null);
|
||||
var cargo = transport.TraitOrDefault<Cargo>();
|
||||
|
||||
var passengers = context.CreateTable();
|
||||
|
||||
if (cargo != null && cargoTypes != null)
|
||||
{
|
||||
for (var i = 1; i <= cargoTypes.Count; i++)
|
||||
{
|
||||
string cargoType;
|
||||
if (!(cargoTypes [i].TryGetClrValue<String>(out cargoType)))
|
||||
throw new LuaException("Invalid data in cargoTypes array");
|
||||
|
||||
var passenger = CreateActor(owner, cargoType, false);
|
||||
passengers.Add(passengers.Count + 1, passenger.ToLuaValue(context));
|
||||
cargo.Load(transport, passenger);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 2; i <= entryPath.Count; i++)
|
||||
{
|
||||
CPos wpt;
|
||||
if (!(entryPath[i].TryGetClrValue<CPos>(out wpt)))
|
||||
throw new LuaException("Invalid data in entryPath array");
|
||||
|
||||
Move(transport, wpt);
|
||||
}
|
||||
|
||||
if (actionFunc != null)
|
||||
{
|
||||
var af = actionFunc.CopyReference() as LuaFunction;
|
||||
transport.QueueActivity(new CallFunc(() =>
|
||||
{
|
||||
af.Call(transport.ToLuaValue(context), passengers);
|
||||
af.Dispose();
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
var heli = transport.TraitOrDefault<Helicopter>();
|
||||
if (heli != null)
|
||||
{
|
||||
transport.QueueActivity(new Turn(heli.Info.InitialFacing));
|
||||
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));
|
||||
}
|
||||
|
||||
if (exitFunc != null)
|
||||
{
|
||||
var ef = exitFunc.CopyReference() as LuaFunction;
|
||||
transport.QueueActivity(new CallFunc(() =>
|
||||
{
|
||||
ef.Call(transport.ToLuaValue(context));
|
||||
ef.Dispose();
|
||||
}));
|
||||
}
|
||||
else if (exitPath != null)
|
||||
{
|
||||
for (var i = 1; i <= exitPath.Count; i++)
|
||||
{
|
||||
CPos wpt;
|
||||
if (!(exitPath[i].TryGetClrValue<CPos>(out wpt)))
|
||||
throw new LuaException("Invalid data in exitPath array.");
|
||||
|
||||
Move(transport, wpt);
|
||||
}
|
||||
transport.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
|
||||
var ret = context.CreateTable();
|
||||
ret.Add(1, transport.ToLuaValue(context));
|
||||
ret.Add(2, passengers);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,6 +144,27 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
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 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("Removes all triggers from this actor")]
|
||||
public void ClearAll(Actor a)
|
||||
{
|
||||
|
||||
@@ -58,6 +58,17 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
return true;
|
||||
}
|
||||
|
||||
[Desc("Skips over the first numElements members of the array and returns 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 table.")]
|
||||
public LuaValue Random(LuaTable table)
|
||||
{
|
||||
@@ -94,5 +105,17 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
return context.World.Map.CenterOfCell(cell);
|
||||
}
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
[ScriptPropertyGroup("Support Powers")]
|
||||
public class ChronsphereProperties : ScriptActorProperties, Requires<ChronoshiftPowerInfo>
|
||||
{
|
||||
public ChronsphereProperties(Actor self)
|
||||
: base(self) { }
|
||||
public ChronsphereProperties(ScriptContext context, Actor self)
|
||||
: base(context, self) { }
|
||||
|
||||
[Desc("Chronoshift a group of actors. A duration of 0 will teleport the actors permanently.")]
|
||||
public void Chronoshift(LuaTable unitLocationPairs, int duration = 0, bool killCargo = false)
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
[ScriptPropertyGroup("Combat")]
|
||||
public class CombatProperties : ScriptActorProperties, Requires<AttackBaseInfo>, Requires<IMoveInfo>
|
||||
{
|
||||
public CombatProperties(Actor self) : base(self) { }
|
||||
public CombatProperties(ScriptContext context, Actor self)
|
||||
: base(context, self) { }
|
||||
|
||||
[ScriptActorPropertyActivity]
|
||||
[Desc("Seek out and attack nearby targets.")]
|
||||
@@ -35,4 +36,4 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Move.Move(cell, WRange.FromCells(closeEnough))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
readonly IFacing facing;
|
||||
readonly AutoTarget autotarget;
|
||||
|
||||
public GeneralProperties(Actor self) : base(self)
|
||||
public GeneralProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
facing = self.TraitOrDefault<IFacing>();
|
||||
autotarget = self.TraitOrDefault<AutoTarget>();
|
||||
@@ -135,4 +136,4 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
return self.HasScriptProperty(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public class GuardProperties : ScriptActorProperties, Requires<GuardInfo>, Requires<IMoveInfo>
|
||||
{
|
||||
Guard guard;
|
||||
public GuardProperties(Actor self)
|
||||
: base(self)
|
||||
public GuardProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
guard = self.Trait<Guard>();
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public class HealthProperties : ScriptActorProperties, Requires<HealthInfo>
|
||||
{
|
||||
Health health;
|
||||
public HealthProperties(Actor self)
|
||||
: base(self)
|
||||
public HealthProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
health = self.Trait<Health>();
|
||||
}
|
||||
@@ -41,8 +41,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public class InvulnerableProperties : ScriptActorProperties, Requires<ScriptInvulnerableInfo>
|
||||
{
|
||||
ScriptInvulnerable invulnerable;
|
||||
public InvulnerableProperties(Actor self)
|
||||
: base(self)
|
||||
public InvulnerableProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
invulnerable = self.Trait<ScriptInvulnerable>();
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
readonly MissionObjectives mo;
|
||||
|
||||
public MissionObjectiveProperties(Player player)
|
||||
: base(player)
|
||||
public MissionObjectiveProperties(ScriptContext context, Player player)
|
||||
: base(context, player)
|
||||
{
|
||||
mo = player.PlayerActor.Trait<MissionObjectives>();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
[ScriptPropertyGroup("Movement")]
|
||||
public class MobileProperties : ScriptActorProperties, Requires<MobileInfo>
|
||||
{
|
||||
public MobileProperties(Actor self) : base(self) { }
|
||||
public MobileProperties(ScriptContext context, Actor self)
|
||||
: base(context, self) { }
|
||||
|
||||
[ScriptActorPropertyActivity]
|
||||
[Desc("Moves within the cell grid. closeEnough defines an optional range " +
|
||||
|
||||
@@ -9,22 +9,28 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Eluant;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
|
||||
namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
[ScriptPropertyGroup("Player")]
|
||||
public class PlayerProperties : ScriptPlayerProperties
|
||||
{
|
||||
readonly Player p;
|
||||
|
||||
public PlayerProperties(Player player)
|
||||
: base(player)
|
||||
{
|
||||
p = player;
|
||||
}
|
||||
public PlayerProperties(ScriptContext context, Player player)
|
||||
: base(context, player) { }
|
||||
|
||||
[Desc("The player's name.")]
|
||||
public string PlayerName { get { return p.PlayerName; } }
|
||||
public string Name { get { return player.PlayerName; } }
|
||||
|
||||
[Desc("Returns an array of actors representing all ground attack units of this player.")]
|
||||
public LuaTable GetGroundAttackers()
|
||||
{
|
||||
return player.World.ActorsWithTrait<AttackBase>().Select(a => a.Actor)
|
||||
.Where(a => a.Owner == player && !a.IsDead() && a.IsInWorld && a.HasTrait<Mobile>())
|
||||
.Select(a => a.ToLuaValue(context)).ToLuaTable(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
readonly Production p;
|
||||
|
||||
public ProductionProperties(Actor self)
|
||||
: base(self)
|
||||
public ProductionProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
p = self.Trait<Production>();
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
readonly PlayerResources pr;
|
||||
|
||||
public ResourceProperties(Player player)
|
||||
: base(player)
|
||||
public ResourceProperties(ScriptContext context, Player player)
|
||||
: base(context, player)
|
||||
{
|
||||
pr = player.PlayerActor.Trait<PlayerResources>();
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
readonly Cargo cargo;
|
||||
|
||||
public TransportProperties(Actor self)
|
||||
: base(self)
|
||||
public TransportProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
cargo = self.Trait<Cargo>();
|
||||
}
|
||||
@@ -46,8 +46,8 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
readonly ParaDrop paradrop;
|
||||
|
||||
public ParadropPowers(Actor self)
|
||||
: base(self)
|
||||
public ParadropPowers(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
paradrop = self.Trait<ParaDrop>();
|
||||
}
|
||||
|
||||
@@ -18,12 +18,13 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction, OnPlayerWon, OnPlayerLost, OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed };
|
||||
public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction, OnPlayerWon, OnPlayerLost, OnObjectiveAdded,
|
||||
OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnAddedToWorld, OnRemovedFromWorld };
|
||||
|
||||
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
|
||||
public class ScriptTriggersInfo : TraitInfo<ScriptTriggers> { }
|
||||
|
||||
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyObjectivesUpdated, IDisposable
|
||||
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyObjectivesUpdated, INotifyCapture, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisposable
|
||||
{
|
||||
public event Action<Actor> OnKilledInternal = _ => {};
|
||||
|
||||
@@ -43,36 +44,25 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public void TickIdle(Actor self)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnIdle])
|
||||
{
|
||||
var a = self.ToLuaValue(f.Second);
|
||||
f.First.Call(a).Dispose();
|
||||
a.Dispose();
|
||||
}
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
f.First.Call(a).Dispose();
|
||||
}
|
||||
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnDamaged])
|
||||
{
|
||||
var a = self.ToLuaValue(f.Second);
|
||||
var b = e.Attacker.ToLuaValue(f.Second);
|
||||
f.First.Call(a, b).Dispose();
|
||||
a.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
using (var b = e.Attacker.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b).Dispose();
|
||||
}
|
||||
|
||||
public void Killed(Actor self, AttackInfo e)
|
||||
{
|
||||
// Run lua callbacks
|
||||
foreach (var f in Triggers[Trigger.OnKilled])
|
||||
{
|
||||
var a = self.ToLuaValue(f.Second);
|
||||
var b = e.Attacker.ToLuaValue(f.Second);
|
||||
f.First.Call(a, b).Dispose();
|
||||
a.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
using (var b = e.Attacker.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b).Dispose();
|
||||
|
||||
// Run any internally bound callbacks
|
||||
OnKilledInternal(self);
|
||||
@@ -81,69 +71,71 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public void UnitProduced(Actor self, Actor other, CPos exit)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnProduction])
|
||||
{
|
||||
var a = self.ToLuaValue(f.Second);
|
||||
var b = other.ToLuaValue(f.Second);
|
||||
f.First.Call(a, b).Dispose();
|
||||
a.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
using (var b = other.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b).Dispose();
|
||||
}
|
||||
|
||||
public void OnPlayerWon(Player player)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnPlayerWon])
|
||||
{
|
||||
var a = player.ToLuaValue(f.Second);
|
||||
f.First.Call(a).Dispose();
|
||||
a.Dispose();
|
||||
}
|
||||
using (var a = player.ToLuaValue(f.Second))
|
||||
f.First.Call(a).Dispose();
|
||||
}
|
||||
|
||||
public void OnPlayerLost(Player player)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnPlayerLost])
|
||||
{
|
||||
var a = player.ToLuaValue(f.Second);
|
||||
f.First.Call(a).Dispose();
|
||||
a.Dispose();
|
||||
}
|
||||
using (var a = player.ToLuaValue(f.Second))
|
||||
f.First.Call(a).Dispose();
|
||||
}
|
||||
|
||||
public void OnObjectiveAdded(Player player, int id)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnObjectiveAdded])
|
||||
{
|
||||
var a = player.ToLuaValue(f.Second);
|
||||
var b = id.ToLuaValue(f.Second);
|
||||
f.First.Call(a, b).Dispose();
|
||||
a.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
using (var a = player.ToLuaValue(f.Second))
|
||||
using (var b = id.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b).Dispose();
|
||||
}
|
||||
|
||||
public void OnObjectiveCompleted(Player player, int id)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnObjectiveCompleted])
|
||||
{
|
||||
var a = player.ToLuaValue(f.Second);
|
||||
var b = id.ToLuaValue(f.Second);
|
||||
f.First.Call(a, b).Dispose();
|
||||
a.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
using (var a = player.ToLuaValue(f.Second))
|
||||
using (var b = id.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b).Dispose();
|
||||
}
|
||||
|
||||
public void OnObjectiveFailed(Player player, int id)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnObjectiveFailed])
|
||||
{
|
||||
var a = player.ToLuaValue(f.Second);
|
||||
var b = id.ToLuaValue(f.Second);
|
||||
f.First.Call(a, b).Dispose();
|
||||
a.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
using (var a = player.ToLuaValue(f.Second))
|
||||
using (var b = id.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b).Dispose();
|
||||
}
|
||||
|
||||
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnCapture])
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
using (var b = captor.ToLuaValue(f.Second))
|
||||
using (var c = oldOwner.ToLuaValue(f.Second))
|
||||
using (var d = newOwner.ToLuaValue(f.Second))
|
||||
f.First.Call(a, b, c, d).Dispose();
|
||||
}
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnAddedToWorld])
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
f.First.Call(a).Dispose();
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
foreach (var f in Triggers[Trigger.OnRemovedFromWorld])
|
||||
using (var a = self.ToLuaValue(f.Second))
|
||||
f.First.Call(a).Dispose();
|
||||
}
|
||||
|
||||
public void Clear(Trigger trigger)
|
||||
|
||||
Reference in New Issue
Block a user