From 2cff2d8bbed827723b804458777543a5bfc3733a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 8 Jul 2013 22:10:05 +1200 Subject: [PATCH] Improve Leap behavior: * Configurable jump speed. * Configurable jump angle. * Configurable attack sound (uses weapon report). * Don't accidentally eat tanks. --- OpenRA.Mods.RA/Activities/Leap.cs | 45 +++++++++++++++++------------ OpenRA.Mods.RA/Attack/AttackLeap.cs | 16 ++++++++-- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/Leap.cs b/OpenRA.Mods.RA/Activities/Leap.cs index 64898fa68b..289e87e379 100644 --- a/OpenRA.Mods.RA/Activities/Leap.cs +++ b/OpenRA.Mods.RA/Activities/Leap.cs @@ -10,6 +10,7 @@ using System; using System.Linq; +using OpenRA.GameRules; using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Render; using OpenRA.Traits; @@ -19,47 +20,53 @@ namespace OpenRA.Mods.RA.Activities class Leap : Activity { Mobile mobile; + WeaponInfo weapon; - PPos from; - PPos to; + WPos from; + WPos to; + int ticks; + int length; + WAngle angle; - int moveFraction; - const int length = 6; - - public Leap(Actor self, Target target) + public Leap(Actor self, Actor target, WeaponInfo weapon, WRange speed, WAngle angle) { - if (!target.IsActor) - throw new InvalidOperationException("Leap requires a target actor"); - - var targetMobile = target.Actor.TraitOrDefault(); + var targetMobile = target.TraitOrDefault(); if (targetMobile == null) throw new InvalidOperationException("Leap requires a target actor with the Mobile trait"); + this.weapon = weapon; + this.angle = angle; mobile = self.Trait(); mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, targetMobile.fromCell, targetMobile.fromSubCell); mobile.IsMoving = true; - from = self.CenterLocation; - to = Util.CenterOfCell(targetMobile.fromCell) + MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; + from = self.CenterPosition; + 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().Attacking(self, target); - Sound.Play("dogg5p.aud", self.CenterLocation); + self.Trait().Attacking(self, Target.FromActor(target)); + + if (weapon.Report != null && weapon.Report.Any()) + Sound.Play(weapon.Report.Random(self.World.SharedRandom), self.CenterLocation); } public override Activity Tick(Actor self) { - if (moveFraction == 0 && IsCanceled) + if (ticks == 0 && IsCanceled) return NextActivity; - mobile.AdjustPxPosition(self, PPos.Lerp(from, to, moveFraction++, length - 1)); - if (moveFraction >= length) + mobile.AdjustPxPosition(self, PPos.FromWPosHackZ(WPos.LerpQuadratic(from, to, angle, ++ticks, length))); + if (ticks >= length) { mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); mobile.FinishedMoving(self); mobile.IsMoving = false; - // Kill whatever else is in our new cell - self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell).Except(new []{self}).Do(a => a.Kill(self)); + self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell) + .Except(new []{self}).Where(t => weapon.IsValidAgainst(t)) + .Do(t => t.Kill(self)); + return NextActivity; } diff --git a/OpenRA.Mods.RA/Attack/AttackLeap.cs b/OpenRA.Mods.RA/Attack/AttackLeap.cs index 0dbf477093..75683b1673 100644 --- a/OpenRA.Mods.RA/Attack/AttackLeap.cs +++ b/OpenRA.Mods.RA/Attack/AttackLeap.cs @@ -10,6 +10,7 @@ using System; using System.Linq; +using OpenRA.FileFormats; using OpenRA.Mods.RA.Activities; using OpenRA.Traits; @@ -17,17 +18,26 @@ namespace OpenRA.Mods.RA { 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); } } class AttackLeap : AttackFrontal, ISync { + 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) { - if (!CanAttack(self, target)) + if (!CanAttack(self, target) || !target.IsActor) return; var a = ChooseArmamentForTarget(target); @@ -40,7 +50,7 @@ namespace OpenRA.Mods.RA return; self.CancelActivity(); - self.QueueActivity(new Leap(self, target)); + self.QueueActivity(new Leap(self, target.Actor, a.Weapon, info.Speed, info.Angle)); } } }