Merge pull request #12477 from pchote/conditions-lint

Add a conditions lint rule + other rules fixes.
This commit is contained in:
Oliver Brakmann
2016-12-23 14:27:22 +01:00
committed by GitHub
44 changed files with 325 additions and 161 deletions

View File

@@ -46,11 +46,11 @@ namespace OpenRA.Traits
}
}
[AttributeUsage(AttributeTargets.Field)]
public sealed class UpgradeGrantedReferenceAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class GrantedConditionReferenceAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field)]
public sealed class UpgradeUsedReferenceAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ConsumedConditionReferenceAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field)]
public sealed class PaletteDefinitionAttribute : Attribute

View File

@@ -0,0 +1,72 @@
#region Copyright & License Information
/*
* Copyright 2007-2016 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;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Lint
{
public class CheckConditions : ILintRulesPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
{
foreach (var actorInfo in rules.Actors)
{
if (actorInfo.Key.StartsWith("^", StringComparison.Ordinal))
continue;
var granted = new HashSet<string>();
var consumed = new HashSet<string>();
foreach (var trait in actorInfo.Value.TraitInfos<ITraitInfo>())
{
var fieldConsumed = trait.GetType().GetFields()
.Where(x => x.HasAttribute<ConsumedConditionReferenceAttribute>())
.SelectMany(f => LintExts.GetFieldValues(trait, f, emitError));
var propertyConsumed = trait.GetType().GetProperties()
.Where(x => x.HasAttribute<ConsumedConditionReferenceAttribute>())
.SelectMany(p => LintExts.GetPropertyValues(trait, p, emitError));
var fieldGranted = trait.GetType().GetFields()
.Where(x => x.HasAttribute<GrantedConditionReferenceAttribute>())
.SelectMany(f => LintExts.GetFieldValues(trait, f, emitError));
var propertyGranted = trait.GetType().GetProperties()
.Where(x => x.HasAttribute<GrantedConditionReferenceAttribute>())
.SelectMany(f => LintExts.GetPropertyValues(trait, f, emitError));
foreach (var c in fieldConsumed.Concat(propertyConsumed))
if (!string.IsNullOrEmpty(c))
consumed.Add(c);
foreach (var g in fieldGranted.Concat(propertyGranted))
if (!string.IsNullOrEmpty(g))
granted.Add(g);
}
var unconsumed = granted.Except(consumed);
if (unconsumed.Any())
emitWarning("Actor type `{0}` grants conditions that are not consumed: {1}".F(actorInfo.Key, unconsumed.JoinWith(", ")));
var ungranted = consumed.Except(granted);
if (ungranted.Any())
emitError("Actor type `{0}` consumes conditions that are not granted: {1}".F(actorInfo.Key, ungranted.JoinWith(", ")));
if ((consumed.Any() || granted.Any()) && actorInfo.Value.TraitInfoOrDefault<UpgradeManagerInfo>() == null)
emitError("Actor type `{0}` defines conditions but does not include an UpgradeManager".F(actorInfo.Key));
}
}
}
}

View File

@@ -10,6 +10,7 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -24,20 +25,37 @@ namespace OpenRA.Mods.Common.Lint
var type = fieldInfo.FieldType;
if (type == typeof(string))
return new[] { (string)fieldInfo.GetValue(ruleInfo) };
if (type == typeof(string[]))
return (string[])fieldInfo.GetValue(ruleInfo);
if (type == typeof(HashSet<string>))
return (HashSet<string>)fieldInfo.GetValue(ruleInfo);
if (typeof(IEnumerable<string>).IsAssignableFrom(type))
return fieldInfo.GetValue(ruleInfo) as IEnumerable<string>;
if (type == typeof(BooleanExpression))
{
var expr = (BooleanExpression)fieldInfo.GetValue(ruleInfo);
return expr != null ? expr.Variables : Enumerable.Empty<string>();
}
emitError("Bad type for reference on {0}.{1}. Supported types: string, string[], HashSet<string>, BooleanExpression"
throw new InvalidOperationException("Bad type for reference on {0}.{1}. Supported types: string, IEnumerable<string>, BooleanExpression"
.F(ruleInfo.GetType().Name, fieldInfo.Name));
}
return new string[] { };
public static IEnumerable<string> GetPropertyValues(object ruleInfo, PropertyInfo propertyInfo, Action<string> emitError)
{
var type = propertyInfo.PropertyType;
if (type == typeof(string))
return new[] { (string)propertyInfo.GetValue(ruleInfo) };
if (typeof(IEnumerable).IsAssignableFrom(type))
return (IEnumerable<string>)propertyInfo.GetValue(ruleInfo);
if (type == typeof(BooleanExpression))
{
var expr = (BooleanExpression)propertyInfo.GetValue(ruleInfo);
return expr != null ? expr.Variables : Enumerable.Empty<string>();
}
throw new InvalidOperationException("Bad type for reference on {0}.{1}. Supported types: string, IEnumerable<string>, BooleanExpression"
.F(ruleInfo.GetType().Name, propertyInfo.Name));
}
}
}

View File

@@ -181,6 +181,7 @@
<Compile Include="Lint\CheckDeathTypes.cs" />
<Compile Include="Lint\CheckRangeLimit.cs" />
<Compile Include="Lint\CheckVoiceReferences.cs" />
<Compile Include="Lint\CheckConditions.cs" />
<Compile Include="Lint\CheckTargetHealthRadius.cs" />
<Compile Include="Lint\LintBuildablePrerequisites.cs" />
<Compile Include="Lint\LintExts.cs" />

View File

@@ -52,11 +52,11 @@ namespace OpenRA.Mods.Common.Traits
[VoiceReference] public readonly string Voice = "Action";
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while airborne.")]
public readonly string AirborneCondition = null;
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while at cruise altitude.")]
public readonly string CruisingCondition = null;

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Used together with ClassicProductionQueue.")]
public class PrimaryBuildingInfo : ITraitInfo
{
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while this is the primary building.")]
public readonly string PrimaryCondition = null;

View File

@@ -55,20 +55,22 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Cursor to display when unable to unload the passengers.")]
public readonly string UnloadBlockedCursor = "deploy-blocked";
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while waiting for cargo to load.")]
public readonly string LoadingCondition = null;
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while passengers are loaded.",
"Condition can stack with multiple passengers.")]
public readonly string LoadedCondition = null;
[UpgradeGrantedReference]
[Desc("Conditions to grant when specified actors are loaded inside the transport.",
"A dictionary of [actor id]: [condition].")]
public readonly Dictionary<string, string> PassengerConditions = new Dictionary<string, string>();
[GrantedConditionReference]
public IEnumerable<string> LinterPassengerConditions { get { return PassengerConditions.Values; } }
public object Create(ActorInitializer init) { return new Cargo(init, this); }
}

View File

@@ -17,11 +17,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Can be carried by actors with the `Carryall` trait.")]
public class CarryableInfo : UpgradableTraitInfo
{
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while a carryall has been reserved.")]
public readonly string ReservedCondition = null;
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while being carried.")]
public readonly string CarriedCondition = null;

View File

@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
public readonly HashSet<string> CloakTypes = new HashSet<string> { "Cloak" };
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while cloaked.")]
public readonly string CloakedCondition = null;

View File

@@ -27,6 +27,9 @@ namespace OpenRA.Mods.Common.Traits
"Value is a list of the upgrade types to grant")]
public readonly Dictionary<int, string> Conditions = null;
[GrantedConditionReference]
public IEnumerable<string> LinterConditions { get { return Conditions.Values; } }
[Desc("Palette for the level up sprite.")]
[PaletteReference] public readonly string LevelUpPalette = "effect";

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnPrerequisiteInfo : ITraitInfo
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant.")]
public readonly string Condition = null;

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits
public readonly int FallRate = 13;
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while parachuting.")]
public readonly string ParachutingCondition = null;

View File

@@ -20,10 +20,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly CVec Offset = CVec.Zero;
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("Conditions to grant for each accepted plug type.")]
public readonly Dictionary<string, string> Conditions = null;
[GrantedConditionReference]
public IEnumerable<string> LinterConditions { get { return Conditions.Values; } }
public object Create(ActorInitializer init) { return new Pluggable(init, this); }
}

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
"Externally granted conditions that aren't explicitly whitelisted will be silently ignored.")]
public class ExternalConditionsInfo : TraitInfo<ExternalConditions>
{
[UpgradeGrantedReference]
[GrantedConditionReference]
public readonly string[] Conditions = { };
}

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
class GrantConditionInfo : UpgradableTraitInfo
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnDamageStateInfo : ITraitInfo, Requires<HealthInfo>
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;

View File

@@ -21,11 +21,12 @@ namespace OpenRA.Mods.Common.Traits
{
public class GrantConditionOnDeployInfo : ITraitInfo
{
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant while the actor is undeployed.")]
public readonly string UndeployedCondition = null;
[UpgradeGrantedReference, FieldLoader.Require]
[FieldLoader.Require]
[GrantedConditionReference]
[Desc("The condition to grant after deploying and revoke before undeploying.")]
public readonly string DeployedCondition = null;

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnMovementInfo : UpgradableTraitInfo, Requires<IMoveInfo>
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnTerrainInfo : ITraitInfo
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;

View File

@@ -17,12 +17,12 @@ namespace OpenRA.Mods.Common.Traits
public class StackedConditionInfo : TraitInfo<StackedCondition>
{
[FieldLoader.Require]
[UpgradeUsedReference]
[ConsumedConditionReference]
[Desc("Condition to monitor.")]
public readonly string Condition = null;
[FieldLoader.Require]
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("Conditions to grant when the monitored condition is granted multiple times.",
"The first entry is activated at 2x grants, second entry at 3x grants, and so on.")]
public readonly string[] StackedConditions = { };

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Traits
{
static readonly IReadOnlyDictionary<string, bool> NoConditions = new ReadOnlyDictionary<string, bool>(new Dictionary<string, bool>());
[UpgradeUsedReference]
[ConsumedConditionReference]
[Desc("Boolean expression defining the condition to enable this trait.")]
public readonly BooleanExpression RequiresCondition = null;

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.D2k.Traits
[Desc("The number of ticks it takes to get in place under the target to attack.")]
public readonly int AttackDelay = 30;
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while attacking.")]
public readonly string AttackingCondition = null;

View File

@@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Traits
{
[VoiceReference] public readonly string Voice = "Action";
[UpgradeGrantedReference]
[GrantedConditionReference]
[Desc("The condition to grant to self while disguised.")]
public readonly string DisguisedCondition = null;

View File

@@ -53,6 +53,7 @@ TRAN:
HELI:
Inherits: ^Helicopter
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1200
Tooltip:
@@ -111,6 +112,7 @@ HELI:
ORCA:
Inherits: ^Helicopter
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1200
Tooltip:
@@ -167,7 +169,6 @@ C17:
TurnSpeed: 5
Speed: 326
Repulsable: False
AirborneCondition: airborne
MaximumPitch: 36
Health:
HP: 25
@@ -206,7 +207,6 @@ A10:
TurnSpeed: 4
Speed: 373
Repulsable: False
AirborneCondition: airborne
Health:
HP: 150
Armor:

View File

@@ -116,9 +116,18 @@
RequiresCondition: rank-elite
ZOffset: 256
^AcceptsCloakCrate:
Cloak:
InitialDelay: 15
CloakDelay: 90
CloakSound: trans1.aud
UncloakSound: trans1.aud
RequiresCondition: cloak
ExternalConditions@CLOAK:
Conditions: cloak
^Vehicle:
Inherits@1: ^ExistsInWorld
Inherits@2: ^GainsExperience
Inherits@3: ^SpriteActor
Huntable:
Mobile:
@@ -153,14 +162,6 @@
Guardable:
Tooltip:
GenericName: Vehicle
Cloak:
InitialDelay: 15
CloakDelay: 90
CloakSound: trans1.aud
UncloakSound: trans1.aud
RequiresCondition: cloak
ExternalConditions@CLOAK:
Conditions: cloak
MustBeDestroyed:
Voiced:
VoiceSet: VehicleVoice
@@ -184,7 +185,6 @@
^Helicopter:
Inherits@1: ^ExistsInWorld
Inherits@2: ^GainsExperience
Inherits@3: ^SpriteActor
Huntable:
AppearsOnRadar:
@@ -231,7 +231,6 @@
^Infantry:
Inherits@1: ^ExistsInWorld
Inherits@2: ^GainsExperience
Inherits@3: ^SpriteActor
Huntable:
Health:
@@ -517,7 +516,6 @@
^Ship:
Inherits@1: ^ExistsInWorld
Inherits@2: ^GainsExperience
Inherits@3: ^SpriteActor
Huntable:
Mobile:
@@ -839,7 +837,6 @@
Offset: 43, 128, 0
ZOffset: -129
Aircraft:
AirborneCondition: airborne
CanHover: True
FallsToEarth:
Spins: True

View File

@@ -1,5 +1,6 @@
E1:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 100
Tooltip:
@@ -21,6 +22,7 @@ E1:
E2:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 160
Tooltip:
@@ -48,6 +50,7 @@ E2:
E3:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 300
Tooltip:
@@ -72,6 +75,7 @@ E3:
E4:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 200
Tooltip:
@@ -97,6 +101,7 @@ E4:
E5:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 300
Tooltip:
@@ -148,10 +153,10 @@ E6:
CaptureTypes: building, husk
PlayerExperience: 50
-AutoTarget:
-GainsExperience:
RMBO:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1000
Tooltip:

View File

@@ -1,5 +1,6 @@
BOAT:
Inherits: ^Ship
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 300
Tooltip:

View File

@@ -31,13 +31,12 @@ MCV:
BaseBuilding:
SpawnActorOnDeath:
Actor: MCV.Husk
-GainsExperience:
-Cloak:
SelectionDecorations:
VisualBounds: 36,36
HARV:
Inherits: ^Tank
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 1000
Tooltip:
@@ -68,7 +67,6 @@ HARV:
Range: 4c0
SpawnActorOnDeath:
Actor: HARV.Husk
-GainsExperience:
WithHarvestAnimation:
WithDockingAnimation:
Explodes:
@@ -78,6 +76,8 @@ HARV:
APC:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 600
Tooltip:
@@ -126,6 +126,8 @@ APC:
ARTY:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 600
Tooltip:
@@ -161,6 +163,8 @@ ARTY:
FTNK:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 600
Tooltip:
@@ -194,6 +198,8 @@ FTNK:
BGGY:
Inherits: ^Vehicle
Inherits@@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 300
Tooltip:
@@ -228,6 +234,8 @@ BGGY:
BIKE:
Inherits: ^Vehicle
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 500
Tooltip:
@@ -264,6 +272,8 @@ BIKE:
JEEP:
Inherits: ^Vehicle
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 400
Tooltip:
@@ -298,6 +308,8 @@ JEEP:
LTNK:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 700
Tooltip:
@@ -333,6 +345,8 @@ LTNK:
MTNK:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 800
Tooltip:
@@ -369,6 +383,8 @@ MTNK:
HTNK:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 1500
Tooltip:
@@ -418,6 +434,8 @@ HTNK:
MSAM:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 1000
Tooltip:
@@ -454,6 +472,8 @@ MSAM:
MLRS:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Inherits@CLOAK: ^AcceptsCloakCrate
Valued:
Cost: 600
Tooltip:
@@ -496,6 +516,7 @@ MLRS:
STNK:
Inherits: ^Vehicle
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 900
Tooltip:
@@ -516,7 +537,6 @@ STNK:
RevealsShroud:
Range: 7c0
Cloak:
-RequiresCondition:
InitialDelay: 90
CloakDelay: 90
CloakSound: trans1.aud

View File

@@ -28,8 +28,6 @@ World:
Type: LightningStrike
LuaScript:
Scripts: fort-lonestar.lua, fort-lonestar-AI.lua
ExternalConditions:
Conditions: invulnerability
MapBuildRadius:
AllyBuildRadiusLocked: True
AllyBuildRadiusEnabled: True

View File

@@ -57,7 +57,10 @@ V05:
Actor: healcrate
DOG:
# HACK: Disable experience without killing the linter
-GainsExperience:
ExternalConditions@EXPERIENCE:
Conditions: rank-veteran-1, rank-veteran-2, rank-veteran-3, rank-elite
SPY:
Mobile:

View File

@@ -1,5 +1,5 @@
BADR:
Inherits: ^Plane
Inherits: ^NeutralPlane
ParaDrop:
DropRange: 4c0
Health:
@@ -18,7 +18,6 @@ BADR:
SelectionDecorations:
RenderSelectionBars: False
-Voiced:
-GainsExperience:
Tooltip:
Name: Badger
Contrail@1:
@@ -39,7 +38,7 @@ BADR:
Experience: 1000
BADR.Bomber:
Inherits: ^Plane
Inherits: ^NeutralPlane
AttackBomber:
Armament:
Weapon: ParaBomb
@@ -59,7 +58,6 @@ BADR.Bomber:
SelectionDecorations:
RenderSelectionBars: False
-Voiced:
-GainsExperience:
Tooltip:
Name: Badger
Contrail@1:
@@ -358,7 +356,7 @@ HIND:
Prerequisites: aircraft.upgraded
U2:
Inherits: ^Plane
Inherits: ^NeutralPlane
Health:
HP: 2000
Tooltip:
@@ -377,7 +375,6 @@ U2:
RenderSelectionBars: False
-Voiced:
-Targetable@AIRBORNE:
-GainsExperience:
Contrail@1:
Offset: -725,683,0
Contrail@2:

View File

@@ -410,9 +410,8 @@
VoiceSet: VehicleVoice
WithFacingSpriteBody:
^Plane:
^NeutralPlane:
Inherits@1: ^ExistsInWorld
Inherits@2: ^GainsExperience
Inherits@3: ^IronCurtainable
Inherits@4: ^SpriteActor
Huntable:
@@ -428,7 +427,6 @@
RepairBuildings: fix
RearmBuildings: afld
AirborneCondition: airborne
CruisingCondition: cruising
Targetable@GROUND:
TargetTypes: Ground, Repair, Vehicle
RequiresCondition: !airborne
@@ -463,6 +461,10 @@
Voiced:
VoiceSet: GenericVoice
^Plane:
Inherits: ^NeutralPlane
Inherits@2: ^GainsExperience
^Helicopter:
Inherits: ^Plane
Tooltip:
@@ -470,6 +472,7 @@
Aircraft:
RearmBuildings: hpad
CanHover: True
CruisingCondition: cruising
GpsDot:
String: Helicopter
Hovers@CRUISING:
@@ -798,8 +801,6 @@
Tooltip:
GenericName: Destroyed Plane
Aircraft:
AirborneCondition: airborne
CruisingCondition: cruising
FallsToEarth:
Spins: False
Moves: True
@@ -813,8 +814,6 @@
Tooltip:
GenericName: Destroyed Helicopter
Aircraft:
AirborneCondition: airborne
CruisingCondition: cruising
CanHover: True
FallsToEarth:
BodyOrientation:

View File

@@ -64,6 +64,7 @@ DSHP:
ORCA:
Inherits: ^Helicopter
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1000
Tooltip:
@@ -104,7 +105,8 @@ ORCA:
Actor: ORCA.Husk
ORCAB:
Inherits: ^Plane
Inherits: ^Aircraft
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1600
Tooltip:
@@ -121,10 +123,11 @@ ORCAB:
MaximumPitch: 120
TurnSpeed: 3
Speed: 96
AirborneCondition: airborne
CruisingCondition: cruising
MoveIntoShroud: false
TakeoffSound: orcaup1.aud
LandingSound: orcadwn1.aud
ReturnOnIdle:
Health:
HP: 260
Armor:
@@ -225,7 +228,8 @@ TRNSPORT:
Actor: TRNSPORT.Husk
SCRIN:
Inherits: ^Plane
Inherits: ^Aircraft
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1500
Tooltip:
@@ -240,6 +244,7 @@ SCRIN:
Voiced:
VoiceSet: Scrin
Aircraft:
CruiseAltitude: 2560
MaximumPitch: 90
TurnSpeed: 3
Speed: 168
@@ -247,6 +252,7 @@ SCRIN:
MoveIntoShroud: false
TakeoffSound: dropup1.aud
LandingSound: dropdwn1.aud
ReturnOnIdle:
Health:
HP: 280
Armor:
@@ -273,6 +279,7 @@ SCRIN:
APACHE:
Inherits: ^Helicopter
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1000
Tooltip:
@@ -319,7 +326,6 @@ APACHE:
Actor: APACHE.Husk
HUNTER:
Inherits@1: ^GainsExperience
Inherits@2: ^ExistsInWorld
Valued:
Cost: 1000
@@ -338,6 +344,7 @@ HUNTER:
Speed: 355
CruiseAltitude: 256
CanHover: True
CruisingCondition: cruising
Targetable:
TargetTypes: Ground, Vehicle
HiddenUnderFog:

View File

@@ -26,6 +26,7 @@ WEEDGUY:
UMAGON:
Inherits: ^Soldier
Inherits@2: ^HealsOnTiberium
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 400
Tooltip:
@@ -82,6 +83,7 @@ CHAMSPY:
MUTANT:
Inherits: ^Soldier
Inherits@2: ^HealsOnTiberium
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 100
Tooltip:
@@ -106,6 +108,7 @@ MUTANT:
MWMN:
Inherits: ^Soldier
Inherits@2: ^HealsOnTiberium
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 100
Tooltip:
@@ -130,6 +133,7 @@ MWMN:
MUTANT3:
Inherits: ^Soldier
Inherits@2: ^HealsOnTiberium
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 100
Tooltip:
@@ -210,6 +214,7 @@ DOGGIE:
Inherits@1: ^Infantry
Inherits@2: ^RegularInfantryDeath
Inherits@3: ^HealsOnTiberium
Inherits@EXPERIENCE: ^GainsExperience
Tooltip:
Name: Tiberian Fiend
Health:
@@ -258,6 +263,7 @@ VISC_SML:
VISC_LRG:
Inherits: ^Visceroid
Inherits@CRATESTATS: ^CrateStatModifiers
Tooltip:
Name: Adult Visceroid
Health:

View File

@@ -1264,6 +1264,7 @@ GALITE:
SelectionDecorations:
VisualBounds: 25, 35, 0, -12
-Cloak@EXTERNALCLOAK:
-ExternalConditions@EXTERNALCLOAK:
TSTLAMP:
Inherits: GALITE

View File

@@ -1,5 +1,7 @@
4TNK:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1700
Tooltip:
@@ -90,6 +92,7 @@ BUS:
Mobile:
TurnSpeed: 5
Speed: 113
RequiresCondition: !empdisable && !loading
Health:
HP: 100
Armor:
@@ -114,6 +117,7 @@ PICK:
Mobile:
TurnSpeed: 5
Speed: 113
RequiresCondition: !empdisable && !loading
Health:
HP: 100
Armor:
@@ -138,6 +142,7 @@ CAR:
Mobile:
TurnSpeed: 5
Speed: 113
RequiresCondition: !empdisable && !loading
Health:
HP: 100
Armor:
@@ -162,6 +167,7 @@ WINI:
Mobile:
TurnSpeed: 5
Speed: 113
RequiresCondition: !empdisable && !loading
Health:
HP: 200
Armor:

View File

@@ -21,22 +21,22 @@
500: rank-veteran
1000: rank-elite
FirepowerMultiplier@VETERAN:
RequiresCondition: (rank-veteran && !rank-elite) || crate-firepower
RequiresCondition: rank-veteran && !rank-elite
Modifier: 110
FirepowerMultiplier@ELITE:
RequiresCondition: rank-elite || (rank-veteran && crate-firepower)
RequiresCondition: rank-elite
Modifier: 130
DamageMultiplier@VETERAN:
RequiresCondition: (rank-veteran && !rank-elite) || crate-damage
RequiresCondition: rank-veteran && !rank-elite
Modifier: 90
DamageMultiplier@ELITE:
RequiresCondition: rank-elite || (rank-veteran && crate-damage)
RequiresCondition: rank-elite
Modifier: 75
SpeedMultiplier@VETERAN:
RequiresCondition: (rank-veteran && !rank-elite) || crate-speed
RequiresCondition: rank-veteran && !rank-elite
Modifier: 120
SpeedMultiplier@ELITE:
RequiresCondition: rank-elite || (rank-veteran && crate-speed)
RequiresCondition: rank-elite
Modifier: 140
ReloadDelayMultiplier@VETERAN:
RequiresCondition: rank-veteran && !rank-elite
@@ -64,8 +64,19 @@
ReferencePoint: Bottom, Right
RequiresCondition: rank-elite
ZOffset: 256
^CrateStatModifiers:
FirepowerMultiplier@CRATES:
RequiresCondition: crate-firepower
Modifier: 200
DamageMultiplier@CRATES:
RequiresCondition: crate-damage
Modifier: 50
SpeedMultiplier@CRATES:
RequiresCondition: crate-speed
Modifier: 170
ExternalConditions@CRATES:
Conditions: crate-firepower, crate-damage, crate-speed, crate-cloak
Conditions: crate-firepower, crate-damage, crate-speed
^EmpDisable:
UpgradeOverlay@EMPDISABLE:
@@ -88,11 +99,6 @@
ExternalConditions@EMPDISABLE:
Conditions: empdisable
^EmpDisableMobile:
Inherits: ^EmpDisable
Mobile:
RequiresCondition: !empdisable && !deployed && !loading
^Cloakable:
Cloak@EXTERNALCLOAK:
RequiresCondition: cloakgenerator || crate-cloak
@@ -257,10 +263,10 @@
RenderSprites:
^Infantry:
Inherits@1: ^GainsExperience
Inherits@2: ^ExistsInWorld
Inherits@3: ^SpriteActor
Inherits@4: ^Cloakable
Inherits@CRATESTATS: ^CrateStatModifiers
Huntable:
DrawLineToTarget:
Health:
@@ -401,7 +407,7 @@
^Cyborg:
Inherits@1: ^Infantry
Inherits@2: ^EmpDisableMobile
Inherits@2: ^EmpDisable
Inherits@3: ^HealsOnTiberium
ExplosionOnDamageTransition:
Weapon: CyborgExplode
@@ -425,6 +431,8 @@
SpeedMultiplier@CRITICAL:
RequiresCondition: criticalspeed
Modifier: 50
Mobile:
RequiresCondition: !empdisable
^CivilianInfantry:
Inherits@1: ^Infantry
@@ -439,11 +447,11 @@
MaxMoveDelay: 750
^Vehicle:
Inherits@1: ^GainsExperience
Inherits@2: ^ExistsInWorld
Inherits@3: ^EmpDisableMobile
Inherits@3: ^EmpDisable
Inherits@4: ^Cloakable
Inherits@5: ^DamagedByVeins
Inherits@CRATESTATS: ^CrateStatModifiers
Huntable:
DrawLineToTarget:
Mobile:
@@ -461,6 +469,7 @@
PathingCost: 90
TurnSpeed: 5
Voice: Move
RequiresCondition: !empdisable
Selectable:
Bounds: 40,24
WithTextControlGroupDecoration:
@@ -527,22 +536,15 @@
BlueTiberium: 70
Veins: 70
^VoxelVehicle:
Inherits: ^Vehicle
BodyOrientation:
QuantizedFacings: 0
RenderVoxels:
WithVoxelBody:
^VoxelTank:
Inherits: ^Tank
^VoxelActor:
BodyOrientation:
QuantizedFacings: 0
RenderVoxels:
WithVoxelBody:
^CivilianVoxelVehicle:
Inherits: ^VoxelVehicle
Inherits: ^Vehicle
Inherits: ^VoxelActor
-MustBeDestroyed:
^CivilianVoxelCrusher:
@@ -551,7 +553,6 @@
Crushes: wall, crate, infantry
^Aircraft:
Inherits@1: ^GainsExperience
Inherits@2: ^ExistsInWorld
Inherits@3: ^Cloakable
Huntable:
@@ -570,7 +571,6 @@
Palette: pips
Aircraft:
AirborneCondition: airborne
CruisingCondition: cruising
RepairBuildings: gadept
RearmBuildings: gahpad, nahpad
LandWhenIdle: false
@@ -598,15 +598,10 @@
Aircraft:
CruiseAltitude: 2048
CanHover: True
CruisingCondition: cruising
Hovers@CRUISING:
RequiresCondition: cruising
^Plane:
Inherits: ^Aircraft
Aircraft:
CruiseAltitude: 2560
ReturnOnIdle:
^AircraftHusk:
RenderVoxels:
RenderSprites:
@@ -615,8 +610,6 @@
QuantizedFacings: 0
CameraPitch: 90
Aircraft:
AirborneCondition: airborne
CruisingCondition: cruising
Health:
HP: 280
Armor:
@@ -755,36 +748,8 @@
DetectCloaked:
Range: 5c0
^DeployedVehicle:
Inherits@1: ^GainsExperience
Inherits@2: ^ExistsInWorld
Inherits@3: ^SpriteActor
Huntable:
Voiced:
VoiceSet: Vehicle
AttackTurreted:
Voice: Attack
AutoTarget:
RenderRangeCircle:
DrawLineToTarget:
Building:
Dimensions: 1,1
Footprint: x
TerrainTypes: Clear, Road, DirtRoad, Rough
WithSpriteBody:
WithMakeAnimation:
WithTextControlGroupDecoration:
SelectionDecorations:
Palette: pips
Selectable:
Targetable:
TargetTypes: Ground, Building, Repair
Guardable:
HiddenUnderFog:
ActorLostNotification:
^Train:
Inherits@1: ^EmpDisableMobile
Inherits@1: ^EmpDisable
Inherits@2: ^ExistsInWorld
Inherits@3: ^Cloakable
Huntable:
@@ -799,10 +764,10 @@
TurnSpeed: 5
Voice: Move
Speed: 113
RequiresCondition: !empdisable
Cargo:
Types: Infantry
UnloadVoice: Unload
LoadingCondition: loading
Health:
HP: 100
Armor:

View File

@@ -1,5 +1,6 @@
E2:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Buildable:
Queue: Infantry
BuildPaletteOrder: 20
@@ -26,6 +27,7 @@ E2:
MEDIC:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 600
Tooltip:
@@ -61,6 +63,7 @@ MEDIC:
JUMPJET:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 600
Tooltip:
@@ -95,6 +98,7 @@ JUMPJET:
GHOST:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Inherits@2: ^HealsOnTiberium
Valued:
Cost: 1750

View File

@@ -1,5 +1,6 @@
APC:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Valued:
Cost: 800
Tooltip:
@@ -14,6 +15,7 @@ APC:
Speed: 113
TerrainSpeeds:
Water: 80
RequiresCondition: !empdisable && !loading
Health:
HP: 200
Armor:
@@ -46,7 +48,9 @@ APC:
MovingInterval: 6
HVR:
Inherits: ^VoxelVehicle
Inherits: ^Vehicle
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 900
Tooltip:
@@ -100,6 +104,7 @@ HVR:
SMECH:
Inherits: ^Vehicle
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 500
Tooltip:
@@ -142,6 +147,7 @@ SMECH:
MMCH:
Inherits: ^Tank
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 800
Tooltip:
@@ -189,7 +195,9 @@ MMCH:
LocalOffset: 0, 0, 408
HMEC:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 3000
Tooltip:
@@ -230,7 +238,9 @@ HMEC:
LocalOffset: 0, 0, 360
SONIC:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1300
Tooltip:

View File

@@ -1,5 +1,6 @@
E3:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Buildable:
Queue: Infantry
BuildPaletteOrder: 20
@@ -27,6 +28,7 @@ E3:
CYBORG:
Inherits: ^Cyborg
Inherits@EXPERIENCE: ^GainsExperience
Armor:
Type: Light
Valued:
@@ -60,6 +62,7 @@ CYBORG:
CYC2:
Inherits: ^Cyborg
Inherits@EXPERIENCE: ^GainsExperience
Armor:
Type: Heavy
Valued:

View File

@@ -160,7 +160,32 @@ NASAM:
VisualBounds: 40, 36, -3, -8
GAARTY:
Inherits@1: ^DeployedVehicle
Inherits@1: ^GainsExperience
Inherits@2: ^ExistsInWorld
Inherits@3: ^SpriteActor
Huntable:
Voiced:
VoiceSet: Vehicle
AttackTurreted:
Voice: Attack
AutoTarget:
RenderRangeCircle:
DrawLineToTarget:
Building:
Dimensions: 1,1
Footprint: x
TerrainTypes: Clear, Road, DirtRoad, Rough
WithSpriteBody:
WithMakeAnimation:
WithTextControlGroupDecoration:
SelectionDecorations:
Palette: pips
Selectable:
Targetable:
TargetTypes: Ground, Building, Repair
Guardable:
HiddenUnderFog:
ActorLostNotification:
Valued:
Cost: 975
Tooltip:

View File

@@ -1,5 +1,7 @@
BGGY:
Inherits: ^VoxelVehicle
Inherits: ^Vehicle
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 500
Tooltip:
@@ -33,7 +35,9 @@ BGGY:
-WithIdleOverlay@VEINS:
BIKE:
Inherits: ^VoxelVehicle
Inherits: ^Vehicle
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 600
Tooltip:
@@ -66,7 +70,9 @@ BIKE:
AutoTarget:
TTNK:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 800
Tooltip:
@@ -84,6 +90,7 @@ TTNK:
TurnSpeed: 5
Speed: 85
Crushes: wall, crate, infantry
RequiresCondition: !empdisable && undeployed
Health:
HP: 350
Armor:
@@ -160,7 +167,9 @@ TTNK:
RequiresCondition: undeployed
ART2:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 975
Tooltip:
@@ -190,7 +199,8 @@ ART2:
Voice: Move
REPAIR:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Buildable:
Queue: Vehicle
BuildPaletteOrder: 70
@@ -218,7 +228,8 @@ REPAIR:
Voice: Attack
WEED:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Valued:
Cost: 1400
Tooltip:
@@ -254,13 +265,13 @@ WEED:
MaxHeightDelta: 3
-WithVoxelBody:
WithVoxelUnloadBody:
-GainsExperience:
-DamagedByTerrain@VEINS:
-GrantConditionOnTerrain@VEINS:
-WithIdleOverlay@VEINS:
SAPC:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Valued:
Cost: 800
Tooltip:
@@ -273,6 +284,7 @@ SAPC:
Mobile:
TurnSpeed: 5
Speed: 71
RequiresCondition: !empdisable && !loading
Health:
HP: 175
Armor:
@@ -289,7 +301,9 @@ SAPC:
EjectOnDeath: true
SUBTANK:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 750
Tooltip:
@@ -317,7 +331,9 @@ SUBTANK:
AutoTarget:
STNK:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Inherits@EXPERIENCE: ^GainsExperience
Valued:
Cost: 1100
Tooltip:

View File

@@ -1,5 +1,6 @@
E1:
Inherits: ^Soldier
Inherits@EXPERIENCE: ^GainsExperience
Buildable:
Queue: Infantry
BuildPaletteOrder: 10
@@ -57,7 +58,6 @@ ENGINEER:
CaptureTypes: building
PlayerExperience: 50
-AutoTarget:
-GainsExperience:
RenderSprites:
Image: engineer.gdi
FactionImages:

View File

@@ -1,5 +1,6 @@
MCV:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Buildable:
Queue: Vehicle
BuildPaletteOrder: 110
@@ -39,7 +40,8 @@ MCV:
nod: mcv.nod
HARV:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
Valued:
Cost: 1400
Tooltip:
@@ -84,7 +86,6 @@ HARV:
RevealsShroud:
Range: 4c0
MaxHeightDelta: 3
-GainsExperience:
-WithVoxelBody:
WithVoxelUnloadBody:
Explodes:
@@ -104,9 +105,9 @@ HARV:
-WithIdleOverlay@VEINS:
LPST:
Inherits: ^VoxelTank
Inherits: ^Tank
Inherits@VOXELS: ^VoxelActor
-AppearsOnRadar:
-GainsExperience:
Buildable:
Queue: Vehicle
BuildPaletteOrder: 100
@@ -127,6 +128,7 @@ LPST:
Mobile:
Speed: 85
TurnSpeed: 5
RequiresCondition: !empdisable && undeployed
RevealsShroud:
Range: 7c0
MaxHeightDelta: 3