Remove RearmBuildings from Aircraft and Minelayer

In favor of using Rearmable trait.
This commit is contained in:
reaperrr
2018-09-27 17:50:35 +02:00
committed by Paul Chote
parent 2485029452
commit 8f1d8a67cc
19 changed files with 191 additions and 69 deletions

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Cnc.Activities
readonly MinelayerInfo info; readonly MinelayerInfo info;
readonly AmmoPool[] ammoPools; readonly AmmoPool[] ammoPools;
readonly IMove movement; readonly IMove movement;
readonly HashSet<string> rearmBuildings; readonly RearmableInfo rearmableInfo;
public LayMines(Actor self) public LayMines(Actor self)
{ {
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Cnc.Activities
info = self.Info.TraitInfo<MinelayerInfo>(); info = self.Info.TraitInfo<MinelayerInfo>();
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray(); ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
movement = self.Trait<IMove>(); movement = self.Trait<IMove>();
rearmBuildings = info.RearmBuildings; rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
@@ -43,11 +43,11 @@ namespace OpenRA.Mods.Cnc.Activities
if (IsCanceled) if (IsCanceled)
return NextActivity; return NextActivity;
if (ammoPools != null && ammoPools.Any(p => p.Info.Name == info.AmmoPoolName && !p.HasAmmo())) if (rearmableInfo != null && ammoPools.Any(p => p.Info.Name == info.AmmoPoolName && !p.HasAmmo()))
{ {
// Rearm (and possibly repair) at rearm building, then back out here to refill the minefield some more // Rearm (and possibly repair) at rearm building, then back out here to refill the minefield some more
var rearmTarget = self.World.Actors.Where(a => self.Owner.Stances[a.Owner] == Stance.Ally var rearmTarget = self.World.Actors.Where(a => self.Owner.Stances[a.Owner] == Stance.Ally
&& rearmBuildings.Contains(a.Info.Name)) && rearmableInfo.RearmActors.Contains(a.Info.Name))
.ClosestTo(self); .ClosestTo(self);
if (rearmTarget == null) if (rearmTarget == null)

View File

@@ -21,10 +21,9 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits namespace OpenRA.Mods.Cnc.Traits
{ {
public class MinelayerInfo : ITraitInfo public class MinelayerInfo : ITraitInfo, Requires<RearmableInfo>
{ {
[ActorReference] public readonly string Mine = "minv"; [ActorReference] public readonly string Mine = "minv";
[ActorReference] public readonly HashSet<string> RearmBuildings = new HashSet<string> { "fix" };
public readonly string AmmoPoolName = "primary"; public readonly string AmmoPoolName = "primary";

View File

@@ -443,22 +443,22 @@ namespace OpenRA.Mods.Common.AI
CountBuildingByCommonName(Info.BuildingCommonNames.Barracks, Player) == 0; CountBuildingByCommonName(Info.BuildingCommonNames.Barracks, Player) == 0;
} }
// For mods like RA (number of building must match the number of aircraft) // For mods like RA (number of RearmActors must match the number of aircraft)
bool HasAdequateAirUnitReloadBuildings(ActorInfo actorInfo) bool HasAdequateAirUnitReloadBuildings(ActorInfo actorInfo)
{ {
var aircraftInfo = actorInfo.TraitInfoOrDefault<AircraftInfo>(); var aircraftInfo = actorInfo.TraitInfoOrDefault<AircraftInfo>();
if (aircraftInfo == null) if (aircraftInfo == null)
return true; return true;
// If the aircraft has at least 1 AmmoPool and defines 1 or more RearmBuildings, check if we have enough of those // If actor isn't Rearmable, it doesn't need a RearmActor to reload
var hasAmmoPool = actorInfo.TraitInfos<AmmoPoolInfo>().Any(); var rearmableInfo = actorInfo.TraitInfoOrDefault<RearmableInfo>();
if (hasAmmoPool && aircraftInfo.RearmBuildings.Count > 0) if (rearmableInfo == null)
{ return true;
var countOwnAir = CountActorsWithTrait<IPositionable>(actorInfo.Name, Player);
var countBuildings = aircraftInfo.RearmBuildings.Sum(b => CountActorsWithTrait<Building>(b, Player)); var countOwnAir = CountActorsWithTrait<IPositionable>(actorInfo.Name, Player);
if (countOwnAir >= countBuildings) var countBuildings = rearmableInfo.RearmActors.Sum(b => CountActorsWithTrait<Building>(b, Player));
return false; if (countOwnAir >= countBuildings)
} return false;
return true; return true;
} }

View File

@@ -127,7 +127,11 @@ namespace OpenRA.Mods.Common.AI
protected static bool ReloadsAutomatically(Actor a) protected static bool ReloadsAutomatically(Actor a)
{ {
var ammoPools = a.TraitsImplementing<AmmoPool>(); var ammoPools = a.TraitsImplementing<AmmoPool>();
return ammoPools.All(x => x.AutoReloads); var rearmable = a.TraitOrDefault<Rearmable>();
if (rearmable == null)
return true;
return ammoPools.All(ap => !rearmable.Info.AmmoPools.Contains(ap.Info.Name));
} }
protected static bool IsRearm(Actor a) protected static bool IsRearm(Actor a)

View File

@@ -21,17 +21,17 @@ namespace OpenRA.Mods.Common.Activities
readonly Target target; readonly Target target;
readonly Aircraft aircraft; readonly Aircraft aircraft;
readonly AttackPlane attackPlane; readonly AttackPlane attackPlane;
readonly Rearmable rearmable;
readonly bool autoReloads;
int ticksUntilTurn; int ticksUntilTurn;
public FlyAttack(Actor self, Target target) public FlyAttack(Actor self, Target target)
{ {
this.target = target; this.target = target;
aircraft = self.Trait<Aircraft>(); aircraft = self.Trait<Aircraft>();
attackPlane = self.TraitOrDefault<AttackPlane>(); attackPlane = self.Trait<AttackPlane>();
rearmable = self.TraitOrDefault<Rearmable>();
ticksUntilTurn = attackPlane.AttackPlaneInfo.AttackTurnDelay; ticksUntilTurn = attackPlane.AttackPlaneInfo.AttackTurnDelay;
autoReloads = self.TraitsImplementing<AmmoPool>().All(p => p.AutoReloads);
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
@@ -46,12 +46,11 @@ namespace OpenRA.Mods.Common.Activities
if (!target.IsValidFor(self)) if (!target.IsValidFor(self))
return NextActivity; return NextActivity;
// If all valid weapons have depleted their ammo and RearmBuilding is defined, return to RearmBuilding to reload and then resume the activity // If all valid weapons have depleted their ammo and Rearmable trait exists, return to RearmActor to reload and then resume the activity
if (!autoReloads && aircraft.Info.RearmBuildings.Any() && attackPlane.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self))) if (rearmable != null && attackPlane.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
return ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this); return ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this);
if (attackPlane != null) attackPlane.DoAttack(self, target);
attackPlane.DoAttack(self, target);
if (ChildActivity == null) if (ChildActivity == null)
{ {

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Common.Activities
readonly Aircraft aircraft; readonly Aircraft aircraft;
readonly AttackHeli attackHeli; readonly AttackHeli attackHeli;
readonly bool attackOnlyVisibleTargets; readonly bool attackOnlyVisibleTargets;
readonly bool autoReloads; readonly Rearmable rearmable;
Target target; Target target;
bool canHideUnderFog; bool canHideUnderFog;
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Activities
aircraft = self.Trait<Aircraft>(); aircraft = self.Trait<Aircraft>();
attackHeli = self.Trait<AttackHeli>(); attackHeli = self.Trait<AttackHeli>();
this.attackOnlyVisibleTargets = attackOnlyVisibleTargets; this.attackOnlyVisibleTargets = attackOnlyVisibleTargets;
autoReloads = self.TraitsImplementing<AmmoPool>().All(p => p.AutoReloads); rearmable = self.TraitOrDefault<Rearmable>();
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
@@ -74,8 +74,8 @@ namespace OpenRA.Mods.Common.Activities
return new HeliFly(self, newTarget); return new HeliFly(self, newTarget);
} }
// If all valid weapons have depleted their ammo and RearmBuilding is defined, return to RearmBuilding to reload and then resume the activity // If all valid weapons have depleted their ammo and Rearmable trait exists, return to RearmActor to reload and then resume the activity
if (!autoReloads && aircraft.Info.RearmBuildings.Any() && attackHeli.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self))) if (rearmable != null && attackHeli.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
return ActivityUtils.SequenceActivities(new HeliReturnToBase(self, aircraft.Info.AbortOnResupply), this); return ActivityUtils.SequenceActivities(new HeliReturnToBase(self, aircraft.Info.AbortOnResupply), this);
var dist = targetPos - pos; var dist = targetPos - pos;

View File

@@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
readonly Aircraft aircraft; readonly Aircraft aircraft;
readonly RepairableInfo repairableInfo; readonly RepairableInfo repairableInfo;
readonly Rearmable rearmable;
readonly bool alwaysLand; readonly bool alwaysLand;
readonly bool abortOnResupply; readonly bool abortOnResupply;
Actor dest; Actor dest;
@@ -28,6 +29,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
aircraft = self.Trait<Aircraft>(); aircraft = self.Trait<Aircraft>();
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>(); repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmable = self.TraitOrDefault<Rearmable>();
this.alwaysLand = alwaysLand; this.alwaysLand = alwaysLand;
this.abortOnResupply = abortOnResupply; this.abortOnResupply = abortOnResupply;
this.dest = dest; this.dest = dest;
@@ -35,9 +37,11 @@ namespace OpenRA.Mods.Common.Activities
public Actor ChooseResupplier(Actor self, bool unreservedOnly) public Actor ChooseResupplier(Actor self, bool unreservedOnly)
{ {
var rearmBuildings = aircraft.Info.RearmBuildings; if (rearmable == null)
return null;
return self.World.Actors.Where(a => a.Owner == self.Owner return self.World.Actors.Where(a => a.Owner == self.Owner
&& rearmBuildings.Contains(a.Info.Name) && rearmable.Info.RearmActors.Contains(a.Info.Name)
&& (!unreservedOnly || !Reservable.IsReserved(a))) && (!unreservedOnly || !Reservable.IsReserved(a)))
.ClosestTo(self); .ClosestTo(self);
} }
@@ -119,8 +123,8 @@ namespace OpenRA.Mods.Common.Activities
if (repairableInfo != null && repairableInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged) if (repairableInfo != null && repairableInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged)
return true; return true;
return aircraft.Info.RearmBuildings.Contains(dest.Info.Name) && self.TraitsImplementing<AmmoPool>() return rearmable != null && rearmable.Info.RearmActors.Contains(dest.Info.Name)
.Any(p => !p.AutoReloads && !p.FullAmmo()); && rearmable.RearmableAmmoPools.Any(p => !p.FullAmmo());
} }
} }
} }

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Mods.Common.Activities
readonly Aircraft aircraft; readonly Aircraft aircraft;
readonly AircraftInfo aircraftInfo; readonly AircraftInfo aircraftInfo;
readonly RepairableInfo repairableInfo; readonly RepairableInfo repairableInfo;
readonly Rearmable rearmable;
readonly bool alwaysLand; readonly bool alwaysLand;
readonly bool abortOnResupply; readonly bool abortOnResupply;
bool isCalculated; bool isCalculated;
@@ -37,14 +38,18 @@ namespace OpenRA.Mods.Common.Activities
aircraft = self.Trait<Aircraft>(); aircraft = self.Trait<Aircraft>();
aircraftInfo = self.Info.TraitInfo<AircraftInfo>(); aircraftInfo = self.Info.TraitInfo<AircraftInfo>();
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>(); repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmable = self.TraitOrDefault<Rearmable>();
} }
public static Actor ChooseResupplier(Actor self, bool unreservedOnly) public static Actor ChooseResupplier(Actor self, bool unreservedOnly)
{ {
var rearmBuildings = self.Info.TraitInfo<AircraftInfo>().RearmBuildings; var rearmInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
if (rearmInfo == null)
return null;
return self.World.ActorsHavingTrait<Reservable>() return self.World.ActorsHavingTrait<Reservable>()
.Where(a => a.Owner == self.Owner .Where(a => a.Owner == self.Owner
&& rearmBuildings.Contains(a.Info.Name) && rearmInfo.RearmActors.Contains(a.Info.Name)
&& (!unreservedOnly || !Reservable.IsReserved(a))) && (!unreservedOnly || !Reservable.IsReserved(a)))
.ClosestTo(self); .ClosestTo(self);
} }
@@ -109,8 +114,8 @@ namespace OpenRA.Mods.Common.Activities
if (repairableInfo != null && repairableInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged) if (repairableInfo != null && repairableInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged)
return true; return true;
return aircraftInfo.RearmBuildings.Contains(dest.Info.Name) && self.TraitsImplementing<AmmoPool>() return rearmable != null && rearmable.Info.RearmActors.Contains(dest.Info.Name)
.Any(p => !p.AutoReloads && !p.FullAmmo()); && rearmable.RearmableAmmoPools.Any(p => !p.FullAmmo());
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)

