diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index e2aa444cdb..c3b0e8e62c 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -314,6 +314,8 @@ + + diff --git a/OpenRA.Mods.Common/Traits/AffectsShroud.cs b/OpenRA.Mods.Common/Traits/AffectsShroud.cs index 9ad85a6ce8..a501c1a484 100644 --- a/OpenRA.Mods.Common/Traits/AffectsShroud.cs +++ b/OpenRA.Mods.Common/Traits/AffectsShroud.cs @@ -34,7 +34,8 @@ namespace OpenRA.Mods.Common.Traits readonly HashSet footprint; [Sync] CPos cachedLocation; - [Sync] bool cachedTraitDisabled; + [Sync] WDist cachedRange; + [Sync] protected bool CachedTraitDisabled { get; private set; } protected abstract void AddCellsToPlayerShroud(Actor self, Player player, PPos[] uv); protected abstract void RemoveCellsFromPlayerShroud(Actor self, Player player); @@ -80,12 +81,14 @@ namespace OpenRA.Mods.Common.Traits var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); var projectedLocation = self.World.Map.CellContaining(projectedPos); var traitDisabled = IsTraitDisabled; + var range = Range; - if (cachedLocation == projectedLocation && traitDisabled == cachedTraitDisabled) + if (cachedLocation == projectedLocation && cachedRange == range && traitDisabled == CachedTraitDisabled) return; + cachedRange = range; cachedLocation = projectedLocation; - cachedTraitDisabled = traitDisabled; + CachedTraitDisabled = traitDisabled; var cells = ProjectedCells(self); foreach (var p in self.World.Players) @@ -100,7 +103,7 @@ namespace OpenRA.Mods.Common.Traits var centerPosition = self.CenterPosition; var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); cachedLocation = self.World.Map.CellContaining(projectedPos); - cachedTraitDisabled = IsTraitDisabled; + CachedTraitDisabled = IsTraitDisabled; var cells = ProjectedCells(self); foreach (var p in self.World.Players) @@ -113,6 +116,6 @@ namespace OpenRA.Mods.Common.Traits RemoveCellsFromPlayerShroud(self, p); } - public WDist Range { get { return cachedTraitDisabled ? WDist.Zero : Info.Range; } } + public virtual WDist Range { get { return CachedTraitDisabled ? WDist.Zero : Info.Range; } } } } diff --git a/OpenRA.Mods.Common/Traits/CreatesShroud.cs b/OpenRA.Mods.Common/Traits/CreatesShroud.cs index 4416d820ba..42bf6b9933 100644 --- a/OpenRA.Mods.Common/Traits/CreatesShroud.cs +++ b/OpenRA.Mods.Common/Traits/CreatesShroud.cs @@ -9,6 +9,8 @@ */ #endregion +using System.Collections.Generic; +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -24,9 +26,20 @@ namespace OpenRA.Mods.Common.Traits public class CreatesShroud : AffectsShroud { readonly CreatesShroudInfo info; + ICreatesShroudModifier[] rangeModifiers; public CreatesShroud(Actor self, CreatesShroudInfo info) - : base(self, info) { this.info = info; } + : base(self, info) + { + this.info = info; + } + + protected override void Created(Actor self) + { + base.Created(self); + + rangeModifiers = self.TraitsImplementing().ToArray(); + } protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) { @@ -37,5 +50,18 @@ namespace OpenRA.Mods.Common.Traits } protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveSource(this); } + + public override WDist Range + { + get + { + if (CachedTraitDisabled) + return WDist.Zero; + + var revealsShroudModifier = rangeModifiers.Select(x => x.GetCreatesShroudModifier()); + var range = Util.ApplyPercentageModifiers(Info.Range.Length, revealsShroudModifier); + return new WDist(range); + } + } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Multipliers/CreatesShroudMultiplier.cs b/OpenRA.Mods.Common/Traits/Multipliers/CreatesShroudMultiplier.cs new file mode 100644 index 0000000000..81edd8aacc --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Multipliers/CreatesShroudMultiplier.cs @@ -0,0 +1,34 @@ +#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 + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("Modifies the shroud range created by this actor.")] + public class CreatesShroudMultiplierInfo : ConditionalTraitInfo + { + [FieldLoader.Require] + [Desc("Percentage modifier to apply.")] + public readonly int Modifier = 100; + + public override object Create(ActorInitializer init) { return new CreatesShroudMultiplier(this); } + } + + public class CreatesShroudMultiplier : ConditionalTrait, ICreatesShroudModifier + { + public CreatesShroudMultiplier(CreatesShroudMultiplierInfo info) + : base(info) { } + + int ICreatesShroudModifier.GetCreatesShroudModifier() + { + return IsTraitDisabled ? 100 : Info.Modifier; + } + } +} diff --git a/OpenRA.Mods.Common/Traits/Multipliers/RevealsShroudMultiplier.cs b/OpenRA.Mods.Common/Traits/Multipliers/RevealsShroudMultiplier.cs new file mode 100644 index 0000000000..99384e09d4 --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Multipliers/RevealsShroudMultiplier.cs @@ -0,0 +1,34 @@ +#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 + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("Modifies the shroud range revealed by this actor.")] + public class RevealsShroudMultiplierInfo : ConditionalTraitInfo + { + [FieldLoader.Require] + [Desc("Percentage modifier to apply.")] + public readonly int Modifier = 100; + + public override object Create(ActorInitializer init) { return new RevealsShroudMultiplier(this); } + } + + public class RevealsShroudMultiplier : ConditionalTrait, IRevealsShroudModifier + { + public RevealsShroudMultiplier(RevealsShroudMultiplierInfo info) + : base(info) { } + + int IRevealsShroudModifier.GetRevealsShroudModifier() + { + return IsTraitDisabled ? 100 : Info.Modifier; + } + } +} diff --git a/OpenRA.Mods.Common/Traits/RevealsShroud.cs b/OpenRA.Mods.Common/Traits/RevealsShroud.cs index 9fc1140158..f6b2dcaa81 100644 --- a/OpenRA.Mods.Common/Traits/RevealsShroud.cs +++ b/OpenRA.Mods.Common/Traits/RevealsShroud.cs @@ -9,6 +9,8 @@ */ #endregion +using System.Collections.Generic; +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -28,6 +30,7 @@ namespace OpenRA.Mods.Common.Traits { readonly RevealsShroudInfo info; readonly Shroud.SourceType type; + IRevealsShroudModifier[] rangeModifiers; public RevealsShroud(Actor self, RevealsShroudInfo info) : base(self, info) @@ -37,6 +40,13 @@ namespace OpenRA.Mods.Common.Traits : Shroud.SourceType.PassiveVisibility; } + protected override void Created(Actor self) + { + base.Created(self); + + rangeModifiers = self.TraitsImplementing().ToArray(); + } + protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) { if (!info.ValidStances.HasStance(p.Stances[self.Owner])) @@ -46,5 +56,18 @@ namespace OpenRA.Mods.Common.Traits } protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveSource(this); } + + public override WDist Range + { + get + { + if (CachedTraitDisabled) + return WDist.Zero; + + var revealsShroudModifier = rangeModifiers.Select(x => x.GetRevealsShroudModifier()); + var range = Util.ApplyPercentageModifiers(Info.Range.Length, revealsShroudModifier); + return new WDist(range); + } + } } } diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index e76a025425..cca6f002f5 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -357,6 +357,12 @@ namespace OpenRA.Mods.Common.Traits [RequireExplicitImplementation] public interface IGainsExperienceModifier { int GetGainsExperienceModifier(); } + [RequireExplicitImplementation] + public interface ICreatesShroudModifier { int GetCreatesShroudModifier(); } + + [RequireExplicitImplementation] + public interface IRevealsShroudModifier { int GetRevealsShroudModifier(); } + [RequireExplicitImplementation] public interface ICustomMovementLayer {