Allow opportunity fire for aircraft.
This commit is contained in:
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
aircraft = self.Trait<Aircraft>();
|
aircraft = self.Trait<Aircraft>();
|
||||||
attackAircraft = self.Trait<AttackAircraft>();
|
attackAircraft = self.Trait<AttackAircraft>();
|
||||||
rearmable = self.TraitOrDefault<Rearmable>();
|
rearmable = self.TraitOrDefault<Rearmable>();
|
||||||
ticksUntilTurn = attackAircraft.AttackAircraftInfo.AttackTurnDelay;
|
ticksUntilTurn = attackAircraft.Info.AttackTurnDelay;
|
||||||
|
|
||||||
// The target may become hidden between the initial order request and the first tick (e.g. if queued)
|
// The target may become hidden between the initial order request and the first tick (e.g. if queued)
|
||||||
// Moving to any position (even if quite stale) is still better than immediately giving up
|
// Moving to any position (even if quite stale) is still better than immediately giving up
|
||||||
@@ -64,7 +64,12 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
if (IsCanceling)
|
if (IsCanceling)
|
||||||
{
|
{
|
||||||
// Cancel the requested target, but keep firing on it while in range
|
// Cancel the requested target, but keep firing on it while in range
|
||||||
|
if (attackAircraft.Info.PersistentTargeting)
|
||||||
|
{
|
||||||
attackAircraft.OpportunityTarget = attackAircraft.RequestedTarget;
|
attackAircraft.OpportunityTarget = attackAircraft.RequestedTarget;
|
||||||
|
attackAircraft.OpportunityForceAttack = attackAircraft.RequestedForceAttack;
|
||||||
|
}
|
||||||
|
|
||||||
attackAircraft.RequestedTarget = Target.Invalid;
|
attackAircraft.RequestedTarget = Target.Invalid;
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
@@ -130,7 +135,6 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
if (self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length < aircraft.Info.MinAirborneAltitude)
|
if (self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length < aircraft.Info.MinAirborneAltitude)
|
||||||
QueueChild(self, new TakeOff(self), true);
|
QueueChild(self, new TakeOff(self), true);
|
||||||
|
|
||||||
// TODO: This should fire each weapon at its maximum range
|
|
||||||
if (attackAircraft != null && target.IsInRange(self.CenterPosition, attackAircraft.GetMinimumRange()))
|
if (attackAircraft != null && target.IsInRange(self.CenterPosition, attackAircraft.GetMinimumRange()))
|
||||||
QueueChild(self, new FlyTimed(ticksUntilTurn, self), true);
|
QueueChild(self, new FlyTimed(ticksUntilTurn, self), true);
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,12 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
if (IsCanceling)
|
if (IsCanceling)
|
||||||
{
|
{
|
||||||
// Cancel the requested target, but keep firing on it while in range
|
// Cancel the requested target, but keep firing on it while in range
|
||||||
|
if (attackAircraft.Info.PersistentTargeting)
|
||||||
|
{
|
||||||
attackAircraft.OpportunityTarget = attackAircraft.RequestedTarget;
|
attackAircraft.OpportunityTarget = attackAircraft.RequestedTarget;
|
||||||
|
attackAircraft.OpportunityForceAttack = attackAircraft.RequestedForceAttack;
|
||||||
|
}
|
||||||
|
|
||||||
attackAircraft.RequestedTarget = Target.Invalid;
|
attackAircraft.RequestedTarget = Target.Invalid;
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,10 +191,9 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
return AttackStatus.NeedsToMove;
|
return AttackStatus.NeedsToMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetedPosition = attack.GetTargetPosition(pos, target);
|
if (!attack.TargetInFiringArc(self, target, attack.Info.FacingTolerance))
|
||||||
var desiredFacing = (targetedPosition - pos).Yaw.Facing;
|
|
||||||
if (!Util.FacingWithinTolerance(facing.Facing, desiredFacing, ((AttackFrontalInfo)attack.Info).FacingTolerance))
|
|
||||||
{
|
{
|
||||||
|
var desiredFacing = (attack.GetTargetPosition(pos, target) - pos).Yaw.Facing;
|
||||||
attackStatus |= AttackStatus.NeedsToTurn;
|
attackStatus |= AttackStatus.NeedsToTurn;
|
||||||
QueueChild(self, new Turn(self, desiredFacing), true);
|
QueueChild(self, new Turn(self, desiredFacing), true);
|
||||||
return AttackStatus.NeedsToTurn;
|
return AttackStatus.NeedsToTurn;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
if (attack == null && autoTarget != null)
|
if (attack == null && autoTarget != null)
|
||||||
{
|
{
|
||||||
var target = autoTarget.ScanForTarget(self, true);
|
var target = autoTarget.ScanForTarget(self, true, true);
|
||||||
if (target.Type != TargetType.Invalid)
|
if (target.Type != TargetType.Invalid)
|
||||||
{
|
{
|
||||||
if (inner != null)
|
if (inner != null)
|
||||||
|
|||||||
@@ -20,29 +20,18 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Delay, in game ticks, before non-hovering aircraft turns to attack.")]
|
[Desc("Delay, in game ticks, before non-hovering aircraft turns to attack.")]
|
||||||
public readonly int AttackTurnDelay = 50;
|
public readonly int AttackTurnDelay = 50;
|
||||||
|
|
||||||
[Desc("Tolerance for attack angle. Range [0, 128], 128 covers 360 degrees.")]
|
|
||||||
public readonly int FacingTolerance = 0;
|
|
||||||
|
|
||||||
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
|
||||||
{
|
|
||||||
base.RulesetLoaded(rules, ai);
|
|
||||||
|
|
||||||
if (FacingTolerance < 0 || FacingTolerance > 128)
|
|
||||||
throw new YamlException("Facing tolerance must be in range of [0, 128], 128 covers 360 degrees.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new AttackAircraft(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new AttackAircraft(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AttackAircraft : AttackFollow
|
public class AttackAircraft : AttackFollow
|
||||||
{
|
{
|
||||||
public readonly AttackAircraftInfo AttackAircraftInfo;
|
public new readonly AttackAircraftInfo Info;
|
||||||
readonly AircraftInfo aircraftInfo;
|
readonly AircraftInfo aircraftInfo;
|
||||||
|
|
||||||
public AttackAircraft(Actor self, AttackAircraftInfo info)
|
public AttackAircraft(Actor self, AttackAircraftInfo info)
|
||||||
: base(self, info)
|
: base(self, info)
|
||||||
{
|
{
|
||||||
AttackAircraftInfo = info;
|
Info = info;
|
||||||
aircraftInfo = self.Info.TraitInfo<AircraftInfo>();
|
aircraftInfo = self.Info.TraitInfo<AircraftInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,14 +53,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!base.CanAttack(self, target))
|
if (!base.CanAttack(self, target))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var pos = self.CenterPosition;
|
return TargetInFiringArc(self, target, base.Info.FacingTolerance);
|
||||||
var targetedPosition = GetTargetPosition(pos, target);
|
|
||||||
var delta = targetedPosition - pos;
|
|
||||||
|
|
||||||
if (delta.HorizontalLengthSquared == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return Util.FacingWithinTolerance(facing.Facing, delta.Yaw.Facing, AttackAircraftInfo.FacingTolerance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public class AttackBomberInfo : AttackBaseInfo
|
public class AttackBomberInfo : AttackBaseInfo
|
||||||
{
|
{
|
||||||
public readonly int FacingTolerance = 2;
|
[Desc("Tolerance for attack angle. Range [0, 128], 128 covers 360 degrees.")]
|
||||||
|
public readonly new int FacingTolerance = 2;
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new AttackBomber(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new AttackBomber(init.Self, this); }
|
||||||
}
|
}
|
||||||
@@ -49,10 +50,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
inAttackRange = false;
|
inAttackRange = false;
|
||||||
|
|
||||||
var f = facing.Facing;
|
facingTarget = TargetInFiringArc(self, target, info.FacingTolerance);
|
||||||
var delta = target.CenterPosition - self.CenterPosition;
|
|
||||||
var facingToTarget = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : f;
|
|
||||||
facingTarget = Math.Abs(facingToTarget - f) % 256 <= info.FacingTolerance;
|
|
||||||
|
|
||||||
foreach (var a in Armaments)
|
foreach (var a in Armaments)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,17 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
[VoiceReference] public readonly string Voice = "Action";
|
[VoiceReference] public readonly string Voice = "Action";
|
||||||
|
|
||||||
|
[Desc("Tolerance for attack angle. Range [0, 128], 128 covers 360 degrees.")]
|
||||||
|
public readonly int FacingTolerance = 128;
|
||||||
|
|
||||||
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
|
{
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
|
|
||||||
|
if (FacingTolerance < 0 || FacingTolerance > 128)
|
||||||
|
throw new YamlException("Facing tolerance must be in range of [0, 128], 128 covers 360 degrees.");
|
||||||
|
}
|
||||||
|
|
||||||
public override abstract object Create(ActorInitializer init);
|
public override abstract object Create(ActorInitializer init);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +112,21 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return () => armaments;
|
return () => armaments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TargetInFiringArc(Actor self, Target target, int facingTolerance)
|
||||||
|
{
|
||||||
|
if (facing == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var pos = self.CenterPosition;
|
||||||
|
var targetedPosition = GetTargetPosition(pos, target);
|
||||||
|
var delta = targetedPosition - pos;
|
||||||
|
|
||||||
|
if (delta.HorizontalLengthSquared == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return Util.FacingWithinTolerance(facing.Facing, delta.Yaw.Facing, facingTolerance);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual bool CanAttack(Actor self, Target target)
|
protected virtual bool CanAttack(Actor self, Target target)
|
||||||
{
|
{
|
||||||
if (!self.IsInWorld || IsTraitDisabled || IsTraitPaused)
|
if (!self.IsInWorld || IsTraitDisabled || IsTraitPaused)
|
||||||
|
|||||||
@@ -23,21 +23,28 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Automatically acquire and fire on targets of opportunity when not actively attacking.")]
|
[Desc("Automatically acquire and fire on targets of opportunity when not actively attacking.")]
|
||||||
public readonly bool OpportunityFire = true;
|
public readonly bool OpportunityFire = true;
|
||||||
|
|
||||||
|
[Desc("Keep firing on targets even after attack order is cancelled")]
|
||||||
|
public readonly bool PersistentTargeting = true;
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new AttackFollow(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new AttackFollow(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AttackFollow : AttackBase, INotifyOwnerChanged
|
public class AttackFollow : AttackBase, INotifyOwnerChanged
|
||||||
{
|
{
|
||||||
|
public new readonly AttackFollowInfo Info;
|
||||||
public Target RequestedTarget;
|
public Target RequestedTarget;
|
||||||
protected bool requestedForceAttack;
|
public bool RequestedForceAttack;
|
||||||
public int RequestedTargetLastTick;
|
public int RequestedTargetLastTick;
|
||||||
public Target OpportunityTarget;
|
public Target OpportunityTarget;
|
||||||
protected bool opportunityForceAttack;
|
public bool OpportunityForceAttack;
|
||||||
Mobile mobile;
|
Mobile mobile;
|
||||||
AutoTarget autoTarget;
|
AutoTarget autoTarget;
|
||||||
|
|
||||||
public AttackFollow(Actor self, AttackFollowInfo info)
|
public AttackFollow(Actor self, AttackFollowInfo info)
|
||||||
: base(self, info) { }
|
: base(self, info)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Created(Actor self)
|
protected override void Created(Actor self)
|
||||||
{
|
{
|
||||||
@@ -58,6 +65,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var armaments = ChooseArmamentsForTarget(target, forceAttack);
|
var armaments = ChooseArmamentsForTarget(target, forceAttack);
|
||||||
foreach (var a in armaments)
|
foreach (var a in armaments)
|
||||||
if (target.IsInRange(pos, a.MaxRange()) && (a.Weapon.MinRange == WDist.Zero || !target.IsInRange(pos, a.Weapon.MinRange)))
|
if (target.IsInRange(pos, a.MaxRange()) && (a.Weapon.MinRange == WDist.Zero || !target.IsInRange(pos, a.Weapon.MinRange)))
|
||||||
|
if (TargetInFiringArc(self, target, Info.FacingTolerance))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -82,7 +90,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
if (RequestedTarget.Type != TargetType.Invalid)
|
if (RequestedTarget.Type != TargetType.Invalid)
|
||||||
{
|
{
|
||||||
IsAiming = CanAimAtTarget(self, RequestedTarget, requestedForceAttack);
|
IsAiming = CanAimAtTarget(self, RequestedTarget, RequestedForceAttack);
|
||||||
if (IsAiming)
|
if (IsAiming)
|
||||||
DoAttack(self, RequestedTarget);
|
DoAttack(self, RequestedTarget);
|
||||||
}
|
}
|
||||||
@@ -91,16 +99,16 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
IsAiming = false;
|
IsAiming = false;
|
||||||
|
|
||||||
if (OpportunityTarget.Type != TargetType.Invalid)
|
if (OpportunityTarget.Type != TargetType.Invalid)
|
||||||
IsAiming = CanAimAtTarget(self, OpportunityTarget, opportunityForceAttack);
|
IsAiming = CanAimAtTarget(self, OpportunityTarget, OpportunityForceAttack);
|
||||||
|
|
||||||
if (!IsAiming && ((AttackFollowInfo)Info).OpportunityFire && autoTarget != null &&
|
if (!IsAiming && Info.OpportunityFire && autoTarget != null &&
|
||||||
!autoTarget.IsTraitDisabled && autoTarget.Stance >= UnitStance.Defend)
|
!autoTarget.IsTraitDisabled && autoTarget.Stance >= UnitStance.Defend)
|
||||||
{
|
{
|
||||||
OpportunityTarget = autoTarget.ScanForTarget(self, false);
|
OpportunityTarget = autoTarget.ScanForTarget(self, false, false);
|
||||||
opportunityForceAttack = false;
|
OpportunityForceAttack = false;
|
||||||
|
|
||||||
if (OpportunityTarget.Type != TargetType.Invalid)
|
if (OpportunityTarget.Type != TargetType.Invalid)
|
||||||
IsAiming = CanAimAtTarget(self, OpportunityTarget, opportunityForceAttack);
|
IsAiming = CanAimAtTarget(self, OpportunityTarget, OpportunityForceAttack);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsAiming)
|
if (IsAiming)
|
||||||
@@ -123,7 +131,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!queued)
|
if (!queued)
|
||||||
{
|
{
|
||||||
RequestedTarget = target;
|
RequestedTarget = target;
|
||||||
requestedForceAttack = forceAttack;
|
RequestedForceAttack = forceAttack;
|
||||||
RequestedTargetLastTick = self.World.WorldTick;
|
RequestedTargetLastTick = self.World.WorldTick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,8 +194,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (IsCanceling)
|
if (IsCanceling)
|
||||||
{
|
{
|
||||||
// Cancel the requested target, but keep firing on it while in range
|
// Cancel the requested target, but keep firing on it while in range
|
||||||
|
if (attack.Info.PersistentTargeting)
|
||||||
|
{
|
||||||
attack.OpportunityTarget = attack.RequestedTarget;
|
attack.OpportunityTarget = attack.RequestedTarget;
|
||||||
attack.opportunityForceAttack = attack.requestedForceAttack;
|
attack.OpportunityForceAttack = attack.RequestedForceAttack;
|
||||||
|
}
|
||||||
|
|
||||||
attack.RequestedTarget = Target.Invalid;
|
attack.RequestedTarget = Target.Invalid;
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
@@ -201,7 +213,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return this;
|
return this;
|
||||||
|
|
||||||
bool targetIsHiddenActor;
|
bool targetIsHiddenActor;
|
||||||
attack.requestedForceAttack = forceAttack;
|
attack.RequestedForceAttack = forceAttack;
|
||||||
attack.RequestedTarget = target = target.Recalculate(self.Owner, out targetIsHiddenActor);
|
attack.RequestedTarget = target = target.Recalculate(self.Owner, out targetIsHiddenActor);
|
||||||
attack.RequestedTargetLastTick = self.World.WorldTick;
|
attack.RequestedTargetLastTick = self.World.WorldTick;
|
||||||
hasTicked = true;
|
hasTicked = true;
|
||||||
|
|||||||
@@ -17,27 +17,20 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Unit got to face the target")]
|
[Desc("Unit got to face the target")]
|
||||||
public class AttackFrontalInfo : AttackBaseInfo, Requires<IFacingInfo>
|
public class AttackFrontalInfo : AttackBaseInfo, Requires<IFacingInfo>
|
||||||
{
|
{
|
||||||
public readonly int FacingTolerance = 0;
|
[Desc("Tolerance for attack angle. Range [0, 128], 128 covers 360 degrees.")]
|
||||||
|
public readonly new int FacingTolerance = 0;
|
||||||
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
|
||||||
{
|
|
||||||
base.RulesetLoaded(rules, ai);
|
|
||||||
|
|
||||||
if (FacingTolerance < 0 || FacingTolerance > 128)
|
|
||||||
throw new YamlException("Facing tolerance must be in range of [0, 128], 128 covers 360 degrees.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new AttackFrontal(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new AttackFrontal(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AttackFrontal : AttackBase
|
public class AttackFrontal : AttackBase
|
||||||
{
|
{
|
||||||
readonly AttackFrontalInfo info;
|
public new readonly AttackFrontalInfo Info;
|
||||||
|
|
||||||
public AttackFrontal(Actor self, AttackFrontalInfo info)
|
public AttackFrontal(Actor self, AttackFrontalInfo info)
|
||||||
: base(self, info)
|
: base(self, info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.Info = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool CanAttack(Actor self, Target target)
|
protected override bool CanAttack(Actor self, Target target)
|
||||||
@@ -45,14 +38,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!base.CanAttack(self, target))
|
if (!base.CanAttack(self, target))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var pos = self.CenterPosition;
|
return TargetInFiringArc(self, target, Info.FacingTolerance);
|
||||||
var targetedPosition = GetTargetPosition(pos, target);
|
|
||||||
var delta = targetedPosition - pos;
|
|
||||||
|
|
||||||
if (delta.HorizontalLengthSquared == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return Util.FacingWithinTolerance(facing.Facing, delta.Yaw.Facing, info.FacingTolerance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("It will try to hunt down the enemy if it is set to AttackAnything.")]
|
[Desc("It will try to hunt down the enemy if it is set to AttackAnything.")]
|
||||||
public readonly bool AllowMovement = true;
|
public readonly bool AllowMovement = true;
|
||||||
|
|
||||||
|
[Desc("It will try to pivot to face the enemy if stance is not HoldFire.")]
|
||||||
|
public readonly bool AllowTurning = true;
|
||||||
|
|
||||||
[Desc("Set to a value >1 to override weapons maximum range for this.")]
|
[Desc("Set to a value >1 to override weapons maximum range for this.")]
|
||||||
public readonly int ScanRadius = -1;
|
public readonly int ScanRadius = -1;
|
||||||
|
|
||||||
@@ -228,7 +231,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var allowMove = Info.AllowMovement && Stance > UnitStance.Defend;
|
var allowMove = Info.AllowMovement && Stance > UnitStance.Defend;
|
||||||
ScanAndAttack(self, allowMove);
|
var allowTurn = Info.AllowTurning && Stance > UnitStance.HoldFire;
|
||||||
|
ScanAndAttack(self, allowMove, allowTurn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ITick.Tick(Actor self)
|
void ITick.Tick(Actor self)
|
||||||
@@ -240,7 +244,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
--nextScanTime;
|
--nextScanTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Target ScanForTarget(Actor self, bool allowMove)
|
public Target ScanForTarget(Actor self, bool allowMove, bool allowTurn)
|
||||||
{
|
{
|
||||||
if (nextScanTime <= 0 && ActiveAttackBases.Any())
|
if (nextScanTime <= 0 && ActiveAttackBases.Any())
|
||||||
{
|
{
|
||||||
@@ -253,7 +257,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (attackStances != OpenRA.Traits.Stance.None)
|
if (attackStances != OpenRA.Traits.Stance.None)
|
||||||
{
|
{
|
||||||
var range = Info.ScanRadius > 0 ? WDist.FromCells(Info.ScanRadius) : ab.GetMaximumRange();
|
var range = Info.ScanRadius > 0 ? WDist.FromCells(Info.ScanRadius) : ab.GetMaximumRange();
|
||||||
return ChooseTarget(self, ab, attackStances, range, allowMove);
|
return ChooseTarget(self, ab, attackStances, range, allowMove, allowTurn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,9 +265,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return Target.Invalid;
|
return Target.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScanAndAttack(Actor self, bool allowMove)
|
public void ScanAndAttack(Actor self, bool allowMove, bool allowTurn)
|
||||||
{
|
{
|
||||||
var target = ScanForTarget(self, allowMove);
|
var target = ScanForTarget(self, allowMove, allowTurn);
|
||||||
if (target.Type != TargetType.Invalid)
|
if (target.Type != TargetType.Invalid)
|
||||||
Attack(self, target, allowMove);
|
Attack(self, target, allowMove);
|
||||||
}
|
}
|
||||||
@@ -276,7 +280,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
ab.AttackTarget(target, false, allowMove);
|
ab.AttackTarget(target, false, allowMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
Target ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove)
|
Target ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove, bool allowTurn)
|
||||||
{
|
{
|
||||||
var chosenTarget = Target.Invalid;
|
var chosenTarget = Target.Invalid;
|
||||||
var chosenTargetPriority = int.MinValue;
|
var chosenTargetPriority = int.MinValue;
|
||||||
@@ -353,6 +357,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!armaments.Any())
|
if (!armaments.Any())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!allowTurn && !ab.TargetInFiringArc(self, target, ab.Info.FacingTolerance))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Evaluate whether we want to target this actor
|
// Evaluate whether we want to target this actor
|
||||||
var targetRange = (target.CenterPosition - self.CenterPosition).Length;
|
var targetRange = (target.CenterPosition - self.CenterPosition).Length;
|
||||||
foreach (var ati in validPriorities)
|
foreach (var ati in validPriorities)
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ HELI:
|
|||||||
ScanRadius: 4
|
ScanRadius: 4
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
OpportunityFire: false
|
||||||
|
PersistentTargeting: false
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
Ammo: 10
|
Ammo: 10
|
||||||
PipCount: 5
|
PipCount: 5
|
||||||
@@ -150,6 +152,8 @@ ORCA:
|
|||||||
ScanRadius: 5
|
ScanRadius: 5
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
OpportunityFire: false
|
||||||
|
PersistentTargeting: false
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
Ammo: 6
|
Ammo: 6
|
||||||
PipCount: 6
|
PipCount: 6
|
||||||
|
|||||||
@@ -475,6 +475,7 @@
|
|||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
IdleSequences: idle1, idle2
|
IdleSequences: idle1, idle2
|
||||||
StandSequences: stand, stand2
|
StandSequences: stand, stand2
|
||||||
|
AttackFrontal:
|
||||||
|
|
||||||
^CivInfantry:
|
^CivInfantry:
|
||||||
Inherits: ^Infantry
|
Inherits: ^Infantry
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ E1:
|
|||||||
ScanRadius: 4
|
ScanRadius: 4
|
||||||
Armament:
|
Armament:
|
||||||
Weapon: M16
|
Weapon: M16
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
IdleSequences: idle1,idle2,idle3,idle4
|
IdleSequences: idle1,idle2,idle3,idle4
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
@@ -55,7 +54,6 @@ E2:
|
|||||||
FireDelay: 15
|
FireDelay: 15
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 300,0,-227
|
ProneOffset: 300,0,-227
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: throw
|
DefaultAttackSequence: throw
|
||||||
Explodes:
|
Explodes:
|
||||||
@@ -91,7 +89,6 @@ E3:
|
|||||||
FireDelay: 5
|
FireDelay: 5
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 180,0,-200
|
ProneOffset: 180,0,-200
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
|
|
||||||
@@ -124,7 +121,6 @@ E4:
|
|||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 190,0,-198
|
ProneOffset: 190,0,-198
|
||||||
AttackFrontal:
|
|
||||||
WithMuzzleOverlay:
|
WithMuzzleOverlay:
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
@@ -159,7 +155,6 @@ E5:
|
|||||||
MuzzleSequence: muzzle
|
MuzzleSequence: muzzle
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 190,0,-190
|
ProneOffset: 190,0,-190
|
||||||
AttackFrontal:
|
|
||||||
WithMuzzleOverlay:
|
WithMuzzleOverlay:
|
||||||
-DamagedByTerrain:
|
-DamagedByTerrain:
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
@@ -196,6 +191,7 @@ E6:
|
|||||||
PlayerExperience: 50
|
PlayerExperience: 50
|
||||||
Selectable:
|
Selectable:
|
||||||
Priority: 5
|
Priority: 5
|
||||||
|
-AttackFrontal:
|
||||||
|
|
||||||
RMBO:
|
RMBO:
|
||||||
Inherits: ^Soldier
|
Inherits: ^Soldier
|
||||||
|
|||||||
@@ -335,6 +335,7 @@
|
|||||||
Radius: 96
|
Radius: 96
|
||||||
MapEditorData:
|
MapEditorData:
|
||||||
Categories: Infantry
|
Categories: Infantry
|
||||||
|
AttackFrontal:
|
||||||
|
|
||||||
^Plane:
|
^Plane:
|
||||||
Inherits@1: ^ExistsInWorld
|
Inherits@1: ^ExistsInWorld
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ light_inf:
|
|||||||
Speed: 43
|
Speed: 43
|
||||||
Armament:
|
Armament:
|
||||||
Weapon: LMG
|
Weapon: LMG
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
|
|
||||||
@@ -52,6 +51,7 @@ engineer:
|
|||||||
-RevealOnFire:
|
-RevealOnFire:
|
||||||
Voiced:
|
Voiced:
|
||||||
VoiceSet: EngineerVoice
|
VoiceSet: EngineerVoice
|
||||||
|
-AttackFrontal:
|
||||||
|
|
||||||
trooper:
|
trooper:
|
||||||
Inherits: ^Infantry
|
Inherits: ^Infantry
|
||||||
@@ -80,7 +80,6 @@ trooper:
|
|||||||
LocalOffset: 128,0,256
|
LocalOffset: 128,0,256
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 324,0,-204
|
ProneOffset: 324,0,-204
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
|
|
||||||
@@ -130,6 +129,7 @@ thumper:
|
|||||||
Intensity: 1000
|
Intensity: 1000
|
||||||
Falloff: 0, 0, 0, 100, 100, 100, 25, 11, 6, 4, 3, 2, 1, 0
|
Falloff: 0, 0, 0, 100, 100, 100, 25, 11, 6, 4, 3, 2, 1, 0
|
||||||
RequiresCondition: deployed
|
RequiresCondition: deployed
|
||||||
|
-AttackFrontal:
|
||||||
|
|
||||||
fremen:
|
fremen:
|
||||||
Inherits: ^Infantry
|
Inherits: ^Infantry
|
||||||
@@ -159,7 +159,6 @@ fremen:
|
|||||||
Weapon: Fremen_S
|
Weapon: Fremen_S
|
||||||
Armament@SECONDARY:
|
Armament@SECONDARY:
|
||||||
Weapon: Fremen_L
|
Weapon: Fremen_L
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
Cloak:
|
Cloak:
|
||||||
@@ -201,7 +200,6 @@ grenadier:
|
|||||||
FireDelay: 3
|
FireDelay: 3
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 96,100,-64
|
ProneOffset: 96,100,-64
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: throw
|
DefaultAttackSequence: throw
|
||||||
Explodes:
|
Explodes:
|
||||||
@@ -236,7 +234,6 @@ sardaukar:
|
|||||||
Weapon: M_LMG
|
Weapon: M_LMG
|
||||||
Armament@SECONDARY:
|
Armament@SECONDARY:
|
||||||
Weapon: M_HMG
|
Weapon: M_HMG
|
||||||
AttackFrontal:
|
|
||||||
Voiced:
|
Voiced:
|
||||||
VoiceSet: GenericVoice
|
VoiceSet: GenericVoice
|
||||||
Explodes:
|
Explodes:
|
||||||
@@ -295,6 +292,7 @@ saboteur:
|
|||||||
ValidDamageStates: Critical
|
ValidDamageStates: Critical
|
||||||
Voiced:
|
Voiced:
|
||||||
VoiceSet: SaboteurVoice
|
VoiceSet: SaboteurVoice
|
||||||
|
-AttackFrontal:
|
||||||
|
|
||||||
nsfremen:
|
nsfremen:
|
||||||
Inherits: fremen
|
Inherits: fremen
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ MIG:
|
|||||||
PauseOnCondition: !ammo
|
PauseOnCondition: !ammo
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
Aircraft:
|
Aircraft:
|
||||||
CruiseAltitude: 2560
|
CruiseAltitude: 2560
|
||||||
InitialFacing: 192
|
InitialFacing: 192
|
||||||
@@ -180,6 +181,7 @@ YAK:
|
|||||||
PauseOnCondition: !ammo
|
PauseOnCondition: !ammo
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
Aircraft:
|
Aircraft:
|
||||||
CruiseAltitude: 2560
|
CruiseAltitude: 2560
|
||||||
InitialFacing: 192
|
InitialFacing: 192
|
||||||
@@ -302,6 +304,7 @@ HELI:
|
|||||||
PauseOnCondition: !ammo
|
PauseOnCondition: !ammo
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
Aircraft:
|
Aircraft:
|
||||||
LandWhenIdle: false
|
LandWhenIdle: false
|
||||||
TurnSpeed: 4
|
TurnSpeed: 4
|
||||||
@@ -369,6 +372,7 @@ HIND:
|
|||||||
PauseOnCondition: !ammo
|
PauseOnCondition: !ammo
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
Aircraft:
|
Aircraft:
|
||||||
LandWhenIdle: false
|
LandWhenIdle: false
|
||||||
TurnSpeed: 4
|
TurnSpeed: 4
|
||||||
|
|||||||
@@ -448,6 +448,7 @@
|
|||||||
StandSequences: stand,stand2
|
StandSequences: stand,stand2
|
||||||
DetectCloaked:
|
DetectCloaked:
|
||||||
CloakTypes: Thief
|
CloakTypes: Thief
|
||||||
|
AttackFrontal:
|
||||||
|
|
||||||
^CivInfantry:
|
^CivInfantry:
|
||||||
Inherits: ^Infantry
|
Inherits: ^Infantry
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ DOG:
|
|||||||
Armament:
|
Armament:
|
||||||
Weapon: DogJaw
|
Weapon: DogJaw
|
||||||
ReloadingCondition: attack-cooldown
|
ReloadingCondition: attack-cooldown
|
||||||
|
-AttackFrontal:
|
||||||
AttackLeap:
|
AttackLeap:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
PauseOnCondition: attacking || attack-cooldown
|
PauseOnCondition: attacking || attack-cooldown
|
||||||
@@ -91,7 +92,6 @@ E1:
|
|||||||
Name: garrisoned
|
Name: garrisoned
|
||||||
Weapon: Vulcan
|
Weapon: Vulcan
|
||||||
MuzzleSequence: garrison-muzzle
|
MuzzleSequence: garrison-muzzle
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
RequiresCondition: !parachute
|
RequiresCondition: !parachute
|
||||||
@@ -139,7 +139,6 @@ E2:
|
|||||||
FireDelay: 15
|
FireDelay: 15
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 256,64,-331
|
ProneOffset: 256,64,-331
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: throw
|
DefaultAttackSequence: throw
|
||||||
RequiresCondition: !parachute
|
RequiresCondition: !parachute
|
||||||
@@ -184,7 +183,6 @@ E3:
|
|||||||
Weapon: Dragon
|
Weapon: Dragon
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 384,0,-395
|
ProneOffset: 384,0,-395
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
RequiresCondition: !parachute
|
RequiresCondition: !parachute
|
||||||
@@ -231,7 +229,6 @@ E4:
|
|||||||
Weapon: Flamer
|
Weapon: Flamer
|
||||||
TakeCover:
|
TakeCover:
|
||||||
ProneOffset: 160,0,-288
|
ProneOffset: 160,0,-288
|
||||||
AttackFrontal:
|
|
||||||
Explodes:
|
Explodes:
|
||||||
Weapon: VisualExplode
|
Weapon: VisualExplode
|
||||||
EmptyWeapon: VisualExplode
|
EmptyWeapon: VisualExplode
|
||||||
@@ -289,6 +286,7 @@ E6:
|
|||||||
VoiceSet: EngineerVoice
|
VoiceSet: EngineerVoice
|
||||||
Selectable:
|
Selectable:
|
||||||
Priority: 5
|
Priority: 5
|
||||||
|
-AttackFrontal:
|
||||||
|
|
||||||
SPY:
|
SPY:
|
||||||
Inherits: ^Soldier
|
Inherits: ^Soldier
|
||||||
@@ -342,7 +340,6 @@ SPY:
|
|||||||
CloakTypes: Cloak, Thief
|
CloakTypes: Cloak, Thief
|
||||||
Armament:
|
Armament:
|
||||||
Weapon: SilencedPPK
|
Weapon: SilencedPPK
|
||||||
AttackFrontal:
|
|
||||||
AttackMove:
|
AttackMove:
|
||||||
Voice: Move
|
Voice: Move
|
||||||
Voiced:
|
Voiced:
|
||||||
@@ -400,7 +397,6 @@ E7:
|
|||||||
Name: garrisoned
|
Name: garrisoned
|
||||||
Weapon: Colt45
|
Weapon: Colt45
|
||||||
MuzzleSequence: garrison-muzzle
|
MuzzleSequence: garrison-muzzle
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
StandSequences: stand
|
StandSequences: stand
|
||||||
@@ -445,7 +441,6 @@ MEDI:
|
|||||||
OutsideRangeCursor: heal
|
OutsideRangeCursor: heal
|
||||||
TargetStances: Ally
|
TargetStances: Ally
|
||||||
ForceTargetStances: None
|
ForceTargetStances: None
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
IdleSequences: idle
|
IdleSequences: idle
|
||||||
StandSequences: stand
|
StandSequences: stand
|
||||||
@@ -610,6 +605,7 @@ THF:
|
|||||||
ValidDamageStates: Critical
|
ValidDamageStates: Critical
|
||||||
Mobile:
|
Mobile:
|
||||||
Speed: 71
|
Speed: 71
|
||||||
|
-AttackFrontal:
|
||||||
|
|
||||||
SHOK:
|
SHOK:
|
||||||
Inherits: ^Soldier
|
Inherits: ^Soldier
|
||||||
@@ -690,7 +686,6 @@ SNIPER:
|
|||||||
Name: garrisoned
|
Name: garrisoned
|
||||||
Weapon: Sniper
|
Weapon: Sniper
|
||||||
MuzzleSequence: garrison-muzzle
|
MuzzleSequence: garrison-muzzle
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: shoot
|
DefaultAttackSequence: shoot
|
||||||
Cloak:
|
Cloak:
|
||||||
@@ -732,7 +727,6 @@ Zombie:
|
|||||||
Speed: 42
|
Speed: 42
|
||||||
AutoTarget:
|
AutoTarget:
|
||||||
ScanRadius: 5
|
ScanRadius: 5
|
||||||
AttackFrontal:
|
|
||||||
WithInfantryBody:
|
WithInfantryBody:
|
||||||
DefaultAttackSequence: bite
|
DefaultAttackSequence: bite
|
||||||
IdleSequences: idle1
|
IdleSequences: idle1
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ ORCA:
|
|||||||
PauseOnCondition: !ammo
|
PauseOnCondition: !ammo
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
PauseOnCondition: empdisable
|
PauseOnCondition: empdisable
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
@@ -158,6 +159,7 @@ ORCAB:
|
|||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
PauseOnCondition: empdisable
|
PauseOnCondition: empdisable
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
Ammo: 10
|
Ammo: 10
|
||||||
@@ -297,6 +299,7 @@ SCRIN:
|
|||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
PauseOnCondition: empdisable
|
PauseOnCondition: empdisable
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
Ammo: 15
|
Ammo: 15
|
||||||
@@ -346,6 +349,7 @@ APACHE:
|
|||||||
PauseOnCondition: !ammo
|
PauseOnCondition: !ammo
|
||||||
AttackAircraft:
|
AttackAircraft:
|
||||||
FacingTolerance: 20
|
FacingTolerance: 20
|
||||||
|
PersistentTargeting: false
|
||||||
Voice: Attack
|
Voice: Attack
|
||||||
PauseOnCondition: empdisable
|
PauseOnCondition: empdisable
|
||||||
AmmoPool:
|
AmmoPool:
|
||||||
|
|||||||
Reference in New Issue
Block a user