Skip to content

Commit

Permalink
Remove RearmBuildings from Aircraft and Minelayer in favor of Rearmab…
Browse files Browse the repository at this point in the history
…le trait
  • Loading branch information
reaperrr committed Dec 28, 2017
1 parent 18d1a49 commit d0525b8
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 56 deletions.
6 changes: 3 additions & 3 deletions OpenRA.Mods.Cnc/Activities/LayMines.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public class LayMines : Activity
readonly MinelayerInfo info;
readonly AmmoPool[] ammoPools;
readonly IMove movement;
readonly HashSet<string> rearmBuildings;
readonly HashSet<string> rearmActors;

public LayMines(Actor self)
{
minelayer = self.TraitOrDefault<Minelayer>();
info = self.Info.TraitInfo<MinelayerInfo>();
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
movement = self.Trait<IMove>();
rearmBuildings = info.RearmBuildings;
rearmActors = self.Info.TraitInfo<RearmableInfo>().RearmActors;
}

public override Activity Tick(Actor self)
Expand All @@ -47,7 +47,7 @@ public override Activity Tick(Actor self)
{
// 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
&& rearmBuildings.Contains(a.Info.Name))
&& rearmActors.Contains(a.Info.Name))
.ClosestTo(self);

if (rearmTarget == null)
Expand Down
3 changes: 1 addition & 2 deletions OpenRA.Mods.Cnc/Traits/Minelayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@

namespace OpenRA.Mods.Cnc.Traits
{
public class MinelayerInfo : ITraitInfo
public class MinelayerInfo : ITraitInfo, Requires<RearmableInfo>
{
[ActorReference] public readonly string Mine = "minv";
[ActorReference] public readonly HashSet<string> RearmBuildings = new HashSet<string> { "fix" };

public readonly string AmmoPoolName = "primary";

Expand Down
14 changes: 9 additions & 5 deletions OpenRA.Mods.Common/AI/HackyAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -497,19 +497,23 @@ public bool HasMinimumProc()
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)
{
var aircraftInfo = actorInfo.TraitInfoOrDefault<AircraftInfo>();
if (aircraftInfo == null)
return true;

// If the aircraft has at least 1 AmmoPool and defines 1 or more RearmBuildings, check if we have enough of those
var hasAmmoPool = actorInfo.TraitInfos<AmmoPoolInfo>().Any();
if (hasAmmoPool && aircraftInfo.RearmBuildings.Count > 0)
// If actor isn't Rearmable, it doesn't need a RearmActor to reload
var rearmableInfo = actorInfo.TraitInfoOrDefault<RearmableInfo>();
if (rearmableInfo == null)
return true;

// If the aircraft has at least 1 AmmoPool, check if we have enough RearmActors
if (actorInfo.HasTraitInfo<AmmoPoolInfo>())
{
var countOwnAir = CountUnits(actorInfo.Name, Player);
var countBuildings = aircraftInfo.RearmBuildings.Sum(b => CountBuilding(b, Player));
var countBuildings = rearmableInfo.RearmActors.Sum(b => CountBuilding(b, Player));
if (countOwnAir >= countBuildings)
return false;
}
Expand Down
13 changes: 6 additions & 7 deletions OpenRA.Mods.Common/Activities/Air/FlyAttack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ public class FlyAttack : Activity
readonly Target target;
readonly Aircraft aircraft;
readonly AttackPlane attackPlane;
readonly Rearmable rearmable;

readonly bool autoReloads;
int ticksUntilTurn;

public FlyAttack(Actor self, Target target)
{
this.target = target;
aircraft = self.Trait<Aircraft>();
attackPlane = self.TraitOrDefault<AttackPlane>();
attackPlane = self.Trait<AttackPlane>();
rearmable = self.TraitOrDefault<Rearmable>();
ticksUntilTurn = attackPlane.AttackPlaneInfo.AttackTurnDelay;
autoReloads = self.TraitsImplementing<AmmoPool>().All(p => p.AutoReloads);
}

public override Activity Tick(Actor self)
Expand All @@ -46,12 +46,11 @@ public override Activity Tick(Actor self)
if (!target.IsValidFor(self))
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 (!autoReloads && aircraft.Info.RearmBuildings.Any() && attackPlane.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
// If all valid weapons have depleted their ammo and Rearmable trait exists, return to RearmActor to reload and then resume the activity
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);

if (attackPlane != null)
attackPlane.DoAttack(self, target);
attackPlane.DoAttack(self, target);

if (ChildActivity == null)
{
Expand Down
8 changes: 4 additions & 4 deletions OpenRA.Mods.Common/Activities/Air/HeliAttack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class HeliAttack : Activity
readonly Aircraft helicopter;
readonly AttackHeli attackHeli;
readonly bool attackOnlyVisibleTargets;
readonly bool autoReloads;
readonly Rearmable rearmable;

Target target;
bool canHideUnderFog;
Expand All @@ -47,7 +47,7 @@ public HeliAttack(Actor self, Target target, bool attackOnlyVisibleTargets = tru
helicopter = self.Trait<Aircraft>();
attackHeli = self.Trait<AttackHeli>();
this.attackOnlyVisibleTargets = attackOnlyVisibleTargets;
autoReloads = self.TraitsImplementing<AmmoPool>().All(p => p.AutoReloads);
rearmable = self.TraitOrDefault<Rearmable>();
}

public override Activity Tick(Actor self)
Expand All @@ -74,8 +74,8 @@ public override Activity Tick(Actor self)
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 (!autoReloads && helicopter.Info.RearmBuildings.Any() && attackHeli.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
// If all valid weapons have depleted their ammo and Rearmable trait exists, return to RearmActor to reload and then resume the activity
if (rearmable != null && attackHeli.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
return ActivityUtils.SequenceActivities(new HeliReturnToBase(self, helicopter.Info.AbortOnResupply), this);

var dist = targetPos - pos;
Expand Down
25 changes: 15 additions & 10 deletions OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class HeliReturnToBase : Activity
{
readonly Aircraft aircraft;
readonly RepairableInfo repairableInfo;
readonly RearmableInfo rearmableInfo;
readonly bool alwaysLand;
readonly bool abortOnResupply;
Actor dest;
Expand All @@ -28,16 +29,20 @@ public HeliReturnToBase(Actor self, bool abortOnResupply, Actor dest = null, boo
{
aircraft = self.Trait<Aircraft>();
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
this.alwaysLand = alwaysLand;
this.abortOnResupply = abortOnResupply;
this.dest = dest;
}

public Actor ChooseHelipad(Actor self, bool unreservedOnly)
public Actor ChooseResupplier(Actor self, bool unreservedOnly)
{
var rearmBuildings = aircraft.Info.RearmBuildings;
if (rearmableInfo == null)
return null;

var rearmActors = rearmableInfo.RearmActors;
return self.World.Actors.Where(a => a.Owner == self.Owner
&& rearmBuildings.Contains(a.Info.Name)
&& rearmActors.Contains(a.Info.Name)
&& (!unreservedOnly || !Reservable.IsReserved(a)))
.ClosestTo(self);
}
Expand All @@ -53,27 +58,27 @@ public override Activity Tick(Actor self)
return NextActivity;

if (dest == null || dest.IsDead || Reservable.IsReserved(dest))
dest = ChooseHelipad(self, true);
dest = ChooseResupplier(self, true);

var initialFacing = aircraft.Info.InitialFacing;

if (dest == null || dest.IsDead)
{
var nearestHpad = ChooseHelipad(self, false);
var nearestResupplier = ChooseResupplier(self, false);

if (nearestHpad == null)
if (nearestResupplier == null)
return ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity);
else
{
var distanceFromHelipad = (nearestHpad.CenterPosition - self.CenterPosition).HorizontalLength;
var distanceFromResupplier = (nearestResupplier.CenterPosition - self.CenterPosition).HorizontalLength;
var distanceLength = aircraft.Info.WaitDistanceFromResupplyBase.Length;

// If no pad is available, move near one and wait
if (distanceFromHelipad > distanceLength)
if (distanceFromResupplier > distanceLength)
{
var randomPosition = WVec.FromPDF(self.World.SharedRandom, 2) * distanceLength / 1024;

var target = Target.FromPos(nearestHpad.CenterPosition + randomPosition);
var target = Target.FromPos(nearestResupplier.CenterPosition + randomPosition);

return ActivityUtils.SequenceActivities(new HeliFly(self, target, WDist.Zero, aircraft.Info.WaitDistanceFromResupplyBase), this);
}
Expand Down Expand Up @@ -110,7 +115,7 @@ bool ShouldLandAtBuilding(Actor self, Actor dest)
if (repairableInfo != null && repairableInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged)
return true;

return aircraft.Info.RearmBuildings.Contains(dest.Info.Name) && self.TraitsImplementing<AmmoPool>()
return rearmableInfo != null && rearmableInfo.RearmActors.Contains(dest.Info.Name) && self.TraitsImplementing<AmmoPool>()
.Any(p => !p.AutoReloads && !p.FullAmmo());
}
}
Expand Down
22 changes: 14 additions & 8 deletions OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class ReturnToBase : Activity
readonly Aircraft aircraft;
readonly AircraftInfo aircraftInfo;
readonly RepairableInfo repairableInfo;
readonly RearmableInfo rearmableInfo;
readonly bool alwaysLand;
readonly bool abortOnResupply;
bool isCalculated;
Expand All @@ -37,22 +38,27 @@ public ReturnToBase(Actor self, bool abortOnResupply, Actor dest = null, bool al
aircraft = self.Trait<Aircraft>();
aircraftInfo = self.Info.TraitInfo<AircraftInfo>();
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
}

public static Actor ChooseAirfield(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;

var rearmActors = rearmInfo.RearmActors;
return self.World.ActorsHavingTrait<Reservable>()
.Where(a => a.Owner == self.Owner
&& rearmBuildings.Contains(a.Info.Name)
&& rearmActors.Contains(a.Info.Name)
&& (!unreservedOnly || !Reservable.IsReserved(a)))
.ClosestTo(self);
}

void Calculate(Actor self)
{
if (dest == null || dest.IsDead || Reservable.IsReserved(dest))
dest = ChooseAirfield(self, true);
dest = ChooseResupplier(self, true);

if (dest == null)
return;
Expand Down Expand Up @@ -106,7 +112,7 @@ bool ShouldLandAtBuilding(Actor self, Actor dest)
if (repairableInfo != null && repairableInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged)
return true;

return aircraftInfo.RearmBuildings.Contains(dest.Info.Name) && self.TraitsImplementing<AmmoPool>()
return rearmableInfo != null && rearmableInfo.RearmActors.Contains(dest.Info.Name) && self.TraitsImplementing<AmmoPool>()
.Any(p => !p.AutoReloads && !p.FullAmmo());
}

Expand All @@ -125,11 +131,11 @@ public override Activity Tick(Actor self)

if (dest == null || dest.IsDead)
{
var nearestAfld = ChooseAirfield(self, false);
var nearestResupplier = ChooseResupplier(self, false);

if (nearestAfld != null)
if (nearestResupplier != null)
return ActivityUtils.SequenceActivities(
new Fly(self, Target.FromActor(nearestAfld), WDist.Zero, aircraft.Info.WaitDistanceFromResupplyBase),
new Fly(self, Target.FromActor(nearestResupplier), WDist.Zero, aircraft.Info.WaitDistanceFromResupplyBase),
new FlyCircle(self, aircraft.Info.NumberOfTicksToVerifyAvailableAirport),
this);
else
Expand Down
13 changes: 6 additions & 7 deletions OpenRA.Mods.Common/Traits/Air/Aircraft.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ public class AircraftInfo : ITraitInfo, IPositionableInfo, IFacingInfo, IMoveInf
[Desc("The speed at which the aircraft is repulsed from other aircraft. Specify -1 for normal movement speed.")]
public readonly int RepulsionSpeed = -1;

[ActorReference]
public readonly HashSet<string> RearmBuildings = new HashSet<string> { };

public readonly int InitialFacing = 0;

public readonly int TurnSpeed = 255;
Expand Down Expand Up @@ -152,9 +149,10 @@ public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder
static readonly Pair<CPos, SubCell>[] NoCells = { };

public readonly AircraftInfo Info;
readonly RepairableInfo repairableInfo;
readonly Actor self;

RepairableInfo repairableInfo;
RearmableInfo rearmableInfo;
ConditionManager conditionManager;
IDisposable reservation;
IEnumerable<int> speedModifiers;
Expand Down Expand Up @@ -182,7 +180,6 @@ public Aircraft(ActorInitializer init, AircraftInfo info)
{
Info = info;
self = init.Self;
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();

if (init.Contains<LocationInit>())
SetPosition(self, init.Get<LocationInit, CPos>());
Expand Down Expand Up @@ -211,6 +208,8 @@ void INotifyCreated.Created(Actor self)

protected virtual void Created(Actor self)
{
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
conditionManager = self.TraitOrDefault<ConditionManager>();
speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier());
cachedPosition = self.CenterPosition;
Expand Down Expand Up @@ -450,7 +449,7 @@ public bool AircraftCanEnter(Actor a)
if (self.AppearsHostileTo(a))
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));
}

Expand Down Expand Up @@ -487,7 +486,7 @@ public bool CanLand(CPos cell)
public virtual IEnumerable<Activity> GetResupplyActivities(Actor a)
{
var name = a.Info.Name;
if (Info.RearmBuildings.Contains(name))
if (rearmableInfo != null && rearmableInfo.RearmActors.Contains(name))
yield return new Rearm(self);

// The ResupplyAircraft activity guarantees that we're on the helipad
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

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 RearmActors. If none available, head back to base and circle over it.")]
public class ReturnOnIdleInfo : ITraitInfo, Requires<AircraftInfo>
{
public object Create(ActorInitializer init) { return new ReturnOnIdle(init.Self, this); }
Expand All @@ -36,7 +36,7 @@ void INotifyIdle.TickIdle(Actor self)
if (self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length < aircraftInfo.MinAirborneAltitude)
return;

var airfield = ReturnToBase.ChooseAirfield(self, true);
var airfield = ReturnToBase.ChooseResupplier(self, true);
if (airfield != null)
{
self.QueueActivity(new ReturnToBase(self, aircraftInfo.AbortOnResupply, airfield));
Expand Down
Loading

0 comments on commit d0525b8

Please sign in to comment.