diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
index 132c5cebc8..8d182014a0 100644
--- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
+++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj
@@ -485,6 +485,7 @@
+
diff --git a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs
index a6faa0f59c..a2dca58344 100644
--- a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs
+++ b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs
@@ -109,6 +109,41 @@ namespace OpenRA.Mods.RA.Scripting
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("Removes all triggers from this actor")]
public void ClearAll(Actor a)
{
diff --git a/OpenRA.Mods.RA/Scripting/Properties/MissionObjectiveProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/MissionObjectiveProperties.cs
new file mode 100644
index 0000000000..b11a6b6af4
--- /dev/null
+++ b/OpenRA.Mods.RA/Scripting/Properties/MissionObjectiveProperties.cs
@@ -0,0 +1,70 @@
+#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 OpenRA.Traits;
+using OpenRA.Scripting;
+using OpenRA.Mods.RA;
+
+namespace OpenRA.Mods.RA.Scripting
+{
+ [ScriptPropertyGroup("MissionObjectives")]
+ public class MissionObjectiveProperties : ScriptPlayerProperties
+ {
+ readonly MissionObjectives mo;
+
+ public MissionObjectiveProperties(Player player)
+ : base(player)
+ {
+ mo = player.PlayerActor.Trait();
+ }
+
+ [ScriptActorPropertyActivity]
+ [Desc("Add a primary mission objective for this player. The function returns the " +
+ "ID of the newly created objective, so that it can be referred to later.")]
+ public int AddPrimaryObjective(string description)
+ {
+ return mo.Add(player, description, ObjectiveType.Primary);
+ }
+
+ [ScriptActorPropertyActivity]
+ [Desc("Add a secondary mission objective for this player. The function returns the " +
+ "ID of the newly created objective, so that it can be referred to later.")]
+ public int AddSecondaryObjective(string description)
+ {
+ return mo.Add(player, description, ObjectiveType.Secondary);
+ }
+
+ [ScriptActorPropertyActivity]
+ [Desc("Mark an objective as completed. This needs the objective ID returned " +
+ "by AddObjective as argument. When the player has completed all primary " +
+ "objectives, (s)he has won the game.")]
+ public void MarkCompletedObjective(int id)
+ {
+ mo.MarkCompleted(player, id);
+ }
+
+ [ScriptActorPropertyActivity]
+ [Desc("Mark an objective as failed. This needs the objective ID returned " +
+ "by AddObjective as argument. Secondary objectives do not have any " +
+ "influence whatsoever on the outcome of the game.")]
+ public void MarkFailedObjective(int id)
+ {
+ mo.MarkFailed(player, id);
+ }
+
+ [ScriptActorPropertyActivity]
+ [Desc("Returns true if 'player' has lost all units/actors that have the 'MustBeDestroyed' trait.")]
+ public bool HasNoRequiredUnits()
+ {
+ return player.HasNoRequiredUnits();
+ }
+ }
+}
diff --git a/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs b/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs
index 0961e31bf6..9c2a8e597b 100644
--- a/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs
+++ b/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs
@@ -18,12 +18,12 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Scripting
{
- public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction };
+ public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction, OnPlayerWon, OnPlayerLost, OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed };
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
public class ScriptTriggersInfo : TraitInfo { }
- public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, IDisposable
+ public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyObjectivesUpdated, IDisposable
{
public event Action OnKilledInternal = _ => {};
@@ -90,6 +90,62 @@ namespace OpenRA.Mods.RA.Scripting
}
}
+ 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();
+ }
+ }
+
+ 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();
+ }
+ }
+
+ 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();
+ }
+ }
+
+ 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();
+ }
+ }
+
+ 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();
+ }
+ }
+
public void Clear(Trigger trigger)
{
Triggers[trigger].Clear();
diff --git a/mods/cnc/rules/player.yaml b/mods/cnc/rules/player.yaml
index 6fabed5517..f177d84ce9 100644
--- a/mods/cnc/rules/player.yaml
+++ b/mods/cnc/rules/player.yaml
@@ -2,6 +2,7 @@ Player:
PlaceBuilding:
TechTree:
SupportPowerManager:
+ ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
diff --git a/mods/d2k/rules/player.yaml b/mods/d2k/rules/player.yaml
index 4cbf92ba82..e55955cda7 100644
--- a/mods/d2k/rules/player.yaml
+++ b/mods/d2k/rules/player.yaml
@@ -34,6 +34,7 @@ Player:
BlockedAudio: NoRoom
PlaceBuilding:
SupportPowerManager:
+ ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
diff --git a/mods/ra/rules/player.yaml b/mods/ra/rules/player.yaml
index dfc510caf6..fdf86884bc 100644
--- a/mods/ra/rules/player.yaml
+++ b/mods/ra/rules/player.yaml
@@ -42,6 +42,7 @@ Player:
RequireOwner: false
PlaceBuilding:
SupportPowerManager:
+ ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
diff --git a/mods/ts/rules/player.yaml b/mods/ts/rules/player.yaml
index 48e5ad9742..80a376ccd8 100644
--- a/mods/ts/rules/player.yaml
+++ b/mods/ts/rules/player.yaml
@@ -26,6 +26,7 @@ Player:
LowPowerSlowdown: 3
PlaceBuilding:
SupportPowerManager:
+ ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager: