Merge pull request #12462 from pchote/condition-granters

Upgrades overhaul part 4d: Other condition granters
This commit is contained in:
abcdefg30
2016-12-13 22:28:44 +01:00
committed by GitHub
50 changed files with 657 additions and 517 deletions

View File

@@ -17,7 +17,6 @@ namespace OpenRA.Mods.Common.Activities
{
public class Parachute : Activity
{
readonly UpgradeManager um;
readonly IPositionable pos;
readonly ParachutableInfo para;
readonly WVec fallVector;
@@ -29,7 +28,6 @@ namespace OpenRA.Mods.Common.Activities
public Parachute(Actor self, WPos dropPosition, Actor ignoreActor = null)
{
um = self.TraitOrDefault<UpgradeManager>();
pos = self.TraitOrDefault<IPositionable>();
ignore = ignoreActor;
@@ -44,9 +42,8 @@ namespace OpenRA.Mods.Common.Activities
{
triggered = true;
if (um != null)
foreach (var u in para.ParachuteUpgrade)
um.GrantUpgrade(self, u, this);
foreach (var np in self.TraitsImplementing<INotifyParachute>())
np.OnParachute(self);
// Place the actor and retrieve its visual position (CenterPosition)
pos.SetPosition(self, dropPosition);
@@ -60,12 +57,8 @@ namespace OpenRA.Mods.Common.Activities
var dat = self.World.Map.DistanceAboveTerrain(currentPosition);
pos.SetPosition(self, currentPosition - new WVec(WDist.Zero, WDist.Zero, dat));
if (um != null)
foreach (var u in para.ParachuteUpgrade)
um.RevokeUpgrade(self, u, this);
foreach (var npl in self.TraitsImplementing<INotifyParachuteLanded>())
npl.OnLanded(ignore);
foreach (var np in self.TraitsImplementing<INotifyParachute>())
np.OnLanded(self, ignore);
return NextActivity;
}

View File

@@ -331,7 +331,7 @@
<Compile Include="Traits\GainsExperience.cs" />
<Compile Include="Traits\GivesBounty.cs" />
<Compile Include="Traits\GivesExperience.cs" />
<Compile Include="Traits\GlobalUpgradable.cs" />
<Compile Include="Traits\GrantConditionOnPrerequisite.cs" />
<Compile Include="Traits\Guard.cs" />
<Compile Include="Traits\Guardable.cs" />
<Compile Include="Traits\Harvester.cs" />
@@ -373,7 +373,7 @@
<Compile Include="Traits\Player\ClassicProductionQueue.cs" />
<Compile Include="Traits\Player\ConquestVictoryConditions.cs" />
<Compile Include="Traits\Player\EnemyWatcher.cs" />
<Compile Include="Traits\Player\GlobalUpgradeManager.cs" />
<Compile Include="Traits\Player\GrantConditionOnPrerequisiteManager.cs" />
<Compile Include="Traits\Player\HarvesterAttackNotifier.cs" />
<Compile Include="Traits\Player\MissionObjectives.cs" />
<Compile Include="Traits\Player\PlaceBeacon.cs" />
@@ -490,13 +490,13 @@
<Compile Include="Traits\Transforms.cs" />
<Compile Include="Traits\Turreted.cs" />
<Compile Include="Traits\ProducibleWithLevel.cs" />
<Compile Include="Traits\Upgrades\DeployToUpgrade.cs" />
<Compile Include="Traits\Upgrades\DisableOnUpgrade.cs" />
<Compile Include="Traits\Upgrades\GrantConditionOnDeploy.cs" />
<Compile Include="Traits\Upgrades\DisableOnCondition.cs" />
<Compile Include="Traits\Upgrades\UpgradableTrait.cs" />
<Compile Include="Traits\Upgrades\ProximityExternalCondition.cs" />
<Compile Include="Traits\Upgrades\UpgradeOnDamageState.cs" />
<Compile Include="Traits\Upgrades\UpgradeOnTerrain.cs" />
<Compile Include="Traits\Upgrades\UpgradeOnMovement.cs" />
<Compile Include="Traits\Upgrades\GrantConditionOnDamageState.cs" />
<Compile Include="Traits\Upgrades\GrantConditionOnTerrain.cs" />
<Compile Include="Traits\Upgrades\GrantConditionOnMovement.cs" />
<Compile Include="Traits\Upgrades\UpgradeManager.cs" />
<Compile Include="Traits\Valued.cs" />
<Compile Include="Traits\Voiced.cs" />

View File

@@ -53,12 +53,12 @@ namespace OpenRA.Mods.Common.Traits
[VoiceReference] public readonly string Voice = "Action";
[UpgradeGrantedReference]
[Desc("The upgrades to grant to self while airborne.")]
public readonly string[] AirborneUpgrades = { };
[Desc("The condition to grant to self while airborne.")]
public readonly string AirborneCondition = null;
[UpgradeGrantedReference]
[Desc("The upgrades to grant to self while at cruise altitude.")]
public readonly string[] CruisingUpgrades = { };
[Desc("The condition to grant to self while at cruise altitude.")]
public readonly string CruisingCondition = null;
[Desc("Can the actor hover in place mid-air? If not, then the actor will have to remain in motion (circle around).")]
public readonly bool CanHover = false;
@@ -119,6 +119,8 @@ namespace OpenRA.Mods.Common.Traits
bool airborne;
bool cruising;
bool firstTick = true;
int airborneToken = UpgradeManager.InvalidConditionToken;
int cruisingToken = UpgradeManager.InvalidConditionToken;
bool isMoving;
bool isMovingVertically;
@@ -656,20 +658,20 @@ namespace OpenRA.Mods.Common.Traits
{
if (airborne)
return;
airborne = true;
if (um != null)
foreach (var u in Info.AirborneUpgrades)
um.GrantUpgrade(self, u, this);
if (um != null && !string.IsNullOrEmpty(Info.AirborneCondition) && airborneToken == UpgradeManager.InvalidConditionToken)
airborneToken = um.GrantCondition(self, Info.AirborneCondition);
}
void OnAirborneAltitudeLeft()
{
if (!airborne)
return;
airborne = false;
if (um != null)
foreach (var u in Info.AirborneUpgrades)
um.RevokeUpgrade(self, u, this);
if (um != null && airborneToken != UpgradeManager.InvalidConditionToken)
airborneToken = um.RevokeCondition(self, airborneToken);
}
#endregion
@@ -680,10 +682,10 @@ namespace OpenRA.Mods.Common.Traits
{
if (cruising)
return;
cruising = true;
if (um != null)
foreach (var u in Info.CruisingUpgrades)
um.GrantUpgrade(self, u, this);
if (um != null && !string.IsNullOrEmpty(Info.CruisingCondition) && cruisingToken == UpgradeManager.InvalidConditionToken)
cruisingToken = um.GrantCondition(self, Info.CruisingCondition);
}
void OnCruisingAltitudeLeft()
@@ -691,9 +693,8 @@ namespace OpenRA.Mods.Common.Traits
if (!cruising)
return;
cruising = false;
if (um != null)
foreach (var u in Info.CruisingUpgrades)
um.RevokeUpgrade(self, u, this);
if (um != null && cruisingToken != UpgradeManager.InvalidConditionToken)
cruisingToken = um.RevokeCondition(self, cruisingToken);
}
#endregion

View File

@@ -26,10 +26,11 @@ namespace OpenRA.Mods.Common.Traits
}
[Desc("Used together with ClassicProductionQueue.")]
public class PrimaryBuildingInfo : ITraitInfo, Requires<UpgradeManagerInfo>
public class PrimaryBuildingInfo : ITraitInfo
{
[UpgradeGrantedReference, Desc("The upgrades to grant while the primary building.")]
public readonly string[] Upgrades = { "primary" };
[UpgradeGrantedReference]
[Desc("The condition to grant to self while this is the primary building.")]
public readonly string PrimaryCondition = null;
[Desc("The speech notification to play when selecting a primary building.")]
public readonly string SelectionNotification = "PrimaryBuildingSelected";
@@ -37,25 +38,30 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new PrimaryBuilding(init.Self, this); }
}
public class PrimaryBuilding : IIssueOrder, IResolveOrder
public class PrimaryBuilding : INotifyCreated, IIssueOrder, IResolveOrder
{
readonly PrimaryBuildingInfo info;
readonly UpgradeManager manager;
UpgradeManager um;
int primaryToken = UpgradeManager.InvalidConditionToken;
public bool IsPrimary { get; private set; }
public PrimaryBuilding(Actor self, PrimaryBuildingInfo info)
{
this.info = info;
manager = self.Trait<UpgradeManager>();
}
public IEnumerable<IOrderTargeter> Orders
void INotifyCreated.Created(Actor self)
{
um = self.TraitOrDefault<UpgradeManager>();
}
IEnumerable<IOrderTargeter> IIssueOrder.Orders
{
get { yield return new DeployOrderTargeter("PrimaryProducer", 1); }
}
public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
{
if (order.OrderID == "PrimaryProducer")
return new Order(order.OrderID, self, false);
@@ -63,41 +69,39 @@ namespace OpenRA.Mods.Common.Traits
return null;
}
public void ResolveOrder(Actor self, Order order)
void IResolveOrder.ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "PrimaryProducer")
SetPrimaryProducer(self, !IsPrimary);
}
public void SetPrimaryProducer(Actor self, bool state)
public void SetPrimaryProducer(Actor self, bool isPrimary)
{
if (state == false)
IsPrimary = isPrimary;
if (isPrimary)
{
IsPrimary = false;
foreach (var up in info.Upgrades)
manager.RevokeUpgrade(self, up, this);
return;
// Cancel existing primaries
// TODO: THIS IS SHIT
foreach (var p in self.Info.TraitInfo<ProductionInfo>().Produces)
{
foreach (var b in self.World
.ActorsWithTrait<PrimaryBuilding>()
.Where(a =>
a.Actor != self &&
a.Actor.Owner == self.Owner &&
a.Trait.IsPrimary &&
a.Actor.Info.TraitInfo<ProductionInfo>().Produces.Contains(p)))
b.Trait.SetPrimaryProducer(b.Actor, false);
}
if (um != null && primaryToken == UpgradeManager.InvalidConditionToken && !string.IsNullOrEmpty(info.PrimaryCondition))
primaryToken = um.GrantCondition(self, info.PrimaryCondition);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.SelectionNotification, self.Owner.Faction.InternalName);
}
// TODO: THIS IS SHIT
// Cancel existing primaries
foreach (var p in self.Info.TraitInfo<ProductionInfo>().Produces)
{
var productionType = p; // benign closure hazard
foreach (var b in self.World
.ActorsWithTrait<PrimaryBuilding>()
.Where(a =>
a.Actor.Owner == self.Owner &&
a.Trait.IsPrimary &&
a.Actor.Info.TraitInfo<ProductionInfo>().Produces.Contains(productionType)))
b.Trait.SetPrimaryProducer(b.Actor, false);
}
IsPrimary = true;
foreach (var up in info.Upgrades)
manager.GrantUpgrade(self, up, this);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.SelectionNotification, self.Owner.Faction.InternalName);
else if (primaryToken != UpgradeManager.InvalidConditionToken)
primaryToken = um.RevokeCondition(self, primaryToken);
}
}
}

