Skip to content

Commit

Permalink
Spawn aircraft landed and occupying land or at cruise altitude
Browse files Browse the repository at this point in the history
  • Loading branch information
PunkPun committed Apr 11, 2024
1 parent cf21c8e commit b710df3
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 21 deletions.
100 changes: 83 additions & 17 deletions OpenRA.Mods.Common/Traits/Air/Aircraft.cs
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,32 +1233,81 @@ 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));
QueueChild(new FlyIdle(self));
}

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
{
TryDock();
if (delay > 0)
QueueChild(new Wait(delay));
}
}

public override bool Tick(Actor self)
{
if (!aircraft.Info.TakeOffOnCreation || IsCanceling)
if (!aircraft.Info.TakeOffOnCreation || IsCanceling || creationByMap)
return true;

if (rallyPoint != null && rallyPoint.Length > 0)
Expand All @@ -1270,6 +1321,21 @@ public override bool Tick(Actor self)
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
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
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
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

0 comments on commit b710df3

Please sign in to comment.