diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 908baf3a0b..79aa9ae21b 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -281,6 +281,9 @@ namespace OpenRA.Mods.Common.Traits foreach (var npe in self.TraitsImplementing()) npe.OnPassengerExited(self, a); + foreach (var nec in a.TraitsImplementing()) + nec.OnExitedCargo(a, self); + var p = a.Trait(); p.Transport = null; @@ -347,9 +350,14 @@ namespace OpenRA.Mods.Common.Traits // If not initialized then this will be notified in the first tick if (initialized) + { foreach (var npe in self.TraitsImplementing()) npe.OnPassengerEntered(self, a); + foreach (var nec in a.TraitsImplementing()) + nec.OnEnteredCargo(a, self); + } + var p = a.Trait(); p.Transport = self; @@ -446,6 +454,9 @@ namespace OpenRA.Mods.Common.Traits foreach (var npe in self.TraitsImplementing()) npe.OnPassengerEntered(self, c); + + foreach (var nec in c.TraitsImplementing()) + nec.OnEnteredCargo(c, self); } initialized = true; diff --git a/OpenRA.Mods.Common/Traits/Passenger.cs b/OpenRA.Mods.Common/Traits/Passenger.cs index 2ad05743b4..a99042cb84 100644 --- a/OpenRA.Mods.Common/Traits/Passenger.cs +++ b/OpenRA.Mods.Common/Traits/Passenger.cs @@ -38,14 +38,31 @@ namespace OpenRA.Mods.Common.Traits [Desc("Range from self for looking for an alternate transport (default: 5.5 cells).")] public readonly WDist AlternateTransportScanRange = WDist.FromCells(11) / 2; + [GrantedConditionReference] + [Desc("The condition to grant to when this actor is loaded inside any transport.")] + public readonly string CargoCondition = null; + + [Desc("Conditions to grant when this actor is loaded inside specified transport.", + "A dictionary of [actor id]: [condition].")] + public readonly Dictionary CargoConditions = new Dictionary(); + + [GrantedConditionReference] + public IEnumerable LinterCargoConditions { get { return CargoConditions.Values; } } + [VoiceReference] public readonly string Voice = "Action"; public object Create(ActorInitializer init) { return new Passenger(this); } } - public class Passenger : IIssueOrder, IResolveOrder, IOrderVoice, INotifyRemovedFromWorld + public class Passenger : INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, INotifyRemovedFromWorld, INotifyEnteredCargo, INotifyExitedCargo { public readonly PassengerInfo Info; + public Actor Transport; + + ConditionManager conditionManager; + int anyCargoToken = ConditionManager.InvalidConditionToken; + int specificCargoToken = ConditionManager.InvalidConditionToken; + public Passenger(PassengerInfo info) { Info = info; @@ -58,11 +75,15 @@ namespace OpenRA.Mods.Common.Traits }; } - public Actor Transport; public Cargo ReservedCargo { get; private set; } public IEnumerable Orders { get; private set; } + void INotifyCreated.Created(Actor self) + { + conditionManager = self.TraitOrDefault(); + } + public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) { if (order.OrderID == "EnterTransport" || order.OrderID == "EnterTransports") @@ -94,6 +115,28 @@ namespace OpenRA.Mods.Common.Traits return Info.Voice; } + void INotifyEnteredCargo.OnEnteredCargo(Actor self, Actor cargo) + { + string specificCargoCondition; + if (conditionManager != null) + { + if (anyCargoToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.CargoCondition)) + anyCargoToken = conditionManager.GrantCondition(self, Info.CargoCondition); + + if (specificCargoToken == ConditionManager.InvalidConditionToken && Info.CargoConditions.TryGetValue(cargo.Info.Name, out specificCargoCondition)) + specificCargoToken = conditionManager.GrantCondition(self, specificCargoCondition); + } + } + + void INotifyExitedCargo.OnExitedCargo(Actor self, Actor cargo) + { + if (anyCargoToken != ConditionManager.InvalidConditionToken) + anyCargoToken = conditionManager.RevokeCondition(self, anyCargoToken); + + if (specificCargoToken != ConditionManager.InvalidConditionToken) + specificCargoToken = conditionManager.RevokeCondition(self, specificCargoToken); + } + public void ResolveOrder(Actor self, Order order) { if (order.OrderString == "EnterTransport" || order.OrderString == "EnterTransports") diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index efae316a8d..68ab438fd6 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -150,6 +150,12 @@ namespace OpenRA.Mods.Common.Traits [RequireExplicitImplementation] public interface INotifyPassengerExited { void OnPassengerExited(Actor self, Actor passenger); } + [RequireExplicitImplementation] + public interface INotifyEnteredCargo { void OnEnteredCargo(Actor self, Actor cargo); } + + [RequireExplicitImplementation] + public interface INotifyExitedCargo { void OnExitedCargo(Actor self, Actor cargo); } + [RequireExplicitImplementation] public interface IObservesVariablesInfo : ITraitInfo { }