View File

@@ -54,8 +54,8 @@ namespace OpenRA.Mods.Common.Traits
public readonly HashSet<string> CloakTypes = new HashSet<string> { "Cloak" };
[UpgradeGrantedReference]
[Desc("The upgrades to grant to self while cloaked.")]
public readonly string[] WhileCloakedUpgrades = { };
[Desc("The condition to grant to self while cloaked.")]
public readonly string CloakedCondition = null;
public override object Create(ActorInitializer init) { return new Cloak(this); }
}
@@ -70,6 +70,7 @@ namespace OpenRA.Mods.Common.Traits
CPos? lastPos;
bool wasCloaked = false;
int cloakedToken = UpgradeManager.InvalidConditionToken;
public Cloak(CloakInfo info)
: base(info)
@@ -81,12 +82,11 @@ namespace OpenRA.Mods.Common.Traits
{
upgradeManager = self.TraitOrDefault<UpgradeManager>();
// The upgrade manager exists, but may not have finished being created yet.
// We'll defer the upgrades until the end of the tick, at which point it will be ready.
if (Cloaked)
{
wasCloaked = true;
self.World.AddFrameEndTask(_ => GrantUpgrades(self));
if (upgradeManager != null && cloakedToken == UpgradeManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.CloakedCondition))
cloakedToken = upgradeManager.GrantCondition(self, Info.CloakedCondition);
}
}
@@ -144,13 +144,17 @@ namespace OpenRA.Mods.Common.Traits
var isCloaked = Cloaked;
if (isCloaked && !wasCloaked)
{
GrantUpgrades(self);
if (upgradeManager != null && cloakedToken == UpgradeManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.CloakedCondition))
cloakedToken = upgradeManager.GrantCondition(self, Info.CloakedCondition);
if (!self.TraitsImplementing<Cloak>().Any(a => a != this && a.Cloaked))
Game.Sound.Play(Info.CloakSound, self.CenterPosition);
}
else if (!isCloaked && wasCloaked)
{
RevokeUpgrades(self);
if (cloakedToken != UpgradeManager.InvalidConditionToken)
cloakedToken = upgradeManager.RevokeCondition(self, cloakedToken);
if (!self.TraitsImplementing<Cloak>().Any(a => a != this && a.Cloaked))
Game.Sound.Play(Info.UncloakSound, self.CenterPosition);
}
@@ -176,20 +180,6 @@ namespace OpenRA.Mods.Common.Traits
return color;
}
void GrantUpgrades(Actor self)
{
if (upgradeManager != null)
foreach (var u in Info.WhileCloakedUpgrades)
upgradeManager.GrantUpgrade(self, u, this);
}
void RevokeUpgrades(Actor self)
{
if (upgradeManager != null)
foreach (var u in Info.WhileCloakedUpgrades)
upgradeManager.RevokeUpgrade(self, u, this);
}
void INotifyHarvesterAction.MovingToResources(Actor self, CPos targetCell, Activity next) { }
void INotifyHarvesterAction.MovingToRefinery(Actor self, CPos targetCell, Activity next) { }

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits
}
class Crate : ITick, IPositionable, ICrushable, ISync,
INotifyParachuteLanded, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyCrushed
INotifyParachute, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyCrushed
{
readonly Actor self;
readonly CrateInfo info;
@@ -70,7 +70,8 @@ namespace OpenRA.Mods.Common.Traits
OnCrushInner(crusher);
}
void INotifyParachuteLanded.OnLanded(Actor ignore)
void INotifyParachute.OnParachute(Actor self) { }
void INotifyParachute.OnLanded(Actor self, Actor ignore)
{
// Check whether the crate landed on anything
var landedOn = self.World.ActorMap.GetActorsAt(self.Location)

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Effects;
using OpenRA.Primitives;
using OpenRA.Traits;
@@ -18,13 +19,13 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("This actor's experience increases when it has killed a GivesExperience actor.")]
public class GainsExperienceInfo : ITraitInfo, Requires<ValuedInfo>, Requires<UpgradeManagerInfo>
public class GainsExperienceInfo : ITraitInfo, Requires<ValuedInfo>
{
[FieldLoader.Require]
[Desc("Upgrades to grant at each level.",
[Desc("Condition to grant at each level.",
"Key is the XP requirements for each level as a percentage of our own value.",
"Value is a list of the upgrade types to grant")]
public readonly Dictionary<int, string[]> Upgrades = null;
public readonly Dictionary<int, string> Conditions = null;
[Desc("Palette for the level up sprite.")]
[PaletteReference] public readonly string LevelUpPalette = "effect";
@@ -35,13 +36,14 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new GainsExperience(init, this); }
}
public class GainsExperience : ISync, IResolveOrder
public class GainsExperience : INotifyCreated, ISync, IResolveOrder
{
readonly Actor self;
readonly GainsExperienceInfo info;
readonly UpgradeManager um;
readonly int initialExperience;
readonly List<Pair<int, string[]>> nextLevel = new List<Pair<int, string[]>>();
readonly List<Pair<int, string>> nextLevel = new List<Pair<int, string>>();
UpgradeManager um;
// Stored as a percentage of our value
[Sync] int experience = 0;
@@ -54,16 +56,20 @@ namespace OpenRA.Mods.Common.Traits
self = init.Self;
this.info = info;
MaxLevel = info.Upgrades.Count;
MaxLevel = info.Conditions.Count;
var cost = self.Info.TraitInfo<ValuedInfo>().Cost;
foreach (var kv in info.Upgrades)
foreach (var kv in info.Conditions)
nextLevel.Add(Pair.New(kv.Key * cost, kv.Value));
if (init.Contains<ExperienceInit>())
GiveExperience(init.Get<ExperienceInit, int>(), info.SuppressLevelupAnimation);
initialExperience = init.Get<ExperienceInit, int>();
}
um = self.Trait<UpgradeManager>();
void INotifyCreated.Created(Actor self)
{
um = self.TraitOrDefault<UpgradeManager>();
if (initialExperience > 0)
GiveExperience(initialExperience, info.SuppressLevelupAnimation);
}
public bool CanGainLevel { get { return Level < MaxLevel; } }
@@ -76,17 +82,18 @@ namespace OpenRA.Mods.Common.Traits
public void GiveExperience(int amount, bool silent = false)
{
if (amount < 0)
throw new ArgumentException("Revoking experience is not implemented.", "amount");
experience += amount;
while (Level < MaxLevel && experience >= nextLevel[Level].First)
{
var upgrades = nextLevel[Level].Second;
if (um != null)
um.GrantCondition(self, nextLevel[Level].Second);
Level++;
foreach (var u in upgrades)
um.GrantUpgrade(self, u, this);
if (!silent)
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "LevelUp", self.Owner.Faction.InternalName);

View File

@@ -1,72 +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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Grants upgrades to the actor this is attached to when prerequisites are available.")]
public class GlobalUpgradableInfo : ITraitInfo, Requires<UpgradeManagerInfo>
{
[UpgradeGrantedReference, FieldLoader.Require]
[Desc("List of upgrades to apply.")]
public readonly string[] Upgrades = { };
[FieldLoader.Require]
[Desc("List of required prerequisites.")]
public readonly string[] Prerequisites = { };
public object Create(ActorInitializer init) { return new GlobalUpgradable(init.Self, this); }
}
public class GlobalUpgradable : INotifyAddedToWorld, INotifyRemovedFromWorld
{
readonly GlobalUpgradableInfo info;
readonly GlobalUpgradeManager globalManager;
readonly UpgradeManager manager;
bool wasAvailable;
public GlobalUpgradable(Actor self, GlobalUpgradableInfo info)
{
this.info = info;
globalManager = self.Owner.PlayerActor.Trait<GlobalUpgradeManager>();
manager = self.Trait<UpgradeManager>();
}
public void AddedToWorld(Actor self)
{
if (info.Prerequisites.Any())
globalManager.Register(self, this, info.Prerequisites);
}
public void RemovedFromWorld(Actor self)
{
if (info.Prerequisites.Any())
globalManager.Unregister(self, this, info.Prerequisites);
}
public void PrerequisitesUpdated(Actor self, bool available)
{
if (available == wasAvailable)
return;
if (available)
foreach (var u in info.Upgrades)
manager.GrantUpgrade(self, u, this);
else
foreach (var u in info.Upgrades)
manager.RevokeUpgrade(self, u, this);
wasAvailable = available;
}
}
}

View File

@@ -0,0 +1,78 @@
#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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Grants a condition to the actor this is attached to when prerequisites are available.")]
public class GrantConditionOnPrerequisiteInfo : ITraitInfo
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("The condition to grant.")]
public readonly string Condition = null;
[FieldLoader.Require]
[Desc("List of required prerequisites.")]
public readonly string[] Prerequisites = { };
public object Create(ActorInitializer init) { return new GrantConditionOnPrerequisite(init.Self, this); }
}
public class GrantConditionOnPrerequisite : INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld
{
readonly GrantConditionOnPrerequisiteInfo info;
readonly GrantConditionOnPrerequisiteManager globalManager;
UpgradeManager manager;
int conditionToken = UpgradeManager.InvalidConditionToken;
bool wasAvailable;
public GrantConditionOnPrerequisite(Actor self, GrantConditionOnPrerequisiteInfo info)
{
this.info = info;
globalManager = self.Owner.PlayerActor.Trait<GrantConditionOnPrerequisiteManager>();
}
void INotifyCreated.Created(Actor self)
{
manager = self.TraitOrDefault<UpgradeManager>();
}
void INotifyAddedToWorld.AddedToWorld(Actor self)
{
if (info.Prerequisites.Any())
globalManager.Register(self, this, info.Prerequisites);
}
void INotifyRemovedFromWorld.RemovedFromWorld(Actor self)
{
if (info.Prerequisites.Any())
globalManager.Unregister(self, this, info.Prerequisites);
}
public void PrerequisitesUpdated(Actor self, bool available)
{
if (available == wasAvailable || manager == null)
return;
if (available && conditionToken == UpgradeManager.InvalidConditionToken)
conditionToken = manager.GrantCondition(self, info.Condition);
else if (!available && conditionToken != UpgradeManager.InvalidConditionToken)
conditionToken = manager.RevokeCondition(self, conditionToken);
wasAvailable = available;
}
}
}

View File

@@ -39,27 +39,42 @@ namespace OpenRA.Mods.Common.Traits
public readonly int FallRate = 13;
[UpgradeGrantedReference]
[Desc("Upgrade to grant to this actor when parachuting. Normally used to render the parachute using the WithParachute trait.")]
public readonly string[] ParachuteUpgrade = { "parachute" };
[Desc("The condition to grant to self while parachuting.")]
public readonly string ParachutingCondition = null;
public object Create(ActorInitializer init) { return new Parachutable(init, this); }
public object Create(ActorInitializer init) { return new Parachutable(init.Self, this); }
}
class Parachutable : INotifyParachuteLanded
class Parachutable : INotifyCreated, INotifyParachute
{
readonly Actor self;
readonly ParachutableInfo info;
readonly IPositionable positionable;
public Parachutable(ActorInitializer init, ParachutableInfo info)
UpgradeManager um;
int parachutingToken = UpgradeManager.InvalidConditionToken;
public Parachutable(Actor self, ParachutableInfo info)
{
self = init.Self;
this.info = info;
positionable = self.Trait<IPositionable>();
}
void INotifyParachuteLanded.OnLanded(Actor ignore)
void INotifyCreated.Created(Actor self)
{
um = self.TraitOrDefault<UpgradeManager>();
}
void INotifyParachute.OnParachute(Actor self)
{
if (um != null && parachutingToken == UpgradeManager.InvalidConditionToken && !string.IsNullOrEmpty(info.ParachutingCondition))
parachutingToken = um.GrantCondition(self, info.ParachutingCondition);
}
void INotifyParachute.OnLanded(Actor self, Actor ignore)
{
if (parachutingToken != UpgradeManager.InvalidConditionToken)
parachutingToken = um.RevokeCondition(self, parachutingToken);
if (!info.KilledOnImpassableTerrain)
return;

View File

@@ -17,18 +17,18 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Attach this to the player actor.")]
public class GlobalUpgradeManagerInfo : ITraitInfo, Requires<TechTreeInfo>
public class GrantConditionOnPrerequisiteManagerInfo : ITraitInfo, Requires<TechTreeInfo>
{
public object Create(ActorInitializer init) { return new GlobalUpgradeManager(init); }
public object Create(ActorInitializer init) { return new GrantConditionOnPrerequisiteManager(init); }
}
public class GlobalUpgradeManager : ITechTreeElement
public class GrantConditionOnPrerequisiteManager : ITechTreeElement
{
readonly Actor self;
readonly Dictionary<string, List<Pair<Actor, GlobalUpgradable>>> upgradables = new Dictionary<string, List<Pair<Actor, GlobalUpgradable>>>();
readonly Dictionary<string, List<Pair<Actor, GrantConditionOnPrerequisite>>> upgradables = new Dictionary<string, List<Pair<Actor, GrantConditionOnPrerequisite>>>();
readonly TechTree techTree;
public GlobalUpgradeManager(ActorInitializer init)
public GrantConditionOnPrerequisiteManager(ActorInitializer init)
{
self = init.Self;
techTree = self.Trait<TechTree>();
@@ -39,12 +39,12 @@ namespace OpenRA.Mods.Common.Traits
return "upgrade_" + string.Join("_", prerequisites.OrderBy(a => a));
}
public void Register(Actor actor, GlobalUpgradable u, string[] prerequisites)
public void Register(Actor actor, GrantConditionOnPrerequisite u, string[] prerequisites)
{
var key = MakeKey(prerequisites);
if (!upgradables.ContainsKey(key))
{
upgradables.Add(key, new List<Pair<Actor, GlobalUpgradable>>());
upgradables.Add(key, new List<Pair<Actor, GrantConditionOnPrerequisite>>());
techTree.Add(key, prerequisites, 0, this);
}
@@ -54,7 +54,7 @@ namespace OpenRA.Mods.Common.Traits
u.PrerequisitesUpdated(actor, techTree.HasPrerequisites(prerequisites));
}
public void Unregister(Actor actor, GlobalUpgradable u, string[] prerequisites)
public void Unregister(Actor actor, GrantConditionOnPrerequisite u, string[] prerequisites)
{
var key = MakeKey(prerequisites);
var list = upgradables[key];
@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits
public void PrerequisitesAvailable(string key)
{
List<Pair<Actor, GlobalUpgradable>> list;
List<Pair<Actor, GrantConditionOnPrerequisite>> list;
if (!upgradables.TryGetValue(key, out list))
return;
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Traits
public void PrerequisitesUnavailable(string key)
{
List<Pair<Actor, GlobalUpgradable>> list;
List<Pair<Actor, GrantConditionOnPrerequisite>> list;
if (!upgradables.TryGetValue(key, out list))
return;

View File

@@ -14,13 +14,15 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class PluggableInfo : ITraitInfo, Requires<UpgradeManagerInfo>, UsesInit<PlugsInit>
public class PluggableInfo : ITraitInfo, UsesInit<PlugsInit>
{
[Desc("Footprint cell offset where a plug can be placed.")]
public readonly CVec Offset = CVec.Zero;
[FieldLoader.Require, Desc("Upgrades to grant for each accepted plug type.")]
public readonly Dictionary<string, string[]> Upgrades = null;
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("Conditions to grant for each accepted plug type.")]
public readonly Dictionary<string, string> Conditions = null;
public object Create(ActorInitializer init) { return new Pluggable(init, this); }
}
@@ -30,14 +32,14 @@ namespace OpenRA.Mods.Common.Traits
public readonly PluggableInfo Info;
readonly string initialPlug;
readonly UpgradeManager upgradeManager;
UpgradeManager upgradeManager;
int conditionToken = UpgradeManager.InvalidConditionToken;
string active;
public Pluggable(ActorInitializer init, PluggableInfo info)
{
Info = info;
upgradeManager = init.Self.Trait<UpgradeManager>();
var plugInit = init.Contains<PlugsInit>() ? init.Get<PlugsInit, Dictionary<CVec, string>>() : new Dictionary<CVec, string>();
if (plugInit.ContainsKey(Info.Offset))
@@ -46,24 +48,24 @@ namespace OpenRA.Mods.Common.Traits
public void Created(Actor self)
{
upgradeManager = self.TraitOrDefault<UpgradeManager>();
if (!string.IsNullOrEmpty(initialPlug))
EnablePlug(self, initialPlug);
}
public bool AcceptsPlug(Actor self, string type)
{
return active == null && Info.Upgrades.ContainsKey(type);
return active == null && Info.Conditions.ContainsKey(type);
}
public void EnablePlug(Actor self, string type)
{
string[] upgrades;
if (!Info.Upgrades.TryGetValue(type, out upgrades))
string condition;
if (!Info.Conditions.TryGetValue(type, out condition))
return;
foreach (var u in upgrades)
upgradeManager.GrantUpgrade(self, u, this);
conditionToken = upgradeManager.GrantCondition(self, condition);
active = type;
}
@@ -72,8 +74,10 @@ namespace OpenRA.Mods.Common.Traits
if (type != active)
return;
foreach (var u in Info.Upgrades[type])
upgradeManager.RevokeUpgrade(self, u, this);
if (conditionToken != UpgradeManager.InvalidConditionToken)
conditionToken = upgradeManager.RevokeCondition(self, conditionToken);
active = null;
}
}

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
class WithCrateBody : INotifyParachuteLanded, INotifyAddedToWorld
class WithCrateBody : INotifyParachute, INotifyAddedToWorld
{
readonly Actor self;
readonly Animation anim;
@@ -70,7 +70,9 @@ namespace OpenRA.Mods.Common.Traits.Render
PlaySequence();
}
void INotifyParachuteLanded.OnLanded(Actor ignore)
void INotifyParachute.OnParachute(Actor self) { }
void INotifyParachute.OnLanded(Actor self, Actor ignore)
{
PlaySequence();
}

View File

@@ -14,14 +14,14 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Disable the actor when this trait is enabled by an upgrade.")]
public class DisableOnUpgradeInfo : UpgradableTraitInfo
public class DisableOnConditionInfo : UpgradableTraitInfo
{
public override object Create(ActorInitializer init) { return new DisableOnUpgrade(this); }
public override object Create(ActorInitializer init) { return new DisableOnCondition(this); }
}
public class DisableOnUpgrade : UpgradableTrait<DisableOnUpgradeInfo>, IDisable
public class DisableOnCondition : UpgradableTrait<DisableOnConditionInfo>, IDisable
{
public DisableOnUpgrade(DisableOnUpgradeInfo info)
public DisableOnCondition(DisableOnConditionInfo info)
: base(info) { }
public bool Disabled { get { return !IsTraitDisabled; } }

View File

@@ -14,11 +14,12 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Applies an upgrade to the actor at specified damage states.")]
public class UpgradeOnDamageStateInfo : ITraitInfo, Requires<UpgradeManagerInfo>, Requires<HealthInfo>
public class GrantConditionOnDamageStateInfo : ITraitInfo, Requires<HealthInfo>
{
[UpgradeGrantedReference, FieldLoader.Require]
[Desc("The upgrades to grant.")]
public readonly string[] Upgrades = { };
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;
[Desc("Play a random sound from this list when enabled.")]
public readonly string[] EnabledSounds = { };
@@ -29,59 +30,57 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Levels of damage at which to grant upgrades.")]
public readonly DamageState ValidDamageStates = DamageState.Heavy | DamageState.Critical;
[Desc("Are upgrades irrevocable once the conditions have been met?")]
[Desc("Is the condition irrevocable once it has been activated?")]
public readonly bool GrantPermanently = false;
public object Create(ActorInitializer init) { return new UpgradeOnDamageState(init.Self, this); }
public object Create(ActorInitializer init) { return new GrantConditionOnDamageState(init.Self, this); }
}
public class UpgradeOnDamageState : INotifyDamageStateChanged, INotifyCreated
public class GrantConditionOnDamageState : INotifyDamageStateChanged, INotifyCreated
{
readonly UpgradeOnDamageStateInfo info;
readonly UpgradeManager um;
readonly GrantConditionOnDamageStateInfo info;
readonly Health health;
bool granted;
public UpgradeOnDamageState(Actor self, UpgradeOnDamageStateInfo info)
UpgradeManager manager;
int conditionToken = UpgradeManager.InvalidConditionToken;
public GrantConditionOnDamageState(Actor self, GrantConditionOnDamageStateInfo info)
{
this.info = info;
um = self.Trait<UpgradeManager>();
health = self.Trait<Health>();
}
void INotifyCreated.Created(Actor self)
{
manager = self.TraitOrDefault<UpgradeManager>();
GrantUpgradeOnValidDamageState(self, health.DamageState);
}
void GrantUpgradeOnValidDamageState(Actor self, DamageState state)
{
if (!info.ValidDamageStates.HasFlag(state))
if (!info.ValidDamageStates.HasFlag(state) || conditionToken != UpgradeManager.InvalidConditionToken)
return;
granted = true;
var rand = Game.CosmeticRandom;
var sound = info.EnabledSounds.RandomOrDefault(rand);
conditionToken = manager.GrantCondition(self, info.Condition);
var sound = info.EnabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(sound, self.CenterPosition);
foreach (var u in info.Upgrades)
um.GrantUpgrade(self, u, this);
}
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
if (granted && info.GrantPermanently)
var granted = conditionToken != UpgradeManager.InvalidConditionToken;
if ((granted && info.GrantPermanently) || manager == null)
return;
if (!granted && !info.ValidDamageStates.HasFlag(e.PreviousDamageState))
GrantUpgradeOnValidDamageState(self, health.DamageState);
else if (granted && !info.ValidDamageStates.HasFlag(e.DamageState) && info.ValidDamageStates.HasFlag(e.PreviousDamageState))
{
granted = false;
var rand = Game.CosmeticRandom;
var sound = info.DisabledSounds.RandomOrDefault(rand);
conditionToken = manager.RevokeCondition(self, conditionToken);
var sound = info.DisabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(sound, self.CenterPosition);
foreach (var u in info.Upgrades)
um.RevokeUpgrade(self, u, this);
}
}
}

View File

@@ -19,15 +19,15 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class DeployToUpgradeInfo : ITraitInfo, Requires<UpgradeManagerInfo>
public class GrantConditionOnDeployInfo : ITraitInfo
{
[UpgradeGrantedReference]
[Desc("The upgrades to grant while the actor is undeployed.")]
public readonly string[] UndeployedUpgrades = { };
[Desc("The condition to grant while the actor is undeployed.")]
public readonly string UndeployedCondition = null;
[UpgradeGrantedReference, FieldLoader.Require]
[Desc("The upgrades to grant after deploying and revoke before undeploying.")]
public readonly string[] DeployedUpgrades = { };
[Desc("The condition to grant after deploying and revoke before undeploying.")]
public readonly string DeployedCondition = null;
[Desc("The terrain types that this actor can deploy on to receive these upgrades. " +
"Leave empty to allow any.")]
@@ -57,27 +57,28 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Can this actor undeploy?")]
public readonly bool CanUndeploy = true;
public object Create(ActorInitializer init) { return new DeployToUpgrade(init, this); }
public object Create(ActorInitializer init) { return new GrantConditionOnDeploy(init, this); }
}
public enum DeployState { Undeployed, Deploying, Deployed, Undeploying }
public class DeployToUpgrade : IResolveOrder, IIssueOrder, INotifyCreated
public class GrantConditionOnDeploy : IResolveOrder, IIssueOrder, INotifyCreated
{
readonly Actor self;
readonly DeployToUpgradeInfo info;
readonly UpgradeManager manager;
readonly GrantConditionOnDeployInfo info;
readonly bool checkTerrainType;
readonly bool canTurn;
readonly Lazy<WithSpriteBody> body;
DeployState deployState;
UpgradeManager manager;
int deployedToken = UpgradeManager.InvalidConditionToken;
int undeployedToken = UpgradeManager.InvalidConditionToken;
public DeployToUpgrade(ActorInitializer init, DeployToUpgradeInfo info)
public GrantConditionOnDeploy(ActorInitializer init, GrantConditionOnDeployInfo info)
{
self = init.Self;
this.info = info;
manager = self.Trait<UpgradeManager>();
checkTerrainType = info.AllowedTerrainTypes.Count > 0;
canTurn = self.Info.HasTraitInfo<IFacingInfo>();
body = Exts.Lazy(self.TraitOrDefault<WithSpriteBody>);
@@ -87,6 +88,8 @@ namespace OpenRA.Mods.Common.Traits
public void Created(Actor self)
{
manager = self.TraitOrDefault<UpgradeManager>();
switch (deployState)
{
case DeployState.Undeployed:
@@ -239,32 +242,32 @@ namespace OpenRA.Mods.Common.Traits
void OnDeployStarted()
{
foreach (var up in info.UndeployedUpgrades)
manager.RevokeUpgrade(self, up, this);
if (undeployedToken != UpgradeManager.InvalidConditionToken)
undeployedToken = manager.RevokeCondition(self, undeployedToken);
deployState = DeployState.Deploying;
}
void OnDeployCompleted()
{
foreach (var up in info.DeployedUpgrades)
manager.GrantUpgrade(self, up, this);
if (manager != null && !string.IsNullOrEmpty(info.DeployedCondition) && deployedToken == UpgradeManager.InvalidConditionToken)
deployedToken = manager.GrantCondition(self, info.DeployedCondition);
deployState = DeployState.Deployed;
}
void OnUndeployStarted()
{
foreach (var up in info.DeployedUpgrades)
manager.RevokeUpgrade(self, up, this);
if (deployedToken != UpgradeManager.InvalidConditionToken)
deployedToken = manager.RevokeCondition(self, deployedToken);
deployState = DeployState.Deploying;
}
void OnUndeployCompleted()
{
foreach (var up in info.UndeployedUpgrades)
manager.GrantUpgrade(self, up, this);
if (manager != null && !string.IsNullOrEmpty(info.UndeployedCondition) && undeployedToken == UpgradeManager.InvalidConditionToken)
undeployedToken = manager.GrantCondition(self, info.UndeployedCondition);
deployState = DeployState.Undeployed;
}

View File

@@ -0,0 +1,62 @@
#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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class GrantConditionOnMovementInfo : UpgradableTraitInfo, Requires<IMoveInfo>
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;
[Desc("Apply upgrades on straight vertical movement as well.")]
public readonly bool ConsiderVerticalMovement = false;
public override object Create(ActorInitializer init) { return new GrantConditionOnMovement(init.Self, this); }
}
public class GrantConditionOnMovement : UpgradableTrait<GrantConditionOnMovementInfo>, ITick
{
readonly IMove movement;
UpgradeManager manager;
int conditionToken = UpgradeManager.InvalidConditionToken;
public GrantConditionOnMovement(Actor self, GrantConditionOnMovementInfo info)
: base(info)
{
movement = self.Trait<IMove>();
}
protected override void Created(Actor self)
{
manager = self.TraitOrDefault<UpgradeManager>();
base.Created(self);
}
void ITick.Tick(Actor self)
{
if (manager == null)
return;
var isMovingVertically = Info.ConsiderVerticalMovement ? movement.IsMovingVertically : false;
var isMoving = !IsTraitDisabled && !self.IsDead && (movement.IsMoving || isMovingVertically);
if (isMoving && conditionToken == UpgradeManager.InvalidConditionToken)
conditionToken = manager.GrantCondition(self, Info.Condition);
else if (!isMoving && conditionToken != UpgradeManager.InvalidConditionToken)
conditionToken = manager.RevokeCondition(self, conditionToken);
}
}
}

View File

@@ -0,0 +1,67 @@
#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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class GrantConditionOnTerrainInfo : ITraitInfo
{
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("Condition to grant.")]
public readonly string Condition = null;
[FieldLoader.Require]
[Desc("Terrain names to trigger the upgrade.")]
public readonly string[] TerrainTypes = { };
public object Create(ActorInitializer init) { return new GrantConditionOnTerrain(init, this); }
}
public class GrantConditionOnTerrain : INotifyCreated, ITick
{
readonly GrantConditionOnTerrainInfo info;
UpgradeManager manager;
int conditionToken = UpgradeManager.InvalidConditionToken;
string previousTerrain;
public GrantConditionOnTerrain(ActorInitializer init, GrantConditionOnTerrainInfo info)
{
this.info = info;
}
void INotifyCreated.Created(Actor self)
{
manager = self.TraitOrDefault<UpgradeManager>();
}
public void Tick(Actor self)
{
if (manager == null)
return;
var currentTerrain = self.World.Map.GetTerrainInfo(self.Location).Type;
var wantsGranted = info.TerrainTypes.Contains(currentTerrain);
if (currentTerrain != previousTerrain)
{
if (wantsGranted && conditionToken == UpgradeManager.InvalidConditionToken)
conditionToken = manager.GrantCondition(self, info.Condition);
else if (!wantsGranted && conditionToken != UpgradeManager.InvalidConditionToken)
conditionToken = manager.RevokeCondition(self, conditionToken);
}
previousTerrain = currentTerrain;
}
}
}

View File

@@ -1,75 +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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class UpgradeOnMovementInfo : UpgradableTraitInfo, Requires<UpgradeManagerInfo>, Requires<IMoveInfo>
{
[UpgradeGrantedReference, FieldLoader.Require]
[Desc("The upgrades to grant.")]
public readonly string[] Upgrades = { };
[Desc("Apply upgrades on straight vertical movement as well.")]
public readonly bool ConsiderVerticalMovement = false;
public override object Create(ActorInitializer init) { return new UpgradeOnMovement(init.Self, this); }
}
public class UpgradeOnMovement : UpgradableTrait<UpgradeOnMovementInfo>, ITick
{
readonly UpgradeManager manager;
readonly IMove movement;
bool granted;
public UpgradeOnMovement(Actor self, UpgradeOnMovementInfo info)
: base(info)
{
manager = self.Trait<UpgradeManager>();
movement = self.Trait<IMove>();
}
void Revoke(Actor self)
{
if (!granted)
return;
foreach (var up in Info.Upgrades)
manager.RevokeUpgrade(self, up, this);
granted = false;
}
void ITick.Tick(Actor self)
{
if (IsTraitDisabled)
{
Revoke(self);
return;
}
var isMovingVertically = Info.ConsiderVerticalMovement ? movement.IsMovingVertically : false;
var isMoving = !self.IsDead && (movement.IsMoving || isMovingVertically);
if (isMoving && !granted)
{
foreach (var up in Info.Upgrades)
manager.GrantUpgrade(self, up, this);
granted = true;
}
else if (!isMoving)
Revoke(self);
}
}
}

View File

@@ -1,69 +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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class UpgradeOnTerrainInfo : ITraitInfo, Requires<UpgradeManagerInfo>
{
[UpgradeGrantedReference]
public readonly string[] Upgrades = { "terrain" };
[Desc("Terrain names to trigger the upgrade.")]
public readonly string[] TerrainTypes = { };
public object Create(ActorInitializer init) { return new UpgradeOnTerrain(init, this); }
}
public class UpgradeOnTerrain : ITick
{
readonly Actor self;
readonly UpgradeOnTerrainInfo info;
readonly UpgradeManager manager;
bool granted;
string previousTerrain;
public UpgradeOnTerrain(ActorInitializer init, UpgradeOnTerrainInfo info)
{
self = init.Self;
this.info = info;
manager = self.Trait<UpgradeManager>();
}
public void Tick(Actor self)
{
var currentTerrain = self.World.Map.GetTerrainInfo(self.Location).Type;
var wantsGranted = info.TerrainTypes.Contains(currentTerrain);
if (currentTerrain != previousTerrain)
{
if (wantsGranted && !granted)
{
foreach (var up in info.Upgrades)
manager.GrantUpgrade(self, up, this);
granted = true;
}
else if (!wantsGranted && granted)
{
foreach (var up in info.Upgrades)
manager.RevokeUpgrade(self, up, this);
granted = false;
}
}
previousTerrain = currentTerrain;
}
}
}

View File

@@ -87,7 +87,7 @@ namespace OpenRA.Mods.Common.Traits
public interface INotifyOtherProduction { void UnitProducedByOther(Actor self, Actor producer, Actor produced); }
public interface INotifyDelivery { void IncomingDelivery(Actor self); void Delivered(Actor self); }
public interface INotifyDocking { void Docked(Actor self, Actor harvester); void Undocked(Actor self, Actor harvester); }
public interface INotifyParachuteLanded { void OnLanded(Actor ignore); }
public interface INotifyParachute { void OnParachute(Actor self); void OnLanded(Actor self, Actor ignore); }
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); }
public interface INotifyDiscovered { void OnDiscovered(Actor self, Player discoverer, bool playNotification); }
public interface IRenderActorPreviewInfo : ITraitInfo { IEnumerable<IActorPreview> RenderPreview(ActorPreviewInitializer init); }

View File

@@ -586,6 +586,115 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
if (engineVersion < 20161213)
{
if (node.Key == "Aircraft")
{
ConvertUpgradesToCondition(parent, node, "AirborneUpgrades", "AirborneCondition");
ConvertUpgradesToCondition(parent, node, "CruisingUpgrades", "CruisingCondition");
}
if (node.Key.StartsWith("Cloak", StringComparison.Ordinal))
ConvertUpgradesToCondition(parent, node, "WhileCloakedUpgrades", "CloakedCondition");
if (node.Key == "Disguise")
{
ConvertUpgradesToCondition(parent, node, "Upgrades", "DisguisedCondition");
if (!node.Value.Nodes.Any(n => n.Key == "DisguisedCondition"))
node.Value.Nodes.Add(new MiniYamlNode("DisguisedCondition", "disguise"));
}
if (node.Key == "Parachutable")
{
ConvertUpgradesToCondition(parent, node, "ParachuteUpgrade", "ParachutingCondition");
if (!node.Value.Nodes.Any(n => n.Key == "ParachutingCondition"))
node.Value.Nodes.Add(new MiniYamlNode("ParachutingCondition", "parachute"));
}
if (node.Key == "PrimaryBuilding")
{
ConvertUpgradesToCondition(parent, node, "Upgrades", "PrimaryCondition");
if (!node.Value.Nodes.Any(n => n.Key == "PrimaryCondition"))
node.Value.Nodes.Add(new MiniYamlNode("PrimaryCondition", "primary"));
}
if (node.Key.StartsWith("UpgradeOnDamageState", StringComparison.Ordinal))
{
RenameNodeKey(node, "GrantConditionOnDamageState");
ConvertUpgradesToCondition(parent, node, "Upgrades", "Condition");
}
if (node.Key.StartsWith("UpgradeOnMovement", StringComparison.Ordinal))
{
RenameNodeKey(node, "GrantConditionOnMovement");
ConvertUpgradesToCondition(parent, node, "Upgrades", "Condition");
}
if (node.Key.StartsWith("UpgradeOnTerrain", StringComparison.Ordinal))
{
RenameNodeKey(node, "GrantConditionOnTerrain");
ConvertUpgradesToCondition(parent, node, "Upgrades", "Condition");
if (!node.Value.Nodes.Any(n => n.Key == "Condition"))
node.Value.Nodes.Add(new MiniYamlNode("Condition", "terrain"));
}
if (node.Key == "AttackSwallow")
{
ConvertUpgradesToCondition(parent, node, "AttackingUpgrades", "AttackingCondition");
if (!node.Value.Nodes.Any(n => n.Key == "AttackingCondition"))
node.Value.Nodes.Add(new MiniYamlNode("AttackingCondition", "attacking"));
}
if (node.Key.StartsWith("Pluggable", StringComparison.Ordinal))
{
var upgrades = node.Value.Nodes.FirstOrDefault(n => n.Key == "Upgrades");
if (upgrades != null)
{
upgrades.Key = "Conditions";
foreach (var n in upgrades.Value.Nodes)
{
var conditions = FieldLoader.GetValue<string[]>("", n.Value.Value);
if (conditions.Length > 1)
Console.WriteLine("Unable to automatically migrate multiple Pluggable upgrades to a condition. This must be corrected manually");
}
}
}
if (node.Key.StartsWith("GlobalUpgradable", StringComparison.Ordinal))
{
RenameNodeKey(node, "GrantConditionOnPrerequisite");
ConvertUpgradesToCondition(parent, node, "Upgrades", "Condition");
}
if (node.Key.StartsWith("GlobalUpgradeManager", StringComparison.Ordinal))
RenameNodeKey(node, "GrantConditionOnPrerequisiteManager");
if (node.Key.StartsWith("DeployToUpgrade", StringComparison.Ordinal))
{
RenameNodeKey(node, "GrantConditionOnDeploy");
ConvertUpgradesToCondition(parent, node, "UndeployedUpgrades", "UndeployedCondition");
ConvertUpgradesToCondition(parent, node, "DeployedUpgrades", "DeployedCondition");
}
if (node.Key == "GainsExperience")
{
var upgrades = node.Value.Nodes.FirstOrDefault(n => n.Key == "Upgrades");
if (upgrades != null)
{
upgrades.Key = "Conditions";
foreach (var n in upgrades.Value.Nodes)
{
var conditions = FieldLoader.GetValue<string[]>("", n.Value.Value);
if (conditions.Length > 1)
Console.WriteLine("Unable to automatically migrate multiple GainsExperience upgrades to a condition. This must be corrected manually");
}
}
}
if (node.Key.StartsWith("DisableOnUpgrade", StringComparison.Ordinal))
RenameNodeKey(node, "DisableOnCondition");
}
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
}

View File

@@ -37,6 +37,7 @@ namespace OpenRA.Mods.D2k.Activities
int countdown;
CPos burrowLocation;
AttackState stance;
int attackingToken = UpgradeManager.InvalidConditionToken;
public SwallowActor(Actor self, Target target, WeaponInfo weapon)
{
@@ -45,7 +46,7 @@ namespace OpenRA.Mods.D2k.Activities
sandworm = self.Trait<Sandworm>();
positionable = self.Trait<Mobile>();
swallow = self.Trait<AttackSwallow>();
manager = self.Trait<UpgradeManager>();
manager = self.TraitOrDefault<UpgradeManager>();
radarPings = self.World.WorldActor.TraitOrDefault<RadarPings>();
}
@@ -105,10 +106,12 @@ namespace OpenRA.Mods.D2k.Activities
switch (stance)
{
case AttackState.Uninitialized:
GrantUpgrades(self);
stance = AttackState.Burrowed;
countdown = swallow.Info.AttackDelay;
burrowLocation = self.Location;
if (manager != null && attackingToken == UpgradeManager.InvalidConditionToken &&
!string.IsNullOrEmpty(swallow.Info.AttackingCondition))
attackingToken = manager.GrantCondition(self, swallow.Info.AttackingCondition);
break;
case AttackState.Burrowed:
if (--countdown > 0)
@@ -119,14 +122,14 @@ namespace OpenRA.Mods.D2k.Activities
// The target has moved too far away
if ((burrowLocation - targetLocation).Length > NearEnough)
{
RevokeUpgrades(self);
RevokeCondition(self);
return NextActivity;
}
// The target reached solid ground
if (!positionable.CanEnterCell(targetLocation, null, false))
{
RevokeUpgrades(self);
RevokeCondition(self);
return NextActivity;
}
@@ -135,7 +138,7 @@ namespace OpenRA.Mods.D2k.Activities
if (!targets.Any())
{
RevokeUpgrades(self);
RevokeCondition(self);
return NextActivity;
}
@@ -158,23 +161,17 @@ namespace OpenRA.Mods.D2k.Activities
self.World.AddFrameEndTask(w => self.Dispose());
}
RevokeUpgrades(self);
RevokeCondition(self);
return NextActivity;
}
return this;
}
void GrantUpgrades(Actor self)
void RevokeCondition(Actor self)
{
foreach (var up in swallow.Info.AttackingUpgrades)
manager.GrantUpgrade(self, up, this);
}
void RevokeUpgrades(Actor self)
{
foreach (var up in swallow.Info.AttackingUpgrades)
manager.RevokeUpgrade(self, up, this);
if (attackingToken != UpgradeManager.InvalidConditionToken)
attackingToken = manager.RevokeCondition(self, attackingToken);
}
}
}

View File

@@ -27,8 +27,8 @@ namespace OpenRA.Mods.D2k.Traits
public readonly int AttackDelay = 30;
[UpgradeGrantedReference]
[Desc("The upgrades to grant while attacking.")]
public readonly string[] AttackingUpgrades = { "attacking" };
[Desc("The condition to grant to self while attacking.")]
public readonly string AttackingCondition = null;
public readonly string WormAttackSound = "WORM.WAV";

View File

@@ -65,13 +65,13 @@ namespace OpenRA.Mods.RA.Traits
[VoiceReference] public readonly string Voice = "Action";
[UpgradeGrantedReference]
[Desc("Upgrades to grant when disguised.")]
public readonly string[] Upgrades = { "disguise" };
[Desc("The condition to grant to self while disguised.")]
public readonly string DisguisedCondition = null;
public object Create(ActorInitializer init) { return new Disguise(init.Self, this); }
}
class Disguise : IEffectiveOwner, IIssueOrder, IResolveOrder, IOrderVoice, IRadarColorModifier, INotifyAttack
class Disguise : INotifyCreated, IEffectiveOwner, IIssueOrder, IResolveOrder, IOrderVoice, IRadarColorModifier, INotifyAttack
{
public Player AsPlayer { get; private set; }
public string AsSprite { get; private set; }
@@ -82,14 +82,19 @@ namespace OpenRA.Mods.RA.Traits
readonly Actor self;
readonly DisguiseInfo info;
readonly Lazy<UpgradeManager> um;
UpgradeManager um;
int disguisedToken = UpgradeManager.InvalidConditionToken;
public Disguise(Actor self, DisguiseInfo info)
{
this.self = self;
this.info = info;
}
um = Exts.Lazy(() => self.TraitOrDefault<UpgradeManager>());
void INotifyCreated.Created(Actor self)
{
um = self.TraitOrDefault<UpgradeManager>();
}
public IEnumerable<IOrderTargeter> Orders
@@ -182,18 +187,12 @@ namespace OpenRA.Mods.RA.Traits
foreach (var t in self.TraitsImplementing<INotifyEffectiveOwnerChanged>())
t.OnEffectiveOwnerChanged(self, oldEffectiveOwner, AsPlayer);
if (Disguised != oldDisguiseSetting && um.Value != null)
if (Disguised != oldDisguiseSetting && um != null)
{
foreach (var u in info.Upgrades)
{
if (!um.Value.AcknowledgesUpgrade(self, u))
continue;
if (Disguised)
um.Value.GrantUpgrade(self, u, this);
else
um.Value.RevokeUpgrade(self, u, this);
}
if (Disguised && disguisedToken == UpgradeManager.InvalidConditionToken && !string.IsNullOrEmpty(info.DisguisedCondition))
disguisedToken = um.GrantCondition(self, info.DisguisedCondition);
else if (!Disguised && disguisedToken != UpgradeManager.InvalidConditionToken)
disguisedToken = um.RevokeCondition(self, disguisedToken);
}
}

View File

@@ -167,7 +167,7 @@ C17:
TurnSpeed: 5
Speed: 326
Repulsable: False
AirborneUpgrades: airborne
AirborneCondition: airborne
MaximumPitch: 36
Health:
HP: 25
@@ -206,7 +206,7 @@ A10:
TurnSpeed: 4
Speed: 373
Repulsable: False
AirborneUpgrades: airborne
AirborneCondition: airborne
Health:
HP: 150
Armor:

View File

@@ -16,7 +16,7 @@
^GainsExperience:
GainsExperience:
Upgrades:
Conditions:
200: rank-veteran-1
400: rank-veteran-2
800: rank-veteran-3
@@ -202,8 +202,8 @@
Aircraft:
RepairBuildings: hpad
LandWhenIdle: false
AirborneUpgrades: airborne
CruisingUpgrades: cruising
AirborneCondition: airborne
CruisingCondition: cruising
CanHover: True
HiddenUnderFog:
Type: CenterPosition
@@ -283,8 +283,8 @@
DamageInterval: 16
DamageTypes: TiberiumDeath
RequiresCondition: !hazmatsuits
GlobalUpgradable@BIO:
Upgrades: hazmatsuits
GrantConditionOnPrerequisite@BIO:
Condition: hazmatsuits
Prerequisites: bio
WithDecoration@HAZMAT:
Image: pips
@@ -309,8 +309,8 @@
HealIfBelow: 100
DamageCooldown: 125
RequiresCondition: hospitalheal
GlobalUpgradable@HOSPITAL:
Upgrades: hospitalheal
GrantConditionOnPrerequisite@HOSPITAL:
Condition: hospitalheal
Prerequisites: hosp
WithDecoration@REDCROSS:
Image: pips
@@ -839,7 +839,7 @@
Offset: 43, 128, 0
ZOffset: -129
Aircraft:
AirborneUpgrades: airborne
AirborneCondition: airborne
CanHover: True
FallsToEarth:
Spins: True

View File

@@ -32,6 +32,6 @@ Player:
Name: Unrestricted
Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons
Id: unrestricted
GlobalUpgradeManager:
GrantConditionOnPrerequisiteManager:
ResourceStorageWarning:
PlayerExperience:

View File

@@ -16,7 +16,7 @@ carryall.reinforce:
LandableTerrainTypes: Sand, Rock, Transition, Spice, SpiceSand, Dune
Repulsable: False
LandWhenIdle: False
AirborneUpgrades: airborne
AirborneCondition: airborne
CanHover: True
Targetable@GROUND:
TargetTypes: Ground, Vehicle

View File

@@ -87,6 +87,7 @@ sandworm:
AttackSwallow:
AttackRequiresEnteringCell: true
IgnoresVisibility: true
AttackingCondition: attacking
Armament:
Weapon: WormJaw
Sandworm:

View File

@@ -16,7 +16,7 @@
^GainsExperience:
GainsExperience:
Upgrades:
Conditions:
200: rank-veteran-1
400: rank-veteran-2
800: rank-veteran-3

View File

@@ -96,8 +96,8 @@ thumper:
Mobile:
Speed: 43
RequiresCondition: !deployed
DeployToUpgrade:
DeployedUpgrades: deployed
GrantConditionOnDeploy:
DeployedCondition: deployed
Facing: 128
AllowedTerrainTypes: Sand, Spice, Dune, SpiceSand
WithInfantryBody:

View File

@@ -88,7 +88,7 @@ Player:
Id: unrestricted
EnemyWatcher:
HarvesterInsurance:
GlobalUpgradeManager:
GrantConditionOnPrerequisiteManager:
ResourceStorageWarning:
AdviceInterval: 26
PlayerExperience:

View File

@@ -88,10 +88,11 @@ construction_yard:
WithBuildingPlacedOverlay:
Palette: d2k
PrimaryBuilding:
PrimaryCondition: primary
ProvidesPrerequisite@buildingname:
GlobalUpgradable:
GrantConditionOnPrerequisite:
Prerequisites: upgrade.conyard
Upgrades: stardecoration
Condition: stardecoration
WithDecoration@upgraded:
RequiresSelection: true
Image: pips
@@ -181,6 +182,7 @@ barracks:
Production:
Produces: Infantry
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
ProvidesPrerequisite@atreides:
Prerequisite: barracks.atreides
@@ -201,9 +203,9 @@ barracks:
smuggler: barracks.ordos
mercenary: barracks.ordos
ProvidesPrerequisite@buildingname:
GlobalUpgradable:
GrantConditionOnPrerequisite:
Prerequisites: upgrade.barracks
Upgrades: stardecoration
Condition: stardecoration
WithDecoration@upgraded:
RequiresSelection: true
Image: pips
@@ -360,6 +362,7 @@ light_factory:
Production:
Produces: Vehicle
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
ProvidesPrerequisite@atreides:
Prerequisite: light.atreides
@@ -380,9 +383,9 @@ light_factory:
Sequence: idle-top
Power:
Amount: -125
GlobalUpgradable:
GrantConditionOnPrerequisite:
Prerequisites: upgrade.light
Upgrades: stardecoration
Condition: stardecoration
WithDecoration@upgraded:
RequiresSelection: true
Image: pips
@@ -430,6 +433,7 @@ heavy_factory:
Production:
Produces: Armor
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
ProvidesPrerequisite@atreides:
Prerequisite: heavy.atreides
@@ -459,9 +463,9 @@ heavy_factory:
ProvidesPrerequisite@buildingname:
SelectionDecorations:
VisualBounds: 96,96
GlobalUpgradable:
GrantConditionOnPrerequisite:
Prerequisites: upgrade.heavy
Upgrades: stardecoration
Condition: stardecoration
WithDecoration@upgraded:
RequiresSelection: true
Image: pips
@@ -567,6 +571,7 @@ starport:
Palette: starportlights
ProductionBar:
PrimaryBuilding:
PrimaryCondition: primary
RequiresPower:
CanPowerDown:
PowerupSound: EnablePower
@@ -836,9 +841,9 @@ high_tech_factory:
Amount: -75
SelectionDecorations:
VisualBounds: 96,96
GlobalUpgradable:
GrantConditionOnPrerequisite:
Prerequisites: upgrade.hightech
Upgrades: stardecoration
Condition: stardecoration
WithDecoration@upgraded:
RequiresSelection: true
Image: pips

View File

@@ -17,7 +17,7 @@ World:
GivesBounty:
Percentage: 0
GainsExperience:
Upgrades:
Conditions:
DamageMultiplier@UNKILLABLE:
RequiresCondition: unkillable
Modifier: 0
@@ -28,7 +28,7 @@ World:
GivesBounty:
Percentage: 0
GainsExperience:
Upgrades:
Conditions:
DamageMultiplier@UNKILLABLE:
RequiresCondition: unkillable
Modifier: 0
@@ -39,7 +39,7 @@ World:
GivesBounty:
Percentage: 0
GainsExperience:
Upgrades:
Conditions:
DeathSounds@NORMAL:
VolumeMultiplier: 0.1
DeathSounds@BURNED:
@@ -56,7 +56,7 @@ World:
GivesBounty:
Percentage: 0
GainsExperience:
Upgrades:
Conditions:
DamageMultiplier@UNKILLABLE:
RequiresCondition: unkillable
Modifier: 0

View File

@@ -15,7 +15,7 @@
^GainsExperience:
GainsExperience:
Upgrades:
Conditions:
200: rank-veteran-1
400: rank-veteran-2
800: rank-veteran-3
@@ -191,6 +191,7 @@
GroundCorpsePalette:
WaterCorpseSequence:
WaterCorpsePalette:
ParachutingCondition: parachute
Explodes:
Weapon: UnitExplodeSmall
EmptyWeapon: UnitExplodeSmall
@@ -290,8 +291,8 @@
HealIfBelow: 100
DamageCooldown: 125
RequiresCondition: hospitalheal
GlobalUpgradable:
Upgrades: hospitalheal
GrantConditionOnPrerequisite:
Condition: hospitalheal
Prerequisites: hosp
DeathSounds@NORMAL:
DeathTypes: DefaultDeath, BulletDeath, SmallExplosionDeath, ExplosionDeath
@@ -307,6 +308,7 @@
GroundImpactSound: squishy2.aud
WaterImpactSound: splash9.aud
WaterCorpseSequence: small_splash
ParachutingCondition: parachute
Cloneable:
Types: Infantry
Voiced:
@@ -425,8 +427,8 @@
Aircraft:
RepairBuildings: fix
RearmBuildings: afld
AirborneUpgrades: airborne
CruisingUpgrades: cruising
AirborneCondition: airborne
CruisingCondition: cruising
Targetable@GROUND:
TargetTypes: Ground, Repair, Vehicle
RequiresCondition: !airborne
@@ -796,8 +798,8 @@
Tooltip:
GenericName: Destroyed Plane
Aircraft:
AirborneUpgrades: airborne
CruisingUpgrades: cruising
AirborneCondition: airborne
CruisingCondition: cruising
FallsToEarth:
Spins: False
Moves: True
@@ -811,8 +813,8 @@
Tooltip:
GenericName: Destroyed Helicopter
Aircraft:
AirborneUpgrades: airborne
CruisingUpgrades: cruising
AirborneCondition: airborne
CruisingCondition: cruising
CanHover: True
FallsToEarth:
BodyOrientation:
@@ -884,6 +886,7 @@
Parachutable:
FallRate: 26
KilledOnImpassableTerrain: false
ParachutingCondition: parachute
Passenger:
WithParachute:
Image: parach

View File

@@ -211,6 +211,7 @@ SPY:
Voice: Move
Disguise:
Voice: Move
DisguisedCondition: disguise
Infiltrates:
Types: SpyInfiltrate
PlayerExperience: 50

View File

@@ -69,7 +69,7 @@ Player:
Name: Unrestricted
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.high, techlevel.unrestricted
Id: unrestricted
GlobalUpgradeManager:
GrantConditionOnPrerequisiteManager:
EnemyWatcher:
VeteranProductionIconOverlay:
Image: iconchevrons

View File

@@ -31,7 +31,7 @@ SS:
CloakDelay: 50
CloakSound: subshow1.aud
UncloakSound: subshow1.aud
WhileCloakedUpgrades: underwater
CloakedCondition: underwater
Palette: submerged
Armament:
Weapon: TorpTube
@@ -85,7 +85,7 @@ MSUB:
CloakDelay: 100
CloakSound: subshow1.aud
UncloakSound: subshow1.aud
WhileCloakedUpgrades: underwater
CloakedCondition: underwater
Palette: submerged
Armament@PRIMARY:
Weapon: SubMissile

View File

@@ -134,6 +134,7 @@ SPEN:
Production:
Produces: Ship, Submarine
PrimaryBuilding:
PrimaryCondition: primary
-EmitInfantryOnSell:
RepairsUnits:
FinishRepairingNotification: UnitRepaired
@@ -223,6 +224,7 @@ SYRD:
Production:
Produces: Ship, Boat
PrimaryBuilding:
PrimaryCondition: primary
-EmitInfantryOnSell:
RepairsUnits:
FinishRepairingNotification: UnitRepaired
@@ -854,6 +856,7 @@ WEAP:
RequiresPrerequisites: structures.ukraine
Prerequisite: vehicles.ukraine
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
Power:
Amount: -30
@@ -1060,6 +1063,7 @@ HPAD:
Reservable:
ProductionBar:
PrimaryBuilding:
PrimaryCondition: primary
Power:
Amount: -10
ProvidesPrerequisite@allies:
@@ -1206,6 +1210,7 @@ AFLD:
ProductionBar:
SupportPowerChargeBar:
PrimaryBuilding:
PrimaryCondition: primary
Power:
Amount: -20
ProvidesPrerequisite@buildingname:
@@ -1354,6 +1359,7 @@ BARR:
Production:
Produces: Infantry, Soldier
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
ProvidesPrerequisite:
Prerequisite: barracks
@@ -1428,6 +1434,7 @@ KENN:
Production:
Produces: Infantry, Dog
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
-EmitInfantryOnSell:
Power:
@@ -1472,6 +1479,7 @@ TENT:
Production:
Produces: Infantry, Soldier
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
ProvidesPrerequisite@barracks:
Prerequisite: barracks

View File

@@ -121,7 +121,7 @@ ORCAB:
MaximumPitch: 120
TurnSpeed: 3
Speed: 96
AirborneUpgrades: airborne
AirborneCondition: airborne
MoveIntoShroud: false
TakeoffSound: orcaup1.aud
LandingSound: orcadwn1.aud
@@ -243,7 +243,7 @@ SCRIN:
MaximumPitch: 90
TurnSpeed: 3
Speed: 168
AirborneUpgrades: airborne
AirborneCondition: airborne
MoveIntoShroud: false
TakeoffSound: dropup1.aud
LandingSound: dropdwn1.aud

View File

@@ -64,6 +64,7 @@ CHAMSPY:
Range: 9c0
Passenger:
Disguise:
DisguisedCondition: disguise
WithDecoration@disguise:
Image: pips
Sequence: pip-disguise

View File

@@ -17,7 +17,7 @@
^GainsExperience:
GainsExperience:
Upgrades:
Conditions:
500: rank-veteran
1000: rank-elite
FirepowerMultiplier@VETERAN:
@@ -71,7 +71,7 @@
UpgradeOverlay@EMPDISABLE:
RequiresCondition: empdisable
Palette: disabled
DisableOnUpgrade@EMPDISABLE:
DisableOnCondition@EMPDISABLE:
RequiresCondition: empdisable
TimedConditionBar@EMPDISABLE:
Condition: empdisable
@@ -326,8 +326,8 @@
HealIfBelow: 100
DamageCooldown: 125
RequiresCondition: hospitalheal
GlobalUpgradable@HOSPITAL:
Upgrades: hospitalheal
GrantConditionOnPrerequisite@HOSPITAL:
Condition: hospitalheal
Prerequisites: cahosp
WithDecoration@REDCROSS:
Image: pips
@@ -418,8 +418,8 @@
WithInfantryBody:
DefaultAttackSequence: attack
IdleSequences: idle1,idle2
UpgradeOnDamageState@CRITICAL:
Upgrades: criticalspeed
GrantConditionOnDamageState@CRITICAL:
Condition: criticalspeed
ValidDamageStates: Critical
GrantPermanently: true
SpeedMultiplier@CRITICAL:
@@ -498,11 +498,11 @@
Weapons: SmallDebris
Pieces: 3, 7
Range: 2c0, 5c0
UpgradeOnDamageState@DAMAGED:
Upgrades: damagedspeed
GrantConditionOnDamageState@DAMAGED:
Condition: damagedspeed
ValidDamageStates: Heavy
UpgradeOnDamageState@CRITICAL:
Upgrades: criticalspeed
GrantConditionOnDamageState@CRITICAL:
Condition: criticalspeed
ValidDamageStates: Critical
SpeedMultiplier@DAMAGED:
RequiresCondition: damagedspeed
@@ -569,8 +569,8 @@
SelectionDecorations:
Palette: pips
Aircraft:
AirborneUpgrades: airborne
CruisingUpgrades: cruising
AirborneCondition: airborne
CruisingCondition: cruising
RepairBuildings: gadept
RearmBuildings: gahpad, nahpad
LandWhenIdle: false
@@ -615,8 +615,8 @@
QuantizedFacings: 0
CameraPitch: 90
Aircraft:
AirborneUpgrades: airborne
CruisingUpgrades: cruising
AirborneCondition: airborne
CruisingCondition: cruising
Health:
HP: 280
Armor:
@@ -917,9 +917,9 @@
DamageInterval: 16
DamageTypes: BulletDeath
Terrain: Veins
UpgradeOnTerrain@VEINS:
GrantConditionOnTerrain@VEINS:
TerrainTypes: Veins
Upgrades: veins
Condition: veins
WithIdleOverlay@VEINS:
Sequence: veins
RequiresCondition: veins

View File

@@ -38,7 +38,7 @@ GAPOWR:
DisabledOverlay:
Pluggable@pluga:
Offset: 0,1
Upgrades:
Conditions:
powrup: powrup.a
Power@pluga:
RequiresCondition: powrup.a
@@ -48,7 +48,7 @@ GAPOWR:
Sequence: idle-powrupa
Pluggable@plugb:
Offset: 1,1
Upgrades:
Conditions:
powrup: powrup.b
WithIdleOverlay@plugb:
RequiresCondition: powrup.b
@@ -96,6 +96,7 @@ GAPILE:
Production:
Produces: Infantry
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
WithProductionOverlay@LIGHTS:
Sequence: production-lights
@@ -153,6 +154,7 @@ GAWEAP:
Production:
Produces: Vehicle
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
WithIdleOverlay@ROOF:
Sequence: idle-roof
@@ -206,6 +208,7 @@ GAHPAD:
Production:
Produces: Air
PrimaryBuilding:
PrimaryCondition: primary
Reservable:
RepairsUnits:
PlayerExperience: 15
@@ -435,7 +438,7 @@ GAPLUG:
Amount: -50
Pluggable@pluga:
Offset: 0,2
Upgrades:
Conditions:
plug.ioncannon: plug.ioncannona
plug.hunterseeker: plug.hunterseekera
WithIdleOverlay@ioncannona:
@@ -446,7 +449,7 @@ GAPLUG:
Sequence: idle-hunterseekera
Pluggable@plugb:
Offset: 1,2
Upgrades:
Conditions:
plug.ioncannon: plug.ioncannonb
plug.hunterseeker: plug.hunterseekerb
WithIdleOverlay@ioncannonb:

View File

@@ -126,7 +126,7 @@ GACTWR:
RequiresCondition: tower.sam
Amount: -10
Pluggable:
Upgrades:
Conditions:
tower.vulcan: tower.vulcan
tower.rocket: tower.rocket
tower.sam: tower.sam

View File

@@ -30,8 +30,8 @@ APC:
UnloadVoice: Unload
LoadingCondition: loading
EjectOnDeath: true
UpgradeOnTerrain:
Upgrades: inwater
GrantConditionOnTerrain:
Condition: inwater
TerrainTypes: Water
WithVoxelBody:
RequiresCondition: !inwater
@@ -95,7 +95,7 @@ HVR:
StationaryInterval: 18
MovingInterval: 6
-DamagedByTerrain@VEINS:
-UpgradeOnTerrain@VEINS:
-GrantConditionOnTerrain@VEINS:
-WithIdleOverlay@VEINS:
SMECH:
@@ -137,7 +137,7 @@ SMECH:
Selectable:
Bounds: 20, 32, 0, -8
-DamagedByTerrain@VEINS:
-UpgradeOnTerrain@VEINS:
-GrantConditionOnTerrain@VEINS:
-WithIdleOverlay@VEINS:
MMCH:

View File

@@ -112,6 +112,7 @@ NAHAND:
Production:
Produces: Infantry
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
WithIdleOverlay@LIGHTS:
Sequence: idle-lights
@@ -167,6 +168,7 @@ NAWEAP:
Production:
Produces: Vehicle
PrimaryBuilding:
PrimaryCondition: primary
ProductionBar:
WithIdleOverlay@ROOF:
Sequence: idle-roof
@@ -216,6 +218,7 @@ NAHPAD:
Production:
Produces: Air
PrimaryBuilding:
PrimaryCondition: primary
Reservable:
RepairsUnits:
PlayerExperience: 15

View File

@@ -29,7 +29,7 @@ BGGY:
AutoTarget:
WithMuzzleOverlay:
-DamagedByTerrain@VEINS:
-UpgradeOnTerrain@VEINS:
-GrantConditionOnTerrain@VEINS:
-WithIdleOverlay@VEINS:
BIKE:
@@ -105,9 +105,9 @@ TTNK:
MaxHeightDelta: 3
RenderSprites:
Image: ttnk
DeployToUpgrade:
DeployedUpgrades: deployed
UndeployedUpgrades: undeployed
GrantConditionOnDeploy:
DeployedCondition: deployed
UndeployedCondition: undeployed
DeployAnimation: make
Facing: 160
AllowedTerrainTypes: Clear, Road, DirtRoad, Rough
@@ -256,7 +256,7 @@ WEED:
WithVoxelUnloadBody:
-GainsExperience:
-DamagedByTerrain@VEINS:
-UpgradeOnTerrain@VEINS:
-GrantConditionOnTerrain@VEINS:
-WithIdleOverlay@VEINS:
SAPC:

View File

@@ -1,7 +1,7 @@
Player:
AlwaysVisible:
TechTree:
GlobalUpgradeManager:
GrantConditionOnPrerequisiteManager:
ClassicProductionQueue@Building:
Type: Building
BuildDurationModifier: 120

View File

@@ -100,7 +100,7 @@ HARV:
gdi: harv.gdi
nod: harv.nod
-DamagedByTerrain@VEINS:
-UpgradeOnTerrain@VEINS:
-GrantConditionOnTerrain@VEINS:
-WithIdleOverlay@VEINS:
LPST:
@@ -137,9 +137,9 @@ LPST:
FactionImages:
gdi: lpst.gdi
nod: lpst.nod
DeployToUpgrade:
DeployedUpgrades: deployed
UndeployedUpgrades: undeployed
GrantConditionOnDeploy:
DeployedCondition: deployed
UndeployedCondition: undeployed
DeployAnimation: make
Facing: 160
AllowedTerrainTypes: Clear, Road, DirtRoad, Rough
@@ -156,4 +156,4 @@ LPST:
RenderDetectionCircle:
TrailCount: 3
Carryable:
RequiresCondition: undeployed
RequiresCondition: undeployed