From bf47affd2e690e7fdf7cc371bfcda85fb043068a Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 12 Jan 2017 13:53:55 +0100 Subject: [PATCH] Add bounce logic to Bullet Allows Bullet projectiles to bounce off ground. --- OpenRA.Mods.Common/Projectiles/Bullet.cs | 35 +++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/OpenRA.Mods.Common/Projectiles/Bullet.cs b/OpenRA.Mods.Common/Projectiles/Bullet.cs index fce58cc640..9f2ad0802d 100644 --- a/OpenRA.Mods.Common/Projectiles/Bullet.cs +++ b/OpenRA.Mods.Common/Projectiles/Bullet.cs @@ -63,6 +63,13 @@ namespace OpenRA.Mods.Common.Projectiles [Desc("Arc in WAngles, two values indicate variable arc.")] public readonly WAngle[] LaunchAngle = { WAngle.Zero }; + [Desc("Up to how many times does this bullet bounce when touching ground without hitting a target.", + "0 implies exploding on contact with the originally targeted position.")] + public readonly int BounceCount = 0; + + [Desc("Modify distance of each bounce by this percentage of previous distance.")] + public readonly int BounceRangeModifier = 60; + [Desc("Interval in ticks between each spawned Trail animation.")] public readonly int TrailInterval = 2; @@ -96,10 +103,11 @@ namespace OpenRA.Mods.Common.Projectiles ContrailRenderable contrail; string trailPalette; - [Sync] WPos pos, target; + [Sync] WPos pos, target, source; int length; [Sync] int facing; int ticks, smokeTicks; + int remainingBounces; public Actor SourceActor { get { return args.SourceActor; } } @@ -108,6 +116,7 @@ namespace OpenRA.Mods.Common.Projectiles this.info = info; this.args = args; pos = args.Source; + source = args.Source; var world = args.SourceActor.World; @@ -150,6 +159,7 @@ namespace OpenRA.Mods.Common.Projectiles trailPalette += args.SourceActor.Owner.InternalName; smokeTicks = info.TrailDelay; + remainingBounces = info.BounceCount; } int GetEffectiveFacing() @@ -171,7 +181,7 @@ namespace OpenRA.Mods.Common.Projectiles anim.Tick(); var lastPos = pos; - pos = WPos.LerpQuadratic(args.Source, target, angle, ticks, length); + pos = WPos.LerpQuadratic(source, target, angle, ticks, length); // Check for walls or other blocking obstacles var shouldExplode = false; @@ -185,7 +195,7 @@ namespace OpenRA.Mods.Common.Projectiles if (!string.IsNullOrEmpty(info.TrailImage) && --smokeTicks < 0) { - var delayedPos = WPos.LerpQuadratic(args.Source, target, angle, ticks - info.TrailDelay, length); + var delayedPos = WPos.LerpQuadratic(source, target, angle, ticks - info.TrailDelay, length); world.AddFrameEndTask(w => w.Add(new SpriteEffect(delayedPos, w, info.TrailImage, info.TrailSequences.Random(world.SharedRandom), trailPalette, false, false, GetEffectiveFacing()))); @@ -195,8 +205,25 @@ namespace OpenRA.Mods.Common.Projectiles if (info.ContrailLength > 0) contrail.Update(pos); + var flightLengthReached = ticks++ >= length; + var shouldBounce = remainingBounces > 0; + + if (flightLengthReached && shouldBounce) + { + target += (pos - source) * info.BounceRangeModifier / 100; + var dat = world.Map.DistanceAboveTerrain(target); + target += new WVec(0, 0, -dat.Length); + length = Math.Max((target - pos).Length / speed.Length, 1); + ticks = 0; + source = pos; + remainingBounces--; + } + // Flight length reached / exceeded - shouldExplode |= ticks++ >= length; + shouldExplode |= flightLengthReached && !shouldBounce; + + // Driving into cell with higher height level + shouldExplode |= world.Map.DistanceAboveTerrain(pos).Length < 0; if (shouldExplode) Explode(world);