Added: UnitStanceDefensive
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
<Compile Include="Activities\Demolish.cs" />
|
||||
<Compile Include="Activities\Enter.cs" />
|
||||
<Compile Include="Activities\EnterTransport.cs" />
|
||||
<Compile Include="UnitStances\UnitStanceDefensive.cs" />
|
||||
<Compile Include="UnitStances\UnitStanceAggressive.cs" />
|
||||
<Compile Include="Air\Fly.cs" />
|
||||
<Compile Include="Air\FlyAttack.cs" />
|
||||
|
||||
163
OpenRA.Mods.RA/UnitStances/UnitStanceDefensive.cs
Normal file
163
OpenRA.Mods.RA/UnitStances/UnitStanceDefensive.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
public class UnitStanceDefensiveInfo : UnitStanceInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new UnitStanceDefensive(init.self, this); }
|
||||
public readonly int MaxDistance = 5;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return Fire
|
||||
///
|
||||
/// Will fire only when fired upon
|
||||
/// </summary>
|
||||
public class UnitStanceDefensive : UnitStance, INotifyDamage
|
||||
{
|
||||
public enum ETargetType
|
||||
{
|
||||
None,
|
||||
Location,
|
||||
Actor
|
||||
}
|
||||
|
||||
[Sync] public int MaxDistance;
|
||||
public Target DefendTarget = Target.None;
|
||||
public ETargetType TargetType = ETargetType.None;
|
||||
public bool WaitingForIdle = false;
|
||||
[Sync]
|
||||
public bool IsReturning { get; protected set; }
|
||||
|
||||
public UnitStanceDefensive(Actor self, UnitStanceDefensiveInfo info)
|
||||
: base(self, info)
|
||||
{
|
||||
MaxDistance = info.MaxDistance;
|
||||
|
||||
base.AllowMultiTrigger = true;
|
||||
}
|
||||
|
||||
protected override void OnActivate(Actor self)
|
||||
{
|
||||
DefendThis(self.CenterLocation);
|
||||
|
||||
if (!self.IsIdle)
|
||||
WaitForIdle();
|
||||
}
|
||||
|
||||
protected void DefendThis(float2 target)
|
||||
{
|
||||
DefendTarget = Target.FromPos(target);
|
||||
TargetType = ETargetType.Location;
|
||||
}
|
||||
|
||||
protected void DefendThis(Actor target)
|
||||
{
|
||||
DefendTarget = Target.FromActor(target);
|
||||
TargetType = ETargetType.Actor;
|
||||
}
|
||||
|
||||
protected override void OnScan(Actor self)
|
||||
{
|
||||
if (TargetType == ETargetType.None) return;
|
||||
if (IsReturning) return;
|
||||
if (!self.IsIdle) return;
|
||||
if (!self.HasTrait<AttackBase>()) return;
|
||||
|
||||
var target = ScanForTarget(self);
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
AttackTarget(self, target, false);
|
||||
}
|
||||
|
||||
protected override void OnTick(Actor self)
|
||||
{
|
||||
if (!self.HasTrait<AttackBase>()) return;
|
||||
|
||||
// when the unit is doing nothing or the target actor is gone, tell him to defend the current location
|
||||
if ((WaitingForIdle && self.IsIdle) || (self.IsIdle && (TargetType == ETargetType.Actor && !DefendTarget.IsValid)))
|
||||
{
|
||||
IsReturning = false;
|
||||
WaitingForIdle = false;
|
||||
DefendThis(self.CenterLocation);
|
||||
|
||||
return;
|
||||
}
|
||||
if (IsReturning && self.IsIdle)
|
||||
{
|
||||
IsReturning = false;
|
||||
}
|
||||
|
||||
if (TargetType != ETargetType.None)
|
||||
{
|
||||
if ((self.CenterLocation - DefendTarget.CenterLocation).Length > MaxDistance * Game.CellSize)
|
||||
{
|
||||
Return(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnOrder(Actor self, Order order)
|
||||
{
|
||||
WaitForIdle();
|
||||
}
|
||||
|
||||
private void WaitForIdle()
|
||||
{
|
||||
// could be an attack or move order ... => 'disable' the stance for now (invalidate the target)
|
||||
DefendTarget = Target.None;
|
||||
TargetType = ETargetType.None;
|
||||
WaitingForIdle = true;
|
||||
}
|
||||
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
{
|
||||
if (!Active) return;
|
||||
if (TargetType == ETargetType.None) return;
|
||||
if (IsReturning) return;
|
||||
if (!self.HasTrait<AttackBase>()) return;
|
||||
|
||||
ReturnFire(self, e, false); // only triggers when standing still
|
||||
}
|
||||
|
||||
public override string OrderString
|
||||
{
|
||||
get { return "StanceDefensive"; }
|
||||
}
|
||||
|
||||
public override Color SelectionColor
|
||||
{
|
||||
get { return Color.LightGoldenrodYellow; }
|
||||
}
|
||||
|
||||
protected override string Shape
|
||||
{
|
||||
get { return "xxxx\nxxxx"; }
|
||||
}
|
||||
|
||||
protected void Return(Actor self)
|
||||
{
|
||||
if ((TargetType == ETargetType.None) || (!DefendTarget.IsValid && (TargetType == ETargetType.Actor && !DefendTarget.IsValid))) return;
|
||||
IsReturning = true;
|
||||
|
||||
var attackBase = self.TraitOrDefault<AttackBase>();
|
||||
|
||||
|
||||
|
||||
// Reset the attack target => otherwise it will not pick up enemies anymore!
|
||||
|
||||
// This should result in unsetting the target (could do it directly, this seems more 'valid')
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
self.CancelActivity();
|
||||
attackBase.ResolveOrder(self, new Order("Stop", self));
|
||||
self.QueueActivity(self.Trait<Mobile>().MoveWithinRange(DefendTarget, 1));
|
||||
WaitForIdle();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,10 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
|
||||
public char AttackMoveKey = 'a';
|
||||
public char HoldGroundKey = 'g'; // Hold (G)round
|
||||
// public char DefensiveKey = 'd'; // (D)efensive
|
||||
public char DefensiveKey = 'd'; // (D)efensive
|
||||
public char AggressiveKey = 'a'; // (A)ggressive
|
||||
public char ReturnFireKey = 'r'; // (R)eturn Fire
|
||||
public char HoldFire = 'h'; // (h)old fire
|
||||
public char HoldFireKey = 'h'; // (h)old fire
|
||||
public readonly OrderManager OrderManager;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
@@ -73,11 +73,17 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
|
||||
// stance: Hold Fire
|
||||
// description: Prevents attacking (ie no autotarget is being done)
|
||||
if (e.KeyChar == HoldFire && (e.Modifiers.HasModifier(Modifiers.Alt)))
|
||||
if (e.KeyChar == HoldFireKey && (e.Modifiers.HasModifier(Modifiers.Alt)))
|
||||
{
|
||||
return EnableStance<UnitStanceHoldFire>();
|
||||
}
|
||||
|
||||
// stance: Defensive
|
||||
if (e.KeyChar == DefensiveKey && (e.Modifiers.HasModifier(Modifiers.Alt)))
|
||||
{
|
||||
return EnableStance<UnitStanceDefensive>();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user