Files
OpenRA/OpenRA.Mods.RA/Attack/AttackTurreted.cs

109 lines
2.8 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class AttackTurretedInfo : AttackBaseInfo, Requires<TurretedInfo>
{
public override object Create(ActorInitializer init) { return new AttackTurreted(init.self); }
}
class AttackTurreted : AttackBase, INotifyBuildComplete, ISync
{
public Target Target { get; protected set; }
protected IEnumerable<Turreted> turrets;
[Sync] protected bool buildComplete;
public AttackTurreted(Actor self) : base(self)
{
turrets = self.TraitsImplementing<Turreted>();
}
protected override bool CanAttack(Actor self, Target target)
{
if (self.HasTrait<Building>() && !buildComplete)
return false;
if (!target.IsValid) return false;
bool canAttack = false;
foreach (var t in turrets)
if (t.FaceTarget(self, target))
canAttack = true;
if (!canAttack) return false;
return base.CanAttack(self, target);
}
public override void Tick(Actor self)
{
base.Tick(self);
DoAttack(self, Target);
IsAttacking = Target.IsValid;
}
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new AttackActivity(newTarget, allowMove);
}
public override void ResolveOrder(Actor self, Order order)
{
base.ResolveOrder(self, order);
if (order.OrderString == "Stop")
Target = Target.Invalid;
}
public virtual void BuildingComplete(Actor self) { buildComplete = true; }
class AttackActivity : Activity
{
readonly Target target;
readonly bool allowMove;
public AttackActivity(Target newTarget, bool allowMove)
{
this.target = newTarget;
this.allowMove = allowMove;
}
public override Activity Tick(Actor self)
{
if (IsCanceled || !target.IsValid) return NextActivity;
if (self.IsDisabled()) return this;
var attack = self.Trait<AttackTurreted>();
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
var weapon = attack.ChooseArmamentForTarget(target);
if (weapon != null)
{
var range = WRange.FromCells(Math.Max(0, (int)weapon.Weapon.Range - RangeTolerance));
attack.Target = target;
if (allowMove && self.HasTrait<Mobile>() && !self.Info.Traits.Get<MobileInfo>().OnRails)
return Util.SequenceActivities(new Follow(target, range), this);
}
return NextActivity;
}
}
}
}