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
{