Fix air unit resupply #5966

This commit is contained in:
PedroFerreiraRamos
2016-06-02 18:22:21 -03:00
parent 60d7ef99d4
commit 958e35d61f
8 changed files with 94 additions and 9 deletions

View File

@@ -105,6 +105,7 @@ Also thanks to:
* Paolo Chiodi (paolochiodi) * Paolo Chiodi (paolochiodi)
* Paul Dovydaitis (pdovy) * Paul Dovydaitis (pdovy)
* Pavlos Touboulidis (pav) * Pavlos Touboulidis (pav)
* Pedro Ferreira Ramos (bateramos)
* Pizzaoverhead * Pizzaoverhead
* Piët Delport (pjdelport) * Piët Delport (pjdelport)
* Psydev * Psydev

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Activities
// Move to the next activity only if all ammo pools are depleted and none reload automatically // Move to the next activity only if all ammo pools are depleted and none reload automatically
// TODO: This should check whether there is ammo left that is actually suitable for the target // TODO: This should check whether there is ammo left that is actually suitable for the target
if (ammoPools.All(x => !x.Info.SelfReloads && !x.HasAmmo())) if (ammoPools.All(x => !x.Info.SelfReloads && !x.HasAmmo()))
return NextActivity; return ActivityUtils.SequenceActivities(new ReturnToBase(self), NextActivity);
if (attackPlane != null) if (attackPlane != null)
attackPlane.DoAttack(self, target); attackPlane.DoAttack(self, target);

View File

@@ -0,0 +1,36 @@
#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 OpenRA.Activities;
using OpenRA.Mods.Common.Traits;
namespace OpenRA.Mods.Common.Activities
{
public class FlyCircleTimed : FlyCircle
{
int remainingTicks;
public FlyCircleTimed(int ticks, Actor self) : base(self)
{
remainingTicks = ticks;
}
public override Activity Tick(Actor self)
{
if (IsCanceled || remainingTicks-- == 0)
return NextActivity;
base.Tick(self);
return this;
}
}
}

View File

@@ -44,13 +44,28 @@ namespace OpenRA.Mods.Common.Activities
{ {
var rearmBuildings = heli.Info.RearmBuildings; var rearmBuildings = heli.Info.RearmBuildings;
var nearestHpad = self.World.ActorsHavingTrait<Reservable>() var nearestHpad = self.World.ActorsHavingTrait<Reservable>()
.Where(a => a.Owner == self.Owner && rearmBuildings.Contains(a.Info.Name)) .Where(a => a.Owner == self.Owner && rearmBuildings.Contains(a.Info.Name))
.ClosestTo(self); .ClosestTo(self);
if (nearestHpad == null) if (nearestHpad == null)
return ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity); return ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity);
else else
return ActivityUtils.SequenceActivities(new HeliFly(self, Target.FromActor(nearestHpad))); {
var distanceFromHelipad = (nearestHpad.CenterPosition - self.CenterPosition).HorizontalLength;
var distanceLength = heli.Info.WaitDistanceFromResupplyBase.Length;
// If no pad is available, move near one and wait
if (distanceFromHelipad > distanceLength)
{
var randomPosition = WVec.FromPDF(self.World.SharedRandom, 2) * distanceLength / 1024;
var target = Target.FromPos(nearestHpad.CenterPosition + randomPosition);
return ActivityUtils.SequenceActivities(new HeliFly(self, target, WDist.Zero, heli.Info.WaitDistanceFromResupplyBase), this);
}
return this;
}
} }
heli.MakeReservation(dest); heli.MakeReservation(dest);
@@ -62,7 +77,8 @@ namespace OpenRA.Mods.Common.Activities
new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)), new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)),
new Turn(self, initialFacing), new Turn(self, initialFacing),
new HeliLand(self, false), new HeliLand(self, false),
new ResupplyAircraft(self)); new ResupplyAircraft(self),
NextActivity);
} }
} }
} }

View File

@@ -32,8 +32,17 @@ namespace OpenRA.Mods.Common.Activities
if (host == null) if (host == null)
return NextActivity; return NextActivity;
if (aircraft.IsPlane)
return ActivityUtils.SequenceActivities(
aircraft.GetResupplyActivities(host)
.Append(new CallFunc(() => aircraft.UnReserve()))
.Append(new WaitFor(() => NextActivity != null || Reservable.IsReserved(host)))
.Append(new TakeOff(self))
.Append(NextActivity).ToArray());
// If is helicopter move away as soon as the resupply ends
return ActivityUtils.SequenceActivities( return ActivityUtils.SequenceActivities(
aircraft.GetResupplyActivities(host).Append(NextActivity).ToArray()); aircraft.GetResupplyActivities(host).Append(new TakeOff(self)).Append(NextActivity).ToArray());
} }
} }
} }

View File

@@ -106,11 +106,13 @@ namespace OpenRA.Mods.Common.Activities
{ {
var nearestAfld = ChooseAirfield(self, false); var nearestAfld = ChooseAirfield(self, false);
self.CancelActivity();
if (nearestAfld != null) if (nearestAfld != null)
return ActivityUtils.SequenceActivities(new Fly(self, Target.FromActor(nearestAfld)), new FlyCircle(self)); return ActivityUtils.SequenceActivities(
new Fly(self, Target.FromActor(nearestAfld), WDist.Zero, plane.Info.WaitDistanceFromResupplyBase),
new FlyCircleTimed(plane.Info.NumberOfTicksToVerifyAvailableAirport, self),
this);
else else
return new FlyCircle(self); return NextActivity;
} }
List<Activity> landingProcedures = new List<Activity>(); List<Activity> landingProcedures = new List<Activity>();
@@ -123,6 +125,7 @@ namespace OpenRA.Mods.Common.Activities
// Fix a problem when the airplane is send to resupply near the airport // Fix a problem when the airplane is send to resupply near the airport
landingProcedures.Add(new Fly(self, Target.FromPos(w3), WDist.Zero, new WDist(turnRadius / 2))); landingProcedures.Add(new Fly(self, Target.FromPos(w3), WDist.Zero, new WDist(turnRadius / 2)));
landingProcedures.Add(new Land(self, Target.FromActor(dest))); landingProcedures.Add(new Land(self, Target.FromActor(dest)));
landingProcedures.Add(new ResupplyAircraft(self));
landingProcedures.Add(NextActivity); landingProcedures.Add(NextActivity);
return ActivityUtils.SequenceActivities(landingProcedures.ToArray()); return ActivityUtils.SequenceActivities(landingProcedures.ToArray());

View File

@@ -774,6 +774,7 @@
<Compile Include="Traits\Buildings\FreeActorWithDelivery.cs" /> <Compile Include="Traits\Buildings\FreeActorWithDelivery.cs" />
<Compile Include="Traits\ExitsDebugOverlay.cs" /> <Compile Include="Traits\ExitsDebugOverlay.cs" />
<Compile Include="Traits\World\ExitsDebugOverlayManager.cs" /> <Compile Include="Traits\World\ExitsDebugOverlayManager.cs" />
<Compile Include="Activities\Air\FlyCircleTimed.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>

View File

@@ -83,6 +83,12 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Sound to play when the actor is landing.")] [Desc("Sound to play when the actor is landing.")]
public readonly string LandingSound = null; public readonly string LandingSound = null;
[Desc("The distance of the resupply base that the aircraft will wait for its turn.")]
public readonly WDist WaitDistanceFromResupplyBase = new WDist(3072);
[Desc("The number of ticks that a airplane will wait to make a new search for an available airport.")]
public readonly int NumberOfTicksToVerifyAvailableAirport = 150;
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); } public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
bool IOccupySpaceInfo.SharesCell { get { return false; } } bool IOccupySpaceInfo.SharesCell { get { return false; } }
} }
@@ -98,6 +104,7 @@ namespace OpenRA.Mods.Common.Traits
UpgradeManager um; UpgradeManager um;
IDisposable reservation; IDisposable reservation;
Actor reservedActor;
IEnumerable<int> speedModifiers; IEnumerable<int> speedModifiers;
[Sync] public int Facing { get; set; } [Sync] public int Facing { get; set; }
@@ -181,6 +188,13 @@ namespace OpenRA.Mods.Common.Traits
if (!Info.Repulsable) if (!Info.Repulsable)
return WVec.Zero; return WVec.Zero;
if (reservation != null)
{
var distanceFromReservationActor = (reservedActor.CenterPosition - self.CenterPosition).HorizontalLength;
if (distanceFromReservationActor < Info.WaitDistanceFromResupplyBase.Length)
return WVec.Zero;
}
// Repulsion only applies when we're flying! // Repulsion only applies when we're flying!
var altitude = self.World.Map.DistanceAboveTerrain(CenterPosition).Length; var altitude = self.World.Map.DistanceAboveTerrain(CenterPosition).Length;
if (altitude != Info.CruiseAltitude.Length) if (altitude != Info.CruiseAltitude.Length)
@@ -261,7 +275,10 @@ namespace OpenRA.Mods.Common.Traits
UnReserve(); UnReserve();
var reservable = target.TraitOrDefault<Reservable>(); var reservable = target.TraitOrDefault<Reservable>();
if (reservable != null) if (reservable != null)
{
reservation = reservable.Reserve(target, self, this); reservation = reservable.Reserve(target, self, this);
reservedActor = target;
}
} }
public void UnReserve() public void UnReserve()
@@ -271,6 +288,8 @@ namespace OpenRA.Mods.Common.Traits
reservation.Dispose(); reservation.Dispose();
reservation = null; reservation = null;
reservedActor = null;
if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length <= Info.LandAltitude.Length) if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length <= Info.LandAltitude.Length)
self.QueueActivity(new TakeOff(self)); self.QueueActivity(new TakeOff(self));
} }