From ca1448c7ba962874f266e74900637ed86ff7a8c8 Mon Sep 17 00:00:00 2001 From: Mustafa Alperen Seki Date: Thu, 13 Jul 2017 17:04:09 +0200 Subject: [PATCH] Add Support of Types for GivesBuildableArea --- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 2 ++ .../Traits/Buildings/Building.cs | 31 ++++++++-------- .../Traits/Buildings/GivesBuildableArea.cs | 36 +++++++++++++++++++ .../Traits/Buildings/RequiresBuildableArea.cs | 29 +++++++++++++++ .../UtilityCommands/UpgradeRules.cs | 24 +++++++++++++ mods/cnc/rules/defaults.yaml | 9 +++-- mods/d2k/rules/defaults.yaml | 3 ++ mods/d2k/rules/structures.yaml | 17 +++++---- mods/ra/maps/bomber-john/rules.yaml | 1 - mods/ra/maps/fort-lonestar/rules.yaml | 2 ++ mods/ra/rules/civilian.yaml | 1 + mods/ra/rules/defaults.yaml | 11 ++++-- mods/ra/rules/fakes.yaml | 6 ++-- mods/ra/rules/structures.yaml | 11 +++--- mods/ts/rules/defaults.yaml | 8 +++-- mods/ts/rules/nod-structures.yaml | 3 +- 16 files changed, 157 insertions(+), 37 deletions(-) create mode 100644 OpenRA.Mods.Common/Traits/Buildings/GivesBuildableArea.cs create mode 100644 OpenRA.Mods.Common/Traits/Buildings/RequiresBuildableArea.cs diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 5388ce8430..25bb436d75 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -286,6 +286,7 @@ + @@ -293,6 +294,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Buildings/Building.cs b/OpenRA.Mods.Common/Traits/Buildings/Building.cs index d099b8a155..cc846960d7 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Building.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Building.cs @@ -19,10 +19,6 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - [Desc("Remove this trait to limit base-walking by cheap or defensive buildings.")] - public class GivesBuildableAreaInfo : TraitInfo { } - public class GivesBuildableArea { } - public enum FootprintCellType { Empty = '_', @@ -36,10 +32,6 @@ namespace OpenRA.Mods.Common.Traits [Desc("Where you are allowed to place the building (Water, Clear, ...)")] public readonly HashSet TerrainTypes = new HashSet(); - [Desc("The range to the next building it can be constructed. Set it higher for walls.", - "Set to '-1' to disable adjacency checks.")] - public readonly int Adjacent = 2; - [Desc("x means cell is blocked, capital X means blocked but not counting as targetable, ", "= means part of the footprint but passable, _ means completely empty.")] [FieldLoader.LoadUsing("LoadFootprint")] @@ -175,19 +167,28 @@ namespace OpenRA.Mods.Common.Traits return null; } + bool ActorGrantsValidArea(Actor a, RequiresBuildableAreaInfo rba) + { + return rba.AreaTypes.Overlaps(a.TraitsImplementing() + .SelectMany(gba => gba.AreaTypes)); + } + public virtual bool IsCloseEnoughToBase(World world, Player p, string buildingName, CPos topLeft) { + var requiresBuildableArea = world.Map.Rules.Actors[buildingName].TraitInfoOrDefault(); var mapBuildRadius = world.WorldActor.Trait(); - if (Adjacent < 0 || p.PlayerActor.Trait().BuildAnywhere) + + if (requiresBuildableArea == null || p.PlayerActor.Trait().BuildAnywhere) return true; if (mapBuildRadius.BuildRadiusEnabled && RequiresBaseProvider && FindBaseProvider(world, p, topLeft) == null) return false; + var adjacent = requiresBuildableArea.Adjacent; var buildingMaxBounds = Dimensions; - var scanStart = world.Map.Clamp(topLeft - new CVec(Adjacent, Adjacent)); - var scanEnd = world.Map.Clamp(topLeft + buildingMaxBounds + new CVec(Adjacent, Adjacent)); + var scanStart = world.Map.Clamp(topLeft - new CVec(adjacent, adjacent)); + var scanEnd = world.Map.Clamp(topLeft + buildingMaxBounds + new CVec(adjacent, adjacent)); var nearnessCandidates = new List(); var bi = world.WorldActor.Trait(); @@ -205,12 +206,12 @@ namespace OpenRA.Mods.Common.Traits { var unitsAtPos = world.ActorMap.GetActorsAt(pos).Where(a => a.IsInWorld && (a.Owner == p || (allyBuildEnabled && a.Owner.Stances[p] == Stance.Ally)) - && a.Info.HasTraitInfo()); + && ActorGrantsValidArea(a, requiresBuildableArea)); if (unitsAtPos.Any()) nearnessCandidates.Add(pos); } - else if (buildingAtPos.IsInWorld && buildingAtPos.Info.HasTraitInfo() + else if (buildingAtPos.IsInWorld && ActorGrantsValidArea(buildingAtPos, requiresBuildableArea) && (buildingAtPos.Owner == p || (allyBuildEnabled && buildingAtPos.Owner.Stances[p] == Stance.Ally))) nearnessCandidates.Add(pos); } @@ -219,8 +220,8 @@ namespace OpenRA.Mods.Common.Traits var buildingTiles = Tiles(topLeft).ToList(); return nearnessCandidates .Any(a => buildingTiles - .Any(b => Math.Abs(a.X - b.X) <= Adjacent - && Math.Abs(a.Y - b.Y) <= Adjacent)); + .Any(b => Math.Abs(a.X - b.X) <= adjacent + && Math.Abs(a.Y - b.Y) <= adjacent)); } public IReadOnlyDictionary OccupiedCells(ActorInfo info, CPos topLeft, SubCell subCell = SubCell.Any) diff --git a/OpenRA.Mods.Common/Traits/Buildings/GivesBuildableArea.cs b/OpenRA.Mods.Common/Traits/Buildings/GivesBuildableArea.cs new file mode 100644 index 0000000000..c5b1fc746a --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Buildings/GivesBuildableArea.cs @@ -0,0 +1,36 @@ +#region Copyright & License Information +/* + * Copyright 2007-2017 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 System.Collections.Generic; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("This actor allows placement of other actors with 'RequiresBuildableArea' trait around it.")] + public class GivesBuildableAreaInfo : ConditionalTraitInfo + { + [FieldLoader.Require] + [Desc("Types of buildable area this actor gives.")] + public readonly HashSet AreaTypes = new HashSet(); + + public override object Create(ActorInitializer init) { return new GivesBuildableArea(this); } + } + + public class GivesBuildableArea : ConditionalTrait + { + public GivesBuildableArea(GivesBuildableAreaInfo info) + : base(info) { } + + readonly HashSet noAreaTypes = new HashSet(); + + public HashSet AreaTypes { get { return !IsTraitDisabled ? Info.AreaTypes : noAreaTypes; } } + } +} diff --git a/OpenRA.Mods.Common/Traits/Buildings/RequiresBuildableArea.cs b/OpenRA.Mods.Common/Traits/Buildings/RequiresBuildableArea.cs new file mode 100644 index 0000000000..8f92b0036e --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Buildings/RequiresBuildableArea.cs @@ -0,0 +1,29 @@ +#region Copyright & License Information +/* + * Copyright 2007-2017 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 System.Collections.Generic; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("This actor requires another actor with 'GivesBuildableArea' trait around to be placed.")] + public class RequiresBuildableAreaInfo : TraitInfo, Requires + { + [FieldLoader.Require] + [Desc("Types of buildable are this actor requires.")] + public readonly HashSet AreaTypes = new HashSet(); + + [Desc("Maximum range from the actor with 'GivesBuildableArea' this can be placed at.")] + public readonly int Adjacent = 2; + } + + public class RequiresBuildableArea { } +} diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 77877f0f9a..136f89c24f 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -1210,6 +1210,30 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + if (engineVersion < 20171120) + { + // AreaTypes support is added to GivesBuildableArea and it is required. + var givesBuildableArea = node.Value.Nodes.FirstOrDefault(n => n.Key == "GivesBuildableArea"); + if (givesBuildableArea != null) + givesBuildableArea.Value.Nodes.Add(new MiniYamlNode("AreaTypes", "building")); + + // RequiresBuildableArea trait is added and Building.Adjacent is moved there. + var building = node.Value.Nodes.FirstOrDefault(n => n.Key == "Building"); + if (building != null) + { + var adjacent = building.Value.Nodes.FirstOrDefault(n => n.Key == "Adjacent"); + var areaTypes = new MiniYamlNode("AreaTypes", "building"); + var requiresBuildableArea = new MiniYamlNode("RequiresBuildableArea", ""); + + requiresBuildableArea.Value.Nodes.Add(areaTypes); + if (adjacent != null) + requiresBuildableArea.Value.Nodes.Add(adjacent); + + node.Value.Nodes.Add(requiresBuildableArea); + building.Value.Nodes.Remove(adjacent); + } + } + UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1); } diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index a39a2e8cb9..6512cd4a4d 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -691,10 +691,12 @@ ^BaseBuilding: Inherits: ^Building Building: - Adjacent: 4 RequiresBaseProvider: true BuildSounds: constru2.aud, hvydoor1.aud TerrainTypes: Clear,Road + RequiresBuildableArea: + AreaTypes: building + Adjacent: 4 MustBeDestroyed: RequiredForShortGame: true RepairableBuilding: @@ -705,6 +707,7 @@ DeathSequence: dead UseDeathTypeSuffix: false GivesBuildableArea: + AreaTypes: building EmitInfantryOnSell: ActorTypes: e6,e1,e1,e1 EngineerRepairable: @@ -796,8 +799,10 @@ Dimensions: 1,1 Footprint: x BuildSounds: hvydoor1.aud - Adjacent: 7 TerrainTypes: Clear,Road + RequiresBuildableArea: + AreaTypes: building + Adjacent: 4 Targetable: TargetTypes: Ground, Wall Crushable: diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index 4213ce46f3..13858b6c7b 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -395,8 +395,11 @@ Footprint: x TerrainTypes: Rock, Concrete BuildSounds: BUILD1.WAV + RequiresBuildableArea: + AreaTypes: building Adjacent: 3 GivesBuildableArea: + AreaTypes: building Capturable: CaptureThreshold: 100 SoundOnDamageTransition: diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index 599335c24f..e33d034015 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -1,10 +1,12 @@ ^concrete: AlwaysVisible: Building: - Adjacent: 4 TerrainTypes: Rock BuildSounds: CHUNG.WAV AllowInvalidPlacement: true + RequiresBuildableArea: + AreaTypes: building + Adjacent: 4 LaysTerrain: Template: 88 TerrainTypes: Rock @@ -55,7 +57,6 @@ construction_yard: Building: Footprint: xxx xxx === Dimensions: 3,3 - Adjacent: 4 LocalCenterOffset: 0,-512,0 LaysTerrain: TerrainTypes: Rock @@ -324,7 +325,7 @@ silo: Cost: 120 Tooltip: Name: Silo - Building: + RequiresBuildableArea: Adjacent: 4 -GivesBuildableArea: Health: @@ -677,8 +678,10 @@ wall: AppearsOnRadar: Building: BuildSounds: CHUNG.WAV - Adjacent: 7 TerrainTypes: Rock, Concrete + RequiresBuildableArea: + AreaTypes: building + Adjacent: 7 Health: HP: 2000 Armor: @@ -729,8 +732,9 @@ medium_gun_turret: Tooltip: Name: Gun Turret Building: - Adjacent: 4 BuildSounds: CHUNG.WAV + RequiresBuildableArea: + Adjacent: 4 Sellable: SellSounds: CHUNG.WAV Selectable: @@ -775,8 +779,9 @@ large_gun_turret: Tooltip: Name: Rocket Turret Building: - Adjacent: 4 BuildSounds: CHUNG.WAV + RequiresBuildableArea: + Adjacent: 4 Sellable: SellSounds: CHUNG.WAV Selectable: diff --git a/mods/ra/maps/bomber-john/rules.yaml b/mods/ra/maps/bomber-john/rules.yaml index 449c8c403a..1aca12a31e 100644 --- a/mods/ra/maps/bomber-john/rules.yaml +++ b/mods/ra/maps/bomber-john/rules.yaml @@ -141,7 +141,6 @@ MINVV: HiddenUnderFog: Building: TerrainTypes: Clear,Road - Adjacent: -1 Buildable: Queue: Building BuildPaletteOrder: 10 diff --git a/mods/ra/maps/fort-lonestar/rules.yaml b/mods/ra/maps/fort-lonestar/rules.yaml index 94372086bb..80f2db1fa1 100644 --- a/mods/ra/maps/fort-lonestar/rules.yaml +++ b/mods/ra/maps/fort-lonestar/rules.yaml @@ -175,6 +175,7 @@ FTUR: Power: Amount: 0 GivesBuildableArea: + AreaTypes: building PBOX: Buildable: @@ -188,6 +189,7 @@ PBOX: Power: Amount: 0 GivesBuildableArea: + AreaTypes: building DOG: Buildable: diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index dfbaced362..aac076b050 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -85,6 +85,7 @@ FCOM: CaptureCompleteTime: 30 ExternalCapturableBar: GivesBuildableArea: + AreaTypes: building BaseProvider: Range: 8c0 EngineerRepairable: diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 352f8d084d..41639c62a5 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -587,6 +587,8 @@ Footprint: x TerrainTypes: Clear,Road RequiresBaseProvider: True + RequiresBuildableArea: + AreaTypes: building SoundOnDamageTransition: DamagedSounds: kaboom1.aud DestroyedSounds: kaboom22.aud @@ -616,6 +618,7 @@ Huntable: UpdatesPlayerStatistics: GivesBuildableArea: + AreaTypes: building RepairableBuilding: PlayerExperience: 25 EngineerRepairable: @@ -662,8 +665,10 @@ Dimensions: 1,1 Footprint: x BuildSounds: placbldg.aud - Adjacent: 7 TerrainTypes: Clear,Road + RequiresBuildableArea: + AreaTypes: building + Adjacent: 7 SoundOnDamageTransition: DamagedSounds: sandbag2.aud DestroyedSounds: sandbag2.aud @@ -706,12 +711,14 @@ Tooltip: Name: Gate Gate: - Adjacent: 4 BlocksProjectilesHeight: 0 BuildSounds: place2.aud OpeningSound: cashturn.aud ClosingSound: cashturn.aud TerrainTypes: Clear, Road + RequiresBuildableArea: + AreaTypes: building + Adjacent: 4 EditorTilesetFilter: Categories: Wall diff --git a/mods/ra/rules/fakes.yaml b/mods/ra/rules/fakes.yaml index 12c9fcc983..6d76cf95eb 100644 --- a/mods/ra/rules/fakes.yaml +++ b/mods/ra/rules/fakes.yaml @@ -49,8 +49,9 @@ SYRF: Building: Footprint: XXX xxx XXX Dimensions: 3,3 - Adjacent: 8 TerrainTypes: Water + RequiresBuildableArea: + Adjacent: 8 RenderSprites: Image: SYRD Valued: @@ -91,8 +92,9 @@ SPEF: Building: Footprint: XXX xxx XXX Dimensions: 3,3 - Adjacent: 8 TerrainTypes: Water + RequiresBuildableArea: + Adjacent: 8 RenderSprites: Image: SPEN Valued: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 838e2ea60d..6a5362194b 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -125,8 +125,10 @@ SPEN: Building: Footprint: XXX xxx XXX Dimensions: 3,3 - Adjacent: 8 TerrainTypes: Water + RequiresBuildableArea: + AreaTypes: building + Adjacent: 8 -GivesBuildableArea: Health: HP: 1000 @@ -227,8 +229,9 @@ SYRD: Building: Footprint: XXX xxx XXX Dimensions: 3,3 - Adjacent: 8 TerrainTypes: Water + RequiresBuildableArea: + Adjacent: 8 -GivesBuildableArea: Health: HP: 1000 @@ -1154,8 +1157,6 @@ SILO: Cost: 150 Tooltip: Name: Silo - Building: - Adjacent: 2 -GivesBuildableArea: Health: HP: 300 @@ -1603,8 +1604,6 @@ KENN: Cost: 100 Tooltip: Name: Kennel - Building: - Adjacent: 2 -GivesBuildableArea: Health: HP: 300 diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index c5a5e5c47c..345667ee5e 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -309,6 +309,8 @@ Footprint: x BuildSounds: place2.aud TerrainTypes: Clear, Road, DirtRoad, Rough + RequiresBuildableArea: + AreaTypes: building Adjacent: 4 FrozenUnderFog: SoundOnDamageTransition: @@ -340,6 +342,7 @@ Inherits@1: ^BasicBuilding Inherits@2: ^EmpDisable GivesBuildableArea: + AreaTypes: building Capturable: RepairableBuilding: IndicatorPalette: mouse @@ -439,8 +442,10 @@ Dimensions: 1,1 Footprint: x BuildSounds: place2.aud - Adjacent: 7 TerrainTypes: Clear, Rough, Road, DirtRoad, Green, Sand, Pavement + RequiresBuildableArea: + AreaTypes: building + Adjacent: 7 SoundOnDamageTransition: DamagedSounds: expnew01.aud DestroyedSounds: crmble2.aud @@ -1134,7 +1139,6 @@ OpenSequence: open Tooltip: Gate: - Adjacent: 4 BuildSounds: place2.aud OpeningSound: gateup1.aud ClosingSound: gatedwn1.aud diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index 31a1b58e9b..b732362bd2 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -348,9 +348,10 @@ NATMPL: Tooltip: Name: Temple of Nod Building: - Adjacent: 3 Footprint: xxxx xxxx xxxX Dimensions: 4,3 + RequiresBuildableArea: + Adjacent: 3 Selectable: Bounds: 134, 120, 12, -12 Health: