Merge pull request #6087 from ScottNZ/planerepulsion

Add plane repulsion
This commit is contained in:
Taryn Hill
2014-07-28 17:25:52 -05:00
6 changed files with 91 additions and 45 deletions

View File

@@ -22,6 +22,11 @@ namespace OpenRA.Mods.RA.Air
public class AircraftInfo : ITraitInfo, IFacingInfo, IOccupySpaceInfo, UsesInit<LocationInit>, UsesInit<FacingInit>
{
public readonly WRange CruiseAltitude = new WRange(1280);
public readonly WRange IdealSeparation = new WRange(1706);
[Desc("Whether the aircraft can be repulsed.")]
public readonly bool Repulsable = true;
[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 string[] RepairBuildings = { "fix" };
@@ -38,7 +43,7 @@ namespace OpenRA.Mods.RA.Air
public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld
{
static readonly Pair<CPos, SubCell>[] NoCells = new Pair<CPos, SubCell>[] { };
static readonly Pair<CPos, SubCell>[] NoCells = { };
readonly AircraftInfo info;
readonly Actor self;
@@ -60,13 +65,61 @@ namespace OpenRA.Mods.RA.Air
if (init.Contains<CenterPositionInit>())
SetPosition(self, init.Get<CenterPositionInit, WPos>());
this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : info.InitialFacing;
Facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : info.InitialFacing;
}
public void Repulse()
{
var repulsionForce = GetRepulsionForce();
var repulsionFacing = Util.GetFacing(repulsionForce, -1);
if (repulsionFacing == -1)
return;
var speed = info.RepulsionSpeed != -1 ? info.RepulsionSpeed : MovementSpeed;
SetPosition(self, CenterPosition + FlyStep(speed, repulsionFacing));
}
public virtual WVec GetRepulsionForce()
{
if (!info.Repulsable)
return WVec.Zero;
// Repulsion only applies when we're flying!
var altitude = CenterPosition.Z;
if (altitude != info.CruiseAltitude.Range)
return WVec.Zero;
return self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation)
.Where(a => !a.IsDead() && a.HasTrait<Aircraft>())
.Select(GetRepulsionForce)
.Aggregate(WVec.Zero, (a, b) => a + b);
}
public WVec GetRepulsionForce(Actor other)
{
if (self == other || other.CenterPosition.Z < self.CenterPosition.Z)
return WVec.Zero;
var d = self.CenterPosition - other.CenterPosition;
var distSq = d.HorizontalLengthSquared;
if (distSq > info.IdealSeparation.Range * info.IdealSeparation.Range)
return WVec.Zero;
if (distSq < 1)
{
var yaw = self.World.SharedRandom.Next(0, 1023);
var rot = new WRot(WAngle.Zero, WAngle.Zero, new WAngle(yaw));
return new WVec(1024, 0, 0).Rotate(rot);
}
return (d * 1024 * 8) / (int)distSq;
}
public Actor GetActorBelow()
{
if (self.CenterPosition.Z != 0)
return null; // not on the ground.
return null; // not on the ground.
return self.World.ActorMap.GetUnitsAt(self.Location)
.FirstOrDefault(a => a.HasTrait<Reservable>());
@@ -158,7 +211,11 @@ namespace OpenRA.Mods.RA.Air
public WVec FlyStep(int facing)
{
var speed = MovementSpeed;
return FlyStep(MovementSpeed, facing);
}
public WVec FlyStep(int speed, int facing)
{
var dir = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing));
return speed * dir / 1024;
}

View File

