From 1bcc07ce6980bad1c6f3678b196367f92f7391b8 Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Sat, 11 Jul 2015 16:30:27 -0500 Subject: [PATCH] Add property requirements to safe traits --- OpenRA.Mods.Common/Traits/Armament.cs | 4 ++-- OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs | 9 ++++++--- OpenRA.Mods.Common/Traits/Buildings/FreeActor.cs | 2 +- .../Traits/Buildings/TargetableBuilding.cs | 1 + OpenRA.Mods.Common/Traits/Crates/ExplodeCrateAction.cs | 2 +- OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs | 2 +- .../Traits/Crates/GrantUpgradeCrateAction.cs | 2 +- .../Traits/Crates/SupportPowerCrateAction.cs | 2 +- OpenRA.Mods.Common/Traits/CustomBuildTimeValue.cs | 1 + OpenRA.Mods.Common/Traits/CustomSelectionSize.cs | 1 + OpenRA.Mods.Common/Traits/CustomSellValue.cs | 1 + OpenRA.Mods.Common/Traits/GlobalUpgradable.cs | 3 ++- OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs | 3 ++- .../Traits/Infantry/TerrainModifiesDamage.cs | 9 ++------- OpenRA.Mods.Common/Traits/Mobile.cs | 2 +- OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs | 1 + OpenRA.Mods.Common/Traits/Plug.cs | 1 + OpenRA.Mods.Common/Traits/Pluggable.cs | 9 ++------- OpenRA.Mods.Common/Traits/Production.cs | 1 + OpenRA.Mods.Common/Traits/ProximityCaptor.cs | 1 + OpenRA.Mods.Common/Traits/Render/TimedUpgradeBar.cs | 1 + OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs | 1 + OpenRA.Mods.Common/Traits/StoresResources.cs | 2 ++ .../Traits/SupportPowers/GrantUpgradePower.cs | 2 +- .../Traits/SupportPowers/SpawnActorPower.cs | 2 ++ OpenRA.Mods.Common/Traits/ThrowsParticle.cs | 1 + OpenRA.Mods.Common/Traits/ThrowsShrapnel.cs | 2 +- OpenRA.Mods.Common/Traits/TransformOnPassenger.cs | 2 +- OpenRA.Mods.Common/Traits/Transforms.cs | 2 +- OpenRA.Mods.Common/Traits/Upgrades/DeployToUpgrade.cs | 2 +- OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs | 2 +- OpenRA.Mods.Common/Traits/Valued.cs | 1 + .../Traits/VeteranProductionIconOverlay.cs | 1 + OpenRA.Mods.Common/Traits/Voiced.cs | 1 + .../Traits/World/PaletteFromCurrentTileset.cs | 1 + OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs | 2 ++ .../Traits/World/PaletteFromPaletteWithAlpha.cs | 2 ++ .../Traits/World/PaletteFromPlayerPaletteWithAlpha.cs | 2 ++ OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs | 1 + .../Traits/World/PlayerPaletteFromCurrentTileset.cs | 1 + .../Traits/Buildings/FreeActorWithDelivery.cs | 7 +------ OpenRA.Mods.D2k/Traits/Buildings/LaysTerrain.cs | 1 + OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs | 1 + OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs | 2 ++ OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs | 2 ++ OpenRA.Mods.D2k/Traits/World/PaletteFromScaledPalette.cs | 2 ++ OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs | 1 + OpenRA.Mods.RA/Traits/Cloneable.cs | 1 + .../Traits/Infiltration/InfiltrateForSupportPower.cs | 2 +- OpenRA.Mods.RA/Traits/LeavesHusk.cs | 2 +- 50 files changed, 68 insertions(+), 41 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Armament.cs b/OpenRA.Mods.Common/Traits/Armament.cs index f36d7823d0..7d61442ce1 100644 --- a/OpenRA.Mods.Common/Traits/Armament.cs +++ b/OpenRA.Mods.Common/Traits/Armament.cs @@ -28,8 +28,8 @@ namespace OpenRA.Mods.Common.Traits { public readonly string Name = "primary"; - [WeaponReference] - [Desc("Has to be defined here and in weapons.yaml.")] + [WeaponReference, FieldLoader.Require] + [Desc("Has to be defined in weapons.yaml as well.")] public readonly string Weapon = null; [Desc("Which limited ammo pool (if present) should this armament be assigned to.")] diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs index 158461f851..87a502dc00 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs @@ -27,14 +27,17 @@ namespace OpenRA.Mods.Common.Traits [Desc("Cargo can fire their weapons out of fire ports.")] public class AttackGarrisonedInfo : AttackFollowInfo, Requires { + [FieldLoader.Require] [Desc("Fire port offsets in local coordinates.")] - public readonly WVec[] PortOffsets = { }; + public readonly WVec[] PortOffsets = null; + [FieldLoader.Require] [Desc("Fire port yaw angles.")] - public readonly WAngle[] PortYaws = { }; + public readonly WAngle[] PortYaws = null; + [FieldLoader.Require] [Desc("Fire port yaw cone angle.")] - public readonly WAngle[] PortCones = { }; + public readonly WAngle[] PortCones = null; public readonly string MuzzlePalette = "effect"; diff --git a/OpenRA.Mods.Common/Traits/Buildings/FreeActor.cs b/OpenRA.Mods.Common/Traits/Buildings/FreeActor.cs index ca018b8601..16ec0b8583 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/FreeActor.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/FreeActor.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits "If you want more than one unit to appear copy this section and assign IDs like FreeActor@2, ...")] public class FreeActorInfo : ITraitInfo { - [ActorReference] + [ActorReference, FieldLoader.Require] [Desc("Name of the actor.")] public readonly string Actor = null; diff --git a/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs b/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs index 6eb0049105..e81b8fafbc 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs @@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits { public class TargetableBuildingInfo : ITraitInfo, ITargetableInfo, Requires { + [FieldLoader.Require] public readonly string[] TargetTypes = { }; public string[] GetTargetTypes() { return TargetTypes; } diff --git a/OpenRA.Mods.Common/Traits/Crates/ExplodeCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/ExplodeCrateAction.cs index 6123112c4f..48f7ea4438 100644 --- a/OpenRA.Mods.Common/Traits/Crates/ExplodeCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/ExplodeCrateAction.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits class ExplodeCrateActionInfo : CrateActionInfo { [Desc("The weapon to fire upon collection.")] - [WeaponReference] public string Weapon = null; + [WeaponReference, FieldLoader.Require] public string Weapon = null; public override object Create(ActorInitializer init) { return new ExplodeCrateAction(init.Self, this); } } diff --git a/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs index cc1d8bed3d..a4df257b13 100644 --- a/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits class GiveUnitCrateActionInfo : CrateActionInfo { [Desc("The list of units to spawn.")] - [ActorReference] + [ActorReference, FieldLoader.Require] public readonly string[] Units = { }; [Desc("Races that are allowed to trigger this action")] diff --git a/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs index 9c04991d86..9db05ff227 100644 --- a/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs @@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Grants an upgrade to the collector.")] public class GrantUpgradeCrateActionInfo : CrateActionInfo { - [UpgradeGrantedReference] + [UpgradeGrantedReference, FieldLoader.Require] [Desc("The upgrades to apply.")] public readonly string[] Upgrades = { }; diff --git a/OpenRA.Mods.Common/Traits/Crates/SupportPowerCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/SupportPowerCrateAction.cs index 7e5013a1d3..3e1047be34 100644 --- a/OpenRA.Mods.Common/Traits/Crates/SupportPowerCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/SupportPowerCrateAction.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits class SupportPowerCrateActionInfo : CrateActionInfo { [Desc("Which proxy actor, which grants the support power, to spawn.")] - [ActorReference] public readonly string Proxy = null; + [ActorReference, FieldLoader.Require] public readonly string Proxy = null; public override object Create(ActorInitializer init) { return new SupportPowerCrateAction(init.Self, this); } } diff --git a/OpenRA.Mods.Common/Traits/CustomBuildTimeValue.cs b/OpenRA.Mods.Common/Traits/CustomBuildTimeValue.cs index 8efb1bfd1d..bdd7ea4c3d 100644 --- a/OpenRA.Mods.Common/Traits/CustomBuildTimeValue.cs +++ b/OpenRA.Mods.Common/Traits/CustomBuildTimeValue.cs @@ -15,6 +15,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Overrides the build time calculated by actor value.")] public class CustomBuildTimeValueInfo : TraitInfo { + [FieldLoader.Require] [Desc("Measured in ticks.")] public readonly int Value = 0; } diff --git a/OpenRA.Mods.Common/Traits/CustomSelectionSize.cs b/OpenRA.Mods.Common/Traits/CustomSelectionSize.cs index e3eca9e5dd..30a3a5652d 100644 --- a/OpenRA.Mods.Common/Traits/CustomSelectionSize.cs +++ b/OpenRA.Mods.Common/Traits/CustomSelectionSize.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits "Examples: bridge huts and crates.")] public class CustomSelectionSizeInfo : ITraitInfo { + [FieldLoader.Require] public readonly int[] CustomBounds = null; public object Create(ActorInitializer init) { return new CustomSelectionSize(this); } diff --git a/OpenRA.Mods.Common/Traits/CustomSellValue.cs b/OpenRA.Mods.Common/Traits/CustomSellValue.cs index 42a7a39ab7..67a12d8692 100644 --- a/OpenRA.Mods.Common/Traits/CustomSellValue.cs +++ b/OpenRA.Mods.Common/Traits/CustomSellValue.cs @@ -15,6 +15,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Allow a non-standard sell/repair value to avoid buy-sell exploits.")] public class CustomSellValueInfo : TraitInfo { + [FieldLoader.Require] public readonly int Value = 0; } diff --git a/OpenRA.Mods.Common/Traits/GlobalUpgradable.cs b/OpenRA.Mods.Common/Traits/GlobalUpgradable.cs index a49b854d9b..6b5f33398e 100644 --- a/OpenRA.Mods.Common/Traits/GlobalUpgradable.cs +++ b/OpenRA.Mods.Common/Traits/GlobalUpgradable.cs @@ -16,10 +16,11 @@ namespace OpenRA.Mods.Common.Traits [Desc("Grants upgrades to the actor this is attached to when prerequisites are available.")] public class GlobalUpgradableInfo : ITraitInfo, Requires { - [UpgradeGrantedReference] + [UpgradeGrantedReference, FieldLoader.Require] [Desc("List of upgrades to apply.")] public readonly string[] Upgrades = { }; + [FieldLoader.Require] [Desc("List of required prerequisites.")] public readonly string[] Prerequisites = { }; diff --git a/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs b/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs index b84b1ce5a4..56b9a7170e 100644 --- a/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs +++ b/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs @@ -24,8 +24,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Prone movement speed as a percentage of the normal speed.")] public readonly int SpeedModifier = 50; + [FieldLoader.Require] [Desc("Damage types that trigger prone state. Defined on the warheads.")] - public readonly string[] DamageTriggers = new string[0]; + public readonly string[] DamageTriggers = null; [FieldLoader.LoadUsing("LoadModifiers")] [Desc("Damage modifiers for each damage type (defined on the warheads) while the unit is prone.")] diff --git a/OpenRA.Mods.Common/Traits/Infantry/TerrainModifiesDamage.cs b/OpenRA.Mods.Common/Traits/Infantry/TerrainModifiesDamage.cs index cd4eeb4ca8..81a9cd082f 100644 --- a/OpenRA.Mods.Common/Traits/Infantry/TerrainModifiesDamage.cs +++ b/OpenRA.Mods.Common/Traits/Infantry/TerrainModifiesDamage.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits { public class TerrainModifiesDamageInfo : ITraitInfo { - [FieldLoader.LoadUsing("LoadPercents")] + [FieldLoader.LoadUsing("LoadPercents", true)] [Desc("Damage percentage for specific terrain types. 120 = 120%, 80 = 80%, etc.")] public readonly Dictionary TerrainModifier = null; @@ -28,12 +28,7 @@ namespace OpenRA.Mods.Common.Traits static object LoadPercents(MiniYaml y) { - MiniYaml percents; - - if (!y.ToDictionary().TryGetValue("TerrainModifier", out percents)) - return new Dictionary(); - - return percents.Nodes.ToDictionary( + return y.ToDictionary()["TerrainModifier"].Nodes.ToDictionary( kv => FieldLoader.GetValue("(key)", kv.Key), kv => FieldLoader.GetValue("(value)", kv.Value.Value)); } diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index ed25c3efd5..c3e102a9a3 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Unit is able to move.")] public class MobileInfo : IMoveInfo, IOccupySpaceInfo, IFacingInfo, UsesInit, UsesInit, UsesInit { - [FieldLoader.LoadUsing("LoadSpeeds")] + [FieldLoader.LoadUsing("LoadSpeeds", true)] [Desc("Set Water: 0 for ground units and lower the value on rough terrain.")] public readonly Dictionary TerrainSpeeds; diff --git a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs index 7f05ee84e8..7932a8c385 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Traits "at the same time. Will only work together with the Production: trait.")] public class ProductionQueueInfo : ITraitInfo { + [FieldLoader.Require] [Desc("What kind of production will be added (e.g. Building, Infantry, Vehicle, ...)")] public readonly string Type = null; diff --git a/OpenRA.Mods.Common/Traits/Plug.cs b/OpenRA.Mods.Common/Traits/Plug.cs index 625d8b4389..9d69c35749 100644 --- a/OpenRA.Mods.Common/Traits/Plug.cs +++ b/OpenRA.Mods.Common/Traits/Plug.cs @@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits { public class PlugInfo : TraitInfo { + [FieldLoader.Require] [Desc("Plug type (matched against Upgrades in Pluggable)")] public readonly string Type = null; } diff --git a/OpenRA.Mods.Common/Traits/Pluggable.cs b/OpenRA.Mods.Common/Traits/Pluggable.cs index 34804b99d3..d91a850aaa 100644 --- a/OpenRA.Mods.Common/Traits/Pluggable.cs +++ b/OpenRA.Mods.Common/Traits/Pluggable.cs @@ -19,18 +19,13 @@ namespace OpenRA.Mods.Common.Traits [Desc("Footprint cell offset where a plug can be placed.")] public readonly CVec Offset = CVec.Zero; - [FieldLoader.LoadUsing("LoadUpgrades")] + [FieldLoader.LoadUsing("LoadUpgrades", true)] [Desc("Upgrades to grant for each accepted plug type.")] public readonly Dictionary Upgrades = null; static object LoadUpgrades(MiniYaml y) { - MiniYaml upgrades; - - if (!y.ToDictionary().TryGetValue("Upgrades", out upgrades)) - return new Dictionary(); - - return upgrades.Nodes.ToDictionary( + return y.ToDictionary()["Upgrades"].Nodes.ToDictionary( kv => kv.Key, kv => FieldLoader.GetValue("(value)", kv.Value.Value)); } diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index 3860a21d93..46dc6ed45b 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -21,6 +21,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("This unit has access to build queues.")] public class ProductionInfo : ITraitInfo { + [FieldLoader.Require] [Desc("e.g. Infantry, Vehicles, Aircraft, Buildings")] public readonly string[] Produces = { }; diff --git a/OpenRA.Mods.Common/Traits/ProximityCaptor.cs b/OpenRA.Mods.Common/Traits/ProximityCaptor.cs index 913bd677d6..cb40d26829 100644 --- a/OpenRA.Mods.Common/Traits/ProximityCaptor.cs +++ b/OpenRA.Mods.Common/Traits/ProximityCaptor.cs @@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Actor can capture ProximityCapturable actors.")] public class ProximityCaptorInfo : ITraitInfo { + [FieldLoader.Require] public readonly string[] Types = { }; public object Create(ActorInitializer init) { return new ProximityCaptor(this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/TimedUpgradeBar.cs b/OpenRA.Mods.Common/Traits/Render/TimedUpgradeBar.cs index a447433aba..58ae1669a9 100644 --- a/OpenRA.Mods.Common/Traits/Render/TimedUpgradeBar.cs +++ b/OpenRA.Mods.Common/Traits/Render/TimedUpgradeBar.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Visualizes the remaining time for an upgrade.")] class TimedUpgradeBarInfo : ITraitInfo, Requires { + [FieldLoader.Require] [Desc("Upgrade that this bar corresponds to")] public readonly string Upgrade = null; diff --git a/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs b/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs index c8d971d457..7ad82ca1c7 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs @@ -15,6 +15,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Plays a looping audio file at the actor position. Attach this to the `World` actor to cover the whole map.")] class AmbientSoundInfo : ITraitInfo { + [FieldLoader.Require] public readonly string SoundFile = null; public object Create(ActorInitializer init) { return new AmbientSound(init.Self, this); } diff --git a/OpenRA.Mods.Common/Traits/StoresResources.cs b/OpenRA.Mods.Common/Traits/StoresResources.cs index d9fe185256..638228cfb9 100644 --- a/OpenRA.Mods.Common/Traits/StoresResources.cs +++ b/OpenRA.Mods.Common/Traits/StoresResources.cs @@ -18,9 +18,11 @@ namespace OpenRA.Mods.Common.Traits [Desc("Used for silos.")] class StoresResourcesInfo : ITraitInfo { + [FieldLoader.Require] [Desc("Number of little squares used to display how filled unit is.")] public readonly int PipCount = 0; public readonly PipType PipColor = PipType.Yellow; + [FieldLoader.Require] public readonly int Capacity = 0; public object Create(ActorInitializer init) { return new StoresResources(init.Self, this); } } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs index 2e4b8f3ab1..e78e5822cd 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits { class GrantUpgradePowerInfo : SupportPowerInfo { - [UpgradeGrantedReference] + [UpgradeGrantedReference, FieldLoader.Require] [Desc("The upgrades to apply.")] public readonly string[] Upgrades = { }; diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs index 56f7704a2b..8a4f93cace 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs @@ -12,12 +12,14 @@ using OpenRA.Effects; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Effects; using OpenRA.Primitives; +using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Spawns an actor that stays for a limited amount of time.")] public class SpawnActorPowerInfo : SupportPowerInfo { + [ActorReference, FieldLoader.Require] [Desc("Actor to spawn.")] public readonly string Actor = null; diff --git a/OpenRA.Mods.Common/Traits/ThrowsParticle.cs b/OpenRA.Mods.Common/Traits/ThrowsParticle.cs index 575239ebae..04a8340c2f 100644 --- a/OpenRA.Mods.Common/Traits/ThrowsParticle.cs +++ b/OpenRA.Mods.Common/Traits/ThrowsParticle.cs @@ -15,6 +15,7 @@ namespace OpenRA.Mods.Common.Traits { class ThrowsParticleInfo : ITraitInfo, Requires, Requires { + [FieldLoader.Require] public readonly string Anim = null; [Desc("Initial position relative to body")] diff --git a/OpenRA.Mods.Common/Traits/ThrowsShrapnel.cs b/OpenRA.Mods.Common/Traits/ThrowsShrapnel.cs index aea6878568..b610b7ccd5 100644 --- a/OpenRA.Mods.Common/Traits/ThrowsShrapnel.cs +++ b/OpenRA.Mods.Common/Traits/ThrowsShrapnel.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Throws particles when the actor is destroyed that do damage on impact.")] public class ThrowsShrapnelInfo : ITraitInfo { - [WeaponReference] + [WeaponReference, FieldLoader.Require] public string[] Weapons = { }; public int[] Pieces = { 3, 10 }; public WDist[] Range = { WDist.FromCells(2), WDist.FromCells(5) }; diff --git a/OpenRA.Mods.Common/Traits/TransformOnPassenger.cs b/OpenRA.Mods.Common/Traits/TransformOnPassenger.cs index 3c04a97839..a9d042409d 100644 --- a/OpenRA.Mods.Common/Traits/TransformOnPassenger.cs +++ b/OpenRA.Mods.Common/Traits/TransformOnPassenger.cs @@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits { public class TransformOnPassengerInfo : ITraitInfo { - [ActorReference] public readonly string[] PassengerTypes = { }; + [ActorReference, FieldLoader.Require] public readonly string[] PassengerTypes = { }; [ActorReference] public readonly string OnEnter = null; [ActorReference] public readonly string OnExit = null; public readonly bool SkipMakeAnims = false; diff --git a/OpenRA.Mods.Common/Traits/Transforms.cs b/OpenRA.Mods.Common/Traits/Transforms.cs index a6acd7d661..47fe16ba06 100644 --- a/OpenRA.Mods.Common/Traits/Transforms.cs +++ b/OpenRA.Mods.Common/Traits/Transforms.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Actor becomes a specified actor type when this trait is triggered.")] public class TransformsInfo : ITraitInfo { - [Desc("Actor to transform into."), ActorReference] + [Desc("Actor to transform into."), ActorReference, FieldLoader.Require] public readonly string IntoActor = null; [Desc("Offset to spawn the transformed actor relative to the current cell.")] diff --git a/OpenRA.Mods.Common/Traits/Upgrades/DeployToUpgrade.cs b/OpenRA.Mods.Common/Traits/Upgrades/DeployToUpgrade.cs index 379b5e62a2..d8afed2266 100644 --- a/OpenRA.Mods.Common/Traits/Upgrades/DeployToUpgrade.cs +++ b/OpenRA.Mods.Common/Traits/Upgrades/DeployToUpgrade.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits { public class DeployToUpgradeInfo : ITraitInfo, Requires { - [UpgradeGrantedReference] + [UpgradeGrantedReference, FieldLoader.Require] [Desc("The upgrades to grant when deploying and revoke when undeploying.")] public readonly string[] Upgrades = { }; diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs index c55c761f19..adadbb936e 100644 --- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs +++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Applies an upgrade to actors within a specified range.")] public class UpgradeActorsNearInfo : ITraitInfo { - [UpgradeGrantedReference] + [UpgradeGrantedReference, FieldLoader.Require] [Desc("The upgrades to grant.")] public readonly string[] Upgrades = { }; diff --git a/OpenRA.Mods.Common/Traits/Valued.cs b/OpenRA.Mods.Common/Traits/Valued.cs index cc3dbb99ef..6f454a4f7e 100644 --- a/OpenRA.Mods.Common/Traits/Valued.cs +++ b/OpenRA.Mods.Common/Traits/Valued.cs @@ -15,6 +15,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("How much the unit is worth.")] public class ValuedInfo : TraitInfo { + [FieldLoader.Require] [Desc("Used in production, but also for bounties so remember to set it > 0 even for NPCs.")] public readonly int Cost = 0; } diff --git a/OpenRA.Mods.Common/Traits/VeteranProductionIconOverlay.cs b/OpenRA.Mods.Common/Traits/VeteranProductionIconOverlay.cs index efdb46815f..2ae8004cb4 100644 --- a/OpenRA.Mods.Common/Traits/VeteranProductionIconOverlay.cs +++ b/OpenRA.Mods.Common/Traits/VeteranProductionIconOverlay.cs @@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Traits "The icon change occurs when LevelupWhenCreated.Prerequisites are met.")] public class VeteranProductionIconOverlayInfo : ITraitInfo, Requires { + [FieldLoader.Require] [Desc("Image used for the overlay.")] public readonly string Image = null; diff --git a/OpenRA.Mods.Common/Traits/Voiced.cs b/OpenRA.Mods.Common/Traits/Voiced.cs index 1a12a474cb..f773e3dbfb 100644 --- a/OpenRA.Mods.Common/Traits/Voiced.cs +++ b/OpenRA.Mods.Common/Traits/Voiced.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("This actor has a voice.")] public class VoicedInfo : ITraitInfo { + [FieldLoader.Require] [Desc("Which voice set to use.")] [VoiceSetReference] public readonly string VoiceSet = null; diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs index dd12d3e8b7..5cbe1fb7b7 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Loads the palette specified in the tileset definition")] class PaletteFromCurrentTilesetInfo : ITraitInfo { + [FieldLoader.Require] [Desc("internal palette name")] public readonly string Name = null; [Desc("Map listed indices to shadow. Ignores previous color.")] diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs index f5fa5c7040..49b62b1e3e 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs @@ -17,10 +17,12 @@ namespace OpenRA.Mods.Common.Traits { class PaletteFromFileInfo : ITraitInfo { + [FieldLoader.Require] [Desc("internal palette name")] public readonly string Name = null; [Desc("If defined, load the palette only for this tileset.")] public readonly string Tileset = null; + [FieldLoader.Require] [Desc("filename to load")] public readonly string Filename = null; [Desc("Map listed indices to shadow. Ignores previous color.")] diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs index b6b9de1027..905e2df069 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs @@ -19,9 +19,11 @@ namespace OpenRA.Mods.D2k.Traits [Desc("Create a palette by applying alpha transparency to another palette.")] class PaletteFromPaletteWithAlphaInfo : ITraitInfo { + [FieldLoader.Require] [Desc("Internal palette name")] public readonly string Name = null; + [FieldLoader.Require] [Desc("The name of the palette to base off.")] public readonly string BasePalette = null; diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs index 908c22f44d..18c3ed643b 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs @@ -19,9 +19,11 @@ namespace OpenRA.Mods.D2k.Traits [Desc("Create player palettes by applying alpha transparency to another player palette.")] class PaletteFromPlayerPaletteWithAlphaInfo : ITraitInfo { + [FieldLoader.Require] [Desc("The prefix for the resulting player palettes")] public readonly string BaseName = null; + [FieldLoader.Require] [Desc("The name of the player palette to base off.")] public readonly string BasePalette = null; diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs index ecdf275618..18afeb6fc3 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Creates a single color palette without any base palette file.")] class PaletteFromRGBAInfo : ITraitInfo { + [FieldLoader.Require] [Desc("internal palette name")] public readonly string Name = null; [Desc("If defined, load the palette only for this tileset.")] diff --git a/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs b/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs index 3a6f642fd6..b55b7b6cd1 100644 --- a/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs +++ b/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs @@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits { class PlayerPaletteFromCurrentTilesetInfo : ITraitInfo { + [FieldLoader.Require] [Desc("internal palette name")] public readonly string Name = null; [Desc("Map listed indices to shadow.")] diff --git a/OpenRA.Mods.D2k/Traits/Buildings/FreeActorWithDelivery.cs b/OpenRA.Mods.D2k/Traits/Buildings/FreeActorWithDelivery.cs index 48156b98a8..97aa9f7aa8 100644 --- a/OpenRA.Mods.D2k/Traits/Buildings/FreeActorWithDelivery.cs +++ b/OpenRA.Mods.D2k/Traits/Buildings/FreeActorWithDelivery.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.D2k.Traits "If you want more than one unit to be delivered, copy this section and assign IDs like FreeActorWithDelivery@2, ...")] public class FreeActorWithDeliveryInfo : FreeActorInfo { - [ActorReference] + [ActorReference, FieldLoader.Require] [Desc("Name of the delivering actor. This actor must have the `Carryall` trait")] public readonly string DeliveringActor = null; @@ -43,11 +43,6 @@ namespace OpenRA.Mods.D2k.Traits public FreeActorWithDelivery(ActorInitializer init, FreeActorWithDeliveryInfo info) { - if (string.IsNullOrEmpty(info.Actor)) - throw new InvalidDataException("Actor type was not specified!"); - if (string.IsNullOrEmpty(info.DeliveringActor)) - throw new InvalidDataException("Delivering actor type was not specified!"); - self = init.Self; Info = info; diff --git a/OpenRA.Mods.D2k/Traits/Buildings/LaysTerrain.cs b/OpenRA.Mods.D2k/Traits/Buildings/LaysTerrain.cs index 61c7501d58..74745ebdf5 100644 --- a/OpenRA.Mods.D2k/Traits/Buildings/LaysTerrain.cs +++ b/OpenRA.Mods.D2k/Traits/Buildings/LaysTerrain.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.D2k.Traits "the actor footprint will be filled with this tile.")] public readonly ushort Template = 0; + [FieldLoader.Require] [Desc("The terrain types that this template will be placed on")] public readonly string[] TerrainTypes = { }; diff --git a/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs index bb6c7c450d..dea8aa6c38 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs @@ -17,6 +17,7 @@ namespace OpenRA.Mods.D2k.Traits [Desc("Rendered together with an attack.")] public class WithAttackOverlayInfo : ITraitInfo, Requires { + [FieldLoader.Require] [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = null; diff --git a/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs b/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs index df51a3b768..bbf61dfd62 100644 --- a/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs +++ b/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs @@ -19,8 +19,10 @@ namespace OpenRA.Mods.D2k.Traits { class FogPaletteFromR8Info : ITraitInfo { + [FieldLoader.Require] [Desc("Internal palette name")] public readonly string Name = null; + [FieldLoader.Require] [Desc("Filename to load")] public readonly string Filename = null; [Desc("Palette byte offset")] diff --git a/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs b/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs index 6ef623db12..de390ef405 100644 --- a/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs +++ b/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs @@ -19,8 +19,10 @@ namespace OpenRA.Mods.D2k.Traits { class PaletteFromR8Info : ITraitInfo { + [FieldLoader.Require] [Desc("Internal palette name")] public readonly string Name = null; + [FieldLoader.Require] [Desc("Filename to load")] public readonly string Filename = null; [Desc("Palette byte offset")] diff --git a/OpenRA.Mods.D2k/Traits/World/PaletteFromScaledPalette.cs b/OpenRA.Mods.D2k/Traits/World/PaletteFromScaledPalette.cs index d0609df4db..976555843e 100644 --- a/OpenRA.Mods.D2k/Traits/World/PaletteFromScaledPalette.cs +++ b/OpenRA.Mods.D2k/Traits/World/PaletteFromScaledPalette.cs @@ -19,9 +19,11 @@ namespace OpenRA.Mods.D2k.Traits [Desc("Create a palette by applying a scale and offset to the colors in another palette.")] class PaletteFromScaledPaletteInfo : ITraitInfo { + [FieldLoader.Require] [Desc("Internal palette name")] public readonly string Name = null; + [FieldLoader.Require] [Desc("The name of the palette to base off.")] public readonly string BasePalette = null; diff --git a/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs b/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs index 94bcec980d..c32c9bdb50 100644 --- a/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs +++ b/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs @@ -17,6 +17,7 @@ namespace OpenRA.Mods.RA.Traits [Desc("Creates a free duplicate of produced units.")] public class ClonesProducedUnitsInfo : ITraitInfo, Requires, Requires { + [FieldLoader.Require] [Desc("Uses the \"Cloneable\" trait to determine whether or not we should clone a produced unit.")] public readonly string[] CloneableTypes = { }; diff --git a/OpenRA.Mods.RA/Traits/Cloneable.cs b/OpenRA.Mods.RA/Traits/Cloneable.cs index ba3b90356f..3e4d8b04f7 100644 --- a/OpenRA.Mods.RA/Traits/Cloneable.cs +++ b/OpenRA.Mods.RA/Traits/Cloneable.cs @@ -16,6 +16,7 @@ namespace OpenRA.Mods.RA.Traits [Desc("Actors with the \"ClonesProducedUnits\" trait will produce a free duplicate of me.")] public class CloneableInfo : TraitInfo { + [FieldLoader.Require] [Desc("This unit's cloneable type is:")] public readonly string[] Types = { }; } diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs index 718f2305d0..225ab808c7 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs @@ -15,7 +15,7 @@ namespace OpenRA.Mods.RA.Traits { class InfiltrateForSupportPowerInfo : ITraitInfo { - [ActorReference] public readonly string Proxy = null; + [ActorReference, FieldLoader.Require] public readonly string Proxy = null; public object Create(ActorInitializer init) { return new InfiltrateForSupportPower(this); } } diff --git a/OpenRA.Mods.RA/Traits/LeavesHusk.cs b/OpenRA.Mods.RA/Traits/LeavesHusk.cs index c5e0ab1e4b..95c5d784d6 100644 --- a/OpenRA.Mods.RA/Traits/LeavesHusk.cs +++ b/OpenRA.Mods.RA/Traits/LeavesHusk.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA.Traits [Desc("Spawn another actor immediately upon death.")] public class LeavesHuskInfo : ITraitInfo { - [ActorReference] + [ActorReference, FieldLoader.Require] public readonly string HuskActor = null; public object Create(ActorInitializer init) { return new LeavesHusk(init, this); }