Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spawn aircraft occupying land or at cruise altitude #21366

Open
wants to merge 2 commits into
base: bleed
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
99 changes: 78 additions & 21 deletions OpenRA.Mods.Common/Traits/Air/Aircraft.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ public WAngle GetTurnSpeed(bool isIdleTurn)
public bool RequireForceMove;

readonly int creationActivityDelay;
readonly bool creationByMap;
readonly CPos[] creationRallyPoint;

bool notify = true;
Expand All @@ -312,12 +313,13 @@ public Aircraft(ActorInitializer init, AircraftInfo info)
self = init.Self;

var locationInit = init.GetOrDefault<LocationInit>();
if (locationInit != null)
SetPosition(self, locationInit.Value);

var centerPositionInit = init.GetOrDefault<CenterPositionInit>();
if (centerPositionInit != null)
SetPosition(self, centerPositionInit.Value);
if (locationInit != null || centerPositionInit != null)
{
var pos = centerPositionInit?.Value ?? self.World.Map.CenterOfCell(locationInit.Value);
creationByMap = init.Contains<SpawnedByMapInit>();
SetPosition(self, pos);
}

Facing = init.GetValue<FacingInit, WAngle>(Info.InitialFacing);
creationActivityDelay = init.GetValue<CreationActivityDelayInit, int>(0);
Expand Down Expand Up @@ -1220,8 +1222,8 @@ void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary

Activity ICreationActivity.GetCreationActivity()
{
if (creationRallyPoint != null || creationActivityDelay > 0)
return new AssociateWithAirfieldActivity(self, creationActivityDelay, creationRallyPoint);
if (creationRallyPoint != null || creationActivityDelay > 0 || creationByMap)
return new AssociateWithAirfieldActivity(this, creationActivityDelay, creationRallyPoint, creationByMap);

return null;
}
Expand All @@ -1231,27 +1233,69 @@ sealed class AssociateWithAirfieldActivity : Activity
readonly Aircraft aircraft;
readonly int delay;
readonly CPos[] rallyPoint;
readonly bool creationByMap;

public AssociateWithAirfieldActivity(Actor self, int delay, CPos[] rallyPoint)
public AssociateWithAirfieldActivity(Aircraft self, int delay, CPos[] rallyPoint, bool creationByMap)
{
aircraft = self.Trait<Aircraft>();
aircraft = self;
this.delay = delay;
this.rallyPoint = rallyPoint;
this.creationByMap = creationByMap;
}

protected override void OnFirstRun(Actor self)
{
var host = aircraft.GetActorBelow();
if (host != null)
var cpos = self.Location;
var pos = self.CenterPosition;
bool TryDock()
{
aircraft.MakeReservation(host);
var host = aircraft.GetActorBelow();
if (host != null)
{
// Center the actor on the resupplier.
var exit = host.NearestExitOrDefault(pos);
pos = host.CenterPosition;
pos = new WPos(pos.X, pos.Y, pos.Z - self.World.Map.DistanceAboveTerrain(pos).Length);
if (exit != null)
{
pos += exit.Info.SpawnOffset;
if (exit.Info.Facing != null)
aircraft.Facing = exit.Info.Facing.Value;
}

aircraft.AddInfluence(cpos);
aircraft.SetPosition(self, pos);
aircraft.MakeReservation(host);

// Freshly created aircraft shouldn't block the exit, so we allow them to yield their reservation.
aircraft.AllowYieldingReservation();
return true;
}

// Freshly created aircraft shouldn't block the exit, so we allow them to yield their reservation.
aircraft.AllowYieldingReservation();
return false;
}

if (delay > 0)
QueueChild(new Wait(delay));
if (creationByMap)
{
if (TryDock())
return;

pos = new WPos(pos.X, pos.Y, pos.Z - self.World.Map.DistanceAboveTerrain(pos).Length);

if (!aircraft.Info.TakeOffOnCreation && aircraft.CanLand(cpos))
{
aircraft.AddInfluence(cpos);
aircraft.SetPosition(self, pos);
}
else
aircraft.SetPosition(self, new WPos(pos.X, pos.Y, pos.Z + aircraft.Info.CruiseAltitude.Length));
}
else
{
TryDock();
if (delay > 0)
QueueChild(new Wait(delay));
}
}

public override bool Tick(Actor self)
Expand All @@ -1260,16 +1304,29 @@ public override bool Tick(Actor self)
return true;

if (rallyPoint != null && rallyPoint.Length > 0)
{
foreach (var cell in rallyPoint)
QueueChild(new AttackMoveActivity(self, () => aircraft.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed)));
}
else if (self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length <= aircraft.LandAltitude.Length)
QueueChild(new TakeOff(self));

aircraft.UnReserve();
if (!creationByMap)
aircraft.UnReserve();

return true;
}

public override IEnumerable<Target> GetTargets(Actor self)
{
if (ChildActivity != null)
return ChildActivity.GetTargets(self);

return Target.None;
}

public override IEnumerable<TargetLineNode> TargetLineNodes(Actor self)
{
if (ChildActivity != null)
foreach (var n in ChildActivity.TargetLineNodes(self))
yield return n;
}
}

public class AircraftMoveOrderTargeter : IOrderTargeter
Expand Down
12 changes: 8 additions & 4 deletions OpenRA.Mods.Common/Traits/World/SpawnMapActors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void WorldLoaded(World world, WorldRenderer wr)
}

actorReference.Add(new SkipMakeAnimsInit());
actorReference.Add(new SpawnedByMapInit(kv.Key));
actorReference.Add(new SpawnedByMapInit());

if (PreventMapSpawn(world, actorReference, preventMapSpawns))
continue;
Expand All @@ -66,9 +66,13 @@ static bool PreventMapSpawn(World world, ActorReference actorReference, IEnumera
}

public class SkipMakeAnimsInit : RuntimeFlagInit { }
public class SpawnedByMapInit : ValueActorInit<string>, ISuppressInitExport, ISingleInstanceInit
public class SpawnedByMapInit : ActorInit, ISuppressInitExport, ISingleInstanceInit
{
public SpawnedByMapInit(string value)
: base(value) { }
protected SpawnedByMapInit(string instanceName)
: base(instanceName) { }

public SpawnedByMapInit() { }

public override MiniYaml Save() => null;
}
}
2 changes: 2 additions & 0 deletions OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ void SpawnUnitsForPlayer(World w, Player p)
new OwnerInit(p),
new SkipMakeAnimsInit(),
new FacingInit(facing),
new SpawnedByMapInit(),
});
}

Expand Down Expand Up @@ -123,6 +124,7 @@ void SpawnUnitsForPlayer(World w, Player p)
new LocationInit(validCell),
new SubCellInit(subCell),
new FacingInit(facing),
new SpawnedByMapInit(),
});
}
}
Expand Down
1 change: 1 addition & 0 deletions mods/d2k/rules/aircraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ carryall.reinforce:
LandableTerrainTypes: Sand, Rock, Transition, Spice, SpiceSand, Dune, Concrete
Repulsable: False
AirborneCondition: airborne
CanForceLand: false
CanSlide: True
VTOL: true
IdleTurnSpeed: 4
Expand Down