diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs
index 32bd6bf229..c468982700 100644
--- a/OpenRA.Game/Traits/TraitsInterfaces.cs
+++ b/OpenRA.Game/Traits/TraitsInterfaces.cs
@@ -181,6 +181,7 @@ namespace OpenRA.Traits
public interface INotifyActorDisposing { void Disposing(Actor self); }
public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); }
public interface INotifyEffectiveOwnerChanged { void OnEffectiveOwnerChanged(Actor self, Player oldEffectiveOwner, Player newEffectiveOwner); }
+ public interface INotifyOwnerLost { void OnOwnerLost(Actor self); }
[RequireExplicitImplementation]
public interface IVoiced
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index b5b134033a..4051d37f47 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -343,6 +343,7 @@
+
@@ -879,6 +880,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/OwnerLostAction.cs b/OpenRA.Mods.Common/Traits/OwnerLostAction.cs
new file mode 100644
index 0000000000..60fd1de903
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/OwnerLostAction.cs
@@ -0,0 +1,51 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2018 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, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System.Linq;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits
+{
+ public enum OwnerLostActionType { ChangeOwner, Dispose, Kill }
+
+ [Desc("Perform an action when the actor's owner is defeated.")]
+ public class OwnerLostActionInfo : ConditionalTraitInfo
+ {
+ [FieldLoader.Require]
+ [Desc("What does this unit do when its owner loses.",
+ "Allowed values are 'ChangeOwner', 'Dispose', 'Kill'")]
+ public readonly OwnerLostActionType Action = OwnerLostActionType.Kill;
+
+ [Desc("Map player to use when 'Action' is 'ChangeOwner'.")]
+ public readonly string Owner = "Neutral";
+
+ public override object Create(ActorInitializer init) { return new OwnerLostAction(init, this); }
+ }
+
+ public class OwnerLostAction : ConditionalTrait, INotifyOwnerLost
+ {
+ public OwnerLostAction(ActorInitializer init, OwnerLostActionInfo info)
+ : base(info) { }
+
+ void INotifyOwnerLost.OnOwnerLost(Actor self)
+ {
+ if (IsTraitDisabled)
+ return;
+
+ if (Info.Action == OwnerLostActionType.Kill)
+ self.Kill(self);
+ else if (Info.Action == OwnerLostActionType.Dispose)
+ self.Dispose();
+ else if (Info.Action == OwnerLostActionType.ChangeOwner)
+ self.ChangeOwner(self.World.Players.First(p => p.InternalName == Info.Owner));
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs b/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs
index 6a40a74261..447458fb34 100644
--- a/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs
+++ b/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs
@@ -70,8 +70,8 @@ namespace OpenRA.Mods.Common.Traits
public void OnPlayerLost(Player player)
{
- foreach (var a in player.World.Actors.Where(a => a.Owner == player))
- a.Kill(a);
+ foreach (var a in player.World.ActorsWithTrait().Where(a => a.Actor.Owner == player))
+ a.Trait.OnOwnerLost(a.Actor);
if (info.SuppressNotifications)
return;
diff --git a/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs b/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs
index bee659e249..0817e9b818 100644
--- a/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs
+++ b/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs
@@ -109,8 +109,8 @@ namespace OpenRA.Mods.Common.Traits
public void OnPlayerLost(Player player)
{
- foreach (var a in player.World.Actors.Where(a => a.Owner == player))
- a.Kill(a);
+ foreach (var a in player.World.ActorsWithTrait().Where(a => a.Actor.Owner == player))
+ a.Trait.OnOwnerLost(a.Actor);
if (info.SuppressNotifications)
return;
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/DefineOwnerLostAction.cs b/OpenRA.Mods.Common/UpdateRules/Rules/DefineOwnerLostAction.cs
new file mode 100644
index 0000000000..6de0d7642f
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/DefineOwnerLostAction.cs
@@ -0,0 +1,46 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2018 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, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace OpenRA.Mods.Common.UpdateRules.Rules
+{
+ public class DefineOwnerLostAction : UpdateRule
+ {
+ public override string Name { get { return "Add OwnerLostAction to player-controlled actors"; } }
+ public override string Description
+ {
+ get
+ {
+ return "A new OwnerLostAction trait has been introduced to control what happens to a\n" +
+ "player's actors when they are defeated. A warning is displayed notifying that\nthis trait must be added to actors.";
+ }
+ }
+
+ bool reported;
+ public override IEnumerable AfterUpdate(ModData modData)
+ {
+ if (!reported)
+ yield return "All player-controlled (or player-capturable) actors should define an OwnerLostAction trait\n" +
+ "specifying an action (Kill, Dispose, ChangeOwner) to apply when the actor's owner is defeated.\n" +
+ "You must manually define this trait on the appropriate default actor templates.\n" +
+ "Actors missing this trait will remain controllable by their owner after they have been defeated.";
+
+ reported = true;
+ }
+
+ public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode)
+ {
+ yield break;
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
index 74cefc988e..3e7de09e52 100644
--- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
+++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
@@ -51,7 +51,8 @@ namespace OpenRA.Mods.Common.UpdateRules
new AddShakeToBridge(),
new AddEditorPlayer(),
new RemovePaletteFromCurrentTileset(),
- new DefineLocomotors()
+ new DefineLocomotors(),
+ new DefineOwnerLostAction()
})
};