diff --git a/OpenRA.Game/Player.cs b/OpenRA.Game/Player.cs index a4da8f438c..6dfd91b9fe 100644 --- a/OpenRA.Game/Player.cs +++ b/OpenRA.Game/Player.cs @@ -49,6 +49,8 @@ namespace OpenRA public Shroud Shroud; public World World { get; private set; } + readonly IFogVisibilityModifier[] fogVisibilities; + CountryInfo ChooseCountry(World world, string name, bool requireSelectable = true) { var selectableCountries = world.Map.Rules.Actors["world"].Traits @@ -113,6 +115,9 @@ namespace OpenRA PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) }); Shroud = PlayerActor.Trait(); + fogVisibilities = PlayerActor.TraitsImplementing() + .ToArray(); + // Enable the bot logic on the host IsBot = botType != null; if (IsBot && Game.IsHost) @@ -149,6 +154,27 @@ namespace OpenRA nsc.Trait.StanceChanged(nsc.Actor, this, target, oldStance, s); } + public bool CanViewActor(Actor a) + { + if (a.TraitsImplementing().Any(t => !t.IsVisible(a, this))) + return false; + + return a.Trait().IsVisible(a, this); + } + + public bool CanTargetActor(Actor a) + { + if (HasFogVisibility) + return true; + + if (a.TraitsImplementing().Any(t => !t.IsVisible(a, this))) + return false; + + return a.Trait().IsVisible(a, this); + } + + public bool HasFogVisibility { get { return fogVisibilities.Any(f => f.HasFogVisibility(this)); } } + #region Scripting interface Lazy luaInterface; diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index c2e7e154df..e4d4ff7deb 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -167,6 +167,8 @@ namespace OpenRA.Traits IEnumerable> RadarSignatureCells(Actor self); } + public interface IDefaultVisibilityInfo { } + public interface IDefaultVisibility { bool IsVisible(Actor self, Player byPlayer); } public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); } public interface IFogVisibilityModifier { bool HasFogVisibility(Player byPlayer); } diff --git a/OpenRA.Game/Traits/World/Shroud.cs b/OpenRA.Game/Traits/World/Shroud.cs index cde61a26aa..ad8a58a5b3 100644 --- a/OpenRA.Game/Traits/World/Shroud.cs +++ b/OpenRA.Game/Traits/World/Shroud.cs @@ -33,8 +33,6 @@ namespace OpenRA.Traits readonly CellLayer generatedShroudCount; readonly CellLayer explored; - readonly Lazy fogVisibilities; - // Cache of visibility that was added, so no matter what crazy trait code does, it // can't make us invalid. readonly Dictionary visibility = new Dictionary(); @@ -62,8 +60,6 @@ namespace OpenRA.Traits self.World.ActorAdded += a => { CPos[] shrouded = null; AddShroudGeneration(a, ref shrouded); }; self.World.ActorRemoved += RemoveShroudGeneration; - fogVisibilities = Exts.Lazy(() => self.TraitsImplementing().ToArray()); - shroudEdgeTest = map.Contains; isExploredTest = IsExploredCore; isVisibleTest = IsVisibleCore; @@ -342,11 +338,6 @@ namespace OpenRA.Traits } } - public bool IsExplored(Actor a) - { - return GetVisOrigins(a).Any(IsExplored); - } - public bool IsVisible(WPos pos) { return IsVisible(map.CellContaining(pos)); @@ -394,31 +385,6 @@ namespace OpenRA.Traits } } - // Actors are hidden under shroud, but not under fog by default - public bool IsVisible(Actor a) - { - if (a.TraitsImplementing().Any(t => !t.IsVisible(a, self.Owner))) - return false; - - return a.Owner.IsAlliedWith(self.Owner) || IsExplored(a); - } - - public bool IsTargetable(Actor a) - { - if (HasFogVisibility()) - return true; - - if (a.TraitsImplementing().Any(t => !t.IsVisible(a, self.Owner))) - return false; - - return GetVisOrigins(a).Any(IsVisible); - } - - public bool HasFogVisibility() - { - return fogVisibilities.Value.Any(f => f.HasFogVisibility(self.Owner)); - } - public bool Contains(MPos uv) { // Check that uv is inside the map area. There is nothing special diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 7ec04d1f72..f2d2115e85 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -70,12 +70,9 @@ namespace OpenRA set { renderPlayer = value; } } - public bool FogObscures(Actor a) { return RenderPlayer != null && !RenderPlayer.Shroud.IsVisible(a); } + public bool FogObscures(Actor a) { return RenderPlayer != null && !RenderPlayer.CanViewActor(a); } public bool FogObscures(CPos p) { return RenderPlayer != null && !RenderPlayer.Shroud.IsVisible(p); } public bool FogObscures(WPos pos) { return RenderPlayer != null && !RenderPlayer.Shroud.IsVisible(pos); } - public bool FogObscures(MPos uv) { return RenderPlayer != null && !RenderPlayer.Shroud.IsVisible(uv); } - - public bool ShroudObscures(Actor a) { return RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(a); } public bool ShroudObscures(CPos p) { return RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(p); } public bool ShroudObscures(WPos pos) { return RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(pos); } public bool ShroudObscures(MPos uv) { return RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(uv); } diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index 41cdff5ffc..cae126458a 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Activities // HACK: This would otherwise break targeting frozen actors // The problem is that Shroud.IsTargetable returns false (as it should) for // frozen actors, but we do want to explicitly target the underlying actor here. - if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.HasTrait() && !self.Owner.Shroud.IsTargetable(Target.Actor)) + if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.HasTrait() && !self.Owner.CanTargetActor(Target.Actor)) return NextActivity; // Try to move within range diff --git a/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs b/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs new file mode 100644 index 0000000000..221602541f --- /dev/null +++ b/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs @@ -0,0 +1,36 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 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. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Linq; +using OpenRA.GameRules; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Lint +{ + class CheckDefaultVisibility : ILintPass + { + public void Run(Action emitError, Action emitWarning, Map map) + { + foreach (var actorInfo in map.Rules.Actors) + { + if (actorInfo.Key.StartsWith("^")) + continue; + + var count = actorInfo.Value.Traits.WithInterface().Count(); + + if (count == 0) + emitError("Actor type `{0}` does not define a default visibility type!".F(actorInfo.Key)); + else if (count > 1) + emitError("Actor type `{0}` defines multiple default visibility types!".F(actorInfo.Key)); + } + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 44e8c69a92..e9a77ec2b8 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -676,6 +676,9 @@ + + + diff --git a/OpenRA.Mods.Common/Traits/AutoTarget.cs b/OpenRA.Mods.Common/Traits/AutoTarget.cs index ba962231fa..436be5f80b 100644 --- a/OpenRA.Mods.Common/Traits/AutoTarget.cs +++ b/OpenRA.Mods.Common/Traits/AutoTarget.cs @@ -156,7 +156,7 @@ namespace OpenRA.Mods.Common.Traits a.AppearsHostileTo(self) && !a.HasTrait() && attack.HasAnyValidWeapons(Target.FromActor(a)) && - self.Owner.Shroud.IsTargetable(a)) + self.Owner.CanTargetActor(a)) .ClosestTo(self); } } diff --git a/OpenRA.Mods.Common/Traits/Crates/HideMapCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/HideMapCrateAction.cs index c102b3321a..97c5485f0d 100644 --- a/OpenRA.Mods.Common/Traits/Crates/HideMapCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/HideMapCrateAction.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.Traits public override int GetSelectionShares(Actor collector) { // don't ever hide the map for people who have GPS. - if (collector.Owner.Shroud.HasFogVisibility()) + if (collector.Owner.HasFogVisibility) return 0; return base.GetSelectionShares(collector); diff --git a/OpenRA.Mods.Common/Traits/Modifiers/AlwaysVisible.cs b/OpenRA.Mods.Common/Traits/Modifiers/AlwaysVisible.cs new file mode 100644 index 0000000000..74c798070c --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Modifiers/AlwaysVisible.cs @@ -0,0 +1,24 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 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. For more information, + * see COPYING. + */ +#endregion + +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("The actor is always considered visible for targeting and rendering purposes.")] + public class AlwaysVisibleInfo : TraitInfo, IDefaultVisibilityInfo { } + public class AlwaysVisible : IDefaultVisibility + { + public bool IsVisible(Actor self, Player byPlayer) + { + return true; + } + } +} diff --git a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs index 154c852257..cdee1d2959 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs @@ -17,17 +17,21 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("This actor will remain visible (but not updated visually) under fog, once discovered.")] - public class FrozenUnderFogInfo : ITraitInfo, Requires + public class FrozenUnderFogInfo : ITraitInfo, Requires, IDefaultVisibilityInfo { public readonly bool StartsRevealed = false; + [Desc("Players with these stances can always see the actor.")] + public readonly Stance AlwaysVisibleStances = Stance.Ally; + public object Create(ActorInitializer init) { return new FrozenUnderFog(init, this); } } - public class FrozenUnderFog : IRenderModifier, IVisibilityModifier, ITick, ISync + public class FrozenUnderFog : IRenderModifier, IDefaultVisibility, ITick, ISync { [Sync] public int VisibilityHash; + readonly FrozenUnderFogInfo info; readonly bool startsRevealed; readonly MPos[] footprint; @@ -41,6 +45,8 @@ namespace OpenRA.Mods.Common.Traits public FrozenUnderFog(ActorInitializer init, FrozenUnderFogInfo info) { + this.info = info; + // Spawned actors (e.g. building husks) shouldn't be revealed startsRevealed = info.StartsRevealed && !init.Contains(); var footprintCells = FootprintUtils.Tiles(init.Self).ToList(); @@ -54,7 +60,11 @@ namespace OpenRA.Mods.Common.Traits public bool IsVisible(Actor self, Player byPlayer) { - return byPlayer == null || visible[byPlayer]; + if (byPlayer == null) + return true; + + var stance = self.Owner.Stances[byPlayer]; + return info.AlwaysVisibleStances.HasFlag(stance) || visible[byPlayer]; } public void Tick(Actor self) diff --git a/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderFog.cs index fa2a44dbb6..a9438fcf8b 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderFog.cs @@ -16,18 +16,22 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("The actor stays invisible under fog of war.")] - public class HiddenUnderFogInfo : TraitInfo { } - - public class HiddenUnderFog : IRenderModifier, IVisibilityModifier + public class HiddenUnderFogInfo : HiddenUnderShroudInfo { - public bool IsVisible(Actor self, Player byPlayer) - { - return byPlayer == null || Shroud.GetVisOrigins(self).Any(byPlayer.Shroud.IsVisible); - } + public override object Create(ActorInitializer init) { return new HiddenUnderFog(this); } + } - public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) + public class HiddenUnderFog : HiddenUnderShroud + { + public HiddenUnderFog(HiddenUnderFogInfo info) + : base(info) { } + + protected override bool IsVisibleInner(Actor self, Player byPlayer) { - return IsVisible(self, self.World.RenderPlayer) ? r : SpriteRenderable.None; + if (!VisibilityFootprint(self).Any(byPlayer.Shroud.IsVisible)) + return false; + + return base.IsVisibleInner(self, byPlayer); } } } diff --git a/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs b/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs new file mode 100644 index 0000000000..3882bfa5ce --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Modifiers/HiddenUnderShroud.cs @@ -0,0 +1,60 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 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. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("The actor stays invisible under the shroud.")] + public class HiddenUnderShroudInfo : ITraitInfo, IDefaultVisibilityInfo + { + [Desc("Players with these stances can always see the actor.")] + public readonly Stance AlwaysVisibleStances = Stance.Ally; + + public virtual object Create(ActorInitializer init) { return new HiddenUnderShroud(this); } + } + + public class HiddenUnderShroud : IDefaultVisibility, IRenderModifier + { + readonly HiddenUnderShroudInfo info; + + public HiddenUnderShroud(HiddenUnderShroudInfo info) + { + this.info = info; + } + + protected IEnumerable VisibilityFootprint(Actor self) + { + return Shroud.GetVisOrigins(self); + } + + protected virtual bool IsVisibleInner(Actor self, Player byPlayer) + { + return VisibilityFootprint(self).Any(byPlayer.Shroud.IsExplored); + } + + public bool IsVisible(Actor self, Player byPlayer) + { + if (byPlayer == null) + return true; + + var stance = self.Owner.Stances[byPlayer]; + return info.AlwaysVisibleStances.HasFlag(stance) || IsVisibleInner(self, byPlayer); + } + + public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) + { + return IsVisible(self, self.World.RenderPlayer) ? r : SpriteRenderable.None; + } + } +} diff --git a/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs b/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs index 3d7247bb03..c4bad798b1 100644 --- a/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs +++ b/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs @@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.Traits continue; // The actor is not currently visible - if (!self.Owner.Shroud.IsVisible(actor.Actor)) + if (!self.Owner.CanViewActor(actor.Actor)) continue; visibleActorIds.Add(actor.Actor.ActorID); diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs index dd8ea887a8..cf810e0aa0 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Traits public void Infiltrated(Actor self, Actor infiltrator) { infiltrator.Owner.Shroud.Explore(self.Owner.Shroud); - if (!self.Owner.Shroud.HasFogVisibility()) + if (!self.Owner.HasFogVisibility) self.Owner.Shroud.ResetExploration(); } } diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs index 642c4983d9..3e33e74ff9 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs @@ -137,7 +137,7 @@ namespace OpenRA.Mods.RA.Traits var targetUnits = power.UnitsInRange(xy).Where(a => !world.FogObscures(a)); foreach (var unit in targetUnits) - if (manager.Self.Owner.Shroud.IsTargetable(unit)) + if (manager.Self.Owner.CanTargetActor(unit)) yield return new SelectionBoxRenderable(unit, Color.Red); } @@ -217,7 +217,7 @@ namespace OpenRA.Mods.RA.Traits public IEnumerable RenderAfterWorld(WorldRenderer wr, World world) { foreach (var unit in power.UnitsInRange(sourceLocation)) - if (manager.Self.Owner.Shroud.IsTargetable(unit)) + if (manager.Self.Owner.CanTargetActor(unit)) yield return new SelectionBoxRenderable(unit, Color.Red); } @@ -238,7 +238,7 @@ namespace OpenRA.Mods.RA.Traits foreach (var unit in power.UnitsInRange(sourceLocation)) { var offset = world.Map.CenterOfCell(xy) - world.Map.CenterOfCell(sourceLocation); - if (manager.Self.Owner.Shroud.IsTargetable(unit)) + if (manager.Self.Owner.CanTargetActor(unit)) foreach (var r in unit.Render(wr)) yield return r.OffsetBy(offset); } @@ -246,7 +246,7 @@ namespace OpenRA.Mods.RA.Traits // Unit tiles foreach (var unit in power.UnitsInRange(sourceLocation)) { - if (manager.Self.Owner.Shroud.IsTargetable(unit)) + if (manager.Self.Owner.CanTargetActor(unit)) { var targetCell = unit.Location + (xy - sourceLocation); var canEnter = manager.Self.Owner.Shroud.IsExplored(targetCell) && diff --git a/mods/cnc/maps/gdi03/map.yaml b/mods/cnc/maps/gdi03/map.yaml index add9dcbe93..e0612e91f2 100644 --- a/mods/cnc/maps/gdi03/map.yaml +++ b/mods/cnc/maps/gdi03/map.yaml @@ -826,6 +826,7 @@ Rules: Description: Provides an overview of the battlefield.\n Requires power to operate. -AirstrikePower: airstrike.proxy: + AlwaysVisible: AirstrikePower: Icon: airstrike StartFullyCharged: True diff --git a/mods/cnc/maps/gdi05a/map.yaml b/mods/cnc/maps/gdi05a/map.yaml index fe87b209c2..4659bdfc18 100644 --- a/mods/cnc/maps/gdi05a/map.yaml +++ b/mods/cnc/maps/gdi05a/map.yaml @@ -921,6 +921,7 @@ Rules: Amount: 500 UseCashTick: yes airstrike.proxy: + AlwaysVisible: AirstrikePower: Icon: airstrike StartFullyCharged: True diff --git a/mods/cnc/maps/gdi05b/map.yaml b/mods/cnc/maps/gdi05b/map.yaml index 744d4300e1..e36a2b6c58 100644 --- a/mods/cnc/maps/gdi05b/map.yaml +++ b/mods/cnc/maps/gdi05b/map.yaml @@ -753,6 +753,7 @@ Rules: Buildable: Prerequisites: ~disabled airstrike.proxy: + AlwaysVisible: AirstrikePower: Icon: airstrike StartFullyCharged: True diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index 6cbdb96c33..35128e930d 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -162,6 +162,8 @@ C17: HP: 25 Armor: Type: Heavy + HiddenUnderFog: + AlwaysVisibleStances: None WithFacingSpriteBody: Cargo: MaxWeight: 10 diff --git a/mods/cnc/rules/civilian.yaml b/mods/cnc/rules/civilian.yaml index c2097631c5..e6e78e2994 100644 --- a/mods/cnc/rules/civilian.yaml +++ b/mods/cnc/rules/civilian.yaml @@ -367,6 +367,7 @@ BRIDGE4: SpawnOffset: 3,2 BRIDGEHUT: + HiddenUnderShroud: Building: Footprint: __ __ Dimensions: 2,2 diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index cf5195edfc..9107d871f4 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -642,6 +642,7 @@ -TargetableUnit: ^Bridge: + HiddenUnderShroud: Tooltip: Name: Bridge TargetableBuilding: @@ -656,6 +657,7 @@ ScriptTriggers: ^Crate: + HiddenUnderShroud: Tooltip: Name: Crate GenericName: Crate diff --git a/mods/cnc/rules/misc.yaml b/mods/cnc/rules/misc.yaml index 0630ff2617..6c4a5a8d0d 100644 --- a/mods/cnc/rules/misc.yaml +++ b/mods/cnc/rules/misc.yaml @@ -31,6 +31,7 @@ CRATE: Units: mcv mpspawn: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: @@ -38,6 +39,7 @@ mpspawn: BodyOrientation: waypoint: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: @@ -51,6 +53,7 @@ waypoint: Palette: colorpicker CAMERA: + AlwaysVisible: Immobile: OccupiesSpace: false Health: @@ -60,6 +63,7 @@ CAMERA: BodyOrientation: CAMERA.small: + AlwaysVisible: Immobile: OccupiesSpace: false Health: diff --git a/mods/cnc/rules/player.yaml b/mods/cnc/rules/player.yaml index 41e536991c..972385a259 100644 --- a/mods/cnc/rules/player.yaml +++ b/mods/cnc/rules/player.yaml @@ -1,4 +1,5 @@ Player: + AlwaysVisible: PlaceBuilding: TechTree: SupportPowerManager: diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index d043c3a41e..a4cba7f11c 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -938,21 +938,25 @@ BRIK: Type: concrete BARRACKS: + AlwaysVisible: Tooltip: Name: Infantry Production Description: Infantry Production VEHICLEPRODUCTION: + AlwaysVisible: Tooltip: Name: Vehicle Production Description: Vehicle Production ANYPOWER: + AlwaysVisible: Tooltip: Name: Power Plant Description: Power Plant ANYHQ: + AlwaysVisible: Tooltip: Name: a communications center Description: a communications center diff --git a/mods/cnc/rules/world.yaml b/mods/cnc/rules/world.yaml index 480d30ec23..dad3757148 100644 --- a/mods/cnc/rules/world.yaml +++ b/mods/cnc/rules/world.yaml @@ -1,4 +1,5 @@ ^BaseWorld: + AlwaysVisible: Inherits: ^Palettes ScreenMap: ActorMap: diff --git a/mods/d2k/rules/arrakis.yaml b/mods/d2k/rules/arrakis.yaml index 85e2ce093a..40a76ac9e5 100644 --- a/mods/d2k/rules/arrakis.yaml +++ b/mods/d2k/rules/arrakis.yaml @@ -1,4 +1,5 @@ spicebloom: + HiddenUnderShroud: RenderBuilding: Building: Footprint: x diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index f05b780298..d87eee569d 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -278,6 +278,7 @@ TargetTypes: Air GroundedTargetTypes: Ground HiddenUnderFog: + AlwaysVisibleStances: None GivesExperience: DrawLineToTarget: ActorLostNotification: diff --git a/mods/d2k/rules/misc.yaml b/mods/d2k/rules/misc.yaml index a0b57b81c0..acaba73a50 100644 --- a/mods/d2k/rules/misc.yaml +++ b/mods/d2k/rules/misc.yaml @@ -1,4 +1,5 @@ crate: + HiddenUnderShroud: Tooltip: Name: Crate Crate: @@ -114,12 +115,14 @@ crate: CustomBounds: 16,16 mpspawn: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: BodyOrientation: waypoint: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: @@ -136,6 +139,7 @@ waypoint: Palette: colorpicker camera: + AlwaysVisible: Immobile: OccupiesSpace: false Health: @@ -145,6 +149,7 @@ camera: BodyOrientation: wormspawner: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: @@ -152,6 +157,7 @@ wormspawner: WormSpawner: upgrade.conyard: + AlwaysVisible: Tooltip: Name: Construction Yard Upgrade Description: Unlocks new construction options @@ -170,6 +176,7 @@ upgrade.conyard: ProvidesPrerequisite@upgradename: upgrade.barracks: + AlwaysVisible: Tooltip: Name: Barracks Upgrade Description: Unlocks additional infantry @@ -188,6 +195,7 @@ upgrade.barracks: ProvidesPrerequisite@upgradename: upgrade.light: + AlwaysVisible: Tooltip: Name: Light Factory Upgrade Description: Unlocks additional light units @@ -206,6 +214,7 @@ upgrade.light: ProvidesPrerequisite@upgradename: upgrade.heavy: + AlwaysVisible: Tooltip: Name: Heavy Factory Upgrade Description: Unlocks advanced technology and heavy weapons @@ -225,6 +234,7 @@ upgrade.heavy: ProvidesPrerequisite@upgradename: upgrade.hightech: + AlwaysVisible: Tooltip: Name: High Tech Factory Upgrade Description: Unlocks the Air Strike superweapon diff --git a/mods/d2k/rules/player.yaml b/mods/d2k/rules/player.yaml index 733f333293..732075aba3 100644 --- a/mods/d2k/rules/player.yaml +++ b/mods/d2k/rules/player.yaml @@ -1,4 +1,5 @@ Player: + AlwaysVisible: TechTree: ClassicProductionQueue@Building: Type: Building diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index d4446ec149..2ae075a0bb 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -1,4 +1,5 @@ ^concrete: + AlwaysVisible: Building: Adjacent: 4 TerrainTypes: Rock @@ -493,6 +494,7 @@ starport: VisualBounds: 96,64 wall: + HiddenUnderShroud: Buildable: Queue: Building Prerequisites: barracks diff --git a/mods/d2k/rules/world.yaml b/mods/d2k/rules/world.yaml index 26f85db217..2051f262ae 100644 --- a/mods/d2k/rules/world.yaml +++ b/mods/d2k/rules/world.yaml @@ -1,5 +1,6 @@ ^BaseWorld: Inherits: ^Palettes + AlwaysVisible: ScreenMap: ActorMap: TerrainGeometryOverlay: diff --git a/mods/ra/maps/allies-03a/map.yaml b/mods/ra/maps/allies-03a/map.yaml index fea2396a9d..4cec468d4c 100644 --- a/mods/ra/maps/allies-03a/map.yaml +++ b/mods/ra/maps/allies-03a/map.yaml @@ -1405,6 +1405,7 @@ Rules: RenderSprites: Image: E7 PRISON: + HiddenUnderShroud: Immobile: OccupiesSpace: false BodyOrientation: diff --git a/mods/ra/maps/allies-03b/map.yaml b/mods/ra/maps/allies-03b/map.yaml index 1ccc8650f8..3e5da47a43 100644 --- a/mods/ra/maps/allies-03b/map.yaml +++ b/mods/ra/maps/allies-03b/map.yaml @@ -1301,6 +1301,7 @@ Rules: RenderSprites: Image: E7 PRISON: + HiddenUnderShroud: Immobile: OccupiesSpace: false BodyOrientation: @@ -1321,6 +1322,7 @@ Rules: RevealsShroud: Range: 40c0 CAMERA.Jeep: + AlwaysVisible: Mobile: TerrainSpeeds: RevealsShroud: diff --git a/mods/ra/maps/allies-05a/map.yaml b/mods/ra/maps/allies-05a/map.yaml index cc20ce373b..ad134ce93b 100644 --- a/mods/ra/maps/allies-05a/map.yaml +++ b/mods/ra/maps/allies-05a/map.yaml @@ -1622,6 +1622,7 @@ Rules: Tooltip: ShowOwnerRow: false Camera.Truk: + AlwaysVisible: Mobile: TerrainSpeeds: RevealsShroud: @@ -1674,6 +1675,7 @@ Rules: CloakDelay: 0 Palette: CloakUpgrade: + AlwaysVisible: Immobile: OccupiesSpace: false BodyOrientation: diff --git a/mods/ra/maps/bomber-john/map.yaml b/mods/ra/maps/bomber-john/map.yaml index e1aa8eeaf1..6c40239ec8 100644 --- a/mods/ra/maps/bomber-john/map.yaml +++ b/mods/ra/maps/bomber-john/map.yaml @@ -879,6 +879,7 @@ Rules: Power: Amount: 0 MINVV: + HiddenUnderFog: Building: Adjacent: 99 TerrainTypes: Clear,Road diff --git a/mods/ra/maps/desert-shellmap/map.yaml b/mods/ra/maps/desert-shellmap/map.yaml index 6c6938f6d8..f1a3e27e83 100644 --- a/mods/ra/maps/desert-shellmap/map.yaml +++ b/mods/ra/maps/desert-shellmap/map.yaml @@ -1329,10 +1329,12 @@ Rules: E7: -AnnounceOnKill: powerproxy.paratroopers: + AlwaysVisible: ParatroopersPower: DisplayBeacon: false DropItems: E1,E1,E2,E3,E4 powerproxy.parazombies: + AlwaysVisible: ParatroopersPower: DropItems: ZOMBIE,ZOMBIE,ZOMBIE,ZOMBIE,ZOMBIE QuantizedFacings: 8 diff --git a/mods/ra/maps/intervention/map.yaml b/mods/ra/maps/intervention/map.yaml index 19ed55d12a..1701f34bb6 100644 --- a/mods/ra/maps/intervention/map.yaml +++ b/mods/ra/maps/intervention/map.yaml @@ -2258,6 +2258,7 @@ Rules: ProvidesPrerequisite: Prerequisite: givefix MAINLAND: + AlwaysVisible: Tooltip: Name: Reach the mainland ProvidesPrerequisite: @@ -2269,6 +2270,7 @@ Rules: Buildable: Prerequisites: givefix GIVEFIX: + AlwaysVisible: Tooltip: Name: Weapons Factory or Helipad MIG: diff --git a/mods/ra/maps/survival02/map.yaml b/mods/ra/maps/survival02/map.yaml index 716ea2e206..469ba69653 100644 --- a/mods/ra/maps/survival02/map.yaml +++ b/mods/ra/maps/survival02/map.yaml @@ -1059,11 +1059,13 @@ Rules: GenericStancePrefix: false ShowOwnerRow: false SovietSquad: + AlwaysVisible: ParatroopersPower: DropItems: E1,E1,E2,E4,E4 QuantizedFacings: 8 DisplayBeacon: false SovietPlatoonUnits: + AlwaysVisible: ParatroopersPower: DropItems: E1,E1,E2,E4,E4,E1,E1,E2,E4,E4 QuantizedFacings: 8 diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index b365048b99..d82541291c 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -487,6 +487,7 @@ SBRIDGE4: SpawnOffset: 2,1 BRIDGEHUT: + HiddenUnderShroud: Building: Footprint: __ __ Dimensions: 2,2 @@ -497,6 +498,7 @@ BRIDGEHUT: TargetTypes: BridgeHut, C4 BRIDGEHUT.small: + HiddenUnderShroud: Building: Footprint: _ Dimensions: 1,1 diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 9de3e1a045..ea91a963e9 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -604,6 +604,7 @@ -TransformOnCapture: ^Bridge: + HiddenUnderShroud: Tooltip: Name: Bridge TargetableBuilding: @@ -653,6 +654,7 @@ RequireTilesets: DESERT ^Crate: + HiddenUnderShroud: Tooltip: Name: Crate GenericName: Crate diff --git a/mods/ra/rules/misc.yaml b/mods/ra/rules/misc.yaml index 2328f4441e..c1afe93759 100644 --- a/mods/ra/rules/misc.yaml +++ b/mods/ra/rules/misc.yaml @@ -1,4 +1,5 @@ MINP: + HiddenUnderShroud: Mine: CrushClasses: mine DetonateClasses: mine @@ -27,6 +28,7 @@ MINP: OccupiesSpace: true MINV: + HiddenUnderShroud: Mine: CrushClasses: mine DetonateClasses: mine @@ -165,6 +167,7 @@ HEALCRATE: Effect: heal CAMERA: + AlwaysVisible: Immobile: OccupiesSpace: false Health: @@ -180,6 +183,7 @@ CAMERA: Image: camera camera.paradrop: + AlwaysVisible: Immobile: OccupiesSpace: false Health: @@ -191,6 +195,7 @@ camera.paradrop: BodyOrientation: SONAR: + AlwaysVisible: Immobile: OccupiesSpace: false Health: @@ -220,6 +225,7 @@ FLARE: BodyOrientation: MINE: + HiddenUnderShroud: Tooltip: Name: Ore Mine RenderBuilding: @@ -238,6 +244,7 @@ MINE: SeedsResource: GMINE: + HiddenUnderShroud: Tooltip: Name: Gem Mine RenderBuilding: @@ -257,6 +264,7 @@ GMINE: ResourceType: Gems RAILMINE: + HiddenUnderShroud: Tooltip: Name: Abandoned Mine RenderBuilding: @@ -273,6 +281,7 @@ RAILMINE: ExcludeTilesets: INTERIOR QUEE: + HiddenUnderShroud: Tooltip: Name: Queen Ant Building: @@ -288,6 +297,7 @@ QUEE: UseTerrainPalette: true LAR1: + HiddenUnderShroud: Tooltip: Name: Ant Larva Building: @@ -304,6 +314,7 @@ LAR1: UseTerrainPalette: true LAR2: + HiddenUnderShroud: Tooltip: Name: Ant Larvae Building: @@ -320,6 +331,7 @@ LAR2: UseTerrainPalette: true powerproxy.parabombs: + AlwaysVisible: AirstrikePower: Icon: parabombs Description: Parabombs (Single Use) @@ -334,6 +346,7 @@ powerproxy.parabombs: CameraActor: camera powerproxy.sonarpulse: + AlwaysVisible: SpawnActorPower: Icon: sonar Description: Sonar Pulse @@ -348,6 +361,7 @@ powerproxy.sonarpulse: EffectPalette: moveflash powerproxy.paratroopers: + AlwaysVisible: ParatroopersPower: Icon: paratroopers Description: Paratroopers @@ -361,12 +375,14 @@ powerproxy.paratroopers: BeaconPoster: pinficon mpspawn: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: BodyOrientation: waypoint: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: diff --git a/mods/ra/rules/player.yaml b/mods/ra/rules/player.yaml index 79f607c078..ce7607c5ee 100644 --- a/mods/ra/rules/player.yaml +++ b/mods/ra/rules/player.yaml @@ -1,4 +1,5 @@ Player: + AlwaysVisible: TechTree: ClassicProductionQueue@Building: Type: Building diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 606b70fad4..bd4f760f69 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -1617,16 +1617,19 @@ WOOD: Type: woodfence BARRACKS: + AlwaysVisible: Tooltip: Name: Infantry Production Description: Infantry Production TECHCENTER: + AlwaysVisible: Tooltip: Name: Tech Center Description: Tech Center ANYPOWER: + AlwaysVisible: Tooltip: Name: Power Plant Description: Power Plant diff --git a/mods/ra/rules/world.yaml b/mods/ra/rules/world.yaml index 2d094ad808..9a09ee119c 100644 --- a/mods/ra/rules/world.yaml +++ b/mods/ra/rules/world.yaml @@ -1,5 +1,6 @@ ^BaseWorld: Inherits: ^Palettes + AlwaysVisible: ActorMap: ScreenMap: TerrainGeometryOverlay: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 0415035970..7a53d3715c 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -127,6 +127,7 @@ RequireTilesets: TEMPERAT ^Crate: + HiddenUnderShroud: Tooltip: Name: Crate Crate: @@ -140,6 +141,7 @@ CustomBounds: 24,24 ^Wall: + HiddenUnderShroud: AppearsOnRadar: Building: Dimensions: 1,1 @@ -184,6 +186,7 @@ MustBeDestroyed: ^BuildingPlug: + AlwaysVisible: Building: BuildSounds: place2.aud KillsSelf: @@ -534,6 +537,7 @@ WithActiveAnimation: ^Tree: + HiddenUnderShroud: RenderBuilding: Palette: terrain Building: @@ -545,6 +549,7 @@ Name: Tree ^Rock: + HiddenUnderShroud: RenderBuilding: Palette: terrain Building: @@ -556,6 +561,7 @@ Name: Rock ^Veinhole: + HiddenUnderShroud: RadarColorFromTerrain: Terrain: Tiberium RenderBuilding: diff --git a/mods/ts/rules/misc.yaml b/mods/ts/rules/misc.yaml index a9dd3d0d0d..a938fb8d3e 100644 --- a/mods/ts/rules/misc.yaml +++ b/mods/ts/rules/misc.yaml @@ -1,10 +1,12 @@ mpspawn: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: BodyOrientation: waypoint: + AlwaysVisible: Immobile: OccupiesSpace: false RenderEditorOnly: @@ -26,6 +28,7 @@ waypoint: Palette: colorpicker CAMERA: + AlwaysVisible: Immobile: OccupiesSpace: false Health: diff --git a/mods/ts/rules/player.yaml b/mods/ts/rules/player.yaml index 65af07b43e..970e388ca5 100644 --- a/mods/ts/rules/player.yaml +++ b/mods/ts/rules/player.yaml @@ -1,4 +1,5 @@ Player: + AlwaysVisible: TechTree: ClassicProductionQueue@Building: Type: Building diff --git a/mods/ts/rules/shared-structures.yaml b/mods/ts/rules/shared-structures.yaml index 18f95a456a..d9411eabb1 100644 --- a/mods/ts/rules/shared-structures.yaml +++ b/mods/ts/rules/shared-structures.yaml @@ -137,26 +137,31 @@ GASILO: VisualBounds: 80, 48, -5, 0 ANYPOWER: + AlwaysVisible: Tooltip: Name: Power Plant Description: Power Plant BARRACKS: + AlwaysVisible: Tooltip: Name: Infantry Production Description: Infantry Production FACTORY: + AlwaysVisible: Tooltip: Name: Vehicle Production Description: Vehicle Production RADAR: + AlwaysVisible: Tooltip: Name: Radar Description: Radar TECH: + AlwaysVisible: Tooltip: Name: Tech Center Description: Tech Center diff --git a/mods/ts/rules/world.yaml b/mods/ts/rules/world.yaml index 2c4373ea0c..a5ba5ff0a0 100644 --- a/mods/ts/rules/world.yaml +++ b/mods/ts/rules/world.yaml @@ -1,5 +1,6 @@ ^BaseWorld: Inherits: ^Palettes + AlwaysVisible: ScreenMap: ActorMap: LoadWidgetAtGameStart: