Files
OpenRA/OpenRA.Mods.Common/Traits/Capturable.cs
Paul Chote a53ef6e503 Add CaptureManager trait to fix multiple-trait interactions.
This fixes the various edge cases that occur when multiple
Captures or Capturable traits are defined on an actor and
are toggled using conditions.

The Sabotage threshold field moves from Capturable to
Captures in order to simplify the plumbing. The previous
behaviour ingame can be restored by creating a new
capturable type for each threshold level, each with their
own Captures trait.
2018-10-07 18:46:21 +02:00

79 lines
2.3 KiB
C#

#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 OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("This actor can be captured by a unit with Captures: trait.")]
public class CapturableInfo : ConditionalTraitInfo, Requires<CaptureManagerInfo>
{
[Desc("CaptureTypes (from the Captures trait) that are able to capture this.")]
public readonly BitSet<CaptureType> Types = new BitSet<CaptureType>("building");
[Desc("What diplomatic stances can be captured by this actor.")]
public readonly Stance ValidStances = Stance.Neutral | Stance.Enemy;
public readonly bool CancelActivity = false;
public override object Create(ActorInitializer init) { return new Capturable(init.Self, this); }
public bool CanBeTargetedBy(Actor captor, Player owner)
{
var c = captor.Info.TraitInfoOrDefault<CapturesInfo>();
if (c == null)
return false;
var stance = owner.Stances[captor.Owner];
if (!ValidStances.HasStance(stance))
return false;
if (!c.CaptureTypes.Overlaps(Types))
return false;
return true;
}
}
public class Capturable : ConditionalTrait<CapturableInfo>, INotifyCapture
{
readonly CaptureManager captureManager;
public Capturable(Actor self, CapturableInfo info)
: base(info)
{
captureManager = self.Trait<CaptureManager>();
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
if (Info.CancelActivity)
{
var stop = new Order("Stop", self, false);
foreach (var t in self.TraitsImplementing<IResolveOrder>())
t.ResolveOrder(self, stop);
}
}
public bool CanBeTargetedBy(Actor captor, Player owner)
{
if (IsTraitDisabled)
return false;
return Info.CanBeTargetedBy(captor, owner);
}
protected override void TraitEnabled(Actor self) { captureManager.RefreshCapturable(self); }
protected override void TraitDisabled(Actor self) { captureManager.RefreshCapturable(self); }
}
}