From 367a7f617c7555c2493b4cdd796f615b8bce83ad Mon Sep 17 00:00:00 2001 From: Mustafa Alperen Seki Date: Fri, 23 Mar 2018 11:49:20 +0300 Subject: [PATCH] Added OwnerLostAction Allows customisation of what will happen to an actor when its owner loses. --- OpenRA.Game/Traits/TraitsInterfaces.cs | 1 + OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 2 + OpenRA.Mods.Common/Traits/OwnerLostAction.cs | 51 +++++++++++++++++++ .../Player/ConquestVictoryConditions.cs | 4 +- .../Player/StrategicVictoryConditions.cs | 4 +- .../Rules/DefineOwnerLostAction.cs | 46 +++++++++++++++++ OpenRA.Mods.Common/UpdateRules/UpdatePath.cs | 3 +- 7 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 OpenRA.Mods.Common/Traits/OwnerLostAction.cs create mode 100644 OpenRA.Mods.Common/UpdateRules/Rules/DefineOwnerLostAction.cs 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() }) };