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)
* Paul Dovydaitis (pdovy)
* Pavlos Touboulidis (pav)
* Pedro Ferreira Ramos (bateramos)
* Pizzaoverhead
* Piët Delport (pjdelport)
* 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
// 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()))
return NextActivity;
return ActivityUtils.SequenceActivities(new ReturnToBase(self), NextActivity);
if (attackPlane != null)
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 nearestHpad = self.World.ActorsHavingTrait<Reservable>()
.Where(a => a.Owner == self.Owner && rearmBuildings.Contains(a.Info.Name))
.ClosestTo(self);
.Where(a => a.Owner == self.Owner && rearmBuildings.Contains(a.Info.Name))
.ClosestTo(self);
if (nearestHpad == null)
return ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity);
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);
@@ -62,7 +77,8 @@ namespace OpenRA.Mods.Common.Activities
new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)),
new Turn(self, initialFacing),
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)
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(
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);
self.CancelActivity();
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
return new FlyCircle(self);
return NextActivity;
}
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
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 ResupplyAircraft(self));
landingProcedures.Add(NextActivity);
return ActivityUtils.SequenceActivities(landingProcedures.ToArray());

View File

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

View File

@@ -83,6 +83,12 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Sound to play when the actor is landing.")]
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>(); }
bool IOccupySpaceInfo.SharesCell { get { return false; } }
}
@@ -98,6 +104,7 @@ namespace OpenRA.Mods.Common.Traits
UpgradeManager um;
IDisposable reservation;
Actor reservedActor;
IEnumerable<int> speedModifiers;
[Sync] public int Facing { get; set; }
@@ -181,6 +188,13 @@ namespace OpenRA.Mods.Common.Traits
if (!Info.Repulsable)
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!
var altitude = self.World.Map.DistanceAboveTerrain(CenterPosition).Length;
if (altitude != Info.CruiseAltitude.Length)
@@ -261,7 +275,10 @@ namespace OpenRA.Mods.Common.Traits
UnReserve();
var reservable = target.TraitOrDefault<Reservable>();
if (reservable != null)
{
reservation = reservable.Reserve(target, self, this);
reservedActor = target;
}
}
public void UnReserve()
@@ -271,6 +288,8 @@ namespace OpenRA.Mods.Common.Traits
reservation.Dispose();
reservation = null;
reservedActor = null;
if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length <= Info.LandAltitude.Length)
self.QueueActivity(new TakeOff(self));
}