View File

@@ -21,13 +21,13 @@ namespace OpenRA.Mods.Common.Activities
{ {
readonly Target host; readonly Target host;
readonly WDist closeEnough; readonly WDist closeEnough;
readonly AmmoPool[] ammoPools; readonly Rearmable rearmable;
public Rearm(Actor self, Actor host, WDist closeEnough) public Rearm(Actor self, Actor host, WDist closeEnough)
{ {
this.host = Target.FromActor(host); this.host = Target.FromActor(host);
this.closeEnough = closeEnough; this.closeEnough = closeEnough;
ammoPools = self.TraitsImplementing<AmmoPool>().Where(p => !p.AutoReloads).ToArray(); rearmable = self.Trait<Rearmable>();
} }
protected override void OnFirstRun(Actor self) protected override void OnFirstRun(Actor self)
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Activities
// Reset the ReloadDelay to avoid any issues with early cancellation // Reset the ReloadDelay to avoid any issues with early cancellation
// from previous reload attempts (explicit order, host building died, etc). // from previous reload attempts (explicit order, host building died, etc).
// HACK: this really shouldn't be managed from here // HACK: this really shouldn't be managed from here
foreach (var pool in ammoPools) foreach (var pool in rearmable.RearmableAmmoPools)
pool.RemainingTicks = pool.Info.ReloadDelay; pool.RemainingTicks = pool.Info.ReloadDelay;
if (host.Type == TargetType.Invalid) if (host.Type == TargetType.Invalid)
@@ -73,7 +73,7 @@ namespace OpenRA.Mods.Common.Activities
return NextActivity; return NextActivity;
var complete = true; var complete = true;
foreach (var pool in ammoPools) foreach (var pool in rearmable.RearmableAmmoPools)
{ {
if (!pool.FullAmmo()) if (!pool.FullAmmo())
{ {

View File

@@ -931,6 +931,7 @@
<Compile Include="UpdateRules\Rules\20180923\LowPowerSlowdownToModifier.cs" /> <Compile Include="UpdateRules\Rules\20180923\LowPowerSlowdownToModifier.cs" />
<Compile Include="UpdateRules\Rules\20180923\RemoveHealthPercentageRing.cs" /> <Compile Include="UpdateRules\Rules\20180923\RemoveHealthPercentageRing.cs" />
<Compile Include="UpdateRules\Rules\20180923\RemoveRepairBuildingsFromAircraft.cs" /> <Compile Include="UpdateRules\Rules\20180923\RemoveRepairBuildingsFromAircraft.cs" />
<Compile Include="UpdateRules\Rules\20180923\AddRearmable.cs" />
<Compile Include="Traits\Player\PlayerResources.cs" /> <Compile Include="Traits\Player\PlayerResources.cs" />
<Compile Include="UtilityCommands\DumpSequenceSheetsCommand.cs" /> <Compile Include="UtilityCommands\DumpSequenceSheetsCommand.cs" />
<Compile Include="Traits\Render\WithBuildingRepairDecoration.cs" /> <Compile Include="Traits\Render\WithBuildingRepairDecoration.cs" />

View File

@@ -36,9 +36,6 @@ namespace OpenRA.Mods.Common.Traits
[Desc("The speed at which the aircraft is repulsed from other aircraft. Specify -1 for normal movement speed.")] [Desc("The speed at which the aircraft is repulsed from other aircraft. Specify -1 for normal movement speed.")]
public readonly int RepulsionSpeed = -1; public readonly int RepulsionSpeed = -1;
[ActorReference]
public readonly HashSet<string> RearmBuildings = new HashSet<string> { };
public readonly int InitialFacing = 0; public readonly int InitialFacing = 0;
public readonly int TurnSpeed = 255; public readonly int TurnSpeed = 255;
@@ -155,6 +152,7 @@ namespace OpenRA.Mods.Common.Traits
readonly Actor self; readonly Actor self;
RepairableInfo repairableInfo; RepairableInfo repairableInfo;
RearmableInfo rearmableInfo;
ConditionManager conditionManager; ConditionManager conditionManager;
IDisposable reservation; IDisposable reservation;
IEnumerable<int> speedModifiers; IEnumerable<int> speedModifiers;
@@ -211,6 +209,7 @@ namespace OpenRA.Mods.Common.Traits
protected virtual void Created(Actor self) protected virtual void Created(Actor self)
{ {
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>(); repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
conditionManager = self.TraitOrDefault<ConditionManager>(); conditionManager = self.TraitOrDefault<ConditionManager>();
speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier()); speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier());
cachedPosition = self.CenterPosition; cachedPosition = self.CenterPosition;
@@ -450,7 +449,7 @@ namespace OpenRA.Mods.Common.Traits
if (self.AppearsHostileTo(a)) if (self.AppearsHostileTo(a))
return false; return false;
return Info.RearmBuildings.Contains(a.Info.Name) return (rearmableInfo != null && rearmableInfo.RearmActors.Contains(a.Info.Name))
|| (repairableInfo != null && repairableInfo.RepairBuildings.Contains(a.Info.Name)); || (repairableInfo != null && repairableInfo.RepairBuildings.Contains(a.Info.Name));
} }
@@ -487,7 +486,7 @@ namespace OpenRA.Mods.Common.Traits
public virtual IEnumerable<Activity> GetResupplyActivities(Actor a) public virtual IEnumerable<Activity> GetResupplyActivities(Actor a)
{ {
var name = a.Info.Name; var name = a.Info.Name;
if (Info.RearmBuildings.Contains(name)) if (rearmableInfo != null && rearmableInfo.RearmActors.Contains(name))
yield return new Rearm(self, a, WDist.Zero); yield return new Rearm(self, a, WDist.Zero);
// The ResupplyAircraft activity guarantees that we're on the helipad // The ResupplyAircraft activity guarantees that we're on the helipad
@@ -669,13 +668,13 @@ namespace OpenRA.Mods.Common.Traits
Order IIssueDeployOrder.IssueDeployOrder(Actor self, bool queued) Order IIssueDeployOrder.IssueDeployOrder(Actor self, bool queued)
{ {
if (!Info.RearmBuildings.Any()) if (rearmableInfo == null || !rearmableInfo.RearmActors.Any())
return null; return null;
return new Order("ReturnToBase", self, queued); return new Order("ReturnToBase", self, queued);
} }
bool IIssueDeployOrder.CanIssueDeployOrder(Actor self) { return Info.RearmBuildings.Any(); } bool IIssueDeployOrder.CanIssueDeployOrder(Actor self) { return rearmableInfo != null && rearmableInfo.RearmActors.Any(); }
public string VoicePhraseForOrder(Actor self, Order order) public string VoicePhraseForOrder(Actor self, Order order)
{ {
@@ -689,7 +688,7 @@ namespace OpenRA.Mods.Common.Traits
case "Stop": case "Stop":
return Info.Voice; return Info.Voice;
case "ReturnToBase": case "ReturnToBase":
return Info.RearmBuildings.Any() ? Info.Voice : null; return rearmableInfo != null && rearmableInfo.RearmActors.Any() ? Info.Voice : null;
default: return null; default: return null;
} }
} }
@@ -782,7 +781,7 @@ namespace OpenRA.Mods.Common.Traits
self.QueueActivity(new HeliLand(self, true)); self.QueueActivity(new HeliLand(self, true));
} }
} }
else if (order.OrderString == "ReturnToBase" && Info.RearmBuildings.Any()) else if (order.OrderString == "ReturnToBase" && rearmableInfo != null && rearmableInfo.RearmActors.Any())
{ {
UnReserve(); UnReserve();
self.CancelActivity(); self.CancelActivity();

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Return to a player owned RearmBuildings. If none available, head back to base and circle over it.")] [Desc("Return to a player owned RearmActor. If none available, head back to base and circle over it.")]
public class ReturnOnIdleInfo : ITraitInfo, Requires<AircraftInfo> public class ReturnOnIdleInfo : ITraitInfo, Requires<AircraftInfo>
{ {
public object Create(ActorInitializer init) { return new ReturnOnIdle(init.Self, this); } public object Create(ActorInitializer init) { return new ReturnOnIdle(init.Self, this); }

View File

@@ -97,15 +97,9 @@ namespace OpenRA.Mods.Common.Traits
return true; return true;
} }
// This mostly serves to avoid complicated ReloadAmmoPool look-ups in various other places.
// TODO: Investigate removing this when the Rearm activity is replaced with a condition-based solution.
public bool AutoReloads { get; private set; }
void INotifyCreated.Created(Actor self) void INotifyCreated.Created(Actor self)
{ {
conditionManager = self.TraitOrDefault<ConditionManager>(); conditionManager = self.TraitOrDefault<ConditionManager>();
AutoReloads = self.TraitsImplementing<ReloadAmmoPool>().Any(r => r.Info.AmmoPool == Info.Name && r.Info.RequiresCondition == null);
UpdateCondition(self); UpdateCondition(self);
// HACK: Temporarily needed until Rearm activity is gone for good // HACK: Temporarily needed until Rearm activity is gone for good

View File

@@ -32,19 +32,23 @@ namespace OpenRA.Mods.Common.Traits
public virtual object Create(ActorInitializer init) { return new Repairable(init.Self, this); } public virtual object Create(ActorInitializer init) { return new Repairable(init.Self, this); }
} }
class Repairable : IIssueOrder, IResolveOrder, IOrderVoice class Repairable : IIssueOrder, IResolveOrder, IOrderVoice, INotifyCreated
{ {
public readonly RepairableInfo Info; public readonly RepairableInfo Info;
readonly IHealth health; readonly IHealth health;
readonly IMove movement; readonly IMove movement;
readonly AmmoPool[] ammoPools; Rearmable rearmable;
public Repairable(Actor self, RepairableInfo info) public Repairable(Actor self, RepairableInfo info)
{ {
Info = info; Info = info;
health = self.Trait<IHealth>(); health = self.Trait<IHealth>();
movement = self.Trait<IMove>(); movement = self.Trait<IMove>();
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray(); }
void INotifyCreated.Created(Actor self)
{
rearmable = self.TraitOrDefault<Rearmable>();
} }
public IEnumerable<IOrderTargeter> Orders public IEnumerable<IOrderTargeter> Orders
@@ -70,7 +74,7 @@ namespace OpenRA.Mods.Common.Traits
bool CanRearmAt(Actor target) bool CanRearmAt(Actor target)
{ {
return Info.RepairBuildings.Contains(target.Info.Name); return rearmable != null && rearmable.Info.RearmActors.Contains(target.Info.Name);
} }
bool CanRepair() bool CanRepair()
@@ -80,7 +84,7 @@ namespace OpenRA.Mods.Common.Traits
bool CanRearm() bool CanRearm()
{ {
return ammoPools.Any(x => !x.AutoReloads && !x.FullAmmo()); return rearmable != null && rearmable.RearmableAmmoPools.Any(p => !p.FullAmmo());
} }
public string VoicePhraseForOrder(Actor self, Order order) public string VoicePhraseForOrder(Actor self, Order order)

View File

@@ -0,0 +1,102 @@
#region Copyright & License Information
/*
* Copyright 2007-2018 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class AddRearmable : UpdateRule
{
public override string Name { get { return "Added Rearmable trait and move RearmBuildings properties there"; } }
public override string Description
{
get
{
return "Added Rearmable trait and replaced Aircraft.RearmBuildings and\n" +
"Minelayer.RearmBuildings with Rearmable.RearmActors.";
}
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
{
var aircraftNodes = actorNode.ChildrenMatching("Aircraft");
var minelayerNodes = actorNode.ChildrenMatching("Minelayer");
var ammoPoolNodes = actorNode.ChildrenMatching("AmmoPool");
var addNodes = new List<MiniYamlNode>();
var ammoPoolNames = new List<string>() { "primary" };
foreach (var ap in ammoPoolNodes)
{
var poolName = ap.LastChildMatching("Name");
if (poolName != null && poolName.NodeValue<string>() != "primary")
ammoPoolNames.Add(poolName.NodeValue<string>());
}
var rearmableAdded = false;
foreach (var aircraftNode in aircraftNodes)
{
var rearmBuildings = aircraftNode.LastChildMatching("RearmBuildings");
if (rearmBuildings != null)
{
if (!rearmableAdded)
{
var rearmableNode = new MiniYamlNode("Rearmable", "");
rearmBuildings.MoveAndRenameNode(aircraftNode, rearmableNode, "RearmActors");
// If the list has more than one entry, at least one of them won't be "primary"
if (ammoPoolNames.Count > 1)
{
var ammoPools = new MiniYamlNode("AmmoPools", string.Join(", ", ammoPoolNames));
rearmableNode.AddNode(ammoPools);
}
addNodes.Add(rearmableNode);
rearmableAdded = true;
}
else
aircraftNode.RemoveNodes("RearmBuildings");
}
}
// If it's a minelayer, it won't be an aircraft and rearmableAdded should still be false, so we can use it here
foreach (var minelayerNode in minelayerNodes)
{
var rearmableNode = new MiniYamlNode("Rearmable", "");
var rearmBuildings = minelayerNode.LastChildMatching("RearmBuildings");
if (!rearmableAdded)
{
if (rearmBuildings != null)
rearmBuildings.MoveAndRenameNode(minelayerNode, rearmableNode, "RearmActors");
else
rearmableNode.AddNode(new MiniYamlNode("RearmActors", "fix"));
// If the list has more than one entry, at least one of them won't be "primary"
if (ammoPoolNames.Count > 1)
{
var ammoPools = new MiniYamlNode("AmmoPools", string.Join(", ", ammoPoolNames));
rearmableNode.AddNode(ammoPools);
}
addNodes.Add(rearmableNode);
rearmableAdded = true;
}
else if (rearmableAdded && rearmBuildings != null)
minelayerNode.RemoveNodes("RearmBuildings");
}
foreach (var node in addNodes)
actorNode.AddNode(node);
yield break;
}
}
}

View File

@@ -100,6 +100,7 @@ namespace OpenRA.Mods.Common.UpdateRules
new RemoveHealthPercentageRing(), new RemoveHealthPercentageRing(),
new RenameCrateActionNotification(), new RenameCrateActionNotification(),
new RemoveRepairBuildingsFromAircraft(), new RemoveRepairBuildingsFromAircraft(),
new AddRearmable(),
}) })
}; };

View File

@@ -109,7 +109,6 @@ MIG:
AttackPlane: AttackPlane:
FacingTolerance: 20 FacingTolerance: 20
Aircraft: Aircraft:
RearmBuildings: afld, afld.ukraine
CruiseAltitude: 2560 CruiseAltitude: 2560
InitialFacing: 192 InitialFacing: 192
TurnSpeed: 4 TurnSpeed: 4
@@ -138,6 +137,8 @@ MIG:
Interval: 2 Interval: 2
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: aircraft.upgraded Prerequisites: aircraft.upgraded
Rearmable:
RearmActors: afld, afld.ukraine
YAK: YAK:
Inherits: ^Plane Inherits: ^Plane
@@ -175,7 +176,6 @@ YAK:
AttackPlane: AttackPlane:
FacingTolerance: 20 FacingTolerance: 20
Aircraft: Aircraft:
RearmBuildings: afld, afld.ukraine
CruiseAltitude: 2560 CruiseAltitude: 2560
InitialFacing: 192 InitialFacing: 192
TurnSpeed: 4 TurnSpeed: 4
@@ -204,6 +204,8 @@ YAK:
Prerequisites: aircraft.upgraded Prerequisites: aircraft.upgraded
Selectable: Selectable:
DecorationBounds: 30,28,0,2 DecorationBounds: 30,28,0,2
Rearmable:
RearmActors: afld, afld.ukraine
TRAN: TRAN:
Inherits: ^Helicopter Inherits: ^Helicopter
@@ -292,7 +294,6 @@ HELI:
AttackHeli: AttackHeli:
FacingTolerance: 20 FacingTolerance: 20
Aircraft: Aircraft:
RearmBuildings: hpad
LandWhenIdle: false LandWhenIdle: false
InitialFacing: 224 InitialFacing: 224
TurnSpeed: 4 TurnSpeed: 4
@@ -320,6 +321,8 @@ HELI:
Prerequisites: aircraft.upgraded Prerequisites: aircraft.upgraded
Selectable: Selectable:
DecorationBounds: 36,28 DecorationBounds: 36,28
Rearmable:
RearmActors: hpad
HIND: HIND:
Inherits: ^Helicopter Inherits: ^Helicopter
@@ -357,7 +360,6 @@ HIND:
AttackHeli: AttackHeli:
FacingTolerance: 20 FacingTolerance: 20
Aircraft: Aircraft:
RearmBuildings: hpad
LandWhenIdle: false LandWhenIdle: false
InitialFacing: 224 InitialFacing: 224
TurnSpeed: 4 TurnSpeed: 4
@@ -386,6 +388,8 @@ HIND:
Prerequisites: aircraft.upgraded Prerequisites: aircraft.upgraded
Selectable: Selectable:
DecorationBounds: 38,32 DecorationBounds: 38,32
Rearmable:
RearmActors: hpad
U2: U2:
Inherits: ^NeutralPlane Inherits: ^NeutralPlane

View File

@@ -492,6 +492,8 @@ MNLY:
Weapon: ATMine Weapon: ATMine
RenderSprites: RenderSprites:
Image: MNLY Image: MNLY
Rearmable:
RearmActors: fix
TRUK: TRUK:
Inherits: ^Vehicle Inherits: ^Vehicle

View File

@@ -80,7 +80,6 @@ ORCA:
Selectable: Selectable:
Bounds: 30,24 Bounds: 30,24
Aircraft: Aircraft:
RearmBuildings: gahpad, nahpad
TurnSpeed: 5 TurnSpeed: 5
Speed: 186 Speed: 186
MoveIntoShroud: false MoveIntoShroud: false
@@ -109,6 +108,8 @@ ORCA:
RenderSprites: RenderSprites:
SpawnActorOnDeath: SpawnActorOnDeath:
Actor: ORCA.Husk Actor: ORCA.Husk
Rearmable:
RearmActors: gahpad, nahpad
ORCAB: ORCAB:
Inherits: ^Aircraft Inherits: ^Aircraft
@@ -127,7 +128,6 @@ ORCAB:
Selectable: Selectable:
Bounds: 30,24 Bounds: 30,24
Aircraft: Aircraft:
RearmBuildings: gahpad, nahpad
CruiseAltitude: 3072 CruiseAltitude: 3072
MaximumPitch: 120 MaximumPitch: 120
TurnSpeed: 3 TurnSpeed: 3
@@ -164,6 +164,8 @@ ORCAB:
RequiresCondition: cruising RequiresCondition: cruising
SpawnActorOnDeath: SpawnActorOnDeath:
Actor: ORCAB.Husk Actor: ORCAB.Husk
Rearmable:
RearmActors: gahpad, nahpad
ORCATRAN: ORCATRAN:
Inherits: ^Helicopter Inherits: ^Helicopter
@@ -257,7 +259,6 @@ SCRIN:
Voiced: Voiced:
VoiceSet: Scrin VoiceSet: Scrin
Aircraft: Aircraft:
RearmBuildings: gahpad, nahpad
CruiseAltitude: 2560 CruiseAltitude: 2560
MaximumPitch: 90 MaximumPitch: 90
TurnSpeed: 3 TurnSpeed: 3
@@ -292,6 +293,8 @@ SCRIN:
DeathSounds: DeathSounds:
SpawnActorOnDeath: SpawnActorOnDeath:
Actor: SCRIN.Husk Actor: SCRIN.Husk
Rearmable:
RearmActors: gahpad, nahpad
APACHE: APACHE:
Inherits: ^Helicopter Inherits: ^Helicopter
@@ -310,7 +313,6 @@ APACHE:
Selectable: Selectable:
Bounds: 30,24 Bounds: 30,24
Aircraft: Aircraft:
RearmBuildings: gahpad, nahpad
TurnSpeed: 5 TurnSpeed: 5
Speed: 130 Speed: 130
MoveIntoShroud: false MoveIntoShroud: false
@@ -345,6 +347,8 @@ APACHE:
RenderSprites: RenderSprites:
SpawnActorOnDeath: SpawnActorOnDeath:
Actor: APACHE.Husk Actor: APACHE.Husk
Rearmable:
RearmActors: gahpad, nahpad
HUNTER: HUNTER:
Inherits@2: ^ExistsInWorld Inherits@2: ^ExistsInWorld