Improve Leap behavior:

* Configurable jump speed.
* Configurable jump angle.
* Configurable attack sound (uses weapon report).
* Don't accidentally eat tanks.
This commit is contained in:
Paul Chote
2013-07-08 22:10:05 +12:00
parent 4fbed810dc
commit 2cff2d8bbe
2 changed files with 39 additions and 22 deletions

View File

@@ -10,6 +10,7 @@
using System; using System;
using System.Linq; using System.Linq;
using OpenRA.GameRules;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
using OpenRA.Mods.RA.Render; using OpenRA.Mods.RA.Render;
using OpenRA.Traits; using OpenRA.Traits;
@@ -19,47 +20,53 @@ namespace OpenRA.Mods.RA.Activities
class Leap : Activity class Leap : Activity
{ {
Mobile mobile; Mobile mobile;
WeaponInfo weapon;
PPos from; WPos from;
PPos to; WPos to;
int ticks;
int length;
WAngle angle;
int moveFraction; public Leap(Actor self, Actor target, WeaponInfo weapon, WRange speed, WAngle angle)
const int length = 6;
public Leap(Actor self, Target target)
{ {
if (!target.IsActor) var targetMobile = target.TraitOrDefault<Mobile>();
throw new InvalidOperationException("Leap requires a target actor");
var targetMobile = target.Actor.TraitOrDefault<Mobile>();
if (targetMobile == null) if (targetMobile == null)
throw new InvalidOperationException("Leap requires a target actor with the Mobile trait"); throw new InvalidOperationException("Leap requires a target actor with the Mobile trait");
this.weapon = weapon;
this.angle = angle;
mobile = self.Trait<Mobile>(); mobile = self.Trait<Mobile>();
mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, targetMobile.fromCell, targetMobile.fromSubCell); mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, targetMobile.fromCell, targetMobile.fromSubCell);
mobile.IsMoving = true; mobile.IsMoving = true;
from = self.CenterLocation; from = self.CenterPosition;
to = Util.CenterOfCell(targetMobile.fromCell) + MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; var offset = MobileInfo.SubCellOffsets[targetMobile.fromSubCell];
to = targetMobile.fromCell.CenterPosition + new WVec(offset.X * 1024 / Game.CellSize, offset.Y * 1024 / Game.CellSize, 0);
length = Math.Max((to - from).Length / speed.Range, 1);
self.Trait<RenderInfantry>().Attacking(self, target); self.Trait<RenderInfantry>().Attacking(self, Target.FromActor(target));
Sound.Play("dogg5p.aud", self.CenterLocation);
if (weapon.Report != null && weapon.Report.Any())
Sound.Play(weapon.Report.Random(self.World.SharedRandom), self.CenterLocation);
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
if (moveFraction == 0 && IsCanceled) if (ticks == 0 && IsCanceled)
return NextActivity; return NextActivity;
mobile.AdjustPxPosition(self, PPos.Lerp(from, to, moveFraction++, length - 1)); mobile.AdjustPxPosition(self, PPos.FromWPosHackZ(WPos.LerpQuadratic(from, to, angle, ++ticks, length)));
if (moveFraction >= length) if (ticks >= length)
{ {
mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell);
mobile.FinishedMoving(self); mobile.FinishedMoving(self);
mobile.IsMoving = false; mobile.IsMoving = false;
// Kill whatever else is in our new cell self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell)
self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell).Except(new []{self}).Do(a => a.Kill(self)); .Except(new []{self}).Where(t => weapon.IsValidAgainst(t))
.Do(t => t.Kill(self));
return NextActivity; return NextActivity;
} }

View File

@@ -10,6 +10,7 @@
using System; using System;
using System.Linq; using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Activities;
using OpenRA.Traits; using OpenRA.Traits;
@@ -17,17 +18,26 @@ namespace OpenRA.Mods.RA
{ {
class AttackLeapInfo : AttackFrontalInfo class AttackLeapInfo : AttackFrontalInfo
{ {
[Desc("Leap speed (in units/tick).")]
public readonly WRange Speed = new WRange(426);
public readonly WAngle Angle = WAngle.FromDegrees(20);
public override object Create(ActorInitializer init) { return new AttackLeap(init.self, this); } public override object Create(ActorInitializer init) { return new AttackLeap(init.self, this); }
} }
class AttackLeap : AttackFrontal, ISync class AttackLeap : AttackFrontal, ISync
{ {
AttackLeapInfo info;
public AttackLeap(Actor self, AttackLeapInfo info) public AttackLeap(Actor self, AttackLeapInfo info)
: base(self, info) {} : base(self, info)
{
this.info = info;
}
public override void DoAttack(Actor self, Target target) public override void DoAttack(Actor self, Target target)
{ {
if (!CanAttack(self, target)) if (!CanAttack(self, target) || !target.IsActor)
return; return;
var a = ChooseArmamentForTarget(target); var a = ChooseArmamentForTarget(target);
@@ -40,7 +50,7 @@ namespace OpenRA.Mods.RA
return; return;
self.CancelActivity(); self.CancelActivity();
self.QueueActivity(new Leap(self, target)); self.QueueActivity(new Leap(self, target.Actor, a.Weapon, info.Speed, info.Angle));
} }
} }
} }