@@ -18,8 +18,6 @@ namespace OpenRA.Mods.RA.Air
{
class HelicopterInfo : AircraftInfo, IMoveInfo
{
public readonly WRange IdealSeparation = new WRange(1706);
[Desc("Allow the helicopter land after it has no more commands.")]
public readonly bool LandWhenIdle = true;
@@ -135,41 +133,7 @@ namespace OpenRA.Mods.RA.Air
self.QueueActivity(new TakeOff());
}
// Repulsion only applies when we're flying!
var altitude = CenterPosition.Z;
if (altitude != Info.CruiseAltitude.Range)
return;
var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation)
.Where(a => a.HasTrait<Helicopter>());
var f = otherHelis
.Select(h => GetRepulseForce(self, h))
.Aggregate(WVec.Zero, (a, b) => a + b);
var repulsionFacing = Util.GetFacing(f, -1);
if (repulsionFacing != -1)
SetPosition(self, CenterPosition + FlyStep(repulsionFacing));
}
public WVec GetRepulseForce(Actor self, Actor other)
{
if (self == other || other.CenterPosition.Z < self.CenterPosition.Z)
return WVec.Zero;
var d = self.CenterPosition - other.CenterPosition;
var distSq = d.HorizontalLengthSquared;
if (distSq > Info.IdealSeparation.Range * Info.IdealSeparation.Range)
return WVec.Zero;
if (distSq < 1)
{
var yaw = self.World.SharedRandom.Next(0, 1023);
var rot = new WRot(WAngle.Zero, WAngle.Zero, new WAngle(yaw));
return new WVec(1024, 0, 0).Rotate(rot);
}
return (d * 1024 * 8) / (int)distSq;
Repulse();
}
public Activity MoveTo(CPos cell, int nearEnough) { return new HeliFly(self, Target.FromCell(self.World, cell)); }

View File

@@ -50,6 +50,21 @@ namespace OpenRA.Mods.RA.Air
self.QueueActivity(new TakeOff());
}
Repulse();
}
public override WVec GetRepulsionForce()
{
var repulsionForce = base.GetRepulsionForce();
if (repulsionForce == WVec.Zero)
return WVec.Zero;
var currentDir = FlyStep(Facing);
var dot = WVec.Dot(currentDir, repulsionForce) / (currentDir.HorizontalLength * repulsionForce.HorizontalLength);
// avoid stalling the plane
return dot >= 0 ? repulsionForce : WVec.Zero;
}
public void ResolveOrder(Actor self, Order order)

View File

@@ -153,6 +153,7 @@ C17:
Plane:
ROT: 5
Speed: 326
Repulsable: False
Health:
HP: 25
Armor:
@@ -191,6 +192,7 @@ A10:
Plane:
ROT: 4
Speed: 373
Repulsable: False
Health:
HP: 150
Armor:

View File

@@ -42,6 +42,7 @@ FRIGATE:
Speed: 350
RepairBuildings: repaira,repairo,repairh
RearmBuildings: starporta,starporto,starporth
Repulsable: False
Health:
HP: 500
-TargetableAircraft:
@@ -106,6 +107,7 @@ ORNI.bomber:
Speed: 350
RepairBuildings: repaira,repairo,repairh
RearmBuildings: starporta,starporto,starporth
Repulsable: False
LimitedAmmo:
Ammo: 5
RenderUnit:
@@ -135,6 +137,7 @@ CARRYALL.infantry:
Speed: 280
RepairBuildings: repaira,repairo,repairh
RearmBuildings: starporta,starporto,starporth
Repulsable: False
RenderUnit:
Image: carryall
WithShadow:

View File

@@ -9,6 +9,7 @@ BADR:
Plane:
ROT: 5
Speed: 149
Repulsable: False
RenderUnit:
WithShadow:
IronCurtainable:
@@ -46,6 +47,7 @@ BADR.Bomber:
Plane:
ROT: 5
Speed: 149
Repulsable: False
LimitedAmmo:
Ammo: 7
RenderUnit:
@@ -99,9 +101,10 @@ MIG:
FacingTolerance: 20
Plane:
InitialFacing: 192
ROT: 5
Speed: 186
ROT: 4
Speed: 223
RearmBuildings: afld
RepulsionSpeed: 40
AutoTarget:
TargetWhenIdle: false
TargetWhenDamaged: false
@@ -158,8 +161,9 @@ YAK:
Plane:
RearmBuildings: afld
InitialFacing: 192
ROT: 5
Speed: 149
ROT: 4
Speed: 178
RepulsionSpeed: 40
AutoTarget:
TargetWhenIdle: false
TargetWhenDamaged: false
@@ -343,6 +347,7 @@ U2:
Plane:
ROT: 7
Speed: 373
Repulsable: False
RenderUnit:
WithShadow:
IronCurtainable: