Added: UnitStanceDefensive

This commit is contained in:
geckosoft
2010-11-12 06:48:08 +01:00
committed by Bob
parent d2a0647085
commit 8df47f5a60
3 changed files with 173 additions and 3 deletions

View File

@@ -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" />

View 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();
});
}
}
}

View File

@@ -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;
}