diff --git a/OpenRA.Mods.RA/ThrowsParticle.cs b/OpenRA.Mods.RA/ThrowsParticle.cs index 076000e37f..7f7360d264 100644 --- a/OpenRA.Mods.RA/ThrowsParticle.cs +++ b/OpenRA.Mods.RA/ThrowsParticle.cs @@ -22,14 +22,20 @@ namespace OpenRA.Mods.RA [Desc("Initial position relative to body")] public readonly WVec Offset = WVec.Zero; + [Desc("Minimum distance to throw the particle")] + public readonly WRange MinThrowRange = new WRange(256); + [Desc("Maximum distance to throw the particle")] - public readonly WRange ThrowRange = new WRange(768); + public readonly WRange MaxThrowRange = new WRange(768); - [Desc("Maximum height to throw the particle")] - public readonly WRange ThrowHeight = new WRange(256); + [Desc("Minimum angle to throw the particle")] + public readonly WAngle MinThrowAngle = WAngle.FromDegrees(30); - [Desc("Number of ticks to animate")] - public readonly int Length = 15; + [Desc("Maximum angle to throw the particle")] + public readonly WAngle MaxThrowAngle = WAngle.FromDegrees(60); + + [Desc("Speed to throw the particle (horizontal WPos/tick)")] + public readonly int Velocity = 75; [Desc("Maximum rotation rate")] public readonly float ROT = 15; @@ -39,19 +45,19 @@ namespace OpenRA.Mods.RA class ThrowsParticle : ITick { - ThrowsParticleInfo info; WVec pos; WVec initialPos; WVec finalPos; + WAngle angle; + int tick = 0; + int length; float facing; float rotation; public ThrowsParticle(ActorInitializer init, ThrowsParticleInfo info) { - this.info = info; - var self = init.self; var rs = self.Trait(); var body = self.Trait(); @@ -62,10 +68,12 @@ namespace OpenRA.Mods.RA // Calculate final position var throwRotation = WRot.FromFacing(Game.CosmeticRandom.Next(1024)); - var throwOffset = new WVec((int)(Game.CosmeticRandom.Gauss1D(1)*info.ThrowRange.Range), 0, 0).Rotate(throwRotation); + var throwDistance = Game.CosmeticRandom.Next(info.MinThrowRange.Range, info.MaxThrowRange.Range); initialPos = pos = info.Offset.Rotate(body.QuantizeOrientation(self, WRot.FromFacing(bodyFacing))); - finalPos = initialPos + throwOffset; + finalPos = initialPos + new WVec(throwDistance, 0, 0).Rotate(throwRotation); + angle = new WAngle(Game.CosmeticRandom.Next(info.MinThrowAngle.Angle, info.MaxThrowAngle.Angle)); + length = (finalPos - initialPos).Length / info.Velocity; // Facing rotation rotation = Game.CosmeticRandom.Gauss1D(2) * info.ROT; @@ -77,15 +85,10 @@ namespace OpenRA.Mods.RA public void Tick(Actor self) { - if (tick == info.Length) + if (tick == length) return; - tick++; - // Lerp position horizontally and height along a sinusoid using a cubic ease - var t = (tick*tick*tick / (info.Length*info.Length) - 3*tick*tick / info.Length + 3*tick); - var tp = WVec.Lerp(initialPos, finalPos, t, info.Length); - var th = new WAngle(512*(info.Length - t) / info.Length).Sin()*info.ThrowHeight.Range / 1024; - pos = new WVec(tp.X, tp.Y, th); + pos = WVec.LerpQuadratic(initialPos, finalPos, angle, tick++, length); // Spin the particle facing += rotation;