Merge pull request #12381 from pchote/upgrade-conditions
Upgrades overhaul part 1: EnabledCondition
This commit is contained in:
@@ -15,12 +15,14 @@ using System.ComponentModel;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Support;
|
||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
@@ -396,6 +398,22 @@ namespace OpenRA
|
|||||||
|
|
||||||
return InvalidValueAction(value, fieldType, fieldName);
|
return InvalidValueAction(value, fieldType, fieldName);
|
||||||
}
|
}
|
||||||
|
else if (fieldType == typeof(BooleanExpression))
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new BooleanExpression(value);
|
||||||
|
}
|
||||||
|
catch (InvalidDataException e)
|
||||||
|
{
|
||||||
|
throw new YamlException(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidValueAction(value, fieldType, fieldName);
|
||||||
|
}
|
||||||
else if (fieldType.IsEnum)
|
else if (fieldType.IsEnum)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace OpenRA.Support
|
|||||||
{
|
{
|
||||||
public class BooleanExpression
|
public class BooleanExpression
|
||||||
{
|
{
|
||||||
|
public readonly string Expression;
|
||||||
readonly HashSet<string> variables = new HashSet<string>();
|
readonly HashSet<string> variables = new HashSet<string>();
|
||||||
public IEnumerable<string> Variables { get { return variables; } }
|
public IEnumerable<string> Variables { get { return variables; } }
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ namespace OpenRA.Support
|
|||||||
|
|
||||||
public BooleanExpression(string expression)
|
public BooleanExpression(string expression)
|
||||||
{
|
{
|
||||||
|
Expression = expression;
|
||||||
var openParens = 0;
|
var openParens = 0;
|
||||||
var closeParens = 0;
|
var closeParens = 0;
|
||||||
var tokens = new List<Token>();
|
var tokens = new List<Token>();
|
||||||
@@ -220,7 +222,7 @@ namespace OpenRA.Support
|
|||||||
return new VariableToken(start, expression.Substring(start));
|
return new VariableToken(start, expression.Substring(start));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseSymbol(VariableToken t, Dictionary<string, bool> symbols)
|
static bool ParseSymbol(VariableToken t, IReadOnlyDictionary<string, bool> symbols)
|
||||||
{
|
{
|
||||||
bool value;
|
bool value;
|
||||||
symbols.TryGetValue(t.Symbol, out value);
|
symbols.TryGetValue(t.Symbol, out value);
|
||||||
@@ -269,7 +271,7 @@ namespace OpenRA.Support
|
|||||||
yield return s.Pop();
|
yield return s.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Evaluate(Dictionary<string, bool> symbols)
|
public bool Evaluate(IReadOnlyDictionary<string, bool> symbols)
|
||||||
{
|
{
|
||||||
var s = new Stack<bool>();
|
var s = new Stack<bool>();
|
||||||
foreach (var t in postfix)
|
foreach (var t in postfix)
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
public readonly string OnFireSound = null;
|
public readonly string OnFireSound = null;
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new IonCannonPower(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new IonCannonPower(init.Self, this); }
|
||||||
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { WeaponInfo = rules.Weapons[Weapon.ToLowerInvariant()]; }
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
|
{
|
||||||
|
WeaponInfo = rules.Weapons[Weapon.ToLowerInvariant()];
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IonCannonPower : SupportPower
|
class IonCannonPower : SupportPower
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Support;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.AI
|
namespace OpenRA.Mods.Common.AI
|
||||||
@@ -193,7 +194,7 @@ namespace OpenRA.Mods.Common.AI
|
|||||||
|
|
||||||
bool HasSufficientPowerForActor(ActorInfo actorInfo)
|
bool HasSufficientPowerForActor(ActorInfo actorInfo)
|
||||||
{
|
{
|
||||||
return (actorInfo.TraitInfos<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1)
|
return (actorInfo.TraitInfos<PowerInfo>().Where(i => i.EnabledByDefault)
|
||||||
.Sum(p => p.Amount) + playerPower.ExcessPower) >= ai.Info.MinimumExcessPower;
|
.Sum(p => p.Amount) + playerPower.ExcessPower) >= ai.Info.MinimumExcessPower;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,12 +204,12 @@ namespace OpenRA.Mods.Common.AI
|
|||||||
|
|
||||||
// This gets used quite a bit, so let's cache it here
|
// This gets used quite a bit, so let's cache it here
|
||||||
var power = GetProducibleBuilding(ai.Info.BuildingCommonNames.Power, buildableThings,
|
var power = GetProducibleBuilding(ai.Info.BuildingCommonNames.Power, buildableThings,
|
||||||
a => a.TraitInfos<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(p => p.Amount));
|
a => a.TraitInfos<PowerInfo>().Where(i => i.EnabledByDefault).Sum(p => p.Amount));
|
||||||
|
|
||||||
// First priority is to get out of a low power situation
|
// First priority is to get out of a low power situation
|
||||||
if (playerPower.ExcessPower < ai.Info.MinimumExcessPower)
|
if (playerPower.ExcessPower < ai.Info.MinimumExcessPower)
|
||||||
{
|
{
|
||||||
if (power != null && power.TraitInfos<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(p => p.Amount) > 0)
|
if (power != null && power.TraitInfos<PowerInfo>().Where(i => i.EnabledByDefault).Sum(p => p.Amount) > 0)
|
||||||
{
|
{
|
||||||
HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (low power)", queue.Actor.Owner, power.Name);
|
HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (low power)", queue.Actor.Owner, power.Name);
|
||||||
return power;
|
return power;
|
||||||
@@ -314,7 +315,7 @@ namespace OpenRA.Mods.Common.AI
|
|||||||
if (playerPower.ExcessPower < ai.Info.MinimumExcessPower || !HasSufficientPowerForActor(actor))
|
if (playerPower.ExcessPower < ai.Info.MinimumExcessPower || !HasSufficientPowerForActor(actor))
|
||||||
{
|
{
|
||||||
// Try building a power plant instead
|
// Try building a power plant instead
|
||||||
if (power != null && power.TraitInfos<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(pi => pi.Amount) > 0)
|
if (power != null && power.TraitInfos<PowerInfo>().Where(i => i.EnabledByDefault).Sum(pi => pi.Amount) > 0)
|
||||||
{
|
{
|
||||||
if (playerPower.PowerOutageRemainingTicks > 0)
|
if (playerPower.PowerOutageRemainingTicks > 0)
|
||||||
HackyAI.BotDebug("{0} decided to build {1}: Priority override (is low power)", queue.Actor.Owner, power.Name);
|
HackyAI.BotDebug("{0} decided to build {1}: Priority override (is low power)", queue.Actor.Owner, power.Name);
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
#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 CheckUpgrades : ILintRulesPass
|
|
||||||
{
|
|
||||||
public void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
|
|
||||||
{
|
|
||||||
CheckUpgradesValidity(emitError, rules);
|
|
||||||
CheckUpgradesUsage(emitError, emitWarning, rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CheckUpgradesValidity(Action<string> emitError, Ruleset rules)
|
|
||||||
{
|
|
||||||
var upgradesGranted = GetAllGrantedUpgrades(emitError, rules).ToHashSet();
|
|
||||||
|
|
||||||
foreach (var actorInfo in rules.Actors)
|
|
||||||
{
|
|
||||||
if (actorInfo.Key.StartsWith("^"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (var trait in actorInfo.Value.TraitInfos<ITraitInfo>())
|
|
||||||
{
|
|
||||||
var fields = trait.GetType().GetFields();
|
|
||||||
foreach (var field in fields.Where(x => x.HasAttribute<UpgradeUsedReferenceAttribute>()))
|
|
||||||
{
|
|
||||||
var values = LintExts.GetFieldValues(trait, field, emitError);
|
|
||||||
foreach (var value in values)
|
|
||||||
{
|
|
||||||
if (!upgradesGranted.Contains(value))
|
|
||||||
emitError("Actor type `{0}` uses upgrade `{1}` that is not granted by anything!".F(actorInfo.Key, value));
|
|
||||||
|
|
||||||
if (actorInfo.Value.TraitInfoOrDefault<UpgradeManagerInfo>() == null)
|
|
||||||
emitError("Actor type `{0}` uses upgrade `{1}`, but doesn't have the UpgradeManager trait.".F(actorInfo.Key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CheckUpgradesUsage(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
|
|
||||||
{
|
|
||||||
var upgradesUsed = GetAllUsedUpgrades(emitError, rules).ToHashSet();
|
|
||||||
|
|
||||||
// Check all upgrades granted by traits.
|
|
||||||
foreach (var actorInfo in rules.Actors)
|
|
||||||
{
|
|
||||||
if (actorInfo.Key.StartsWith("^"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (var trait in actorInfo.Value.TraitInfos<ITraitInfo>())
|
|
||||||
{
|
|
||||||
var fields = trait.GetType().GetFields();
|
|
||||||
foreach (var field in fields.Where(x => x.HasAttribute<UpgradeGrantedReferenceAttribute>()))
|
|
||||||
{
|
|
||||||
var values = LintExts.GetFieldValues(trait, field, emitError);
|
|
||||||
foreach (var value in values.Where(x => !upgradesUsed.Contains(x)))
|
|
||||||
emitWarning("Actor type `{0}` grants upgrade `{1}` that is not used by anything!".F(actorInfo.Key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check all upgrades granted by warheads.
|
|
||||||
foreach (var weapon in rules.Weapons)
|
|
||||||
{
|
|
||||||
foreach (var warhead in weapon.Value.Warheads)
|
|
||||||
{
|
|
||||||
var fields = warhead.GetType().GetFields();
|
|
||||||
foreach (var field in fields.Where(x => x.HasAttribute<UpgradeGrantedReferenceAttribute>()))
|
|
||||||
{
|
|
||||||
var values = LintExts.GetFieldValues(warhead, field, emitError);
|
|
||||||
foreach (var value in values.Where(x => !upgradesUsed.Contains(x)))
|
|
||||||
emitWarning("Weapon type `{0}` grants upgrade `{1}` that is not used by anything!".F(weapon.Key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static IEnumerable<string> GetAllGrantedUpgrades(Action<string> emitError, Ruleset rules)
|
|
||||||
{
|
|
||||||
// Get all upgrades granted by traits.
|
|
||||||
foreach (var actorInfo in rules.Actors)
|
|
||||||
{
|
|
||||||
foreach (var trait in actorInfo.Value.TraitInfos<ITraitInfo>())
|
|
||||||
{
|
|
||||||
var fields = trait.GetType().GetFields();
|
|
||||||
foreach (var field in fields.Where(x => x.HasAttribute<UpgradeGrantedReferenceAttribute>()))
|
|
||||||
{
|
|
||||||
var values = LintExts.GetFieldValues(trait, field, emitError);
|
|
||||||
foreach (var value in values)
|
|
||||||
yield return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all upgrades granted by warheads.
|
|
||||||
foreach (var weapon in rules.Weapons)
|
|
||||||
{
|
|
||||||
foreach (var warhead in weapon.Value.Warheads)
|
|
||||||
{
|
|
||||||
var fields = warhead.GetType().GetFields();
|
|
||||||
foreach (var field in fields.Where(x => x.HasAttribute<UpgradeGrantedReferenceAttribute>()))
|
|
||||||
{
|
|
||||||
var values = LintExts.GetFieldValues(warhead, field, emitError);
|
|
||||||
foreach (var value in values)
|
|
||||||
yield return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: HACK because GainsExperience grants upgrades differently to most other sources.
|
|
||||||
var gainsExperience = rules.Actors.SelectMany(x => x.Value.TraitInfos<GainsExperienceInfo>()
|
|
||||||
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
|
|
||||||
|
|
||||||
foreach (var upgrade in gainsExperience)
|
|
||||||
yield return upgrade;
|
|
||||||
|
|
||||||
// TODO: HACK because Pluggable grants upgrades differently to most other sources.
|
|
||||||
var pluggable = rules.Actors.SelectMany(x => x.Value.TraitInfos<PluggableInfo>()
|
|
||||||
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
|
|
||||||
|
|
||||||
foreach (var upgrade in pluggable)
|
|
||||||
yield return upgrade;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IEnumerable<string> GetAllUsedUpgrades(Action<string> emitError, Ruleset rules)
|
|
||||||
{
|
|
||||||
foreach (var actorInfo in rules.Actors)
|
|
||||||
{
|
|
||||||
foreach (var trait in actorInfo.Value.TraitInfos<ITraitInfo>())
|
|
||||||
{
|
|
||||||
var fields = trait.GetType().GetFields();
|
|
||||||
foreach (var field in fields.Where(x => x.HasAttribute<UpgradeUsedReferenceAttribute>()))
|
|
||||||
{
|
|
||||||
var values = LintExts.GetFieldValues(trait, field, emitError);
|
|
||||||
foreach (var value in values)
|
|
||||||
yield return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: HACK because GainsExperience and GainsStatUpgrades do not play by the rules...
|
|
||||||
// We assume everything GainsExperience grants is used by GainsStatUpgrade
|
|
||||||
var gainsExperience = rules.Actors.SelectMany(x => x.Value.TraitInfos<GainsExperienceInfo>()
|
|
||||||
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
|
|
||||||
|
|
||||||
foreach (var upgrade in gainsExperience)
|
|
||||||
yield return upgrade;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using OpenRA.Support;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Lint
|
namespace OpenRA.Mods.Common.Lint
|
||||||
{
|
{
|
||||||
@@ -26,8 +28,13 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
return (string[])fieldInfo.GetValue(ruleInfo);
|
return (string[])fieldInfo.GetValue(ruleInfo);
|
||||||
if (type == typeof(HashSet<string>))
|
if (type == typeof(HashSet<string>))
|
||||||
return (HashSet<string>)fieldInfo.GetValue(ruleInfo);
|
return (HashSet<string>)fieldInfo.GetValue(ruleInfo);
|
||||||
|
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>"
|
emitError("Bad type for reference on {0}.{1}. Supported types: string, string[], HashSet<string>, BooleanExpression"
|
||||||
.F(ruleInfo.GetType().Name, fieldInfo.Name));
|
.F(ruleInfo.GetType().Name, fieldInfo.Name));
|
||||||
|
|
||||||
return new string[] { };
|
return new string[] { };
|
||||||
|
|||||||
@@ -181,7 +181,6 @@
|
|||||||
<Compile Include="Lint\CheckDeathTypes.cs" />
|
<Compile Include="Lint\CheckDeathTypes.cs" />
|
||||||
<Compile Include="Lint\CheckRangeLimit.cs" />
|
<Compile Include="Lint\CheckRangeLimit.cs" />
|
||||||
<Compile Include="Lint\CheckVoiceReferences.cs" />
|
<Compile Include="Lint\CheckVoiceReferences.cs" />
|
||||||
<Compile Include="Lint\CheckUpgrades.cs" />
|
|
||||||
<Compile Include="Lint\CheckTargetHealthRadius.cs" />
|
<Compile Include="Lint\CheckTargetHealthRadius.cs" />
|
||||||
<Compile Include="Lint\LintBuildablePrerequisites.cs" />
|
<Compile Include="Lint\LintBuildablePrerequisites.cs" />
|
||||||
<Compile Include="Lint\LintExts.cs" />
|
<Compile Include="Lint\LintExts.cs" />
|
||||||
@@ -357,7 +356,6 @@
|
|||||||
<Compile Include="Traits\Parachutable.cs" />
|
<Compile Include="Traits\Parachutable.cs" />
|
||||||
<Compile Include="Traits\ParaDrop.cs" />
|
<Compile Include="Traits\ParaDrop.cs" />
|
||||||
<Compile Include="Traits\Passenger.cs" />
|
<Compile Include="Traits\Passenger.cs" />
|
||||||
<Compile Include="Traits\Multipliers\UpgradableMultiplierTrait.cs" />
|
|
||||||
<Compile Include="Traits\Multipliers\DamageMultiplier.cs" />
|
<Compile Include="Traits\Multipliers\DamageMultiplier.cs" />
|
||||||
<Compile Include="Traits\Multipliers\FirepowerMultiplier.cs" />
|
<Compile Include="Traits\Multipliers\FirepowerMultiplier.cs" />
|
||||||
<Compile Include="Traits\Multipliers\InaccuracyMultiplier.cs" />
|
<Compile Include="Traits\Multipliers\InaccuracyMultiplier.cs" />
|
||||||
@@ -443,7 +441,6 @@
|
|||||||
<Compile Include="Traits\Render\WithMuzzleOverlay.cs" />
|
<Compile Include="Traits\Render\WithMuzzleOverlay.cs" />
|
||||||
<Compile Include="Traits\Render\WithParachute.cs" />
|
<Compile Include="Traits\Render\WithParachute.cs" />
|
||||||
<Compile Include="Traits\Render\WithRangeCircle.cs" />
|
<Compile Include="Traits\Render\WithRangeCircle.cs" />
|
||||||
<Compile Include="Traits\Render\WithRankDecoration.cs" />
|
|
||||||
<Compile Include="Traits\Render\WithRearmAnimation.cs" />
|
<Compile Include="Traits\Render\WithRearmAnimation.cs" />
|
||||||
<Compile Include="Traits\Render\WithRepairAnimation.cs" />
|
<Compile Include="Traits\Render\WithRepairAnimation.cs" />
|
||||||
<Compile Include="Traits\Render\WithRepairOverlay.cs" />
|
<Compile Include="Traits\Render\WithRepairOverlay.cs" />
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Desc("Allows you to attach weapons to the unit (use @IdentifierSuffix for > 1)")]
|
[Desc("Allows you to attach weapons to the unit (use @IdentifierSuffix for > 1)")]
|
||||||
public class ArmamentInfo : UpgradableTraitInfo, IRulesetLoaded, Requires<AttackBaseInfo>
|
public class ArmamentInfo : UpgradableTraitInfo, Requires<AttackBaseInfo>
|
||||||
{
|
{
|
||||||
public readonly string Name = "primary";
|
public readonly string Name = "primary";
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new Armament(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new Armament(init.Self, this); }
|
||||||
|
|
||||||
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
{
|
{
|
||||||
WeaponInfo weaponInfo;
|
WeaponInfo weaponInfo;
|
||||||
|
|
||||||
@@ -91,10 +91,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
ModifiedRange = new WDist(Util.ApplyPercentageModifiers(
|
ModifiedRange = new WDist(Util.ApplyPercentageModifiers(
|
||||||
WeaponInfo.Range.Length,
|
WeaponInfo.Range.Length,
|
||||||
ai.TraitInfos<IRangeModifierInfo>().Select(m => m.GetRangeModifierDefault())));
|
ai.TraitInfos<IRangeModifierInfo>().Select(m => m.GetRangeModifierDefault())));
|
||||||
|
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Armament : UpgradableTrait<ArmamentInfo>, INotifyCreated, ITick, IExplodeModifier
|
public class Armament : UpgradableTrait<ArmamentInfo>, ITick, IExplodeModifier
|
||||||
{
|
{
|
||||||
public readonly WeaponInfo Weapon;
|
public readonly WeaponInfo Weapon;
|
||||||
public readonly Barrel[] Barrels;
|
public readonly Barrel[] Barrels;
|
||||||
@@ -139,12 +141,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return new WDist(Util.ApplyPercentageModifiers(Weapon.Range.Length, rangeModifiers));
|
return new WDist(Util.ApplyPercentageModifiers(Weapon.Range.Length, rangeModifiers));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Created(Actor self)
|
protected override void Created(Actor self)
|
||||||
{
|
{
|
||||||
turret = self.TraitsImplementing<Turreted>().FirstOrDefault(t => t.Name == Info.Turret);
|
turret = self.TraitsImplementing<Turreted>().FirstOrDefault(t => t.Name == Info.Turret);
|
||||||
ammoPool = self.TraitsImplementing<AmmoPool>().FirstOrDefault(la => la.Info.Name == Info.AmmoPoolName);
|
ammoPool = self.TraitsImplementing<AmmoPool>().FirstOrDefault(la => la.Info.Name == Info.AmmoPoolName);
|
||||||
coords = self.Trait<BodyOrientation>();
|
coords = self.Trait<BodyOrientation>();
|
||||||
rangeModifiers = self.TraitsImplementing<IRangeModifier>().ToArray().Select(m => m.GetRangeModifier());
|
rangeModifiers = self.TraitsImplementing<IRangeModifier>().ToArray().Select(m => m.GetRangeModifier());
|
||||||
|
|
||||||
|
base.Created(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Tick(Actor self)
|
protected virtual void Tick(Actor self)
|
||||||
@@ -168,12 +172,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
delayedActions.RemoveAll(a => a.First <= 0);
|
delayedActions.RemoveAll(a => a.First <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
|
||||||
{
|
|
||||||
// Split into a protected method to allow subclassing
|
|
||||||
Created(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITick.Tick(Actor self)
|
void ITick.Tick(Actor self)
|
||||||
{
|
{
|
||||||
// Split into a protected method to allow subclassing
|
// Split into a protected method to allow subclassing
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[PaletteReference] public readonly string MuzzlePalette = "effect";
|
[PaletteReference] public readonly string MuzzlePalette = "effect";
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new AttackGarrisoned(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new AttackGarrisoned(init.Self, this); }
|
||||||
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
{
|
{
|
||||||
if (PortOffsets.Length == 0)
|
if (PortOffsets.Length == 0)
|
||||||
throw new YamlException("PortOffsets must have at least one entry.");
|
throw new YamlException("PortOffsets must have at least one entry.");
|
||||||
@@ -67,6 +67,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
Cone = PortCones[i],
|
Cone = PortCones[i],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("This actor can transport Passenger actors.")]
|
[Desc("This actor can transport Passenger actors.")]
|
||||||
public class CargoInfo : ITraitInfo, Requires<IOccupySpaceInfo>, Requires<UpgradeManagerInfo>
|
public class CargoInfo : ITraitInfo, Requires<IOccupySpaceInfo>
|
||||||
{
|
{
|
||||||
[Desc("The maximum sum of Passenger.Weight that this actor can support.")]
|
[Desc("The maximum sum of Passenger.Weight that this actor can support.")]
|
||||||
public readonly int MaxWeight = 0;
|
public readonly int MaxWeight = 0;
|
||||||
@@ -67,7 +67,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public readonly CargoInfo Info;
|
public readonly CargoInfo Info;
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
readonly UpgradeManager upgradeManager;
|
|
||||||
readonly Stack<Actor> cargo = new Stack<Actor>();
|
readonly Stack<Actor> cargo = new Stack<Actor>();
|
||||||
readonly HashSet<Actor> reserves = new HashSet<Actor>();
|
readonly HashSet<Actor> reserves = new HashSet<Actor>();
|
||||||
readonly Lazy<IFacing> facing;
|
readonly Lazy<IFacing> facing;
|
||||||
@@ -76,6 +75,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
int totalWeight = 0;
|
int totalWeight = 0;
|
||||||
int reservedWeight = 0;
|
int reservedWeight = 0;
|
||||||
Aircraft aircraft;
|
Aircraft aircraft;
|
||||||
|
UpgradeManager upgradeManager;
|
||||||
|
|
||||||
CPos currentCell;
|
CPos currentCell;
|
||||||
public IEnumerable<CPos> CurrentAdjacentCells { get; private set; }
|
public IEnumerable<CPos> CurrentAdjacentCells { get; private set; }
|
||||||
@@ -89,7 +89,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
Info = info;
|
Info = info;
|
||||||
Unloading = false;
|
Unloading = false;
|
||||||
checkTerrainType = info.UnloadTerrainTypes.Count > 0;
|
checkTerrainType = info.UnloadTerrainTypes.Count > 0;
|
||||||
upgradeManager = self.Trait<UpgradeManager>();
|
|
||||||
|
|
||||||
if (init.Contains<RuntimeCargoInit>())
|
if (init.Contains<RuntimeCargoInit>())
|
||||||
{
|
{
|
||||||
@@ -127,6 +126,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
aircraft = self.TraitOrDefault<Aircraft>();
|
aircraft = self.TraitOrDefault<Aircraft>();
|
||||||
|
upgradeManager = self.Trait<UpgradeManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetWeight(Actor a) { return a.Info.TraitInfo<PassengerInfo>().Weight; }
|
static int GetWeight(Actor a) { return a.Info.TraitInfo<PassengerInfo>().Weight; }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Can be carried by actors with the `Carryall` trait.")]
|
[Desc("Can be carried by actors with the `Carryall` trait.")]
|
||||||
public class CarryableInfo : ITraitInfo, Requires<UpgradeManagerInfo>
|
public class CarryableInfo : ITraitInfo
|
||||||
{
|
{
|
||||||
[UpgradeGrantedReference]
|
[UpgradeGrantedReference]
|
||||||
[Desc("The upgrades to grant to self while waiting or being carried.")]
|
[Desc("The upgrades to grant to self while waiting or being carried.")]
|
||||||
@@ -27,10 +27,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public virtual object Create(ActorInitializer init) { return new Carryable(init.Self, this); }
|
public virtual object Create(ActorInitializer init) { return new Carryable(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Carryable
|
public class Carryable : INotifyCreated
|
||||||
{
|
{
|
||||||
readonly CarryableInfo info;
|
readonly CarryableInfo info;
|
||||||
readonly UpgradeManager upgradeManager;
|
UpgradeManager upgradeManager;
|
||||||
|
|
||||||
public Actor Carrier { get; private set; }
|
public Actor Carrier { get; private set; }
|
||||||
public bool Reserved { get { return state != State.Free; } }
|
public bool Reserved { get { return state != State.Free; } }
|
||||||
@@ -44,6 +44,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public Carryable(Actor self, CarryableInfo info)
|
public Carryable(Actor self, CarryableInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void INotifyCreated.Created(Actor self)
|
||||||
|
{
|
||||||
upgradeManager = self.Trait<UpgradeManager>();
|
upgradeManager = self.Trait<UpgradeManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public void AddedToWorld(Actor self)
|
public void AddedToWorld(Actor self)
|
||||||
{
|
{
|
||||||
if (!IsTraitDisabled)
|
if (!IsTraitDisabled)
|
||||||
UpgradeEnabled(self);
|
TraitEnabled(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpgradeEnabled(Actor self)
|
protected override void TraitEnabled(Actor self)
|
||||||
{
|
{
|
||||||
if (self.IsDead)
|
if (self.IsDead)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -13,19 +13,25 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Damage taken by this actor is multiplied based on upgrade level.",
|
[Desc("Modifies the damage applied to this actor.",
|
||||||
"Decrease to increase actor's apparent strength.",
|
|
||||||
"Use 0 to make actor invulnerable.")]
|
"Use 0 to make actor invulnerable.")]
|
||||||
public class DamageMultiplierInfo : UpgradeMultiplierTraitInfo
|
public class DamageMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new DamageMultiplier(this, init.Self.Info.Name); }
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new DamageMultiplier(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DamageMultiplier : UpgradeMultiplierTrait, IDamageModifier
|
public class DamageMultiplier : UpgradableTrait<DamageMultiplierInfo>, IDamageModifier
|
||||||
{
|
{
|
||||||
public DamageMultiplier(DamageMultiplierInfo info, string actorType)
|
public DamageMultiplier(DamageMultiplierInfo info)
|
||||||
: base(info, "DamageMultiplier", actorType) { }
|
: base(info) { }
|
||||||
|
|
||||||
int IDamageModifier.GetDamageModifier(Actor attacker, Damage damage) { return GetModifier(); }
|
int IDamageModifier.GetDamageModifier(Actor attacker, Damage damage)
|
||||||
|
{
|
||||||
|
return IsTraitDisabled ? 100 : Info.Modifier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,17 +11,21 @@
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("The firepower of this actor is multiplied based on upgrade level if specified.")]
|
[Desc("Modifies the damage applied by this actor.")]
|
||||||
public class FirepowerMultiplierInfo : UpgradeMultiplierTraitInfo
|
public class FirepowerMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new FirepowerMultiplier(this, init.Self.Info.Name); }
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new FirepowerMultiplier(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FirepowerMultiplier : UpgradeMultiplierTrait, IFirepowerModifier
|
public class FirepowerMultiplier : UpgradableTrait<FirepowerMultiplierInfo>, IFirepowerModifier
|
||||||
{
|
{
|
||||||
public FirepowerMultiplier(FirepowerMultiplierInfo info, string actorType)
|
public FirepowerMultiplier(FirepowerMultiplierInfo info)
|
||||||
: base(info, "FirepowerMultiplier", actorType) { }
|
: base(info) { }
|
||||||
|
|
||||||
int IFirepowerModifier.GetFirepowerModifier() { return GetModifier(); }
|
int IFirepowerModifier.GetFirepowerModifier() { return IsTraitDisabled ? 100 : Info.Modifier; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,17 +11,21 @@
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("The inaccuracy of this actor is multiplied based on upgrade level if specified.")]
|
[Desc("Modifies the inaccuracy of weapons fired by this actor.")]
|
||||||
public class InaccuracyMultiplierInfo : UpgradeMultiplierTraitInfo
|
public class InaccuracyMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new InaccuracyMultiplier(this, init.Self.Info.Name); }
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new InaccuracyMultiplier(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InaccuracyMultiplier : UpgradeMultiplierTrait, IInaccuracyModifier
|
public class InaccuracyMultiplier : UpgradableTrait<InaccuracyMultiplierInfo>, IInaccuracyModifier
|
||||||
{
|
{
|
||||||
public InaccuracyMultiplier(InaccuracyMultiplierInfo info, string actorType)
|
public InaccuracyMultiplier(InaccuracyMultiplierInfo info)
|
||||||
: base(info, "InaccuracyMultiplier", actorType) { }
|
: base(info) { }
|
||||||
|
|
||||||
int IInaccuracyModifier.GetInaccuracyModifier() { return GetModifier(); }
|
int IInaccuracyModifier.GetInaccuracyModifier() { return IsTraitDisabled ? 100 : Info.Modifier; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,22 +13,30 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("The power usage/output of this actor is multiplied based on upgrade level if specified.")]
|
[Desc("Modifies the power usage/output of this actor.")]
|
||||||
public class PowerMultiplierInfo : UpgradeMultiplierTraitInfo
|
public class PowerMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new PowerMultiplier(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new PowerMultiplier(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PowerMultiplier : UpgradeMultiplierTrait, IPowerModifier, INotifyOwnerChanged
|
public class PowerMultiplier : UpgradableTrait<PowerMultiplierInfo>, IPowerModifier, INotifyOwnerChanged
|
||||||
{
|
{
|
||||||
PowerManager power;
|
PowerManager power;
|
||||||
|
|
||||||
public PowerMultiplier(Actor self, PowerMultiplierInfo info)
|
public PowerMultiplier(Actor self, PowerMultiplierInfo info)
|
||||||
: base(info, "PowerMultiplier", self.Info.Name) { power = self.Owner.PlayerActor.Trait<PowerManager>(); }
|
: base(info)
|
||||||
|
{
|
||||||
|
power = self.Owner.PlayerActor.Trait<PowerManager>();
|
||||||
|
}
|
||||||
|
|
||||||
int IPowerModifier.GetPowerModifier() { return GetModifier(); }
|
protected override void TraitEnabled(Actor self) { power.UpdateActor(self); }
|
||||||
|
protected override void TraitDisabled(Actor self) { power.UpdateActor(self); }
|
||||||
|
|
||||||
protected override void Update(Actor self) { power.UpdateActor(self); }
|
int IPowerModifier.GetPowerModifier() { return IsTraitDisabled ? 100 : Info.Modifier; }
|
||||||
|
|
||||||
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,22 +11,21 @@
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Range of this actor is multiplied based on upgrade level.")]
|
[Desc("Modifies the range of weapons fired by this actor.")]
|
||||||
public class RangeMultiplierInfo : UpgradeMultiplierTraitInfo, IRangeModifierInfo
|
public class RangeMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new RangeMultiplier(this, init.Self.Info.Name); }
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
int IRangeModifierInfo.GetRangeModifierDefault()
|
public override object Create(ActorInitializer init) { return new RangeMultiplier(this); }
|
||||||
{
|
|
||||||
return BaseLevel > 0 || UpgradeTypes.Length == 0 ? 100 : Modifier[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RangeMultiplier : UpgradeMultiplierTrait, IRangeModifier
|
public class RangeMultiplier : UpgradableTrait<RangeMultiplierInfo>, IRangeModifierInfo
|
||||||
{
|
{
|
||||||
public RangeMultiplier(RangeMultiplierInfo info, string actorType)
|
public RangeMultiplier(RangeMultiplierInfo info)
|
||||||
: base(info, "RangeMultiplier", actorType) { }
|
: base(info) { }
|
||||||
|
|
||||||
int IRangeModifier.GetRangeModifier() { return GetModifier(); }
|
int IRangeModifierInfo.GetRangeModifierDefault() { return IsTraitDisabled ? 100 : Info.Modifier; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,17 +11,21 @@
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("The reloading time of this actor is multiplied based on upgrade level if specified.")]
|
[Desc("Modifies the reload time of weapons fired by this actor.")]
|
||||||
public class ReloadDelayMultiplierInfo : UpgradeMultiplierTraitInfo
|
public class ReloadDelayMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new ReloadDelayMultiplier(this, init.Self.Info.Name); }
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new ReloadDelayMultiplier(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReloadDelayMultiplier : UpgradeMultiplierTrait, IReloadModifier
|
public class ReloadDelayMultiplier : UpgradableTrait<ReloadDelayMultiplierInfo>, IReloadModifier
|
||||||
{
|
{
|
||||||
public ReloadDelayMultiplier(ReloadDelayMultiplierInfo info, string actorType)
|
public ReloadDelayMultiplier(ReloadDelayMultiplierInfo info)
|
||||||
: base(info, "ReloadDelayMultiplier", actorType) { }
|
: base(info) { }
|
||||||
|
|
||||||
int IReloadModifier.GetReloadModifier() { return GetModifier(); }
|
int IReloadModifier.GetReloadModifier() { return IsTraitDisabled ? 100 : Info.Modifier; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,17 +11,21 @@
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("The speed of this actor is multiplied based on upgrade level if specified.")]
|
[Desc("Modifies the movement speed of this actor.")]
|
||||||
public class SpeedMultiplierInfo : UpgradeMultiplierTraitInfo
|
public class SpeedMultiplierInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new SpeedMultiplier(this, init.Self.Info.Name); }
|
[FieldLoader.Require]
|
||||||
|
[Desc("Percentage modifier to apply.")]
|
||||||
|
public readonly int Modifier = 100;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new SpeedMultiplier(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SpeedMultiplier : UpgradeMultiplierTrait, ISpeedModifier
|
public class SpeedMultiplier : UpgradableTrait<SpeedMultiplierInfo>, ISpeedModifier
|
||||||
{
|
{
|
||||||
public SpeedMultiplier(SpeedMultiplierInfo info, string actorType)
|
public SpeedMultiplier(SpeedMultiplierInfo info)
|
||||||
: base(info, "SpeedMultiplier", actorType) { }
|
: base(info) { }
|
||||||
|
|
||||||
int ISpeedModifier.GetSpeedModifier() { return GetModifier(); }
|
int ISpeedModifier.GetSpeedModifier() { return IsTraitDisabled ? 100 : Info.Modifier; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
#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.Traits;
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
|
||||||
{
|
|
||||||
public abstract class UpgradeMultiplierTraitInfo : ITraitInfo
|
|
||||||
{
|
|
||||||
[UpgradeUsedReference]
|
|
||||||
[Desc("Accepted upgrade types.")]
|
|
||||||
public readonly string[] UpgradeTypes = { };
|
|
||||||
|
|
||||||
[Desc("The lowest upgrade level using the scale.")]
|
|
||||||
public readonly int BaseLevel = 1;
|
|
||||||
|
|
||||||
[FieldLoader.Require]
|
|
||||||
[Desc("Percentages to apply with the first being applied at the base level.",
|
|
||||||
"Repeat last entry to accept time extensions.",
|
|
||||||
"If no upgrade types are specified, then the first/only modifier is always applied.")]
|
|
||||||
public readonly int[] Modifier = { };
|
|
||||||
|
|
||||||
public abstract object Create(ActorInitializer init);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class UpgradeMultiplierTrait : IUpgradable, IDisabledTrait, ISync
|
|
||||||
{
|
|
||||||
readonly UpgradeMultiplierTraitInfo info;
|
|
||||||
[Sync] int level = 0;
|
|
||||||
[Sync] public bool IsTraitDisabled { get; private set; }
|
|
||||||
public int AdjustedLevel { get { return level - info.BaseLevel; } }
|
|
||||||
public IEnumerable<string> UpgradeTypes { get { return info.UpgradeTypes; } }
|
|
||||||
|
|
||||||
protected UpgradeMultiplierTrait(UpgradeMultiplierTraitInfo info, string modifierType, string actorType)
|
|
||||||
{
|
|
||||||
if (info.Modifier.Length == 0)
|
|
||||||
throw new ArgumentException("No modifiers in " + modifierType + " for " + actorType);
|
|
||||||
this.info = info;
|
|
||||||
IsTraitDisabled = info.UpgradeTypes.Length > 0 && info.BaseLevel > 0;
|
|
||||||
level = IsTraitDisabled ? 0 : info.BaseLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AcceptsUpgradeLevel(Actor self, string type, int level)
|
|
||||||
{
|
|
||||||
return level < info.Modifier.Length + info.BaseLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override to receive notice of level change.
|
|
||||||
protected virtual void Update(Actor self) { }
|
|
||||||
|
|
||||||
public void UpgradeLevelChanged(Actor self, string type, int oldLevel, int newLevel)
|
|
||||||
{
|
|
||||||
if (!UpgradeTypes.Contains(type))
|
|
||||||
return;
|
|
||||||
level = newLevel.Clamp(0, Math.Max(info.Modifier.Length + info.BaseLevel - 1, 0));
|
|
||||||
IsTraitDisabled = level < info.BaseLevel;
|
|
||||||
Update(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetModifier()
|
|
||||||
{
|
|
||||||
return IsTraitDisabled ? 100 : info.Modifier[level - info.BaseLevel];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
power = newOwner.PlayerActor.Trait<PowerManager>();
|
power = newOwner.PlayerActor.Trait<PowerManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpgradeDisabled(Actor self)
|
protected override void TraitDisabled(Actor self)
|
||||||
{
|
{
|
||||||
if (!disabled || !Info.CancelWhenDisabled)
|
if (!disabled || !Info.CancelWhenDisabled)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
powerModifiers = Exts.Lazy(() => self.TraitsImplementing<IPowerModifier>().ToArray());
|
powerModifiers = Exts.Lazy(() => self.TraitsImplementing<IPowerModifier>().ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpgradeEnabled(Actor self) { PlayerPower.UpdateActor(self); }
|
protected override void TraitEnabled(Actor self) { PlayerPower.UpdateActor(self); }
|
||||||
protected override void UpgradeDisabled(Actor self) { PlayerPower.UpdateActor(self); }
|
protected override void TraitDisabled(Actor self) { PlayerPower.UpdateActor(self); }
|
||||||
public void AddedToWorld(Actor self) { PlayerPower.UpdateActor(self); }
|
public void AddedToWorld(Actor self) { PlayerPower.UpdateActor(self); }
|
||||||
public void RemovedFromWorld(Actor self) { PlayerPower.RemoveActor(self); }
|
public void RemovedFromWorld(Actor self) { PlayerPower.RemoveActor(self); }
|
||||||
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
public override object Create(ActorInitializer init) { return new LeavesTrails(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new LeavesTrails(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LeavesTrails : UpgradableTrait<LeavesTrailsInfo>, ITick, INotifyCreated
|
public class LeavesTrails : UpgradableTrait<LeavesTrailsInfo>, ITick
|
||||||
{
|
{
|
||||||
BodyOrientation body;
|
BodyOrientation body;
|
||||||
IFacing facing;
|
IFacing facing;
|
||||||
@@ -75,12 +75,14 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
|
|
||||||
WPos cachedPosition;
|
WPos cachedPosition;
|
||||||
public void Created(Actor self)
|
protected override void Created(Actor self)
|
||||||
{
|
{
|
||||||
body = self.Trait<BodyOrientation>();
|
body = self.Trait<BodyOrientation>();
|
||||||
facing = self.TraitOrDefault<IFacing>();
|
facing = self.TraitOrDefault<IFacing>();
|
||||||
cachedFacing = facing != null ? facing.Facing : 0;
|
cachedFacing = facing != null ? facing.Facing : 0;
|
||||||
cachedPosition = self.CenterPosition;
|
cachedPosition = self.CenterPosition;
|
||||||
|
|
||||||
|
base.Created(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ticks;
|
int ticks;
|
||||||
@@ -132,7 +134,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpgradeEnabled(Actor self)
|
protected override void TraitEnabled(Actor self)
|
||||||
{
|
{
|
||||||
cachedPosition = self.CenterPosition;
|
cachedPosition = self.CenterPosition;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
// Defer this lookup until we really need it to ensure we get the correct value.
|
// Defer this lookup until we really need it to ensure we get the correct value.
|
||||||
range = Exts.Lazy(() =>
|
range = Exts.Lazy(() =>
|
||||||
{
|
{
|
||||||
var armaments = ai.TraitInfos<ArmamentInfo>().Where(a => a.UpgradeMinEnabledLevel == 0);
|
var armaments = ai.TraitInfos<ArmamentInfo>().Where(a => a.EnabledByDefault);
|
||||||
if (!armaments.Any())
|
if (!armaments.Any())
|
||||||
return FallbackRange;
|
return FallbackRange;
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
if (Palette != null)
|
if (Palette != null)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WithInfantryBody : UpgradableTrait<WithInfantryBodyInfo>, ITick, INotifyAttack, INotifyIdle, INotifyCreated
|
public class WithInfantryBody : UpgradableTrait<WithInfantryBodyInfo>, ITick, INotifyAttack, INotifyIdle
|
||||||
{
|
{
|
||||||
readonly IMove move;
|
readonly IMove move;
|
||||||
protected readonly Animation DefaultAnimation;
|
protected readonly Animation DefaultAnimation;
|
||||||
@@ -90,9 +90,11 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Created(Actor self)
|
protected override void Created(Actor self)
|
||||||
{
|
{
|
||||||
rsm = self.TraitOrDefault<IRenderInfantrySequenceModifier>();
|
rsm = self.TraitOrDefault<IRenderInfantrySequenceModifier>();
|
||||||
|
|
||||||
|
base.Created(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string NormalizeInfantrySequence(Actor self, string baseSequence)
|
protected virtual string NormalizeInfantrySequence(Actor self, string baseSequence)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
if (image == null)
|
if (image == null)
|
||||||
@@ -128,7 +128,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
rs.Add(anim, info.Palette, info.IsPlayerPalette);
|
rs.Add(anim, info.Palette, info.IsPlayerPalette);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpgradeEnabled(Actor self)
|
protected override void TraitEnabled(Actor self)
|
||||||
{
|
{
|
||||||
if (info.Image == null)
|
if (info.Image == null)
|
||||||
return;
|
return;
|
||||||
@@ -136,7 +136,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
anim.Animation.PlayThen(info.OpeningSequence, () => anim.Animation.PlayRepeating(info.Sequence));
|
anim.Animation.PlayThen(info.OpeningSequence, () => anim.Animation.PlayRepeating(info.Sequence));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpgradeDisabled(Actor self)
|
protected override void TraitDisabled(Actor self)
|
||||||
{
|
{
|
||||||
if (info.Image == null)
|
if (info.Image == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#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
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits.Render
|
|
||||||
{
|
|
||||||
public class WithRankDecorationInfo : WithDecorationInfo
|
|
||||||
{
|
|
||||||
public override object Create(ActorInitializer init) { return new WithRankDecoration(init.Self, this); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class WithRankDecoration : WithDecoration
|
|
||||||
{
|
|
||||||
public WithRankDecoration(Actor self, WithRankDecorationInfo info) : base(self, info) { }
|
|
||||||
|
|
||||||
protected override void UpgradeLevelChanged(Actor self, int oldLevel, int newLevel)
|
|
||||||
{
|
|
||||||
Anim.PlayFetchIndex(Info.Sequence, () => newLevel - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public virtual IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
public virtual IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var anim = new Animation(init.World, image);
|
var anim = new Animation(init.World, image);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Traits.Render
|
namespace OpenRA.Mods.Common.Traits.Render
|
||||||
{
|
{
|
||||||
[Desc("Displays a text overlay relative to the selection box.")]
|
[Desc("Displays a text overlay relative to the selection box.")]
|
||||||
public class WithTextDecorationInfo : UpgradableTraitInfo, IRulesetLoaded
|
public class WithTextDecorationInfo : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
[FieldLoader.Require] [Translate] public readonly string Text = null;
|
[FieldLoader.Require] [Translate] public readonly string Text = null;
|
||||||
|
|
||||||
@@ -47,10 +47,12 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new WithTextDecoration(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new WithTextDecoration(init.Self, this); }
|
||||||
|
|
||||||
void IRulesetLoaded<ActorInfo>.RulesetLoaded(Ruleset rules, ActorInfo info)
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
{
|
{
|
||||||
if (!Game.ModData.Manifest.Fonts.ContainsKey(Font))
|
if (!Game.ModData.Manifest.Fonts.ContainsKey(Font))
|
||||||
throw new YamlException("Font '{0}' is not listed in the mod.yaml's Fonts section".F(Font));
|
throw new YamlException("Font '{0}' is not listed in the mod.yaml's Fonts section".F(Font));
|
||||||
|
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
|
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
|
||||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
|
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
|
||||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||||
{
|
{
|
||||||
if (UpgradeMinEnabledLevel > 0)
|
if (!EnabledByDefault)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||||
|
|||||||
@@ -74,7 +74,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public WeaponInfo WeaponInfo { get; private set; }
|
public WeaponInfo WeaponInfo { get; private set; }
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new NukePower(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new NukePower(init.Self, this); }
|
||||||
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { WeaponInfo = rules.Weapons[MissileWeapon.ToLowerInvariant()]; }
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
|
{
|
||||||
|
WeaponInfo = rules.Weapons[MissileWeapon.ToLowerInvariant()];
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NukePower : SupportPower
|
class NukePower : SupportPower
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public override object Create(ActorInitializer init) { return new Targetable(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new Targetable(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Targetable : UpgradableTrait<TargetableInfo>, ITargetable, INotifyCreated
|
public class Targetable : UpgradableTrait<TargetableInfo>, ITargetable
|
||||||
{
|
{
|
||||||
protected static readonly string[] None = new string[] { };
|
protected static readonly string[] None = new string[] { };
|
||||||
protected Cloak[] cloaks;
|
protected Cloak[] cloaks;
|
||||||
@@ -35,9 +35,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public Targetable(Actor self, TargetableInfo info)
|
public Targetable(Actor self, TargetableInfo info)
|
||||||
: base(info) { }
|
: base(info) { }
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
protected override void Created(Actor self)
|
||||||
{
|
{
|
||||||
cloaks = self.TraitsImplementing<Cloak>().ToArray();
|
cloaks = self.TraitsImplementing<Cloak>().ToArray();
|
||||||
|
|
||||||
|
base.Created(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool TargetableBy(Actor self, Actor viewer)
|
public virtual bool TargetableBy(Actor self, Actor viewer)
|
||||||
|
|||||||
@@ -10,30 +10,32 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Support;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
/// <summary>Use as base class for *Info to subclass of UpgradableTrait. (See UpgradableTrait.)</summary>
|
/// <summary>Use as base class for *Info to subclass of UpgradableTrait. (See UpgradableTrait.)</summary>
|
||||||
public abstract class UpgradableTraitInfo : IUpgradableInfo
|
public abstract class UpgradableTraitInfo : IConditionConsumerInfo, IRulesetLoaded
|
||||||
{
|
{
|
||||||
|
static readonly IReadOnlyDictionary<string, bool> NoConditions = new ReadOnlyDictionary<string, bool>(new Dictionary<string, bool>());
|
||||||
|
|
||||||
[UpgradeUsedReference]
|
[UpgradeUsedReference]
|
||||||
[Desc("The upgrade types which can enable or disable this trait.")]
|
[Desc("Boolean expression defining the condition to enable this trait.")]
|
||||||
public readonly HashSet<string> UpgradeTypes = new HashSet<string>();
|
public readonly BooleanExpression RequiresCondition = null;
|
||||||
|
|
||||||
[Desc("The minimum upgrade level at which this trait is enabled.", "Defaults to 0 (enabled by default).")]
|
|
||||||
public readonly int UpgradeMinEnabledLevel = 0;
|
|
||||||
|
|
||||||
[Desc("The maximum upgrade level at which the trait is enabled.",
|
|
||||||
"Defaults to UpgradeMaxAcceptedLevel (enabled for all levels greater than UpgradeMinEnabledLevel).",
|
|
||||||
"Set this to a value smaller than UpgradeMaxAcceptedLevel to disable the trait at higher levels.",
|
|
||||||
"Use UpgradeMaxAcceptedLevel: 2 (1 more) to be able to extend upgrade time.")]
|
|
||||||
public readonly int UpgradeMaxEnabledLevel = int.MaxValue;
|
|
||||||
|
|
||||||
[Desc("The maximum upgrade level that this trait will accept.")]
|
|
||||||
public readonly int UpgradeMaxAcceptedLevel = 1;
|
|
||||||
|
|
||||||
public abstract object Create(ActorInitializer init);
|
public abstract object Create(ActorInitializer init);
|
||||||
|
|
||||||
|
// HACK: A shim for all the ActorPreview code that used to query UpgradeMinEnabledLevel directly
|
||||||
|
// This can go away after we introduce an InitialUpgrades ActorInit and have the traits query the
|
||||||
|
// condition directly
|
||||||
|
public bool EnabledByDefault { get; private set; }
|
||||||
|
|
||||||
|
public virtual void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
|
{
|
||||||
|
EnabledByDefault = RequiresCondition != null ? RequiresCondition.Evaluate(NoConditions) : true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -41,50 +43,59 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
/// Requires basing *Info on UpgradableTraitInfo and using base(info) constructor.
|
/// Requires basing *Info on UpgradableTraitInfo and using base(info) constructor.
|
||||||
/// Note that EnabledByUpgrade is not called at creation even if this starts as enabled.
|
/// Note that EnabledByUpgrade is not called at creation even if this starts as enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class UpgradableTrait<InfoType> : IUpgradable, IDisabledTrait, ISync where InfoType : UpgradableTraitInfo
|
public abstract class UpgradableTrait<InfoType> : IConditionConsumer, IDisabledTrait, INotifyCreated, ISync where InfoType : UpgradableTraitInfo
|
||||||
{
|
{
|
||||||
public readonly InfoType Info;
|
public readonly InfoType Info;
|
||||||
public IEnumerable<string> UpgradeTypes { get { return Info.UpgradeTypes; } }
|
|
||||||
|
IEnumerable<string> IConditionConsumer.Conditions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Info.RequiresCondition != null)
|
||||||
|
return Info.RequiresCondition.Variables;
|
||||||
|
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Sync] public bool IsTraitDisabled { get; private set; }
|
[Sync] public bool IsTraitDisabled { get; private set; }
|
||||||
|
|
||||||
public UpgradableTrait(InfoType info)
|
public UpgradableTrait(InfoType info)
|
||||||
{
|
{
|
||||||
Info = info;
|
Info = info;
|
||||||
IsTraitDisabled = info.UpgradeTypes != null && info.UpgradeTypes.Count > 0 && info.UpgradeMinEnabledLevel > 0;
|
|
||||||
|
// Conditional traits will be enabled (if appropriate) by the UpgradeManager
|
||||||
|
// calling IConditionConsumer.ConditionsChanged at the end of INotifyCreated.
|
||||||
|
IsTraitDisabled = Info.RequiresCondition != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AcceptsUpgradeLevel(Actor self, string type, int level)
|
protected virtual void Created(Actor self)
|
||||||
{
|
{
|
||||||
return level > 0 && level <= Info.UpgradeMaxAcceptedLevel;
|
if (Info.RequiresCondition == null)
|
||||||
|
TraitEnabled(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpgradeLevelChanged(Actor self, string type, int oldLevel, int newLevel)
|
void INotifyCreated.Created(Actor self) { Created(self); }
|
||||||
{
|
|
||||||
if (!Info.UpgradeTypes.Contains(type))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Restrict the levels to the allowed range
|
void IConditionConsumer.ConditionsChanged(Actor self, IReadOnlyDictionary<string, bool> conditions)
|
||||||
oldLevel = oldLevel.Clamp(0, Info.UpgradeMaxAcceptedLevel);
|
{
|
||||||
newLevel = newLevel.Clamp(0, Info.UpgradeMaxAcceptedLevel);
|
if (Info.RequiresCondition == null)
|
||||||
if (oldLevel == newLevel)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var wasDisabled = IsTraitDisabled;
|
var wasDisabled = IsTraitDisabled;
|
||||||
IsTraitDisabled = newLevel < Info.UpgradeMinEnabledLevel || newLevel > Info.UpgradeMaxEnabledLevel;
|
IsTraitDisabled = !Info.RequiresCondition.Evaluate(conditions);
|
||||||
UpgradeLevelChanged(self, oldLevel, newLevel);
|
|
||||||
|
|
||||||
if (IsTraitDisabled != wasDisabled)
|
if (IsTraitDisabled != wasDisabled)
|
||||||
{
|
{
|
||||||
if (wasDisabled)
|
if (wasDisabled)
|
||||||
UpgradeEnabled(self);
|
TraitEnabled(self);
|
||||||
else
|
else
|
||||||
UpgradeDisabled(self);
|
TraitDisabled(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subclasses can add upgrade support by querying IsTraitDisabled and/or overriding these methods.
|
// Subclasses can add condition support by querying IsTraitDisabled and/or overriding these methods.
|
||||||
protected virtual void UpgradeLevelChanged(Actor self, int oldLevel, int newLevel) { }
|
protected virtual void TraitEnabled(Actor self) { }
|
||||||
protected virtual void UpgradeEnabled(Actor self) { }
|
protected virtual void TraitDisabled(Actor self) { }
|
||||||
protected virtual void UpgradeDisabled(Actor self) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,49 +12,44 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Attach this to a unit to enable dynamic upgrades by warheads, experience, crates, support powers, etc.")]
|
[Desc("Attach this to a unit to enable dynamic upgrades by warheads, experience, crates, support powers, etc.")]
|
||||||
public class UpgradeManagerInfo : TraitInfo<UpgradeManager>, IRulesetLoaded
|
public class UpgradeManagerInfo : TraitInfo<UpgradeManager>, Requires<IConditionConsumerInfo> { }
|
||||||
{
|
|
||||||
public void RulesetLoaded(Ruleset rules, ActorInfo info)
|
|
||||||
{
|
|
||||||
if (!info.Name.StartsWith("^") && !info.TraitInfos<IUpgradableInfo>().Any())
|
|
||||||
throw new YamlException(
|
|
||||||
"There are no upgrades to be managed for actor '{0}'. You are either missing some upgradeable traits, or this UpgradeManager trait is not required.".F(
|
|
||||||
info.Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpgradeManager : INotifyCreated, ITick
|
public class UpgradeManager : INotifyCreated, ITick
|
||||||
{
|
{
|
||||||
class TimedUpgrade
|
/// <summary>Value used to represent an invalid token.</summary>
|
||||||
|
public static readonly int InvalidConditionToken = -1;
|
||||||
|
|
||||||
|
class TimedCondition
|
||||||
{
|
{
|
||||||
public class UpgradeSource
|
public class ConditionSource
|
||||||
{
|
{
|
||||||
public readonly object Source;
|
public readonly object Source;
|
||||||
public int Remaining;
|
public int Remaining;
|
||||||
|
|
||||||
public UpgradeSource(int duration, object source)
|
public ConditionSource(int duration, object source)
|
||||||
{
|
{
|
||||||
Remaining = duration;
|
Remaining = duration;
|
||||||
Source = source;
|
Source = source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly string Upgrade;
|
public readonly string Condition;
|
||||||
public readonly int Duration;
|
public readonly int Duration;
|
||||||
public readonly HashSet<UpgradeSource> Sources;
|
public readonly HashSet<ConditionSource> Sources;
|
||||||
public int Remaining; // Equal to maximum of all Sources.Remaining
|
public int Remaining; // Equal to maximum of all Sources.Remaining
|
||||||
|
|
||||||
public TimedUpgrade(string upgrade, int duration, object source)
|
public TimedCondition(string condition, int duration, object source)
|
||||||
{
|
{
|
||||||
Upgrade = upgrade;
|
Condition = condition;
|
||||||
Duration = duration;
|
Duration = duration;
|
||||||
Remaining = duration;
|
Remaining = duration;
|
||||||
Sources = new HashSet<UpgradeSource> { new UpgradeSource(duration, source) };
|
Sources = new HashSet<ConditionSource> { new ConditionSource(duration, source) };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
@@ -65,29 +60,124 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UpgradeState
|
class ConditionState
|
||||||
{
|
{
|
||||||
public readonly List<IUpgradable> Traits = new List<IUpgradable>();
|
/// <summary>Traits that have registered to be notified when this condition changes.</summary>
|
||||||
public readonly List<object> Sources = new List<object>();
|
public readonly List<IConditionConsumer> Consumers = new List<IConditionConsumer>();
|
||||||
|
|
||||||
|
/// <summary>Unique integers identifying granted instances of the condition.</summary>
|
||||||
|
public readonly HashSet<int> Tokens = new HashSet<int>();
|
||||||
|
|
||||||
|
/// <summary>External callbacks that are to be executed when a timed condition changes.</summary>
|
||||||
public readonly List<Action<int, int>> Watchers = new List<Action<int, int>>();
|
public readonly List<Action<int, int>> Watchers = new List<Action<int, int>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly List<TimedUpgrade> timedUpgrades = new List<TimedUpgrade>();
|
readonly List<TimedCondition> timedConditions = new List<TimedCondition>();
|
||||||
readonly Dictionary<IUpgradable, int> levels = new Dictionary<IUpgradable, int>();
|
|
||||||
Dictionary<string, UpgradeState> upgrades;
|
Dictionary<string, ConditionState> state;
|
||||||
|
|
||||||
|
/// <summary>Each granted condition receives a unique token that is used when revoking.</summary>
|
||||||
|
Dictionary<int, string> tokens = new Dictionary<int, string>();
|
||||||
|
|
||||||
|
int nextToken = 1;
|
||||||
|
|
||||||
|
/// <summary>Temporary shim between the old and new upgrade/condition grant and revoke methods.</summary>
|
||||||
|
Dictionary<Pair<object, string>, int> objectTokenShim = new Dictionary<Pair<object, string>, int>();
|
||||||
|
|
||||||
|
/// <summary>Cache of condition -> enabled state for quick evaluation of boolean conditions.</summary>
|
||||||
|
Dictionary<string, bool> conditionCache = new Dictionary<string, bool>();
|
||||||
|
|
||||||
|
/// <summary>Read-only version of conditionCache that is passed to IConditionConsumers.</summary>
|
||||||
|
IReadOnlyDictionary<string, bool> readOnlyConditionCache;
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
upgrades = new Dictionary<string, UpgradeState>();
|
state = new Dictionary<string, ConditionState>();
|
||||||
foreach (var up in self.TraitsImplementing<IUpgradable>())
|
readOnlyConditionCache = new ReadOnlyDictionary<string, bool>(conditionCache);
|
||||||
foreach (var t in up.UpgradeTypes)
|
|
||||||
upgrades.GetOrAdd(t).Traits.Add(up);
|
var allConsumers = new HashSet<IConditionConsumer>();
|
||||||
|
foreach (var consumer in self.TraitsImplementing<IConditionConsumer>())
|
||||||
|
{
|
||||||
|
allConsumers.Add(consumer);
|
||||||
|
foreach (var condition in consumer.Conditions)
|
||||||
|
{
|
||||||
|
state.GetOrAdd(condition).Consumers.Add(consumer);
|
||||||
|
conditionCache[condition] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable any conditions granted during trait setup
|
||||||
|
foreach (var kv in tokens)
|
||||||
|
{
|
||||||
|
ConditionState conditionState;
|
||||||
|
if (!state.TryGetValue(kv.Value, out conditionState))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
conditionState.Tokens.Add(kv.Key);
|
||||||
|
conditionCache[kv.Value] = conditionState.Tokens.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all traits with their initial condition state
|
||||||
|
foreach (var consumer in allConsumers)
|
||||||
|
consumer.ConditionsChanged(self, readOnlyConditionCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckCanManageUpgrades()
|
void UpdateConditionState(Actor self, string condition, int token, bool isRevoke)
|
||||||
{
|
{
|
||||||
if (upgrades == null)
|
ConditionState conditionState;
|
||||||
throw new InvalidOperationException("Upgrades cannot be managed until the actor has been fully created.");
|
if (!state.TryGetValue(condition, out conditionState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isRevoke)
|
||||||
|
conditionState.Tokens.Remove(token);
|
||||||
|
else
|
||||||
|
conditionState.Tokens.Add(token);
|
||||||
|
|
||||||
|
conditionCache[condition] = conditionState.Tokens.Count > 0;
|
||||||
|
|
||||||
|
foreach (var t in conditionState.Consumers)
|
||||||
|
t.ConditionsChanged(self, readOnlyConditionCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Grants a specified condition.</summary>
|
||||||
|
/// <returns>The token that is used to revoke this condition.</returns>
|
||||||
|
public int GrantCondition(Actor self, string condition)
|
||||||
|
{
|
||||||
|
var token = nextToken++;
|
||||||
|
tokens.Add(token, condition);
|
||||||
|
|
||||||
|
// Conditions may be granted before the state is initialized.
|
||||||
|
// These conditions will be processed in INotifyCreated.Created.
|
||||||
|
if (state != null)
|
||||||
|
UpdateConditionState(self, condition, token, false);
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Revokes a previously granted condition.</summary>
|
||||||
|
/// <returns>The invalid token ID</returns>
|
||||||
|
/// <param name="token">The token ID returned by GrantCondition.</param>
|
||||||
|
public int RevokeCondition(Actor self, int token)
|
||||||
|
{
|
||||||
|
string condition;
|
||||||
|
if (!tokens.TryGetValue(token, out condition))
|
||||||
|
throw new InvalidOperationException("Attempting to revoke condition with invalid token {0} for {1}.".F(token, self));
|
||||||
|
|
||||||
|
tokens.Remove(token);
|
||||||
|
|
||||||
|
// Conditions may be granted and revoked before the state is initialized.
|
||||||
|
if (state != null)
|
||||||
|
UpdateConditionState(self, condition, token, true);
|
||||||
|
|
||||||
|
return InvalidConditionToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Shim methods for legacy upgrade granting code
|
||||||
|
|
||||||
|
void CheckCanManageConditions()
|
||||||
|
{
|
||||||
|
if (state == null)
|
||||||
|
throw new InvalidOperationException("Conditions cannot be managed until the actor has been fully created.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Upgrade level increments are limited to dupesAllowed per source, i.e., if a single
|
/// <summary>Upgrade level increments are limited to dupesAllowed per source, i.e., if a single
|
||||||
@@ -98,11 +188,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
/// remaining upgrade duration will be replaced by the new source.</summary>
|
/// remaining upgrade duration will be replaced by the new source.</summary>
|
||||||
public void GrantTimedUpgrade(Actor self, string upgrade, int duration, object source = null, int dupesAllowed = 1)
|
public void GrantTimedUpgrade(Actor self, string upgrade, int duration, object source = null, int dupesAllowed = 1)
|
||||||
{
|
{
|
||||||
var timed = timedUpgrades.FirstOrDefault(u => u.Upgrade == upgrade);
|
var timed = timedConditions.FirstOrDefault(u => u.Condition == upgrade);
|
||||||
if (timed == null)
|
if (timed == null)
|
||||||
{
|
{
|
||||||
timed = new TimedUpgrade(upgrade, duration, source);
|
timed = new TimedCondition(upgrade, duration, source);
|
||||||
timedUpgrades.Add(timed);
|
timedConditions.Add(timed);
|
||||||
GrantUpgrade(self, upgrade, timed);
|
GrantUpgrade(self, upgrade, timed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,7 +200,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var srcs = timed.Sources.Where(s => s.Source == source);
|
var srcs = timed.Sources.Where(s => s.Source == source);
|
||||||
if (srcs.Count() < dupesAllowed)
|
if (srcs.Count() < dupesAllowed)
|
||||||
{
|
{
|
||||||
timed.Sources.Add(new TimedUpgrade.UpgradeSource(duration, source));
|
timed.Sources.Add(new TimedCondition.ConditionSource(duration, source));
|
||||||
if (AcceptsUpgrade(self, upgrade))
|
if (AcceptsUpgrade(self, upgrade))
|
||||||
GrantUpgrade(self, upgrade, timed);
|
GrantUpgrade(self, upgrade, timed);
|
||||||
else
|
else
|
||||||
@@ -122,108 +212,69 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
timed.Remaining = Math.Max(duration, timed.Remaining);
|
timed.Remaining = Math.Max(duration, timed.Remaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Different upgradeable traits may define (a) different level ranges for the same upgrade type,
|
|
||||||
// and (b) multiple upgrade types for the same trait. The unrestricted level for each trait is
|
|
||||||
// tracked independently so that we can correctly revoke levels without adding the burden of
|
|
||||||
// tracking both the overall (unclamped) and effective (clamped) levels on each individual trait.
|
|
||||||
void NotifyUpgradeLevelChanged(IEnumerable<IUpgradable> traits, Actor self, string upgrade, int levelAdjust)
|
|
||||||
{
|
|
||||||
foreach (var up in traits)
|
|
||||||
{
|
|
||||||
var oldLevel = levels.GetOrAdd(up);
|
|
||||||
var newLevel = levels[up] = oldLevel + levelAdjust;
|
|
||||||
|
|
||||||
// This will internally clamp the levels to its own restricted range
|
|
||||||
up.UpgradeLevelChanged(self, upgrade, oldLevel, newLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetOverallLevel(IUpgradable upgradable)
|
|
||||||
{
|
|
||||||
int level;
|
|
||||||
return levels.TryGetValue(upgradable, out level) ? level : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GrantUpgrade(Actor self, string upgrade, object source)
|
public void GrantUpgrade(Actor self, string upgrade, object source)
|
||||||
{
|
{
|
||||||
CheckCanManageUpgrades();
|
CheckCanManageConditions();
|
||||||
|
objectTokenShim[Pair.New(source, upgrade)] = GrantCondition(self, upgrade);
|
||||||
UpgradeState s;
|
|
||||||
if (!upgrades.TryGetValue(upgrade, out s))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Track the upgrade source so that the upgrade can be removed without conflicts
|
|
||||||
s.Sources.Add(source);
|
|
||||||
|
|
||||||
NotifyUpgradeLevelChanged(s.Traits, self, upgrade, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RevokeUpgrade(Actor self, string upgrade, object source)
|
public void RevokeUpgrade(Actor self, string upgrade, object source)
|
||||||
{
|
{
|
||||||
CheckCanManageUpgrades();
|
CheckCanManageConditions();
|
||||||
|
RevokeCondition(self, objectTokenShim[Pair.New(source, upgrade)]);
|
||||||
UpgradeState s;
|
|
||||||
if (!upgrades.TryGetValue(upgrade, out s))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!s.Sources.Remove(source))
|
|
||||||
throw new InvalidOperationException("Object <{0}> revoked more levels of upgrade {1} than it granted for {2}.".F(source, upgrade, self));
|
|
||||||
|
|
||||||
NotifyUpgradeLevelChanged(s.Traits, self, upgrade, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns true if the actor uses the given upgrade. Does not check the actual level of the upgrade.</summary>
|
/// <summary>Returns true if the actor uses the given upgrade. Does not check the actual level of the upgrade.</summary>
|
||||||
public bool AcknowledgesUpgrade(Actor self, string upgrade)
|
public bool AcknowledgesUpgrade(Actor self, string upgrade)
|
||||||
{
|
{
|
||||||
CheckCanManageUpgrades();
|
CheckCanManageConditions();
|
||||||
return upgrades.ContainsKey(upgrade);
|
return state.ContainsKey(upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns true only if the actor can accept another level of the upgrade.</summary>
|
/// <summary>Returns true only if the actor can accept another level of the upgrade.</summary>
|
||||||
public bool AcceptsUpgrade(Actor self, string upgrade)
|
public bool AcceptsUpgrade(Actor self, string upgrade)
|
||||||
{
|
{
|
||||||
CheckCanManageUpgrades();
|
CheckCanManageConditions();
|
||||||
|
bool enabled;
|
||||||
UpgradeState s;
|
if (!conditionCache.TryGetValue(upgrade, out enabled))
|
||||||
if (!upgrades.TryGetValue(upgrade, out s))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return s.Traits.Any(up => up.AcceptsUpgradeLevel(self, upgrade, GetOverallLevel(up) + 1));
|
return !enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterWatcher(string upgrade, Action<int, int> action)
|
public void RegisterWatcher(string upgrade, Action<int, int> action)
|
||||||
{
|
{
|
||||||
CheckCanManageUpgrades();
|
CheckCanManageConditions();
|
||||||
|
|
||||||
UpgradeState s;
|
ConditionState s;
|
||||||
if (!upgrades.TryGetValue(upgrade, out s))
|
if (!state.TryGetValue(upgrade, out s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s.Watchers.Add(action);
|
s.Watchers.Add(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Watchers will be receiving notifications while the upgrade's level is nonzero.
|
/// <summary>Watchers will be receiving notifications while the condition is enabled.
|
||||||
/// They will also be provided with the number of ticks before the level returns to zero,
|
/// They will also be provided with the number of ticks before the condition is disabled,
|
||||||
/// as well as the duration in ticks of the timed upgrade (provided in the first call to
|
/// as well as the duration in ticks of the timed upgrade (provided in the first call to
|
||||||
/// GrantTimedUpgrade).</summary>
|
/// GrantTimedUpgrade).</summary>
|
||||||
public void Tick(Actor self)
|
void ITick.Tick(Actor self)
|
||||||
{
|
{
|
||||||
CheckCanManageUpgrades();
|
foreach (var u in timedConditions)
|
||||||
|
|
||||||
foreach (var u in timedUpgrades)
|
|
||||||
{
|
{
|
||||||
u.Tick();
|
u.Tick();
|
||||||
foreach (var source in u.Sources)
|
foreach (var source in u.Sources)
|
||||||
if (source.Remaining <= 0)
|
if (source.Remaining <= 0)
|
||||||
RevokeUpgrade(self, u.Upgrade, u);
|
RevokeUpgrade(self, u.Condition, u);
|
||||||
|
|
||||||
u.Sources.RemoveWhere(source => source.Remaining <= 0);
|
u.Sources.RemoveWhere(source => source.Remaining <= 0);
|
||||||
|
|
||||||
foreach (var a in upgrades[u.Upgrade].Watchers)
|
foreach (var a in state[u.Condition].Watchers)
|
||||||
a(u.Duration, u.Remaining);
|
a(u.Duration, u.Remaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
timedUpgrades.RemoveAll(u => u.Remaining <= 0);
|
timedConditions.RemoveAll(u => u.Remaining <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public override object Create(ActorInitializer init) { return new Wanders(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new Wanders(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Wanders : UpgradableTrait<WandersInfo>, INotifyCreated, INotifyIdle, INotifyBecomingIdle
|
public class Wanders : UpgradableTrait<WandersInfo>, INotifyIdle, INotifyBecomingIdle
|
||||||
{
|
{
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
readonly WandersInfo info;
|
readonly WandersInfo info;
|
||||||
@@ -50,9 +50,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
effectiveMoveRadius = info.WanderMoveRadius;
|
effectiveMoveRadius = info.WanderMoveRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
protected override void Created(Actor self)
|
||||||
{
|
{
|
||||||
move = self.Trait<IMove>() as IResolveOrder;
|
move = self.Trait<IMove>() as IResolveOrder;
|
||||||
|
|
||||||
|
base.Created(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnBecomingIdle(Actor self)
|
public virtual void OnBecomingIdle(Actor self)
|
||||||
|
|||||||
@@ -103,15 +103,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[RequireExplicitImplementation]
|
[RequireExplicitImplementation]
|
||||||
public interface INotifyPassengerExited { void OnPassengerExited(Actor self, Actor passenger); }
|
public interface INotifyPassengerExited { void OnPassengerExited(Actor self, Actor passenger); }
|
||||||
|
|
||||||
public interface IUpgradable
|
[RequireExplicitImplementation]
|
||||||
{
|
public interface IConditionConsumerInfo : ITraitInfo { }
|
||||||
IEnumerable<string> UpgradeTypes { get; }
|
|
||||||
bool AcceptsUpgradeLevel(Actor self, string type, int level);
|
|
||||||
void UpgradeLevelChanged(Actor self, string type, int oldLevel, int newLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement to construct before UpgradeManager
|
public interface IConditionConsumer
|
||||||
public interface IUpgradableInfo : ITraitInfo { }
|
{
|
||||||
|
IEnumerable<string> Conditions { get; }
|
||||||
|
void ConditionsChanged(Actor self, IReadOnlyDictionary<string, bool> conditions);
|
||||||
|
}
|
||||||
|
|
||||||
public interface INotifyHarvesterAction
|
public interface INotifyHarvesterAction
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -435,6 +435,48 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rename Replaced upgrade consumers with conditions
|
||||||
|
if (engineVersion < 20161117)
|
||||||
|
{
|
||||||
|
var upgradeTypesNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "UpgradeTypes");
|
||||||
|
if (upgradeTypesNode != null)
|
||||||
|
{
|
||||||
|
var upgradeMinEnabledLevel = 0;
|
||||||
|
var upgradeMaxEnabledLevel = int.MaxValue;
|
||||||
|
var upgradeMaxAcceptedLevel = 1;
|
||||||
|
var upgradeTypes = FieldLoader.GetValue<string[]>("", upgradeTypesNode.Value.Value);
|
||||||
|
var minEnabledNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "UpgradeMinEnabledLevel");
|
||||||
|
if (minEnabledNode != null)
|
||||||
|
upgradeMinEnabledLevel = FieldLoader.GetValue<int>("", minEnabledNode.Value.Value);
|
||||||
|
|
||||||
|
var maxEnabledNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "UpgradeMaxEnabledLevel");
|
||||||
|
if (maxEnabledNode != null)
|
||||||
|
upgradeMaxEnabledLevel = FieldLoader.GetValue<int>("", maxEnabledNode.Value.Value);
|
||||||
|
|
||||||
|
var maxAcceptedNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "UpgradeMaxAcceptedLevel");
|
||||||
|
if (maxAcceptedNode != null)
|
||||||
|
upgradeMaxAcceptedLevel = FieldLoader.GetValue<int>("", maxAcceptedNode.Value.Value);
|
||||||
|
|
||||||
|
var processed = false;
|
||||||
|
if (upgradeTypes.Length == 1 && upgradeMinEnabledLevel == 0 && upgradeMaxEnabledLevel == 0 && upgradeMaxAcceptedLevel == 1)
|
||||||
|
{
|
||||||
|
node.Value.Nodes.Add(new MiniYamlNode("RequiresCondition", "!" + upgradeTypes.First()));
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
else if (upgradeTypes.Length == 1 && upgradeMinEnabledLevel == 1 && upgradeMaxEnabledLevel == int.MaxValue && upgradeMaxAcceptedLevel == 1)
|
||||||
|
{
|
||||||
|
node.Value.Nodes.Add(new MiniYamlNode("RequiresCondition", upgradeTypes.First()));
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed)
|
||||||
|
node.Value.Nodes.RemoveAll(n => n.Key == "UpgradeTypes" || n.Key == "UpgradeMinEnabledLevel" ||
|
||||||
|
n.Key == "UpgradeMaxEnabledLevel" || n.Key == "UpgradeMaxAcceptedLevel");
|
||||||
|
else
|
||||||
|
Console.WriteLine("Unable to automatically migrate {0}:{1} UpgradeTypes to RequiresCondition. This must be corrected manually", parent.Key, node.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
|
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using System;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Support;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : "";
|
var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : "";
|
||||||
requiresLabel.GetText = () => requiresString;
|
requiresLabel.GetText = () => requiresString;
|
||||||
|
|
||||||
var power = actor.TraitInfos<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(i => i.Amount);
|
var power = actor.TraitInfos<PowerInfo>().Where(i => i.EnabledByDefault).Sum(i => i.Amount);
|
||||||
var powerString = power.ToString();
|
var powerString = power.ToString();
|
||||||
powerLabel.GetText = () => powerString;
|
powerLabel.GetText = () => powerString;
|
||||||
powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0)
|
powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0)
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ namespace OpenRA.Test
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class BooleanExpressionTest
|
public class BooleanExpressionTest
|
||||||
{
|
{
|
||||||
Dictionary<string, bool> testValues = new Dictionary<string, bool>()
|
IReadOnlyDictionary<string, bool> testValues = new ReadOnlyDictionary<string, bool>(new Dictionary<string, bool>()
|
||||||
{
|
{
|
||||||
{ "true", true },
|
{ "true", true },
|
||||||
{ "false", false }
|
{ "false", false }
|
||||||
};
|
});
|
||||||
|
|
||||||
void AssertFalse(string expression)
|
void AssertFalse(string expression)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,23 +26,19 @@ TRAN:
|
|||||||
WithIdleOverlay@ROTOR1AIR:
|
WithIdleOverlay@ROTOR1AIR:
|
||||||
Offset: 597,0,85
|
Offset: 597,0,85
|
||||||
Sequence: rotor
|
Sequence: rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTOR1GROUND:
|
WithIdleOverlay@ROTOR1GROUND:
|
||||||
Offset: 597,0,85
|
Offset: 597,0,85
|
||||||
Sequence: slow-rotor
|
Sequence: slow-rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
WithIdleOverlay@ROTOR2AIR:
|
WithIdleOverlay@ROTOR2AIR:
|
||||||
Offset: -597,0,171
|
Offset: -597,0,171
|
||||||
Sequence: rotor2
|
Sequence: rotor2
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTOR2GROUND:
|
WithIdleOverlay@ROTOR2GROUND:
|
||||||
Offset: -597,0,171
|
Offset: -597,0,171
|
||||||
Sequence: slow-rotor2
|
Sequence: slow-rotor2
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Cargo:
|
Cargo:
|
||||||
Types: Infantry
|
Types: Infantry
|
||||||
MaxWeight: 10
|
MaxWeight: 10
|
||||||
@@ -98,13 +94,11 @@ HELI:
|
|||||||
WithIdleOverlay@ROTORAIR:
|
WithIdleOverlay@ROTORAIR:
|
||||||
Offset: 0,0,85
|
Offset: 0,0,85
|
||||||
Sequence: rotor
|
Sequence: rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTORGROUND:
|
WithIdleOverlay@ROTORGROUND:
|
||||||
Offset: 0,0,85
|
Offset: 0,0,85
|
||||||
Sequence: slow-rotor
|
Sequence: slow-rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
WithMuzzleOverlay:
|
WithMuzzleOverlay:
|
||||||
SpawnActorOnDeath:
|
SpawnActorOnDeath:
|
||||||
Actor: HELI.Husk
|
Actor: HELI.Husk
|
||||||
|
|||||||
@@ -17,41 +17,104 @@
|
|||||||
^GainsExperience:
|
^GainsExperience:
|
||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
200: firepower, damage, speed, reload, inaccuracy, rank
|
200: rank-veteran-1
|
||||||
400: firepower, damage, speed, reload, inaccuracy, rank
|
400: rank-veteran-2
|
||||||
800: firepower, damage, speed, reload, inaccuracy, rank
|
800: rank-veteran-3
|
||||||
1600: firepower, damage, speed, reload, inaccuracy, rank, eliteweapon, selfheal
|
1600: rank-elite
|
||||||
FirepowerMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-1:
|
||||||
UpgradeTypes: firepower
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
Modifier: 105, 110, 120, 130
|
Modifier: 95
|
||||||
DamageMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-2:
|
||||||
UpgradeTypes: damage
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
Modifier: 95, 90, 85, 75
|
Modifier: 90
|
||||||
SpeedMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-3:
|
||||||
UpgradeTypes: speed
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
Modifier: 105, 110, 120, 140
|
Modifier: 85
|
||||||
ReloadDelayMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-ELITE:
|
||||||
UpgradeTypes: reload
|
RequiresCondition: rank-elite
|
||||||
Modifier: 95, 90, 85, 75
|
Modifier: 75
|
||||||
InaccuracyMultiplier@EXPERIENCE:
|
FirepowerMultiplier@RANK-1:
|
||||||
UpgradeTypes: inaccuracy
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
Modifier: 90, 80, 70, 50
|
Modifier: 105
|
||||||
|
FirepowerMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 110
|
||||||
|
FirepowerMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 120
|
||||||
|
FirepowerMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 130
|
||||||
|
SpeedMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 105
|
||||||
|
SpeedMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 110
|
||||||
|
SpeedMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 120
|
||||||
|
SpeedMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 140
|
||||||
|
ReloadDelayMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 95
|
||||||
|
ReloadDelayMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 90
|
||||||
|
ReloadDelayMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 85
|
||||||
|
ReloadDelayMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 75
|
||||||
|
InaccuracyMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 90
|
||||||
|
InaccuracyMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 80
|
||||||
|
InaccuracyMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 70
|
||||||
|
InaccuracyMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 50
|
||||||
SelfHealing@ELITE:
|
SelfHealing@ELITE:
|
||||||
Step: 2
|
Step: 2
|
||||||
Delay: 100
|
Delay: 100
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: selfheal
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
WithDecoration@RANK-1:
|
||||||
WithRankDecoration:
|
|
||||||
Image: rank
|
Image: rank
|
||||||
Sequence: rank
|
Sequence: rank-veteran-1
|
||||||
Palette: effect
|
Palette: effect
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: rank
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-2:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-veteran-2
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-3:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-veteran-3
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-ELITE:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-elite
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-elite
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
UpgradeMaxAcceptedLevel: 4
|
|
||||||
|
|
||||||
^Vehicle:
|
^Vehicle:
|
||||||
Inherits@1: ^ExistsInWorld
|
Inherits@1: ^ExistsInWorld
|
||||||
@@ -91,12 +154,11 @@
|
|||||||
Tooltip:
|
Tooltip:
|
||||||
GenericName: Vehicle
|
GenericName: Vehicle
|
||||||
Cloak:
|
Cloak:
|
||||||
UpgradeTypes: cloak
|
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
InitialDelay: 15
|
InitialDelay: 15
|
||||||
CloakDelay: 90
|
CloakDelay: 90
|
||||||
CloakSound: trans1.aud
|
CloakSound: trans1.aud
|
||||||
UncloakSound: trans1.aud
|
UncloakSound: trans1.aud
|
||||||
|
RequiresCondition: cloak
|
||||||
MustBeDestroyed:
|
MustBeDestroyed:
|
||||||
Voiced:
|
Voiced:
|
||||||
VoiceSet: VehicleVoice
|
VoiceSet: VehicleVoice
|
||||||
@@ -127,12 +189,10 @@
|
|||||||
UseLocation: yes
|
UseLocation: yes
|
||||||
Targetable@GROUND:
|
Targetable@GROUND:
|
||||||
TargetTypes: Ground, Vehicle
|
TargetTypes: Ground, Vehicle
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@AIRBORNE:
|
Targetable@AIRBORNE:
|
||||||
TargetTypes: Air
|
TargetTypes: Air
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
WithSpriteControlGroupDecoration:
|
WithSpriteControlGroupDecoration:
|
||||||
Selectable:
|
Selectable:
|
||||||
@@ -160,8 +220,7 @@
|
|||||||
Offset: 43, 128, 0
|
Offset: 43, 128, 0
|
||||||
ZOffset: -129
|
ZOffset: -129
|
||||||
Hovers@CRUISING:
|
Hovers@CRUISING:
|
||||||
UpgradeTypes: cruising
|
RequiresCondition: cruising
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
MustBeDestroyed:
|
MustBeDestroyed:
|
||||||
Voiced:
|
Voiced:
|
||||||
VoiceSet: VehicleVoice
|
VoiceSet: VehicleVoice
|
||||||
@@ -217,12 +276,11 @@
|
|||||||
CargoType: Infantry
|
CargoType: Infantry
|
||||||
HiddenUnderFog:
|
HiddenUnderFog:
|
||||||
DamagedByTerrain:
|
DamagedByTerrain:
|
||||||
UpgradeTypes: hazmatsuits
|
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Terrain: Tiberium, BlueTiberium
|
Terrain: Tiberium, BlueTiberium
|
||||||
Damage: 2
|
Damage: 2
|
||||||
DamageInterval: 16
|
DamageInterval: 16
|
||||||
DamageTypes: TiberiumDeath
|
DamageTypes: TiberiumDeath
|
||||||
|
RequiresCondition: !hazmatsuits
|
||||||
GlobalUpgradable@BIO:
|
GlobalUpgradable@BIO:
|
||||||
Upgrades: hazmatsuits
|
Upgrades: hazmatsuits
|
||||||
Prerequisites: bio
|
Prerequisites: bio
|
||||||
@@ -230,8 +288,7 @@
|
|||||||
Image: pips
|
Image: pips
|
||||||
Sequence: pip-hazmat
|
Sequence: pip-hazmat
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: hazmatsuits
|
RequiresCondition: hazmatsuits
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
ActorLostNotification:
|
ActorLostNotification:
|
||||||
SpawnActorOnDeath:
|
SpawnActorOnDeath:
|
||||||
Probability: 10
|
Probability: 10
|
||||||
@@ -249,8 +306,7 @@
|
|||||||
Delay: 100
|
Delay: 100
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: hospitalheal
|
RequiresCondition: hospitalheal
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
GlobalUpgradable@HOSPITAL:
|
GlobalUpgradable@HOSPITAL:
|
||||||
Upgrades: hospitalheal
|
Upgrades: hospitalheal
|
||||||
Prerequisites: hosp
|
Prerequisites: hosp
|
||||||
@@ -258,8 +314,7 @@
|
|||||||
Image: pips
|
Image: pips
|
||||||
Sequence: pip-heal
|
Sequence: pip-heal
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: hospitalheal
|
RequiresCondition: hospitalheal
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
DetectCloaked:
|
DetectCloaked:
|
||||||
Range: 2c0
|
Range: 2c0
|
||||||
DeathSounds@NORMAL:
|
DeathSounds@NORMAL:
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ LST:
|
|||||||
BuildPaletteOrder: 1000
|
BuildPaletteOrder: 1000
|
||||||
Prerequisites: ~disabled
|
Prerequisites: ~disabled
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: notmobile
|
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Crushes: crate
|
Crushes: crate
|
||||||
TerrainSpeeds:
|
TerrainSpeeds:
|
||||||
Clear: 100
|
Clear: 100
|
||||||
@@ -61,6 +59,7 @@ LST:
|
|||||||
InitialFacing: 0
|
InitialFacing: 0
|
||||||
TurnSpeed: 4
|
TurnSpeed: 4
|
||||||
Speed: 142
|
Speed: 142
|
||||||
|
RequiresCondition: !notmobile
|
||||||
Health:
|
Health:
|
||||||
HP: 400
|
HP: 400
|
||||||
Armor:
|
Armor:
|
||||||
|
|||||||
@@ -88,10 +88,9 @@ APC:
|
|||||||
Queue: Vehicle.GDI
|
Queue: Vehicle.GDI
|
||||||
Description: Armed infantry transport.\nCan attack Aircraft.\n Strong vs Vehicles\n Weak vs Infantry
|
Description: Armed infantry transport.\nCan attack Aircraft.\n Strong vs Vehicles\n Weak vs Infantry
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: notmobile
|
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
TurnSpeed: 8
|
TurnSpeed: 8
|
||||||
Speed: 128
|
Speed: 128
|
||||||
|
RequiresCondition: !notmobile
|
||||||
Health:
|
Health:
|
||||||
HP: 210
|
HP: 210
|
||||||
Armor:
|
Armor:
|
||||||
@@ -517,7 +516,7 @@ STNK:
|
|||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 7c0
|
Range: 7c0
|
||||||
Cloak:
|
Cloak:
|
||||||
-UpgradeTypes:
|
-RequiresCondition:
|
||||||
InitialDelay: 90
|
InitialDelay: 90
|
||||||
CloakDelay: 90
|
CloakDelay: 90
|
||||||
CloakSound: trans1.aud
|
CloakSound: trans1.aud
|
||||||
|
|||||||
@@ -124,8 +124,13 @@ explosion:
|
|||||||
FlipX: true
|
FlipX: true
|
||||||
|
|
||||||
rank:
|
rank:
|
||||||
rank:
|
rank-veteran-1:
|
||||||
Length: *
|
rank-veteran-2:
|
||||||
|
Start: 1
|
||||||
|
rank-veteran-3:
|
||||||
|
Start: 2
|
||||||
|
rank-elite:
|
||||||
|
Start: 3
|
||||||
|
|
||||||
rallypoint:
|
rallypoint:
|
||||||
flag: flagfly
|
flag: flagfly
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ World:
|
|||||||
|
|
||||||
^Building:
|
^Building:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
wall:
|
wall:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
upgrade.conyard:
|
upgrade.conyard:
|
||||||
Valued:
|
Valued:
|
||||||
|
|||||||
@@ -20,12 +20,10 @@ carryall.reinforce:
|
|||||||
CanHover: True
|
CanHover: True
|
||||||
Targetable@GROUND:
|
Targetable@GROUND:
|
||||||
TargetTypes: Ground, Vehicle
|
TargetTypes: Ground, Vehicle
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@AIRBORNE:
|
Targetable@AIRBORNE:
|
||||||
TargetTypes: Air
|
TargetTypes: Air
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
SpawnActorOnDeath:
|
SpawnActorOnDeath:
|
||||||
Actor: carryall.husk
|
Actor: carryall.husk
|
||||||
Carryall:
|
Carryall:
|
||||||
|
|||||||
@@ -72,13 +72,11 @@ sandworm:
|
|||||||
WithIdleAnimation:
|
WithIdleAnimation:
|
||||||
Interval: 160
|
Interval: 160
|
||||||
Sequences: lightninga, lightningb, lightningc, lightningd, lightninge, lightningf
|
Sequences: lightninga, lightningb, lightningc, lightningd, lightninge, lightningf
|
||||||
UpgradeTypes: attacking
|
RequiresCondition: !attacking
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
AmbientSound:
|
AmbientSound:
|
||||||
SoundFile: WRMSIGN1.WAV
|
SoundFile: WRMSIGN1.WAV
|
||||||
Interval: 160
|
Interval: 160
|
||||||
UpgradeTypes: attacking
|
RequiresCondition: !attacking
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
WithAttackOverlay@mouth:
|
WithAttackOverlay@mouth:
|
||||||
Sequence: mouth
|
Sequence: mouth
|
||||||
WithAttackOverlay@sand:
|
WithAttackOverlay@sand:
|
||||||
@@ -106,8 +104,7 @@ sandworm:
|
|||||||
Type: CenterPosition
|
Type: CenterPosition
|
||||||
TerrainTypes: Sand, Dune, SpiceSand, Spice
|
TerrainTypes: Sand, Dune, SpiceSand, Spice
|
||||||
MovingInterval: 3
|
MovingInterval: 3
|
||||||
UpgradeTypes: attacking
|
RequiresCondition: !attacking
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
UpgradeManager:
|
UpgradeManager:
|
||||||
Buildable:
|
Buildable:
|
||||||
Description: Attracted by vibrations in the sand.\nWill eat units whole and has a large appetite.
|
Description: Attracted by vibrations in the sand.\nWill eat units whole and has a large appetite.
|
||||||
|
|||||||
@@ -17,42 +17,105 @@
|
|||||||
^GainsExperience:
|
^GainsExperience:
|
||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
200: firepower, damage, speed, reload, inaccuracy, rank
|
200: rank-veteran-1
|
||||||
400: firepower, damage, speed, reload, inaccuracy, rank
|
400: rank-veteran-2
|
||||||
800: firepower, damage, speed, reload, inaccuracy, rank
|
800: rank-veteran-3
|
||||||
1600: firepower, damage, speed, reload, inaccuracy, rank, eliteweapon, selfheal
|
1600: rank-elite
|
||||||
FirepowerMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-1:
|
||||||
UpgradeTypes: firepower
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
Modifier: 105, 110, 115, 125
|
Modifier: 96
|
||||||
DamageMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-2:
|
||||||
UpgradeTypes: damage
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
Modifier: 96, 92, 88, 80
|
Modifier: 92
|
||||||
SpeedMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-3:
|
||||||
UpgradeTypes: speed
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
Modifier: 105, 110, 115, 125
|
Modifier: 88
|
||||||
ReloadDelayMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-ELITE:
|
||||||
UpgradeTypes: reload
|
RequiresCondition: rank-elite
|
||||||
Modifier: 96, 92, 88, 80
|
Modifier: 80
|
||||||
InaccuracyMultiplier@EXPERIENCE:
|
FirepowerMultiplier@RANK-1:
|
||||||
UpgradeTypes: inaccuracy
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
Modifier: 90, 80, 70, 50
|
Modifier: 105
|
||||||
|
FirepowerMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 110
|
||||||
|
FirepowerMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 115
|
||||||
|
FirepowerMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 125
|
||||||
|
SpeedMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 105
|
||||||
|
SpeedMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 110
|
||||||
|
SpeedMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 115
|
||||||
|
SpeedMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 125
|
||||||
|
ReloadDelayMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 96
|
||||||
|
ReloadDelayMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 92
|
||||||
|
ReloadDelayMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 88
|
||||||
|
ReloadDelayMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 80
|
||||||
|
InaccuracyMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 90
|
||||||
|
InaccuracyMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 80
|
||||||
|
InaccuracyMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 70
|
||||||
|
InaccuracyMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 50
|
||||||
SelfHealing@ELITE:
|
SelfHealing@ELITE:
|
||||||
Step: 0
|
Step: 0
|
||||||
PercentageStep: 4
|
PercentageStep: 4
|
||||||
Delay: 125
|
Delay: 125
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: selfheal
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
WithDecoration@RANK-1:
|
||||||
WithRankDecoration:
|
|
||||||
Image: rank
|
Image: rank
|
||||||
Sequence: rank
|
Sequence: rank-veteran-1
|
||||||
Palette: effect
|
Palette: effect
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: rank
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-2:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-veteran-2
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-3:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-veteran-3
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-ELITE:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-elite
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-elite
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
UpgradeMaxAcceptedLevel: 4
|
|
||||||
|
|
||||||
^Vehicle:
|
^Vehicle:
|
||||||
Inherits@1: ^ExistsInWorld
|
Inherits@1: ^ExistsInWorld
|
||||||
@@ -60,8 +123,6 @@
|
|||||||
Inherits@3: ^SpriteActor
|
Inherits@3: ^SpriteActor
|
||||||
Huntable:
|
Huntable:
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: notmobile
|
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Crushes: crate, spicebloom
|
Crushes: crate, spicebloom
|
||||||
TerrainSpeeds:
|
TerrainSpeeds:
|
||||||
Sand: 100
|
Sand: 100
|
||||||
@@ -73,6 +134,7 @@
|
|||||||
SpiceBlobs: 100
|
SpiceBlobs: 100
|
||||||
Dune: 50
|
Dune: 50
|
||||||
TurnSpeed: 5
|
TurnSpeed: 5
|
||||||
|
RequiresCondition: !notmobile
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
WithSpriteControlGroupDecoration:
|
WithSpriteControlGroupDecoration:
|
||||||
Selectable:
|
Selectable:
|
||||||
|
|||||||
@@ -94,34 +94,28 @@ thumper:
|
|||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 2c768
|
Range: 2c768
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: deployed
|
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Speed: 43
|
Speed: 43
|
||||||
|
RequiresCondition: !deployed
|
||||||
DeployToUpgrade:
|
DeployToUpgrade:
|
||||||
DeployedUpgrades: deployed
|
DeployedUpgrades: deployed
|
||||||
Facing: 128
|
Facing: 128
|
||||||
AllowedTerrainTypes: Sand, Spice, Dune, SpiceSand
|
AllowedTerrainTypes: Sand, Spice, Dune, SpiceSand
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: !deployed
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
WithSpriteBody@DEPLOYED:
|
WithSpriteBody@DEPLOYED:
|
||||||
Sequence: thump
|
Sequence: thump
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@DEPLOYED:
|
WithIdleOverlay@DEPLOYED:
|
||||||
Sequence: thump-sand
|
Sequence: thump-sand
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
AmbientSound:
|
AmbientSound:
|
||||||
SoundFile: THUMPER1.WAV
|
SoundFile: THUMPER1.WAV
|
||||||
Interval: 60
|
Interval: 60
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
AttractsWorms:
|
AttractsWorms:
|
||||||
Intensity: 1000
|
Intensity: 1000
|
||||||
Falloff: 0, 0, 0, 100, 100, 100, 25, 11, 6, 4, 3, 2, 1, 0
|
Falloff: 0, 0, 0, 100, 100, 100, 25, 11, 6, 4, 3, 2, 1, 0
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Passenger:
|
Passenger:
|
||||||
PipType: Blue
|
PipType: Blue
|
||||||
Voiced:
|
Voiced:
|
||||||
|
|||||||
@@ -98,15 +98,13 @@ construction_yard:
|
|||||||
Sequence: tag-upgraded
|
Sequence: tag-upgraded
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: stardecoration
|
RequiresCondition: stardecoration
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithTextDecoration@primary:
|
WithTextDecoration@primary:
|
||||||
RequiresSelection: true
|
RequiresSelection: true
|
||||||
Text: PRIMARY
|
Text: PRIMARY
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
wind_trap:
|
wind_trap:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -212,15 +210,13 @@ barracks:
|
|||||||
Sequence: tag-upgraded
|
Sequence: tag-upgraded
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: stardecoration
|
RequiresCondition: stardecoration
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithTextDecoration@primary:
|
WithTextDecoration@primary:
|
||||||
RequiresSelection: true
|
RequiresSelection: true
|
||||||
Text: PRIMARY
|
Text: PRIMARY
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
refinery:
|
refinery:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -393,15 +389,13 @@ light_factory:
|
|||||||
Sequence: tag-upgraded
|
Sequence: tag-upgraded
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: stardecoration
|
RequiresCondition: stardecoration
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithTextDecoration@primary:
|
WithTextDecoration@primary:
|
||||||
RequiresSelection: true
|
RequiresSelection: true
|
||||||
Text: PRIMARY
|
Text: PRIMARY
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
heavy_factory:
|
heavy_factory:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -474,15 +468,13 @@ heavy_factory:
|
|||||||
Sequence: tag-upgraded
|
Sequence: tag-upgraded
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: stardecoration
|
RequiresCondition: stardecoration
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithTextDecoration@primary:
|
WithTextDecoration@primary:
|
||||||
RequiresSelection: true
|
RequiresSelection: true
|
||||||
Text: PRIMARY
|
Text: PRIMARY
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
outpost:
|
outpost:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -597,8 +589,7 @@ starport:
|
|||||||
Text: PRIMARY
|
Text: PRIMARY
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
wall:
|
wall:
|
||||||
Inherits@1: ^SpriteActor
|
Inherits@1: ^SpriteActor
|
||||||
@@ -854,8 +845,7 @@ high_tech_factory:
|
|||||||
Sequence: tag-upgraded
|
Sequence: tag-upgraded
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: stardecoration
|
RequiresCondition: stardecoration
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
research_centre:
|
research_centre:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
|
|||||||
@@ -151,8 +151,13 @@ poweroff:
|
|||||||
ZOffset: 2047
|
ZOffset: 2047
|
||||||
|
|
||||||
rank:
|
rank:
|
||||||
rank: rank.shp
|
rank-veteran-1: rank.shp
|
||||||
Length: *
|
rank-veteran-2: rank.shp
|
||||||
|
Start: 1
|
||||||
|
rank-veteran-3: rank.shp
|
||||||
|
Start: 2
|
||||||
|
rank-elite: rank.shp
|
||||||
|
Start: 3
|
||||||
|
|
||||||
overlay:
|
overlay:
|
||||||
Defaults: DATA.R8
|
Defaults: DATA.R8
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ HACKE6:
|
|||||||
Captures:
|
Captures:
|
||||||
CaptureTypes: building
|
CaptureTypes: building
|
||||||
Targetable:
|
Targetable:
|
||||||
UpgradeTypes: jail
|
RequiresCondition: !jail
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@PRISONER:
|
Targetable@PRISONER:
|
||||||
TargetTypes: Prisoner
|
TargetTypes: Prisoner
|
||||||
RenderSprites:
|
RenderSprites:
|
||||||
@@ -42,8 +41,7 @@ HACKE6:
|
|||||||
|
|
||||||
MEDI:
|
MEDI:
|
||||||
Targetable:
|
Targetable:
|
||||||
UpgradeTypes: jail
|
RequiresCondition: !jail
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@PRISONER:
|
Targetable@PRISONER:
|
||||||
TargetTypes: Prisoner
|
TargetTypes: Prisoner
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ HACKE6:
|
|||||||
CaptureTypes: building
|
CaptureTypes: building
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
Targetable:
|
Targetable:
|
||||||
UpgradeTypes: jail
|
RequiresCondition: !jail
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@PRISONER:
|
Targetable@PRISONER:
|
||||||
TargetTypes: Prisoner
|
TargetTypes: Prisoner
|
||||||
RenderSprites:
|
RenderSprites:
|
||||||
@@ -43,8 +42,7 @@ HACKE6:
|
|||||||
|
|
||||||
MEDI:
|
MEDI:
|
||||||
Targetable:
|
Targetable:
|
||||||
UpgradeTypes: jail
|
RequiresCondition: !jail
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@PRISONER:
|
Targetable@PRISONER:
|
||||||
TargetTypes: Prisoner
|
TargetTypes: Prisoner
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ World:
|
|||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
^Tank:
|
^Tank:
|
||||||
GivesBounty:
|
GivesBounty:
|
||||||
@@ -30,8 +30,8 @@ World:
|
|||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
^Infantry:
|
^Infantry:
|
||||||
GivesBounty:
|
GivesBounty:
|
||||||
@@ -45,8 +45,8 @@ World:
|
|||||||
DeathSounds@ZAPPED:
|
DeathSounds@ZAPPED:
|
||||||
VolumeMultiplier: 0.1
|
VolumeMultiplier: 0.1
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
^Ship:
|
^Ship:
|
||||||
GivesBounty:
|
GivesBounty:
|
||||||
@@ -54,22 +54,22 @@ World:
|
|||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
^Plane:
|
^Plane:
|
||||||
GivesBounty:
|
GivesBounty:
|
||||||
Percentage: 0
|
Percentage: 0
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
^Building:
|
^Building:
|
||||||
GivesBounty:
|
GivesBounty:
|
||||||
Percentage: 0
|
Percentage: 0
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|
||||||
OILB:
|
OILB:
|
||||||
CashTrickler:
|
CashTrickler:
|
||||||
|
|||||||
@@ -71,8 +71,7 @@ TRUK.Hijackable:
|
|||||||
Buildable:
|
Buildable:
|
||||||
Prerequisites: ~disabled
|
Prerequisites: ~disabled
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: mobile
|
RequiresCondition: mobile
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Cargo:
|
Cargo:
|
||||||
Types: Infantry
|
Types: Infantry
|
||||||
MaxWeight: 5
|
MaxWeight: 5
|
||||||
|
|||||||
@@ -223,23 +223,19 @@ TRAN:
|
|||||||
WithIdleOverlay@ROTOR1AIR:
|
WithIdleOverlay@ROTOR1AIR:
|
||||||
Offset: 597,0,213
|
Offset: 597,0,213
|
||||||
Sequence: rotor
|
Sequence: rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTOR1GROUND:
|
WithIdleOverlay@ROTOR1GROUND:
|
||||||
Offset: 597,0,213
|
Offset: 597,0,213
|
||||||
Sequence: slow-rotor
|
Sequence: slow-rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
WithIdleOverlay@ROTOR2AIR:
|
WithIdleOverlay@ROTOR2AIR:
|
||||||
Offset: -597,0,341
|
Offset: -597,0,341
|
||||||
Sequence: rotor2
|
Sequence: rotor2
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTOR2GROUND:
|
WithIdleOverlay@ROTOR2GROUND:
|
||||||
Offset: -597,0,341
|
Offset: -597,0,341
|
||||||
Sequence: slow-rotor2
|
Sequence: slow-rotor2
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Cargo:
|
Cargo:
|
||||||
Types: Infantry
|
Types: Infantry
|
||||||
MaxWeight: 8
|
MaxWeight: 8
|
||||||
@@ -287,13 +283,11 @@ HELI:
|
|||||||
WithIdleOverlay@ROTORAIR:
|
WithIdleOverlay@ROTORAIR:
|
||||||
Offset: 0,0,85
|
Offset: 0,0,85
|
||||||
Sequence: rotor
|
Sequence: rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTORGROUND:
|
WithIdleOverlay@ROTORGROUND:
|
||||||
Offset: 0,0,85
|
Offset: 0,0,85
|
||||||
Sequence: slow-rotor
|
Sequence: slow-rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
Ammo: 8
|
Ammo: 8
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
@@ -345,12 +339,10 @@ HIND:
|
|||||||
InitialStanceAI: HoldFire
|
InitialStanceAI: HoldFire
|
||||||
WithIdleOverlay@ROTORAIR:
|
WithIdleOverlay@ROTORAIR:
|
||||||
Sequence: rotor
|
Sequence: rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTORGROUND:
|
WithIdleOverlay@ROTORGROUND:
|
||||||
Sequence: slow-rotor
|
Sequence: slow-rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
Ammo: 24
|
Ammo: 24
|
||||||
PipCount: 6
|
PipCount: 6
|
||||||
|
|||||||
@@ -16,48 +16,110 @@
|
|||||||
^GainsExperience:
|
^GainsExperience:
|
||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
200: firepower, damage, speed, reload, inaccuracy, rank
|
200: rank-veteran-1
|
||||||
400: firepower, damage, speed, reload, inaccuracy, rank
|
400: rank-veteran-2
|
||||||
800: firepower, damage, speed, reload, inaccuracy, rank
|
800: rank-veteran-3
|
||||||
1600: firepower, damage, speed, reload, inaccuracy, rank, eliteweapon, selfheal
|
1600: rank-elite
|
||||||
DamageMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-1:
|
||||||
UpgradeTypes: damage
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
Modifier: 95, 90, 85, 75
|
Modifier: 95
|
||||||
FirepowerMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-2:
|
||||||
UpgradeTypes: firepower
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
Modifier: 105, 110, 120, 130
|
Modifier: 90
|
||||||
SpeedMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-3:
|
||||||
UpgradeTypes: speed
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
Modifier: 105, 110, 120, 140
|
Modifier: 85
|
||||||
ReloadDelayMultiplier@EXPERIENCE:
|
DamageMultiplier@RANK-ELITE:
|
||||||
UpgradeTypes: reload
|
RequiresCondition: rank-elite
|
||||||
Modifier: 95, 90, 85, 75
|
Modifier: 75
|
||||||
InaccuracyMultiplier@EXPERIENCE:
|
FirepowerMultiplier@RANK-1:
|
||||||
UpgradeTypes: inaccuracy
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
Modifier: 90, 80, 70, 50
|
Modifier: 105
|
||||||
|
FirepowerMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 110
|
||||||
|
FirepowerMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 120
|
||||||
|
FirepowerMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 130
|
||||||
|
SpeedMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 105
|
||||||
|
SpeedMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 110
|
||||||
|
SpeedMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 120
|
||||||
|
SpeedMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 140
|
||||||
|
ReloadDelayMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 95
|
||||||
|
ReloadDelayMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 90
|
||||||
|
ReloadDelayMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 85
|
||||||
|
ReloadDelayMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 75
|
||||||
|
InaccuracyMultiplier@RANK-1:
|
||||||
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
Modifier: 90
|
||||||
|
InaccuracyMultiplier@RANK-2:
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
Modifier: 80
|
||||||
|
InaccuracyMultiplier@RANK-3:
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
Modifier: 70
|
||||||
|
InaccuracyMultiplier@RANK-ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 50
|
||||||
SelfHealing@ELITE:
|
SelfHealing@ELITE:
|
||||||
Step: 2
|
Step: 2
|
||||||
Delay: 100
|
Delay: 100
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: selfheal
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
WithDecoration@RANK-1:
|
||||||
WithRankDecoration:
|
|
||||||
Image: rank
|
Image: rank
|
||||||
Sequence: rank
|
Sequence: rank-veteran-1
|
||||||
Palette: effect
|
Palette: effect
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: rank
|
RequiresCondition: rank-veteran-1 && !rank-veteran-2
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-2:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-veteran-2
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-veteran-2 && !rank-veteran-3
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-3:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-veteran-3
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-veteran-3 && !rank-elite
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@RANK-ELITE:
|
||||||
|
Image: rank
|
||||||
|
Sequence: rank-elite
|
||||||
|
Palette: effect
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-elite
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
UpgradeMaxAcceptedLevel: 4
|
|
||||||
|
|
||||||
^IronCurtainable:
|
^IronCurtainable:
|
||||||
UpgradeOverlay@IRONCURTAIN:
|
UpgradeOverlay@IRONCURTAIN:
|
||||||
UpgradeTypes: invulnerability
|
RequiresCondition: invulnerability
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
DamageMultiplier@IRONCURTAIN:
|
DamageMultiplier@IRONCURTAIN:
|
||||||
UpgradeTypes: invulnerability
|
RequiresCondition: invulnerability
|
||||||
Modifier: 0
|
Modifier: 0
|
||||||
TimedUpgradeBar:
|
TimedUpgradeBar:
|
||||||
Upgrade: invulnerability
|
Upgrade: invulnerability
|
||||||
@@ -87,8 +149,7 @@
|
|||||||
Bounds: 24, 24
|
Bounds: 24, 24
|
||||||
Targetable:
|
Targetable:
|
||||||
TargetTypes: Ground, Repair, Vehicle
|
TargetTypes: Ground, Repair, Vehicle
|
||||||
UpgradeTypes: parachute
|
RequiresCondition: !parachute
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Repairable:
|
Repairable:
|
||||||
Chronoshiftable:
|
Chronoshiftable:
|
||||||
Passenger:
|
Passenger:
|
||||||
@@ -133,14 +194,13 @@
|
|||||||
EmptyWeapon: UnitExplodeSmall
|
EmptyWeapon: UnitExplodeSmall
|
||||||
WithFacingSpriteBody:
|
WithFacingSpriteBody:
|
||||||
WithParachute:
|
WithParachute:
|
||||||
UpgradeTypes: parachute
|
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
ShadowImage: parach-shadow
|
ShadowImage: parach-shadow
|
||||||
ShadowSequence: idle
|
ShadowSequence: idle
|
||||||
Image: parach
|
Image: parach
|
||||||
Sequence: idle
|
Sequence: idle
|
||||||
OpeningSequence: open
|
OpeningSequence: open
|
||||||
Offset: 0,0,200
|
Offset: 0,0,200
|
||||||
|
RequiresCondition: parachute
|
||||||
BodyOrientation:
|
BodyOrientation:
|
||||||
UseClassicFacingFudge: True
|
UseClassicFacingFudge: True
|
||||||
|
|
||||||
@@ -195,8 +255,7 @@
|
|||||||
Bounds: 12,18,0,-8
|
Bounds: 12,18,0,-8
|
||||||
Targetable:
|
Targetable:
|
||||||
TargetTypes: Ground, Infantry, Disguise
|
TargetTypes: Ground, Infantry, Disguise
|
||||||
UpgradeTypes: parachute
|
RequiresCondition: !parachute
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
QuantizeFacingsFromSequence:
|
QuantizeFacingsFromSequence:
|
||||||
Sequence: stand
|
Sequence: stand
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
@@ -228,8 +287,7 @@
|
|||||||
Delay: 100
|
Delay: 100
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: hospitalheal
|
RequiresCondition: hospitalheal
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
GlobalUpgradable:
|
GlobalUpgradable:
|
||||||
Upgrades: hospitalheal
|
Upgrades: hospitalheal
|
||||||
Prerequisites: hosp
|
Prerequisites: hosp
|
||||||
@@ -252,14 +310,13 @@
|
|||||||
Voiced:
|
Voiced:
|
||||||
VoiceSet: GenericVoice
|
VoiceSet: GenericVoice
|
||||||
WithParachute:
|
WithParachute:
|
||||||
UpgradeTypes: parachute
|
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
ShadowImage: parach-shadow
|
ShadowImage: parach-shadow
|
||||||
ShadowSequence: idle
|
ShadowSequence: idle
|
||||||
Image: parach
|
Image: parach
|
||||||
Sequence: idle
|
Sequence: idle
|
||||||
OpeningSequence: open
|
OpeningSequence: open
|
||||||
Offset: 0,0,427
|
Offset: 0,0,427
|
||||||
|
RequiresCondition: parachute
|
||||||
|
|
||||||
^Soldier:
|
^Soldier:
|
||||||
Inherits: ^Infantry
|
Inherits: ^Infantry
|
||||||
@@ -370,12 +427,10 @@
|
|||||||
CruisingUpgrades: cruising
|
CruisingUpgrades: cruising
|
||||||
Targetable@GROUND:
|
Targetable@GROUND:
|
||||||
TargetTypes: Ground, Repair, Vehicle
|
TargetTypes: Ground, Repair, Vehicle
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@AIRBORNE:
|
Targetable@AIRBORNE:
|
||||||
TargetTypes: Air
|
TargetTypes: Air
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
HiddenUnderFog:
|
HiddenUnderFog:
|
||||||
Type: CenterPosition
|
Type: CenterPosition
|
||||||
AttackMove:
|
AttackMove:
|
||||||
@@ -414,8 +469,7 @@
|
|||||||
GpsDot:
|
GpsDot:
|
||||||
String: Helicopter
|
String: Helicopter
|
||||||
Hovers@CRUISING:
|
Hovers@CRUISING:
|
||||||
UpgradeTypes: cruising
|
RequiresCondition: cruising
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
BodyOrientation:
|
BodyOrientation:
|
||||||
UseClassicFacingFudge: True
|
UseClassicFacingFudge: True
|
||||||
|
|
||||||
@@ -825,13 +879,12 @@
|
|||||||
KilledOnImpassableTerrain: false
|
KilledOnImpassableTerrain: false
|
||||||
Passenger:
|
Passenger:
|
||||||
WithParachute:
|
WithParachute:
|
||||||
UpgradeTypes: parachute
|
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Image: parach
|
Image: parach
|
||||||
Sequence: idle
|
Sequence: idle
|
||||||
OpeningSequence: open
|
OpeningSequence: open
|
||||||
ShadowImage: parach-shadow
|
ShadowImage: parach-shadow
|
||||||
ShadowSequence: idle
|
ShadowSequence: idle
|
||||||
|
RequiresCondition: parachute
|
||||||
UpgradeManager:
|
UpgradeManager:
|
||||||
|
|
||||||
^Mine:
|
^Mine:
|
||||||
|
|||||||
@@ -226,8 +226,7 @@ SPY:
|
|||||||
Palette: effect
|
Palette: effect
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: disguise
|
RequiresCondition: disguise
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
IgnoresDisguise:
|
IgnoresDisguise:
|
||||||
DetectCloaked:
|
DetectCloaked:
|
||||||
CloakTypes: Cloak, Hijacker
|
CloakTypes: Cloak, Hijacker
|
||||||
|
|||||||
@@ -21,12 +21,10 @@ SS:
|
|||||||
Range: 6c0
|
Range: 6c0
|
||||||
Targetable:
|
Targetable:
|
||||||
TargetTypes: Ground, Water, Repair
|
TargetTypes: Ground, Water, Repair
|
||||||
UpgradeTypes: underwater
|
RequiresCondition: !underwater
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@UNDERWATER:
|
Targetable@UNDERWATER:
|
||||||
TargetTypes: Underwater, Repair
|
TargetTypes: Underwater, Repair
|
||||||
UpgradeTypes: underwater
|
RequiresCondition: underwater
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Cloak:
|
Cloak:
|
||||||
CloakTypes: Underwater
|
CloakTypes: Underwater
|
||||||
InitialDelay: 0
|
InitialDelay: 0
|
||||||
@@ -77,12 +75,10 @@ MSUB:
|
|||||||
Range: 6c0
|
Range: 6c0
|
||||||
Targetable:
|
Targetable:
|
||||||
TargetTypes: Ground, Water, Repair
|
TargetTypes: Ground, Water, Repair
|
||||||
UpgradeTypes: underwater
|
RequiresCondition: !underwater
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@UNDERWATER:
|
Targetable@UNDERWATER:
|
||||||
TargetTypes: Underwater, Repair
|
TargetTypes: Underwater, Repair
|
||||||
UpgradeTypes: underwater
|
RequiresCondition: underwater
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Cloak:
|
Cloak:
|
||||||
CloakTypes: Underwater
|
CloakTypes: Underwater
|
||||||
InitialDelay: 0
|
InitialDelay: 0
|
||||||
@@ -230,12 +226,11 @@ LST:
|
|||||||
Armor:
|
Armor:
|
||||||
Type: Heavy
|
Type: Heavy
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: notmobile
|
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
TurnSpeed: 10
|
TurnSpeed: 10
|
||||||
Speed: 113
|
Speed: 113
|
||||||
TerrainSpeeds:
|
TerrainSpeeds:
|
||||||
Beach: 70
|
Beach: 70
|
||||||
|
RequiresCondition: !notmobile
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 6c0
|
Range: 6c0
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
|
|||||||
@@ -174,8 +174,7 @@ SPEN:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
SYRD:
|
SYRD:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -270,8 +269,7 @@ SYRD:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
IRON:
|
IRON:
|
||||||
Inherits: ^ScienceBuilding
|
Inherits: ^ScienceBuilding
|
||||||
@@ -877,8 +875,7 @@ WEAP:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
FACT:
|
FACT:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -1116,8 +1113,7 @@ HPAD:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithRearmAnimation:
|
WithRearmAnimation:
|
||||||
|
|
||||||
AFLD:
|
AFLD:
|
||||||
@@ -1233,8 +1229,7 @@ AFLD:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithRearmAnimation:
|
WithRearmAnimation:
|
||||||
|
|
||||||
POWR:
|
POWR:
|
||||||
@@ -1413,8 +1408,7 @@ BARR:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
KENN:
|
KENN:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -1461,8 +1455,7 @@ KENN:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
TENT:
|
TENT:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -1541,8 +1534,7 @@ TENT:
|
|||||||
Sequence: tag-primary
|
Sequence: tag-primary
|
||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
FIX:
|
FIX:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
|
|||||||
@@ -338,8 +338,7 @@ JEEP:
|
|||||||
Mobile:
|
Mobile:
|
||||||
TurnSpeed: 10
|
TurnSpeed: 10
|
||||||
Speed: 170
|
Speed: 170
|
||||||
UpgradeTypes: notmobile
|
RequiresCondition: !notmobile
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 8c0
|
Range: 8c0
|
||||||
Turreted:
|
Turreted:
|
||||||
@@ -378,8 +377,7 @@ APC:
|
|||||||
Mobile:
|
Mobile:
|
||||||
Speed: 142
|
Speed: 142
|
||||||
Crushes: wall, mine, crate, infantry
|
Crushes: wall, mine, crate, infantry
|
||||||
UpgradeTypes: notmobile
|
RequiresCondition: !notmobile
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 5c0
|
Range: 5c0
|
||||||
Armament:
|
Armament:
|
||||||
@@ -651,8 +649,7 @@ DTRK:
|
|||||||
AttackSuicides:
|
AttackSuicides:
|
||||||
-DamageMultiplier@IRONCURTAIN:
|
-DamageMultiplier@IRONCURTAIN:
|
||||||
KillsSelf:
|
KillsSelf:
|
||||||
UpgradeTypes: invulnerability
|
RequiresCondition: invulnerability
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Chronoshiftable:
|
Chronoshiftable:
|
||||||
ExplodeInstead: yes
|
ExplodeInstead: yes
|
||||||
|
|
||||||
@@ -738,8 +735,7 @@ STNK:
|
|||||||
Mobile:
|
Mobile:
|
||||||
Speed: 142
|
Speed: 142
|
||||||
Crushes: wall, mine, crate, infantry
|
Crushes: wall, mine, crate, infantry
|
||||||
UpgradeTypes: notmobile
|
RequiresCondition: !notmobile
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 7c0
|
Range: 7c0
|
||||||
AutoTarget:
|
AutoTarget:
|
||||||
|
|||||||
@@ -424,8 +424,13 @@ fire:
|
|||||||
ZOffset: 1023
|
ZOffset: 1023
|
||||||
|
|
||||||
rank:
|
rank:
|
||||||
rank:
|
rank-veteran-1:
|
||||||
Length: *
|
rank-veteran-2:
|
||||||
|
Start: 1
|
||||||
|
rank-veteran-3:
|
||||||
|
Start: 2
|
||||||
|
rank-elite:
|
||||||
|
Start: 3
|
||||||
|
|
||||||
iconchevrons:
|
iconchevrons:
|
||||||
veteran:
|
veteran:
|
||||||
|
|||||||
@@ -1447,13 +1447,13 @@ Rules:
|
|||||||
InitialUnits: e1, e1, e2, e2, medic
|
InitialUnits: e1, e1, e2, e2, medic
|
||||||
GACTWR:
|
GACTWR:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
NAOBEL:
|
NAOBEL:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
NALASR:
|
NALASR:
|
||||||
DamageMultiplier@UNKILLABLE:
|
DamageMultiplier@UNKILLABLE:
|
||||||
UpgradeTypes: unkillable
|
RequiresCondition: unkillable
|
||||||
Modifier: 0, 0
|
Modifier: 0
|
||||||
|
|||||||
@@ -147,8 +147,7 @@ ORCAB:
|
|||||||
AutoTarget:
|
AutoTarget:
|
||||||
RenderSprites:
|
RenderSprites:
|
||||||
Hovers@CRUISING:
|
Hovers@CRUISING:
|
||||||
UpgradeTypes: cruising
|
RequiresCondition: cruising
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
SpawnActorOnDeath:
|
SpawnActorOnDeath:
|
||||||
Actor: ORCAB.Husk
|
Actor: ORCAB.Husk
|
||||||
|
|
||||||
@@ -310,13 +309,11 @@ APACHE:
|
|||||||
WithIdleOverlay@ROTORAIR:
|
WithIdleOverlay@ROTORAIR:
|
||||||
Offset: 85,0,384
|
Offset: 85,0,384
|
||||||
Sequence: rotor
|
Sequence: rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@ROTORGROUND:
|
WithIdleOverlay@ROTORGROUND:
|
||||||
Offset: 85,0,384
|
Offset: 85,0,384
|
||||||
Sequence: slow-rotor
|
Sequence: slow-rotor
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
RenderSprites:
|
RenderSprites:
|
||||||
SpawnActorOnDeath:
|
SpawnActorOnDeath:
|
||||||
Actor: APACHE.Husk
|
Actor: APACHE.Husk
|
||||||
@@ -351,8 +348,7 @@ HUNTER:
|
|||||||
Image: GGHUNT
|
Image: GGHUNT
|
||||||
WithFacingSpriteBody:
|
WithFacingSpriteBody:
|
||||||
Hovers@CRUISING:
|
Hovers@CRUISING:
|
||||||
UpgradeTypes: cruising
|
RequiresCondition: cruising
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
QuantizeFacingsFromSequence:
|
QuantizeFacingsFromSequence:
|
||||||
AutoSelectionSize:
|
AutoSelectionSize:
|
||||||
DrawLineToTarget:
|
DrawLineToTarget:
|
||||||
|
|||||||
@@ -70,8 +70,7 @@ CHAMSPY:
|
|||||||
Palette: pips
|
Palette: pips
|
||||||
ReferencePoint: Top, Right
|
ReferencePoint: Top, Right
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: disguise
|
RequiresCondition: disguise
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Infiltrates:
|
Infiltrates:
|
||||||
Types: SpyInfiltrate
|
Types: SpyInfiltrate
|
||||||
-AutoTarget:
|
-AutoTarget:
|
||||||
|
|||||||
@@ -18,69 +18,80 @@
|
|||||||
^GainsExperience:
|
^GainsExperience:
|
||||||
GainsExperience:
|
GainsExperience:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
500: rank, firepower, damage, speed, reload
|
500: rank-veteran
|
||||||
1000: rank, firepower, damage, speed, reload, selfheal, eliteweapon
|
1000: rank-elite
|
||||||
FirepowerMultiplier@EXPERIENCE:
|
FirepowerMultiplier@VETERAN:
|
||||||
UpgradeTypes: firepower
|
RequiresCondition: (rank-veteran && !rank-elite) || crate-firepower
|
||||||
Modifier: 110, 130
|
Modifier: 110
|
||||||
DamageMultiplier@EXPERIENCE:
|
FirepowerMultiplier@ELITE:
|
||||||
UpgradeTypes: damage
|
RequiresCondition: rank-elite || (rank-veteran && crate-firepower)
|
||||||
Modifier: 90, 75
|
Modifier: 130
|
||||||
SpeedMultiplier@EXPERIENCE:
|
DamageMultiplier@VETERAN:
|
||||||
UpgradeTypes: speed
|
RequiresCondition: (rank-veteran && !rank-elite) || crate-damage
|
||||||
Modifier: 120, 140
|
Modifier: 90
|
||||||
ReloadDelayMultiplier@EXPERIENCE:
|
DamageMultiplier@ELITE:
|
||||||
UpgradeTypes: reload
|
RequiresCondition: rank-elite || (rank-veteran && crate-damage)
|
||||||
Modifier: 90, 75
|
Modifier: 75
|
||||||
|
SpeedMultiplier@VETERAN:
|
||||||
|
RequiresCondition: (rank-veteran && !rank-elite) || crate-speed
|
||||||
|
Modifier: 120
|
||||||
|
SpeedMultiplier@ELITE:
|
||||||
|
RequiresCondition: rank-elite || (rank-veteran && crate-speed)
|
||||||
|
Modifier: 140
|
||||||
|
ReloadDelayMultiplier@VETERAN:
|
||||||
|
RequiresCondition: rank-veteran && !rank-elite
|
||||||
|
Modifier: 90
|
||||||
|
ReloadDelayMultiplier@ELITE:
|
||||||
|
RequiresCondition: rank-elite
|
||||||
|
Modifier: 75
|
||||||
SelfHealing@ELITE:
|
SelfHealing@ELITE:
|
||||||
Step: 2
|
Step: 2
|
||||||
Delay: 100
|
Delay: 100
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: selfheal
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
WithDecoration@VETERAN:
|
||||||
WithRankDecoration:
|
|
||||||
Image: rank
|
Image: rank
|
||||||
Sequence: rank
|
Sequence: veteran
|
||||||
Palette: ra
|
Palette: ra
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: rank
|
RequiresCondition: rank-veteran && !rank-elite
|
||||||
|
ZOffset: 256
|
||||||
|
WithDecoration@ELITE:
|
||||||
|
Image: rank
|
||||||
|
Sequence: elite
|
||||||
|
Palette: ra
|
||||||
|
ReferencePoint: Bottom, Right
|
||||||
|
RequiresCondition: rank-elite
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
UpgradeMaxAcceptedLevel: 2
|
|
||||||
|
|
||||||
^EmpDisable:
|
^EmpDisable:
|
||||||
UpgradeOverlay@EMPDISABLE:
|
UpgradeOverlay@EMPDISABLE:
|
||||||
UpgradeTypes: empdisable
|
RequiresCondition: empdisable
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Palette: disabled
|
Palette: disabled
|
||||||
DisableOnUpgrade@EMPDISABLE:
|
DisableOnUpgrade@EMPDISABLE:
|
||||||
UpgradeTypes: empdisable
|
RequiresCondition: empdisable
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
TimedUpgradeBar@EMPDISABLE:
|
TimedUpgradeBar@EMPDISABLE:
|
||||||
Upgrade: empdisable
|
Upgrade: empdisable
|
||||||
Color: FFFFFF
|
Color: FFFFFF
|
||||||
WithIdleOverlay@EMPDISABLE:
|
WithIdleOverlay@EMPDISABLE:
|
||||||
Sequence: emp-overlay
|
Sequence: emp-overlay
|
||||||
Palette: effect
|
Palette: effect
|
||||||
UpgradeTypes: empdisable
|
RequiresCondition: empdisable
|
||||||
ShowToEnemies: true
|
ShowToEnemies: true
|
||||||
ZOffset: 512
|
ZOffset: 512
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
PowerMultiplier@EMPDISABLE:
|
PowerMultiplier@EMPDISABLE:
|
||||||
UpgradeTypes: empdisable
|
RequiresCondition: empdisable
|
||||||
Modifier: 0
|
Modifier: 0
|
||||||
|
|
||||||
^EmpDisableMobile:
|
^EmpDisableMobile:
|
||||||
Inherits: ^EmpDisable
|
Inherits: ^EmpDisable
|
||||||
Mobile:
|
Mobile:
|
||||||
UpgradeTypes: notmobile
|
RequiresCondition: !notmobile
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
|
|
||||||
^Cloakable:
|
^Cloakable:
|
||||||
Cloak@CLOAKGENERATOR:
|
Cloak@CLOAKGENERATOR:
|
||||||
UpgradeTypes: cloakgenerator
|
RequiresCondition: cloakgenerator || crate-cloak
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
InitialDelay: 0
|
InitialDelay: 0
|
||||||
CloakDelay: 90
|
CloakDelay: 90
|
||||||
IsPlayerPalette: true
|
IsPlayerPalette: true
|
||||||
@@ -306,8 +317,7 @@
|
|||||||
Delay: 100
|
Delay: 100
|
||||||
HealIfBelow: 100
|
HealIfBelow: 100
|
||||||
DamageCooldown: 125
|
DamageCooldown: 125
|
||||||
UpgradeTypes: hospitalheal
|
RequiresCondition: hospitalheal
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
GlobalUpgradable@HOSPITAL:
|
GlobalUpgradable@HOSPITAL:
|
||||||
Upgrades: hospitalheal
|
Upgrades: hospitalheal
|
||||||
Prerequisites: cahosp
|
Prerequisites: cahosp
|
||||||
@@ -316,8 +326,7 @@
|
|||||||
Sequence: medic
|
Sequence: medic
|
||||||
Palette: pips
|
Palette: pips
|
||||||
ReferencePoint: Bottom, Right
|
ReferencePoint: Bottom, Right
|
||||||
UpgradeTypes: hospitalheal
|
RequiresCondition: hospitalheal
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
^RegularInfantryDeath:
|
^RegularInfantryDeath:
|
||||||
WithDeathAnimation@normal:
|
WithDeathAnimation@normal:
|
||||||
@@ -406,7 +415,7 @@
|
|||||||
ValidDamageStates: Critical
|
ValidDamageStates: Critical
|
||||||
GrantPermanently: true
|
GrantPermanently: true
|
||||||
SpeedMultiplier@CRITICAL:
|
SpeedMultiplier@CRITICAL:
|
||||||
UpgradeTypes: criticalspeed
|
RequiresCondition: criticalspeed
|
||||||
Modifier: 50
|
Modifier: 50
|
||||||
|
|
||||||
^CivilianInfantry:
|
^CivilianInfantry:
|
||||||
@@ -488,10 +497,10 @@
|
|||||||
Upgrades: criticalspeed
|
Upgrades: criticalspeed
|
||||||
ValidDamageStates: Critical
|
ValidDamageStates: Critical
|
||||||
SpeedMultiplier@DAMAGED:
|
SpeedMultiplier@DAMAGED:
|
||||||
UpgradeTypes: damagedspeed
|
RequiresCondition: damagedspeed
|
||||||
Modifier: 80
|
Modifier: 80
|
||||||
SpeedMultiplier@CRITICAL:
|
SpeedMultiplier@CRITICAL:
|
||||||
UpgradeTypes: criticalspeed
|
RequiresCondition: criticalspeed
|
||||||
Modifier: 60
|
Modifier: 60
|
||||||
Carryable:
|
Carryable:
|
||||||
|
|
||||||
@@ -543,12 +552,10 @@
|
|||||||
UseLocation: true
|
UseLocation: true
|
||||||
Targetable@GROUND:
|
Targetable@GROUND:
|
||||||
TargetTypes: Ground, Vehicle
|
TargetTypes: Ground, Vehicle
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: !airborne
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Targetable@AIRBORNE:
|
Targetable@AIRBORNE:
|
||||||
TargetTypes: Air
|
TargetTypes: Air
|
||||||
UpgradeTypes: airborne
|
RequiresCondition: airborne
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Selectable:
|
Selectable:
|
||||||
WithTextControlGroupDecoration:
|
WithTextControlGroupDecoration:
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
@@ -584,8 +591,7 @@
|
|||||||
CruiseAltitude: 2048
|
CruiseAltitude: 2048
|
||||||
CanHover: True
|
CanHover: True
|
||||||
Hovers@CRUISING:
|
Hovers@CRUISING:
|
||||||
UpgradeTypes: cruising
|
RequiresCondition: cruising
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
^Plane:
|
^Plane:
|
||||||
Inherits: ^Aircraft
|
Inherits: ^Aircraft
|
||||||
@@ -939,5 +945,4 @@
|
|||||||
Upgrades: veins
|
Upgrades: veins
|
||||||
WithIdleOverlay@VEINS:
|
WithIdleOverlay@VEINS:
|
||||||
Sequence: veins
|
Sequence: veins
|
||||||
UpgradeTypes: veins
|
RequiresCondition: veins
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|||||||
@@ -41,24 +41,20 @@ GAPOWR:
|
|||||||
Upgrades:
|
Upgrades:
|
||||||
powrup: powrup.a
|
powrup: powrup.a
|
||||||
Power@pluga:
|
Power@pluga:
|
||||||
UpgradeTypes: powrup.a
|
RequiresCondition: powrup.a
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Amount: 50
|
Amount: 50
|
||||||
WithIdleOverlay@pluga:
|
WithIdleOverlay@pluga:
|
||||||
UpgradeTypes: powrup.a
|
RequiresCondition: powrup.a
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Sequence: idle-powrupa
|
Sequence: idle-powrupa
|
||||||
Pluggable@plugb:
|
Pluggable@plugb:
|
||||||
Offset: 1,1
|
Offset: 1,1
|
||||||
Upgrades:
|
Upgrades:
|
||||||
powrup: powrup.b
|
powrup: powrup.b
|
||||||
WithIdleOverlay@plugb:
|
WithIdleOverlay@plugb:
|
||||||
UpgradeTypes: powrup.b
|
RequiresCondition: powrup.b
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Sequence: idle-powrupb
|
Sequence: idle-powrupb
|
||||||
Power@plugb:
|
Power@plugb:
|
||||||
UpgradeTypes: powrup.b
|
RequiresCondition: powrup.b
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Amount: 50
|
Amount: 50
|
||||||
ProvidesPrerequisite@buildingname:
|
ProvidesPrerequisite@buildingname:
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
@@ -118,8 +114,7 @@ GAPILE:
|
|||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
Color: E0D048
|
Color: E0D048
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
GAWEAP:
|
GAWEAP:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -181,8 +176,7 @@ GAWEAP:
|
|||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
Color: E0D048
|
Color: E0D048
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
GAHPAD:
|
GAHPAD:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -236,8 +230,7 @@ GAHPAD:
|
|||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
Color: E0D048
|
Color: E0D048
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
GADEPT:
|
GADEPT:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -406,8 +399,7 @@ GAPLUG:
|
|||||||
MaxHeightDelta: 3
|
MaxHeightDelta: 3
|
||||||
IonCannonPower:
|
IonCannonPower:
|
||||||
Cursor: ioncannon
|
Cursor: ioncannon
|
||||||
UpgradeTypes: plug.ioncannon
|
RequiresCondition: plug.ioncannona || plug.ioncannonb
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Icon: ioncannon
|
Icon: ioncannon
|
||||||
Effect: explosion
|
Effect: explosion
|
||||||
EffectSequence: ionring
|
EffectSequence: ionring
|
||||||
@@ -421,8 +413,7 @@ GAPLUG:
|
|||||||
DisplayRadarPing: True
|
DisplayRadarPing: True
|
||||||
CameraActor: camera
|
CameraActor: camera
|
||||||
ProduceActorPower:
|
ProduceActorPower:
|
||||||
UpgradeTypes: plug.hunterseeker
|
RequiresCondition: plug.hunterseekera || plug.hunterseekerb
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Description: Hunter Seeker
|
Description: Hunter Seeker
|
||||||
LongDesc: Releases a drone that will acquire and destroy an enemy target.
|
LongDesc: Releases a drone that will acquire and destroy an enemy target.
|
||||||
Icon: hunterseeker
|
Icon: hunterseeker
|
||||||
@@ -437,38 +428,32 @@ GAPLUG:
|
|||||||
Power:
|
Power:
|
||||||
Amount: -150
|
Amount: -150
|
||||||
Power@ioncannon:
|
Power@ioncannon:
|
||||||
UpgradeTypes: plug.ioncannon
|
RequiresCondition: plug.ioncannona || plug.ioncannonb
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Amount: -100
|
Amount: -100
|
||||||
Power@hunterseeker:
|
Power@hunterseeker:
|
||||||
UpgradeTypes: plug.hunterseeker
|
RequiresCondition: plug.hunterseekera || plug.hunterseekerb
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Amount: -50
|
Amount: -50
|
||||||
Pluggable@pluga:
|
Pluggable@pluga:
|
||||||
Offset: 0,2
|
Offset: 0,2
|
||||||
Upgrades:
|
Upgrades:
|
||||||
plug.ioncannon: plug.ioncannon, plug.ioncannona
|
plug.ioncannon: plug.ioncannona
|
||||||
plug.hunterseeker: plug.hunterseeker, plug.hunterseekera
|
plug.hunterseeker: plug.hunterseekera
|
||||||
WithIdleOverlay@ioncannona:
|
WithIdleOverlay@ioncannona:
|
||||||
UpgradeTypes: plug.ioncannona
|
RequiresCondition: plug.ioncannona
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Sequence: idle-ioncannona
|
Sequence: idle-ioncannona
|
||||||
WithIdleOverlay@hunterseekera:
|
WithIdleOverlay@hunterseekera:
|
||||||
UpgradeTypes: plug.hunterseekera
|
RequiresCondition: plug.hunterseekera
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Sequence: idle-hunterseekera
|
Sequence: idle-hunterseekera
|
||||||
Pluggable@plugb:
|
Pluggable@plugb:
|
||||||
Offset: 1,2
|
Offset: 1,2
|
||||||
Upgrades:
|
Upgrades:
|
||||||
plug.ioncannon: plug.ioncannon, plug.ioncannonb
|
plug.ioncannon: plug.ioncannonb
|
||||||
plug.hunterseeker: plug.hunterseeker, plug.hunterseekerb
|
plug.hunterseeker: plug.hunterseekerb
|
||||||
WithIdleOverlay@ioncannonb:
|
WithIdleOverlay@ioncannonb:
|
||||||
UpgradeTypes: plug.ioncannonb
|
RequiresCondition: plug.ioncannonb
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Sequence: idle-ioncannonb
|
Sequence: idle-ioncannonb
|
||||||
WithIdleOverlay@hunterseekerb:
|
WithIdleOverlay@hunterseekerb:
|
||||||
UpgradeTypes: plug.hunterseekerb
|
RequiresCondition: plug.hunterseekerb
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Sequence: idle-hunterseekerb
|
Sequence: idle-hunterseekerb
|
||||||
ProvidesPrerequisite@buildingname:
|
ProvidesPrerequisite@buildingname:
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
|
|||||||
@@ -68,61 +68,51 @@ GACTWR:
|
|||||||
BodyOrientation:
|
BodyOrientation:
|
||||||
QuantizedFacings: 32
|
QuantizedFacings: 32
|
||||||
DetectCloaked:
|
DetectCloaked:
|
||||||
UpgradeTypes: tower
|
RequiresCondition: tower.vulcan || tower.rocket || tower.sam
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Turreted:
|
Turreted:
|
||||||
TurnSpeed: 10
|
TurnSpeed: 10
|
||||||
InitialFacing: 224
|
InitialFacing: 224
|
||||||
AttackTurreted:
|
AttackTurreted:
|
||||||
UpgradeTypes: tower
|
RequiresCondition: tower.vulcan || tower.rocket || tower.sam
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
CanPowerDown:
|
CanPowerDown:
|
||||||
IndicatorPalette: mouse
|
IndicatorPalette: mouse
|
||||||
PowerupSpeech: EnablePower
|
PowerupSpeech: EnablePower
|
||||||
PowerdownSpeech: DisablePower
|
PowerdownSpeech: DisablePower
|
||||||
WithSpriteTurret@VULC:
|
WithSpriteTurret@VULC:
|
||||||
UpgradeTypes: tower.vulcan
|
RequiresCondition: tower.vulcan
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Recoils: false
|
Recoils: false
|
||||||
Sequence: turret-vulcan
|
Sequence: turret-vulcan
|
||||||
WithSpriteTurret@ROCKET:
|
WithSpriteTurret@ROCKET:
|
||||||
UpgradeTypes: tower.rocket
|
RequiresCondition: tower.rocket
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Recoils: false
|
Recoils: false
|
||||||
Sequence: turret-rocket
|
Sequence: turret-rocket
|
||||||
WithSpriteTurret@SAM:
|
WithSpriteTurret@SAM:
|
||||||
UpgradeTypes: tower.sam
|
RequiresCondition: tower.sam
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Recoils: false
|
Recoils: false
|
||||||
Sequence: turret-sam
|
Sequence: turret-sam
|
||||||
Armament@VULCPRIMARY:
|
Armament@VULCPRIMARY:
|
||||||
UpgradeTypes: tower.vulcan
|
RequiresCondition: tower.vulcan
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Weapon: VulcanTower
|
Weapon: VulcanTower
|
||||||
LocalOffset: 416,85,960
|
LocalOffset: 416,85,960
|
||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
MuzzleSplitFacings: 8
|
MuzzleSplitFacings: 8
|
||||||
Armament@VULCSECONDARY:
|
Armament@VULCSECONDARY:
|
||||||
UpgradeTypes: tower.vulcan
|
RequiresCondition: tower.vulcan
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Name: secondary
|
Name: secondary
|
||||||
Weapon: VulcanTower
|
Weapon: VulcanTower
|
||||||
LocalOffset: 416,-85,960
|
LocalOffset: 416,-85,960
|
||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
MuzzleSplitFacings: 8
|
MuzzleSplitFacings: 8
|
||||||
Armament@ROCKET:
|
Armament@ROCKET:
|
||||||
UpgradeTypes: tower.rocket
|
RequiresCondition: tower.rocket
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Weapon: RPGTower
|
Weapon: RPGTower
|
||||||
LocalOffset: 192,-65,1056
|
LocalOffset: 192,-65,1056
|
||||||
Armament@SAM:
|
Armament@SAM:
|
||||||
UpgradeTypes: tower.sam
|
RequiresCondition: tower.sam
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Weapon: RedEye2
|
Weapon: RedEye2
|
||||||
LocalOffset: 384,0,1200
|
LocalOffset: 384,0,1200
|
||||||
WithMuzzleOverlay:
|
WithMuzzleOverlay:
|
||||||
UpgradeTypes: tower.vulcan
|
RequiresCondition: tower.vulcan
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithIdleOverlay@LIGHTS:
|
WithIdleOverlay@LIGHTS:
|
||||||
Sequence: idle-lights
|
Sequence: idle-lights
|
||||||
LineBuildNode:
|
LineBuildNode:
|
||||||
@@ -130,18 +120,16 @@ GACTWR:
|
|||||||
Power@base:
|
Power@base:
|
||||||
Amount: -10
|
Amount: -10
|
||||||
Power@turrets:
|
Power@turrets:
|
||||||
UpgradeTypes: tower
|
RequiresCondition: tower.vulcan || tower.rocket || tower.sam
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Amount: -20
|
Amount: -20
|
||||||
Power@samextra:
|
Power@samextra:
|
||||||
UpgradeTypes: tower.sam
|
RequiresCondition: tower.sam
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Amount: -10
|
Amount: -10
|
||||||
Pluggable:
|
Pluggable:
|
||||||
Upgrades:
|
Upgrades:
|
||||||
tower.vulcan: tower, tower.vulcan
|
tower.vulcan: tower.vulcan
|
||||||
tower.rocket: tower, tower.rocket
|
tower.rocket: tower.rocket
|
||||||
tower.sam: tower, tower.sam
|
tower.sam: tower.sam
|
||||||
ProvidesPrerequisite@buildingname:
|
ProvidesPrerequisite@buildingname:
|
||||||
SelectionDecorations:
|
SelectionDecorations:
|
||||||
VisualBounds: 48, 48, 0, -12
|
VisualBounds: 48, 48, 0, -12
|
||||||
|
|||||||
@@ -34,12 +34,10 @@ APC:
|
|||||||
Upgrades: inwater
|
Upgrades: inwater
|
||||||
TerrainTypes: Water
|
TerrainTypes: Water
|
||||||
WithVoxelBody:
|
WithVoxelBody:
|
||||||
UpgradeTypes: inwater
|
RequiresCondition: !inwater
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
WithVoxelBody@water:
|
WithVoxelBody@water:
|
||||||
Sequence: water
|
Sequence: water
|
||||||
UpgradeTypes: inwater
|
RequiresCondition: inwater
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
LeavesTrails:
|
LeavesTrails:
|
||||||
Image: wake
|
Image: wake
|
||||||
Palette: effect
|
Palette: effect
|
||||||
|
|||||||
@@ -77,21 +77,21 @@ CRATE:
|
|||||||
GrantUpgradeCrateAction@cloak:
|
GrantUpgradeCrateAction@cloak:
|
||||||
SelectionShares: 5
|
SelectionShares: 5
|
||||||
Effect: stealth
|
Effect: stealth
|
||||||
Upgrades: cloakgenerator
|
Upgrades: crate-cloak
|
||||||
Notification: cloak5.aud
|
Notification: cloak5.aud
|
||||||
GrantUpgradeCrateAction@firepower:
|
GrantUpgradeCrateAction@firepower:
|
||||||
SelectionShares: 5
|
SelectionShares: 5
|
||||||
Effect: firepower
|
Effect: firepower
|
||||||
Upgrades: firepower
|
Upgrades: crate-firepower
|
||||||
Notification: 00-i070.aud
|
Notification: 00-i070.aud
|
||||||
GrantUpgradeCrateAction@armor:
|
GrantUpgradeCrateAction@armor:
|
||||||
SelectionShares: 5
|
SelectionShares: 5
|
||||||
Effect: armor
|
Effect: armor
|
||||||
Upgrades: damage
|
Upgrades: crate-damage
|
||||||
Notification: 00-i068.aud
|
Notification: 00-i068.aud
|
||||||
GrantUpgradeCrateAction@speed:
|
GrantUpgradeCrateAction@speed:
|
||||||
SelectionShares: 5
|
SelectionShares: 5
|
||||||
Upgrades: speed
|
Upgrades: crate-speed
|
||||||
Notification: 00-i080.aud
|
Notification: 00-i080.aud
|
||||||
|
|
||||||
SROCK01:
|
SROCK01:
|
||||||
|
|||||||
@@ -128,8 +128,7 @@ NAHAND:
|
|||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
Color: E0D048
|
Color: E0D048
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
NAWEAP:
|
NAWEAP:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -187,8 +186,7 @@ NAWEAP:
|
|||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
Color: E0D048
|
Color: E0D048
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
NAHPAD:
|
NAHPAD:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -242,8 +240,7 @@ NAHPAD:
|
|||||||
ReferencePoint: Top
|
ReferencePoint: Top
|
||||||
Color: E0D048
|
Color: E0D048
|
||||||
ZOffset: 256
|
ZOffset: 256
|
||||||
UpgradeTypes: primary
|
RequiresCondition: primary
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
|
|
||||||
NARADR:
|
NARADR:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
|
|||||||
@@ -55,14 +55,11 @@ BIKE:
|
|||||||
MaxHeightDelta: 3
|
MaxHeightDelta: 3
|
||||||
Armament@PRIMARY:
|
Armament@PRIMARY:
|
||||||
Weapon: BikeMissile
|
Weapon: BikeMissile
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: !rank-elite
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
UpgradeMaxAcceptedLevel: 1
|
|
||||||
LocalOffset: -108,-144,360, -108,144,360
|
LocalOffset: -108,-144,360, -108,144,360
|
||||||
Armament@ELITE:
|
Armament@ELITE:
|
||||||
Weapon: HoverMissile
|
Weapon: HoverMissile
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
LocalOffset: -108,-144,360, -108,144,360
|
LocalOffset: -108,-144,360, -108,144,360
|
||||||
AttackFrontal:
|
AttackFrontal:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
@@ -74,12 +71,10 @@ TTNK:
|
|||||||
Cost: 800
|
Cost: 800
|
||||||
Tooltip:
|
Tooltip:
|
||||||
Name: Tick Tank
|
Name: Tick Tank
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: !deployed
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Tooltip@DEPLOYED:
|
Tooltip@DEPLOYED:
|
||||||
Name: Tick Tank (deployed)
|
Name: Tick Tank (deployed)
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Buildable:
|
Buildable:
|
||||||
Queue: Vehicle
|
Queue: Vehicle
|
||||||
BuildPaletteOrder: 60
|
BuildPaletteOrder: 60
|
||||||
@@ -93,20 +88,16 @@ TTNK:
|
|||||||
HP: 350
|
HP: 350
|
||||||
Armor:
|
Armor:
|
||||||
Type: Light
|
Type: Light
|
||||||
UpgradeTypes: undeployed
|
RequiresCondition: undeployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Armament@PRIMARY:
|
Armament@PRIMARY:
|
||||||
Weapon: 90mm
|
Weapon: 90mm
|
||||||
LocalOffset: 288,0,256
|
LocalOffset: 288,0,256
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: !rank-elite
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
UpgradeMaxAcceptedLevel: 1
|
|
||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
Armament@ELITE:
|
Armament@ELITE:
|
||||||
Weapon: 120mmx
|
Weapon: 120mmx
|
||||||
LocalOffset: 288,0,256
|
LocalOffset: 288,0,256
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
WithMuzzleOverlay:
|
WithMuzzleOverlay:
|
||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
@@ -123,16 +114,12 @@ TTNK:
|
|||||||
DeploySound: place2.aud
|
DeploySound: place2.aud
|
||||||
UndeploySound: clicky1.aud
|
UndeploySound: clicky1.aud
|
||||||
WithVoxelBody:
|
WithVoxelBody:
|
||||||
UpgradeTypes: undeployed
|
RequiresCondition: undeployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithSpriteBody@deployed:
|
WithSpriteBody@deployed:
|
||||||
UpgradeTypes: undeployed
|
RequiresCondition: !undeployed
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
AttackFrontal:
|
AttackFrontal:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
UpgradeTypes: undeployed
|
RequiresCondition: undeployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
UpgradeMaxAcceptedLevel: 1
|
|
||||||
Turreted:
|
Turreted:
|
||||||
TurnSpeed: 6
|
TurnSpeed: 6
|
||||||
Turret: deployed
|
Turret: deployed
|
||||||
@@ -141,38 +128,31 @@ TTNK:
|
|||||||
WithVoxelBarrel:
|
WithVoxelBarrel:
|
||||||
Armament: deployed
|
Armament: deployed
|
||||||
LocalOffset: 128, 0, 256
|
LocalOffset: 128, 0, 256
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithVoxelTurret@deployed:
|
WithVoxelTurret@deployed:
|
||||||
Turret: deployed
|
Turret: deployed
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
AttackTurreted@deployed:
|
AttackTurreted@deployed:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
Armaments: deployed
|
Armaments: deployed
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Armament@deployed:
|
Armament@deployed:
|
||||||
Name: deployed
|
Name: deployed
|
||||||
Turret: deployed
|
Turret: deployed
|
||||||
Weapon: 90mm
|
Weapon: 90mm
|
||||||
LocalOffset: 384,0,256
|
LocalOffset: 384,0,256
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: !rank-elite
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
UpgradeMaxAcceptedLevel: 1
|
|
||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
Armament@deployedElite:
|
Armament@deployedElite:
|
||||||
Name: deployed
|
Name: deployed
|
||||||
Turret: deployed
|
Turret: deployed
|
||||||
Weapon: 120mmx
|
Weapon: 120mmx
|
||||||
LocalOffset: 384,0,256
|
LocalOffset: 384,0,256
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
Armor@deployed:
|
Armor@deployed:
|
||||||
Type: Concrete
|
Type: Concrete
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
AutoTarget:
|
AutoTarget:
|
||||||
|
|
||||||
ART2:
|
ART2:
|
||||||
|
|||||||
@@ -15,13 +15,10 @@ E1:
|
|||||||
Speed: 71
|
Speed: 71
|
||||||
Armament@PRIMARY:
|
Armament@PRIMARY:
|
||||||
Weapon: Minigun
|
Weapon: Minigun
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: !rank-elite
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
UpgradeMaxAcceptedLevel: 1
|
|
||||||
Armament@ELITE:
|
Armament@ELITE:
|
||||||
Weapon: M1Carbine
|
Weapon: M1Carbine
|
||||||
UpgradeTypes: eliteweapon
|
RequiresCondition: rank-elite
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
AttackFrontal:
|
AttackFrontal:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
|
|||||||
@@ -116,12 +116,10 @@ LPST:
|
|||||||
Cost: 950
|
Cost: 950
|
||||||
Tooltip:
|
Tooltip:
|
||||||
Name: Mobile Sensor Array
|
Name: Mobile Sensor Array
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: !deployed
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
Tooltip@DEPLOYED:
|
Tooltip@DEPLOYED:
|
||||||
Name: Mobile Sensor Array (deployed)
|
Name: Mobile Sensor Array (deployed)
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Health:
|
Health:
|
||||||
HP: 600
|
HP: 600
|
||||||
Armor:
|
Armor:
|
||||||
@@ -147,14 +145,11 @@ LPST:
|
|||||||
UndeploySound: clicky1.aud
|
UndeploySound: clicky1.aud
|
||||||
WithVoxelBody:
|
WithVoxelBody:
|
||||||
Image: lpst
|
Image: lpst
|
||||||
UpgradeTypes: undeployed
|
RequiresCondition: undeployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
WithSpriteBody@deployed:
|
WithSpriteBody@deployed:
|
||||||
UpgradeTypes: undeployed
|
RequiresCondition: !undeployed
|
||||||
UpgradeMaxEnabledLevel: 0
|
|
||||||
DetectCloaked:
|
DetectCloaked:
|
||||||
UpgradeTypes: deployed
|
RequiresCondition: deployed
|
||||||
UpgradeMinEnabledLevel: 1
|
|
||||||
Range: 18c0
|
Range: 18c0
|
||||||
RenderDetectionCircle:
|
RenderDetectionCircle:
|
||||||
TrailCount: 3
|
TrailCount: 3
|
||||||
|
|||||||
@@ -62,9 +62,10 @@ crate-effects:
|
|||||||
levelup: veteran
|
levelup: veteran
|
||||||
|
|
||||||
rank:
|
rank:
|
||||||
rank: pips
|
veteran: pips
|
||||||
Start: 7
|
Start: 7
|
||||||
Length: 2
|
elite: pips
|
||||||
|
Start: 8
|
||||||
|
|
||||||
mpspawn:
|
mpspawn:
|
||||||
idle:
|
idle:
|
||||||
|
|||||||
Reference in New Issue
Block a user