Clean up Attack*.

This commit is contained in:
Paul Chote
2014-03-17 12:24:17 +13:00
parent 96cc1276c2
commit 9d1526f4e7
8 changed files with 147 additions and 115 deletions

View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
@@ -35,6 +36,7 @@ namespace OpenRA.Mods.RA
protected Lazy<IFacing> facing;
Lazy<IEnumerable<Armament>> armaments;
protected IEnumerable<Armament> Armaments { get { return armaments.Value; } }
protected Lazy<Building> building;
public AttackBase(Actor self, AttackBaseInfo info)
{
@@ -43,6 +45,7 @@ namespace OpenRA.Mods.RA
armaments = Lazy.New(() => self.TraitsImplementing<Armament>());
facing = Lazy.New(() => self.TraitOrDefault<IFacing>());
building = Lazy.New(() => self.TraitOrDefault<Building>());
}
protected virtual bool CanAttack(Actor self, Target target)
@@ -50,6 +53,10 @@ namespace OpenRA.Mods.RA
if (!self.IsInWorld)
return false;
// Building is under construction or is being sold
if (building.Value != null && !building.Value.BuildComplete)
return false;
if (!target.IsValidFor(self))
return false;

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA
class AttackCharge : AttackOmni, ITick, INotifyAttack, ISync
{
readonly AttackChargeInfo aci;
readonly AttackChargeInfo info;
[Sync] int charges;
[Sync] int timeToRecharge;
@@ -37,25 +37,25 @@ namespace OpenRA.Mods.RA
public AttackCharge(Actor self, AttackChargeInfo info)
: base(self, info)
{
aci = self.Info.Traits.Get<AttackChargeInfo>();
charges = aci.MaxCharges;
this.info = info;
charges = info.MaxCharges;
}
public void Tick(Actor self)
{
if (--timeToRecharge <= 0)
charges = aci.MaxCharges;
charges = info.MaxCharges;
}
public void Attacking(Actor self, Target target, Armament a, Barrel barrel)
{
--charges;
timeToRecharge = aci.ReloadTime;
timeToRecharge = info.ReloadTime;
}
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new ChargeAttack(newTarget);
return new ChargeAttack(this, newTarget);
}
public override void ResolveOrder(Actor self, Order order)
@@ -68,9 +68,12 @@ namespace OpenRA.Mods.RA
class ChargeAttack : Activity
{
readonly AttackCharge attack;
readonly Target target;
public ChargeAttack(Target target)
public ChargeAttack(AttackCharge attack, Target target)
{
this.attack = attack;
this.target = target;
}
@@ -78,23 +81,22 @@ namespace OpenRA.Mods.RA
{
if (IsCanceled || !target.IsValidFor(self))
return NextActivity;
var initDelay = self.Info.Traits.Get<AttackChargeInfo>().InitialChargeDelay;
var attack = self.Trait<AttackCharge>();
if (attack.charges == 0 || !attack.CanAttack(self, target))
return this;
self.Trait<RenderBuildingCharge>().PlayCharge(self);
return Util.SequenceActivities(new Wait(initDelay), new ChargeFire(target), this);
return Util.SequenceActivities(new Wait(attack.info.InitialChargeDelay), new ChargeFire(attack, target), this);
}
}
class ChargeFire : Activity
{
readonly AttackCharge attack;
readonly Target target;
public ChargeFire(Target target)
public ChargeFire(AttackCharge attack, Target target)
{
this.attack = attack;
this.target = target;
}
@@ -103,15 +105,12 @@ namespace OpenRA.Mods.RA
if (IsCanceled || !target.IsValidFor(self))
return NextActivity;
var chargeDelay = self.Info.Traits.Get<AttackChargeInfo>().ChargeDelay;
var attack = self.Trait<AttackCharge>();
if (attack.charges == 0)
return NextActivity;
attack.DoAttack(self, target);
return Util.SequenceActivities(new Wait(chargeDelay), this);
return Util.SequenceActivities(new Wait(attack.info.ChargeDelay), this);
}
}
}

View File

@@ -0,0 +1,103 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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.FileFormats;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class AttackFollowInfo : AttackBaseInfo
{
public override object Create(ActorInitializer init) { return new AttackFollow(init.self, this); }
}
public class AttackFollow : AttackBase, ITick, ISync
{
public Target Target { get; protected set; }
public AttackFollow(Actor self, AttackFollowInfo info)
: base(self, info) { }
protected override bool CanAttack(Actor self, Target target)
{
if (!target.IsValidFor(self))
return false;
return base.CanAttack(self, target);
}
public void Tick(Actor self)
{
DoAttack(self, Target);
IsAttacking = Target.IsValidFor(self);
}
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new AttackActivity(self, newTarget, allowMove);
}
public override void ResolveOrder(Actor self, Order order)
{
base.ResolveOrder(self, order);
if (order.OrderString == "Stop")
Target = Target.Invalid;
}
class AttackActivity : Activity
{
readonly AttackFollow attack;
readonly IMove move;
readonly Target target;
public AttackActivity(Actor self, Target target, bool allowMove)
{
attack = self.Trait<AttackFollow>();
move = allowMove ? self.TraitOrDefault<IMove>() : null;
// HACK: Mobile.OnRails is horrible
var mobile = move as Mobile;
if (mobile != null && mobile.Info.OnRails)
move = null;
this.target = target;
}
public override Activity Tick(Actor self)
{
if (IsCanceled || !target.IsValidFor(self))
return NextActivity;
if (self.IsDisabled())
return this;
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, weapon.Weapon.Range.Range / 1024 - RangeTolerance));
attack.Target = target;
if (move != null)
return Util.SequenceActivities(move.MoveFollow(self, target, range), this);
}
return NextActivity;
}
}
}
}

View File

@@ -25,7 +25,8 @@ namespace OpenRA.Mods.RA
public override void DoAttack(Actor self, Target target)
{
if (!CanAttack(self, target)) return;
if (!CanAttack(self, target))
return;
var arm = Armaments.FirstOrDefault();
if (arm == null)
@@ -34,9 +35,8 @@ namespace OpenRA.Mods.RA
if (!target.IsInRange(self.CenterPosition, arm.Weapon.Range))
return;
var facing = self.TraitOrDefault<IFacing>();
foreach (var a in Armaments)
a.CheckFire(self, facing, target);
a.CheckFire(self, facing.Value, target);
if (target.Actor != null)
target.Actor.ChangeOwner(self.Owner);

View File

@@ -8,7 +8,7 @@
*/
#endregion
using OpenRA.Mods.RA.Buildings;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
@@ -18,34 +18,25 @@ namespace OpenRA.Mods.RA
public override object Create(ActorInitializer init) { return new AttackOmni(init.self, this); }
}
class AttackOmni : AttackBase, INotifyBuildComplete, ISync
class AttackOmni : AttackBase, ISync
{
[Sync] bool buildComplete = false;
public void BuildingComplete(Actor self) { buildComplete = true; }
public AttackOmni(Actor self, AttackOmniInfo info)
: base(self, info) { }
protected override bool CanAttack(Actor self, Target target)
{
var isBuilding = self.HasTrait<Building>() && !buildComplete;
return base.CanAttack(self, target) && !isBuilding;
}
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new SetTarget(newTarget, this);
return new SetTarget(this, newTarget);
}
class SetTarget : Activity
{
readonly Target target;
readonly AttackOmni ao;
readonly AttackOmni attack;
public SetTarget(Target target, AttackOmni ao)
public SetTarget(AttackOmni attack, Target target)
{
this.target = target;
this.ao = ao;
this.attack = attack;
}
public override Activity Tick(Actor self)
@@ -53,7 +44,7 @@ namespace OpenRA.Mods.RA
if (IsCanceled || !target.IsValidFor(self))
return NextActivity;
ao.DoAttack(self, target);
attack.DoAttack(self, target);
return this;
}
}

View File

@@ -35,19 +35,20 @@ namespace OpenRA.Mods.RA
int idleTicks = 0;
PopupState state = PopupState.Open;
Turreted turret;
bool skippedMakeAnimation;
public AttackPopupTurreted(ActorInitializer init, AttackPopupTurretedInfo info)
: base(init.self, info)
{
this.info = info;
buildComplete = init.Contains<SkipMakeAnimsInit>();
turret = turrets.FirstOrDefault();
rb = init.self.Trait<RenderBuilding>();
skippedMakeAnimation = init.Contains<SkipMakeAnimsInit>();
}
protected override bool CanAttack(Actor self, Target target)
{
if (state == PopupState.Transitioning || !buildComplete)
if (state == PopupState.Transitioning || !building.Value.BuildComplete)
return false;
if (!base.CanAttack(self, target))
@@ -90,17 +91,14 @@ namespace OpenRA.Mods.RA
}
}
public override void BuildingComplete(Actor self)
public void BuildingComplete(Actor self)
{
// Set true for SkipMakeAnimsInit
if (buildComplete)
if (!skippedMakeAnimation)
{
state = PopupState.Closed;
rb.PlayCustomAnimRepeating(self, "closed-idle");
turret.desiredFacing = null;
}
buildComplete = true;
}
public float GetDamageModifier(Actor attacker, WarheadInfo warhead)

View File

@@ -10,23 +10,21 @@
using System;
using System.Collections.Generic;
using OpenRA.FileFormats;
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>
class AttackTurretedInfo : AttackFollowInfo, Requires<TurretedInfo>
{
public override object Create(ActorInitializer init) { return new AttackTurreted(init.self, this); }
}
class AttackTurreted : AttackBase, ITick, INotifyBuildComplete, ISync
class AttackTurreted : AttackFollow, ITick, ISync
{
public Target Target { get; protected set; }
protected IEnumerable<Turreted> turrets;
[Sync] protected bool buildComplete;
public AttackTurreted(Actor self, AttackTurretedInfo info)
: base(self, info)
@@ -36,10 +34,7 @@ namespace OpenRA.Mods.RA
protected override bool CanAttack(Actor self, Target target)
{
if (self.HasTrait<Building>() && !buildComplete)
return false;
if (!target.IsValidFor(self))
if (!base.CanAttack(self, target))
return false;
var canAttack = false;
@@ -47,69 +42,7 @@ namespace OpenRA.Mods.RA
if (t.FaceTarget(self, target))
canAttack = true;
if (!canAttack)
return false;
return base.CanAttack(self, target);
}
public void Tick(Actor self)
{
DoAttack(self, Target);
IsAttacking = Target.IsValidFor(self);
}
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.IsValidFor(self))
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, weapon.Weapon.Range.Range / 1024 - RangeTolerance));
attack.Target = target;
var mobile = self.TraitOrDefault<Mobile>();
if (allowMove && mobile != null && !mobile.Info.OnRails)
return Util.SequenceActivities(mobile.MoveFollow(self, target, range), this);
}
return NextActivity;
}
return canAttack;
}
}
}

View File

@@ -485,6 +485,7 @@
<Compile Include="World\BuildableTerrainLayer.cs" />
<Compile Include="Buildings\LaysTerrain.cs" />
<Compile Include="RemoveImmediately.cs" />
<Compile Include="Attack\AttackFollow.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">