From 46a384d1ca0afa8c2b952fa2071f138b25e226be Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 4 Apr 2013 18:50:51 +1300 Subject: [PATCH 01/15] Add WAngle.ArcTan(). --- OpenRA.FileFormats/WAngle.cs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/OpenRA.FileFormats/WAngle.cs b/OpenRA.FileFormats/WAngle.cs index 80dd98aa96..dcc8bcc7fa 100644 --- a/OpenRA.FileFormats/WAngle.cs +++ b/OpenRA.FileFormats/WAngle.cs @@ -67,6 +67,41 @@ namespace OpenRA return new WAngle(Angle - 512).Tan(); } + public static WAngle ArcTan(int y, int x) + { + if (y == 0) + return new WAngle(x >= 0 ? 0 : 512); + + if (x == 0) + return new WAngle(Math.Sign(y)*256); + + var ay = Math.Abs(y); + var ax = Math.Abs(x); + + // Find the closest angle that satisfies y = x*tan(theta) + var bestVal = int.MaxValue; + var bestAngle = 0; + for (var i = 0; i < 256; i++) + { + var val = Math.Abs(1024*ay - ax*TanTable[i]); + if (val < bestVal) + { + bestVal = val; + bestAngle = i; + } + } + + // Calculate quadrant + if (x < 0 && y > 0) + bestAngle = 512 - bestAngle; + else if (x < 0 && y < 0) + bestAngle = 512 + bestAngle; + else if (x > 0 && y < 0) + bestAngle = 1024 - bestAngle; + + return new WAngle(bestAngle); + } + // Must not be used outside rendering code public float RendererRadians() { return (float)(Angle * Math.PI / 512f); } public float RendererDegrees() { return Angle * 0.3515625f; } From 6d52af4553745fa51040c7961a28faedef45ceaf Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 18:40:46 +1200 Subject: [PATCH 02/15] Add probabilistic sampling functions to WRange, WVec. --- OpenRA.FileFormats/WRange.cs | 12 ++++++++++++ OpenRA.FileFormats/WVec.cs | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/OpenRA.FileFormats/WRange.cs b/OpenRA.FileFormats/WRange.cs index 003e2d308a..fbcaa0eeed 100644 --- a/OpenRA.FileFormats/WRange.cs +++ b/OpenRA.FileFormats/WRange.cs @@ -10,6 +10,7 @@ using System; using System.Drawing; +using System.Linq; namespace OpenRA { @@ -34,6 +35,17 @@ namespace OpenRA public static bool operator ==(WRange me, WRange other) { return (me.Range == other.Range); } public static bool operator !=(WRange me, WRange other) { return !(me == other); } + // Sampled a N-sample probability density function in the range [-1024..1024] + // 1 sample produces a rectangular probability + // 2 samples produces a triangular probability + // ... + // N samples approximates a true gaussian + public static WRange FromPDF(Thirdparty.Random r, int samples) + { + return new WRange(Exts.MakeArray(samples, _ => r.Next(-1024, 1024)) + .Sum() / samples); + } + public static bool TryParse(string s, out WRange result) { s = s.ToLowerInvariant(); diff --git a/OpenRA.FileFormats/WVec.cs b/OpenRA.FileFormats/WVec.cs index 72b2df78b9..4039374384 100644 --- a/OpenRA.FileFormats/WVec.cs +++ b/OpenRA.FileFormats/WVec.cs @@ -69,6 +69,16 @@ namespace OpenRA return new WVec(ret.X, ret.Y, ret.Z + offset); } + // Sampled a N-sample probability density function in the range [-1024..1024, -1024..1024] + // 1 sample produces a rectangular probability + // 2 samples produces a triangular probability + // ... + // N samples approximates a true gaussian + public static WVec FromPDF(Thirdparty.Random r, int samples) + { + return new WVec(WRange.FromPDF(r, samples), WRange.FromPDF(r, samples), WRange.Zero); + } + public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode(); } public override bool Equals(object obj) From df46ffeb848178810c056ef77e1538aedb6a9435 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 17:30:06 +1200 Subject: [PATCH 03/15] Convert ProjectileArgs to world coords. --- OpenRA.Game/GameRules/WeaponInfo.cs | 14 +++--- OpenRA.Mods.RA/Armament.cs | 20 +++------ OpenRA.Mods.RA/CarpetBomb.cs | 14 +++--- OpenRA.Mods.RA/Combat.cs | 62 ++++++++++----------------- OpenRA.Mods.RA/Effects/Bullet.cs | 42 ++++++++++-------- OpenRA.Mods.RA/Effects/GravityBomb.cs | 17 +++++--- OpenRA.Mods.RA/Effects/LaserZap.cs | 38 ++++++++-------- OpenRA.Mods.RA/Effects/Missile.cs | 44 +++++++++++-------- OpenRA.Mods.RA/Effects/TeslaZap.cs | 33 +++++++------- 9 files changed, 134 insertions(+), 150 deletions(-) diff --git a/OpenRA.Game/GameRules/WeaponInfo.cs b/OpenRA.Game/GameRules/WeaponInfo.cs index 2c98c65d8c..019e869c8b 100644 --- a/OpenRA.Game/GameRules/WeaponInfo.cs +++ b/OpenRA.Game/GameRules/WeaponInfo.cs @@ -74,8 +74,6 @@ namespace OpenRA.GameRules } } - - public enum DamageModel { Normal, // classic RA damage model: point actors, distance-based falloff @@ -85,14 +83,12 @@ namespace OpenRA.GameRules public class ProjectileArgs { public WeaponInfo weapon; - public Actor firedBy; - public PPos src; - public int srcAltitude; - public int facing; - public Target target; - public PPos dest; - public int destAltitude; public float firepowerModifier = 1.0f; + public int facing; + public WPos source; + public Actor sourceActor; + public WPos passiveTarget; + public Target guidedTarget; } public interface IProjectileInfo { IEffect Create(ProjectileArgs args); } diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index 7eb5faf061..5e3c018146 100755 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -121,26 +121,20 @@ namespace OpenRA.Mods.RA var barrel = Barrels[Burst % Barrels.Length]; var muzzlePosition = self.CenterPosition + MuzzleOffset(self, barrel); - var legacyMuzzlePosition = PPos.FromWPos(muzzlePosition); - var legacyMuzzleAltitude = Game.CellSize*muzzlePosition.Z/1024; var legacyFacing = MuzzleOrientation(self, barrel).Yaw.Angle / 4; var args = new ProjectileArgs { weapon = Weapon, - firedBy = self, - target = target, - src = legacyMuzzlePosition, - srcAltitude = legacyMuzzleAltitude, - - dest = PPos.FromWPos(target.CenterPosition), - destAltitude = target.CenterPosition.Z * Game.CellSize / 1024, - facing = legacyFacing, - firepowerModifier = self.TraitsImplementing() .Select(a => a.GetFirepowerModifier()) - .Product() + .Product(), + + source = muzzlePosition, + sourceActor = self, + passiveTarget = target.CenterPosition, + guidedTarget = target }; attack.ScheduleDelayedAction(Info.FireDelay, () => diff --git a/OpenRA.Mods.RA/CarpetBomb.cs b/OpenRA.Mods.RA/CarpetBomb.cs index 13a40c98ae..e0a9c037be 100644 --- a/OpenRA.Mods.RA/CarpetBomb.cs +++ b/OpenRA.Mods.RA/CarpetBomb.cs @@ -56,17 +56,15 @@ namespace OpenRA.Mods.RA var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; dropDelay = weapon.ROF; - var centerLocation = PPos.FromWPos(self.CenterPosition); - var altitude = self.CenterPosition.Z * Game.CellSize / 1024; + var pos = self.CenterPosition; var args = new ProjectileArgs { - srcAltitude = altitude, - destAltitude = 0, - src = centerLocation, - dest = centerLocation, + weapon = weapon, facing = self.Trait().Facing, - firedBy = self, - weapon = weapon + + source = pos, + sourceActor = self, + passiveTarget = pos - new WVec(0, 0, pos.Z) }; self.World.Add(args.weapon.Projectile.Create(args)); diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 6144d190a6..37b751f09f 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -32,23 +32,21 @@ namespace OpenRA.Mods.RA return null; } - public static void DoImpact(WarheadInfo warhead, ProjectileArgs args) + public static void DoImpact(WPos pos, WarheadInfo warhead, WeaponInfo weapon, Actor firedBy, float firepowerModifier) { - var world = args.firedBy.World; - var targetTile = args.dest.ToCPos(); + var world = firedBy.World; + var targetTile = pos.ToCPos(); if (!world.Map.IsInMap(targetTile)) return; - var isWater = args.destAltitude == 0 && world.GetTerrainInfo(targetTile).IsWater; + var isWater = pos.Z == 0 && world.GetTerrainInfo(targetTile).IsWater; var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion; - var dest = args.dest.ToWPos(args.destAltitude); if (explosionType != null) - world.AddFrameEndTask( - w => w.Add(new Explosion(w, dest, explosionType))); + world.AddFrameEndTask(w => w.Add(new Explosion(w, pos, explosionType))); - Sound.Play(GetImpactSound(warhead, isWater), dest); + Sound.Play(GetImpactSound(warhead, isWater), pos); var smudgeLayers = world.WorldActor.TraitsImplementing().ToDictionary(x => x.Info.Type); @@ -106,12 +104,12 @@ namespace OpenRA.Mods.RA { var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2); var range = new WRange((int)maxSpread * 1024 / Game.CellSize); - var hitActors = world.FindActorsInCircle(args.dest.ToWPos(0), range); + var hitActors = world.FindActorsInCircle(pos, range); foreach (var victim in hitActors) { - var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier); - victim.InflictDamage(args.firedBy, damage, warhead); + var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier); + victim.InflictDamage(firedBy, damage, warhead); } } break; @@ -119,23 +117,22 @@ namespace OpenRA.Mods.RA { foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0])) foreach (var unit in world.FindActorsInBox(t, t)) - unit.InflictDamage(args.firedBy, + unit.InflictDamage(firedBy, (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead); } break; } } - public static void DoImpacts(ProjectileArgs args) + public static void DoImpacts(WPos pos, Actor firedBy, WeaponInfo weapon, float damageModifier) { - foreach (var warhead in args.weapon.Warheads) + foreach (var wh in weapon.Warheads) { - // NOTE(jsd): Fixed access to modified closure bug! - var warheadClosed = warhead; + var warhead = wh; + Action a = () => DoImpact(pos, warhead, weapon, firedBy, damageModifier); - Action a = () => DoImpact(warheadClosed, args); if (warhead.Delay > 0) - args.firedBy.World.AddFrameEndTask( - w => w.Add(new DelayedAction(warheadClosed.Delay, a))); + firedBy.World.AddFrameEndTask( + w => w.Add(new DelayedAction(warhead.Delay, a))); else a(); } @@ -143,24 +140,11 @@ namespace OpenRA.Mods.RA public static void DoExplosion(Actor attacker, string weapontype, WPos pos) { - var pxPos = PPos.FromWPos(pos); - var altitude = pos.Z * Game.CellSize / 1024; - var args = new ProjectileArgs - { - src = pxPos, - dest = pxPos, - srcAltitude = altitude, - destAltitude = altitude, - firedBy = attacker, - target = Target.FromPos(pos), - weapon = Rules.Weapons[weapontype.ToLowerInvariant()], - facing = 0 - }; + var weapon = Rules.Weapons[weapontype.ToLowerInvariant()]; + if (weapon.Report != null && weapon.Report.Any()) + Sound.Play(weapon.Report.Random(attacker.World.SharedRandom), pos); - if (args.weapon.Report != null && args.weapon.Report.Any()) - Sound.Play(args.weapon.Report.Random(attacker.World.SharedRandom), pos); - - DoImpacts(args); + DoImpacts(pos, attacker, weapon, 1f); } static readonly float[] falloff = @@ -177,16 +161,16 @@ namespace OpenRA.Mods.RA return (falloff[u] * (1 - t)) + (falloff[u + 1] * t); } - static float GetDamageToInflict(Actor target, ProjectileArgs args, WarheadInfo warhead, float modifier) + static float GetDamageToInflict(WPos pos, Actor target, WarheadInfo warhead, WeaponInfo weapon, float modifier) { // don't hit air units with splash from ground explosions, etc - if (!args.weapon.IsValidAgainst(target)) + if (!weapon.IsValidAgainst(target)) return 0f; var health = target.Info.Traits.GetOrDefault(); if( health == null ) return 0f; - var distance = (int)Math.Max(0, (target.CenterLocation - args.dest).Length - health.Radius); + var distance = (int)Math.Max(0, (target.CenterPosition - pos).Length * Game.CellSize / 1024 - health.Radius); var falloff = (float)GetDamageFalloff(distance / warhead.Spread); var rawDamage = (float)(warhead.Damage * modifier * falloff); var multiplier = (float)warhead.EffectivenessAgainst(target); diff --git a/OpenRA.Mods.RA/Effects/Bullet.cs b/OpenRA.Mods.RA/Effects/Bullet.cs index 678aec409b..f6bf5276e1 100755 --- a/OpenRA.Mods.RA/Effects/Bullet.cs +++ b/OpenRA.Mods.RA/Effects/Bullet.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -46,6 +46,8 @@ namespace OpenRA.Mods.RA.Effects { readonly BulletInfo Info; readonly ProjectileArgs Args; + PPos src, dest; + int srcAltitude, destAltitude; int t = 0; Animation anim; @@ -58,11 +60,17 @@ namespace OpenRA.Mods.RA.Effects Info = info; Args = args; + src = PPos.FromWPos(args.source); + srcAltitude = args.source.Z * Game.CellSize / 1024; + + dest = PPos.FromWPos(args.passiveTarget); + destAltitude = args.passiveTarget.Z * Game.CellSize / 1024; + if (info.Inaccuracy > 0) { - var factor = ((Args.dest - Args.src).ToCVec().Length) / args.weapon.Range; - Args.dest += (PVecInt) (info.Inaccuracy * factor * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2(); - Log.Write("debug", "Bullet with Inaccuracy; factor: #{0}; Projectile dest: {1}", factor, Args.dest); + var factor = ((dest - src).ToCVec().Length) / args.weapon.Range; + dest += (PVecInt) (info.Inaccuracy * factor * args.sourceActor.World.SharedRandom.Gauss2D(2)).ToInt2(); + Log.Write("debug", "Bullet with Inaccuracy; factor: #{0}; Projectile dest: {1}", factor, dest); } if (Info.Image != null) @@ -73,17 +81,17 @@ namespace OpenRA.Mods.RA.Effects if (Info.ContrailLength > 0) { - var color = Info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.firedBy) : Info.ContrailColor; - Trail = new ContrailRenderable(args.firedBy.World, color, Info.ContrailLength, Info.ContrailDelay, 0); + var color = Info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.sourceActor) : Info.ContrailColor; + Trail = new ContrailRenderable(args.sourceActor.World, color, Info.ContrailLength, Info.ContrailDelay, 0); } } - int TotalTime() { return (Args.dest - Args.src).Length * BaseBulletSpeed / Info.Speed; } + int TotalTime() { return (dest - src).Length * BaseBulletSpeed / Info.Speed; } float GetAltitude() { var at = (float)t / TotalTime(); - return (Args.dest - Args.src).Length * Info.Angle * 4 * at * (1 - at); + return (dest - src).Length * Info.Angle * 4 * at * (1 - at); } int GetEffectiveFacing() @@ -91,7 +99,7 @@ namespace OpenRA.Mods.RA.Effects var at = (float)t / TotalTime(); var attitude = Info.Angle * (1 - 2 * at); - var rawFacing = Traits.Util.GetFacing(Args.dest - Args.src, 0); + var rawFacing = Traits.Util.GetFacing(dest - src, 0); var u = (rawFacing % 128) / 128f; var scale = 512 * u * (1 - u); @@ -112,8 +120,8 @@ namespace OpenRA.Mods.RA.Effects { var at = (float)t / TotalTime(); - var altitude = float2.Lerp(Args.srcAltitude, Args.destAltitude, at); - var pos = float2.Lerp(Args.src.ToFloat2(), Args.dest.ToFloat2(), at) - new float2(0, altitude); + var altitude = float2.Lerp(srcAltitude, destAltitude, at); + var pos = float2.Lerp(src.ToFloat2(), dest.ToFloat2(), at) - new float2(0, altitude); var highPos = (Info.High || Info.Angle > 0) ? (pos - new float2(0, GetAltitude())) @@ -136,13 +144,13 @@ namespace OpenRA.Mods.RA.Effects if (!Info.High) // check for hitting a wall { var at = (float)t / TotalTime(); - var pos = float2.Lerp(Args.src.ToFloat2(), Args.dest.ToFloat2(), at); + var pos = float2.Lerp(src.ToFloat2(), dest.ToFloat2(), at); var cell = ((PPos) pos.ToInt2()).ToCPos(); if (world.ActorMap.GetUnitsAt(cell).Any( a => a.HasTrait())) { - Args.dest = (PPos) pos.ToInt2(); + dest = (PPos) pos.ToInt2(); Explode(world); } } @@ -159,11 +167,11 @@ namespace OpenRA.Mods.RA.Effects { var at = (float)t / TotalTime(); - var altitude = float2.Lerp(Args.srcAltitude, Args.destAltitude, at); - var pos = float2.Lerp(Args.src.ToFloat2(), Args.dest.ToFloat2(), at) - new float2(0, altitude); + var altitude = float2.Lerp(srcAltitude, destAltitude, at); + var pos = float2.Lerp(src.ToFloat2(), dest.ToFloat2(), at) - new float2(0, altitude); var cell = ((PPos)pos.ToInt2()).ToCPos(); - if (!Args.firedBy.World.FogObscures(cell)) + if (!Args.sourceActor.World.FogObscures(cell)) { if (Info.High || Info.Angle > 0) { @@ -184,7 +192,7 @@ namespace OpenRA.Mods.RA.Effects void Explode( World world ) { world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoImpacts(Args); + Combat.DoImpacts(dest.ToWPos(destAltitude), Args.sourceActor, Args.weapon, Args.firepowerModifier); } } } diff --git a/OpenRA.Mods.RA/Effects/GravityBomb.cs b/OpenRA.Mods.RA/Effects/GravityBomb.cs index 3ecedf622b..58e3ffc438 100755 --- a/OpenRA.Mods.RA/Effects/GravityBomb.cs +++ b/OpenRA.Mods.RA/Effects/GravityBomb.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -25,13 +25,16 @@ namespace OpenRA.Mods.RA.Effects public class GravityBomb : IEffect { Animation anim; - int altitude; + int2 dest; + int altitude, destAltitude; ProjectileArgs Args; public GravityBomb(GravityBombInfo info, ProjectileArgs args) { Args = args; - altitude = args.srcAltitude; + altitude = args.source.Z * Game.CellSize / 1024; + destAltitude = args.passiveTarget.Z * Game.CellSize / 1024; + dest = PPos.FromWPos(args.passiveTarget).ToInt2(); anim = new Animation(info.Image); if (anim.HasSequence("open")) @@ -42,10 +45,10 @@ namespace OpenRA.Mods.RA.Effects public void Tick(World world) { - if (--altitude <= Args.destAltitude) + if (--altitude <= destAltitude) { world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoImpacts(Args); + Combat.DoImpacts(Args.passiveTarget, Args.sourceActor, Args.weapon, Args.firepowerModifier); } anim.Tick(); @@ -53,8 +56,8 @@ namespace OpenRA.Mods.RA.Effects public IEnumerable Render(WorldRenderer wr) { - var pos = Args.dest.ToInt2() - new int2(0, altitude) - .5f * anim.Image.size; - yield return new SpriteRenderable(anim.Image, pos, wr.Palette("effect"), Args.dest.Y); + var pos = dest - new int2(0, altitude) - .5f * anim.Image.size; + yield return new SpriteRenderable(anim.Image, pos, wr.Palette("effect"), dest.Y); } } } diff --git a/OpenRA.Mods.RA/Effects/LaserZap.cs b/OpenRA.Mods.RA/Effects/LaserZap.cs index 8514f80a97..5f26485fd7 100755 --- a/OpenRA.Mods.RA/Effects/LaserZap.cs +++ b/OpenRA.Mods.RA/Effects/LaserZap.cs @@ -11,9 +11,9 @@ using System.Collections.Generic; using System.Drawing; using OpenRA.Effects; +using OpenRA.FileFormats; using OpenRA.GameRules; using OpenRA.Graphics; -using OpenRA.FileFormats; using OpenRA.Traits; namespace OpenRA.Mods.RA.Effects @@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Effects public IEffect Create(ProjectileArgs args) { - var c = UsePlayerColor ? args.firedBy.Owner.Color.RGB : Color; + var c = UsePlayerColor ? args.sourceActor.Owner.Color.RGB : Color; return new LaserZap(args, this, c); } } @@ -41,13 +41,16 @@ namespace OpenRA.Mods.RA.Effects int ticks = 0; Color color; bool doneDamage; + bool animationComplete; Animation hitanim; + WPos target; public LaserZap(ProjectileArgs args, LaserZapInfo info, Color color) { this.args = args; this.info = info; this.color = color; + this.target = args.passiveTarget; if (info.HitAnim != null) this.hitanim = new Animation(info.HitAnim); @@ -56,43 +59,36 @@ namespace OpenRA.Mods.RA.Effects public void Tick(World world) { // Beam tracks target - if (args.target.IsValid) - args.dest = args.target.CenterLocation; + if (args.guidedTarget.IsValid) + target = args.guidedTarget.CenterPosition; if (!doneDamage) { if (hitanim != null) - hitanim.PlayThen("idle", - () => world.AddFrameEndTask(w => w.Remove(this))); - Combat.DoImpacts(args); + hitanim.PlayThen("idle", () => animationComplete = true); + + Combat.DoImpacts(target, args.sourceActor, args.weapon, args.firepowerModifier); doneDamage = true; } - ++ticks; if (hitanim != null) hitanim.Tick(); - else - if (ticks >= info.BeamDuration) - world.AddFrameEndTask(w => w.Remove(this)); + + if (++ticks >= info.BeamDuration && animationComplete) + world.AddFrameEndTask(w => w.Remove(this)); } public IEnumerable Render(WorldRenderer wr) { if (ticks < info.BeamDuration) { - var src = new PPos(args.src.X, args.src.Y).ToWPos(args.srcAltitude); - var dest = new PPos(args.dest.X, args.dest.Y).ToWPos(args.destAltitude); - var rc = Color.FromArgb((info.BeamDuration - ticks)*255/info.BeamDuration, color); - - yield return new BeamRenderable(src, 0, dest - src, info.BeamWidth, rc); + var rc = Color.FromArgb((info.BeamDuration - ticks) * 255 / info.BeamDuration, color); + yield return new BeamRenderable(args.source, 0, target - args.source, info.BeamWidth, rc); } if (hitanim != null) - yield return new SpriteRenderable(hitanim.Image, args.dest.ToFloat2(), - wr.Palette("effect"), (int)args.dest.Y); - - if (ticks >= info.BeamDuration) - yield break; + foreach (var r in hitanim.Render(target, wr.Palette("effect"))) + yield return r; } } } diff --git a/OpenRA.Mods.RA/Effects/Missile.cs b/OpenRA.Mods.RA/Effects/Missile.cs index 7eae2bffdb..97051ac7af 100755 --- a/OpenRA.Mods.RA/Effects/Missile.cs +++ b/OpenRA.Mods.RA/Effects/Missile.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -54,6 +54,8 @@ namespace OpenRA.Mods.RA.Effects PVecInt offset; public PSubPos SubPxPosition; public PPos PxPosition { get { return SubPxPosition.ToPPos(); } } + PPos target; + int targetAltitude; readonly Animation anim; int Facing; @@ -66,12 +68,15 @@ namespace OpenRA.Mods.RA.Effects Info = info; Args = args; - SubPxPosition = Args.src.ToPSubPos(); - Altitude = Args.srcAltitude; + SubPxPosition = PPos.FromWPos(Args.source).ToPSubPos(); + Altitude = args.source.Z * Game.CellSize / 1024; Facing = Args.facing; + target = PPos.FromWPos(Args.passiveTarget); + targetAltitude = args.passiveTarget.Z * Game.CellSize / 1024; + if (info.Inaccuracy > 0) - offset = (PVecInt)(info.Inaccuracy * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2(); + offset = (PVecInt)(info.Inaccuracy * args.sourceActor.World.SharedRandom.Gauss2D(2)).ToInt2(); if (Info.Image != null) { @@ -81,8 +86,8 @@ namespace OpenRA.Mods.RA.Effects if (Info.ContrailLength > 0) { - var color = Info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.firedBy) : Info.ContrailColor; - Trail = new ContrailRenderable(args.firedBy.World, color, Info.ContrailLength, Info.ContrailDelay, 0); + var color = Info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.sourceActor) : Info.ContrailColor; + Trail = new ContrailRenderable(args.sourceActor.World, color, Info.ContrailLength, Info.ContrailDelay, 0); } } @@ -94,25 +99,27 @@ namespace OpenRA.Mods.RA.Effects { t += 40; + // Missile tracks target + if (Args.guidedTarget.IsValid) + { + target = PPos.FromWPos(Args.guidedTarget.CenterPosition); + targetAltitude = Args.guidedTarget.CenterPosition.Z * Game.CellSize / 1024; + } + // In pixels - var dist = Args.target.CenterLocation + offset - PxPosition; - - var targetAltitude = 0; - if (Args.target.IsValid) - targetAltitude = Args.target.CenterPosition.Z * Game.CellSize / 1024; - + var dist = target + offset - PxPosition; var jammed = Info.Jammable && world.ActorsWithTrait().Any(tp => (tp.Actor.CenterLocation - PxPosition).ToCVec().Length <= tp.Trait.Range - && (tp.Actor.Owner.Stances[Args.firedBy.Owner] != Stance.Ally - || (tp.Actor.Owner.Stances[Args.firedBy.Owner] == Stance.Ally && tp.Trait.AlliedMissiles)) + && (tp.Actor.Owner.Stances[Args.sourceActor.Owner] != Stance.Ally + || (tp.Actor.Owner.Stances[Args.sourceActor.Owner] == Stance.Ally && tp.Trait.AlliedMissiles)) && world.SharedRandom.Next(100 / tp.Trait.Chance) == 0); if (!jammed) { Altitude += Math.Sign(targetAltitude - Altitude); - if (Args.target.IsValid) + if (Args.guidedTarget.IsValid) Facing = Traits.Util.TickFacing(Facing, Traits.Util.GetFacing(dist, Facing), Info.ROT); @@ -127,7 +134,7 @@ namespace OpenRA.Mods.RA.Effects anim.Tick(); - if (dist.LengthSquared < MissileCloseEnough * MissileCloseEnough && Args.target.IsValid) + if (dist.LengthSquared < MissileCloseEnough * MissileCloseEnough) Explode(world); // TODO: Replace this with a lookup table @@ -168,9 +175,8 @@ namespace OpenRA.Mods.RA.Effects void Explode(World world) { world.AddFrameEndTask(w => w.Remove(this)); - Args.dest = PxPosition; if (t > Info.Arm * 40) /* don't blow up in our launcher's face! */ - Combat.DoImpacts(Args); + Combat.DoImpacts(PxPosition.ToWPos(Altitude), Args.sourceActor, Args.weapon, Args.firepowerModifier); } public IEnumerable Render(WorldRenderer wr) @@ -178,7 +184,7 @@ namespace OpenRA.Mods.RA.Effects if (Info.ContrailLength > 0) yield return Trail; - if (!Args.firedBy.World.FogObscures(PxPosition.ToCPos())) + if (!Args.sourceActor.World.FogObscures(PxPosition.ToCPos())) yield return new SpriteRenderable(anim.Image, PxPosition.ToFloat2() - new float2(0, Altitude), wr.Palette(Args.weapon.Underwater ? "shadow" : "effect"), PxPosition.Y); } diff --git a/OpenRA.Mods.RA/Effects/TeslaZap.cs b/OpenRA.Mods.RA/Effects/TeslaZap.cs index 6b5fe75f00..9671d096b7 100755 --- a/OpenRA.Mods.RA/Effects/TeslaZap.cs +++ b/OpenRA.Mods.RA/Effects/TeslaZap.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -46,13 +46,14 @@ namespace OpenRA.Mods.RA.Effects var bright = SequenceProvider.GetSequence(Info.Image, "bright"); var dim = SequenceProvider.GetSequence(Info.Image, "dim"); - var src = new PPos(Args.src.X, Args.src.Y - Args.srcAltitude); - var dest = new PPos(Args.dest.X, Args.dest.Y - Args.destAltitude); + var source = wr.ScreenPosition(Args.source); + var target = wr.ScreenPosition(Args.passiveTarget); + for (var n = 0; n < Info.DimZaps; n++) - foreach (var z in DrawZapWandering(wr, src, dest, dim)) + foreach (var z in DrawZapWandering(wr, source, target, dim)) yield return z; for (var n = 0; n < Info.BrightZaps; n++) - foreach (var z in DrawZapWandering(wr, src, dest, bright)) + foreach (var z in DrawZapWandering(wr, source, target, bright)) yield return z; } @@ -64,10 +65,8 @@ namespace OpenRA.Mods.RA.Effects if (!doneDamage) { - if (Args.target.IsValid) - Args.dest = Args.target.CenterLocation; - - Combat.DoImpacts(Args); + var pos = Args.guidedTarget.IsValid ? Args.guidedTarget.CenterPosition : Args.passiveTarget; + Combat.DoImpacts(pos, Args.sourceActor, Args.weapon, Args.firepowerModifier); doneDamage = true; } } @@ -83,7 +82,7 @@ namespace OpenRA.Mods.RA.Effects return renderables; } - static IEnumerable DrawZapWandering(WorldRenderer wr, PPos from, PPos to, Sequence s) + static IEnumerable DrawZapWandering(WorldRenderer wr, float2 from, float2 to, Sequence s) { var z = float2.Zero; /* hack */ var dist = to - from; @@ -92,19 +91,19 @@ namespace OpenRA.Mods.RA.Effects var renderables = new List(); if (Game.CosmeticRandom.Next(2) != 0) { - var p1 = from.ToFloat2() + (1 / 3f) * dist.ToFloat2() + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - var p2 = from.ToFloat2() + (2 / 3f) * dist.ToFloat2() + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + var p1 = from + (1 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + var p2 = from + (2 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - renderables.AddRange(DrawZap(wr, from.ToFloat2(), p1, s, out p1)); + renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); renderables.AddRange(DrawZap(wr, p1, p2, s, out p2)); - renderables.AddRange(DrawZap(wr, p2, to.ToFloat2(), s, out z)); + renderables.AddRange(DrawZap(wr, p2, to, s, out z)); } else { - var p1 = from.ToFloat2() + (1 / 2f) * dist.ToFloat2() + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + var p1 = from + (1 / 2f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - renderables.AddRange(DrawZap(wr, from.ToFloat2(), p1, s, out p1)); - renderables.AddRange(DrawZap(wr, p1, to.ToFloat2(), s, out z)); + renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); + renderables.AddRange(DrawZap(wr, p1, to, s, out z)); } return renderables; From 547fcdfa4d963e51da14a5e885f8ba05c5cbdc42 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 17:45:16 +1200 Subject: [PATCH 04/15] Split TeslaRenderable out from TeslaZap. --- OpenRA.Mods.RA/Effects/TeslaZap.cs | 92 +---------------- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 1 + OpenRA.Mods.RA/TeslaZapRenderable.cs | 148 +++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 87 deletions(-) create mode 100755 OpenRA.Mods.RA/TeslaZapRenderable.cs diff --git a/OpenRA.Mods.RA/Effects/TeslaZap.cs b/OpenRA.Mods.RA/Effects/TeslaZap.cs index 9671d096b7..56dfbb32ed 100755 --- a/OpenRA.Mods.RA/Effects/TeslaZap.cs +++ b/OpenRA.Mods.RA/Effects/TeslaZap.cs @@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA.Effects { readonly ProjectileArgs Args; readonly TeslaZapInfo Info; - IEnumerable renderables; + TeslaZapRenderable zap; int timeUntilRemove = 2; // # of frames bool doneDamage = false; bool initialized = false; @@ -41,27 +41,10 @@ namespace OpenRA.Mods.RA.Effects Info = info; } - public IEnumerable GenerateRenderables(WorldRenderer wr) - { - var bright = SequenceProvider.GetSequence(Info.Image, "bright"); - var dim = SequenceProvider.GetSequence(Info.Image, "dim"); - - var source = wr.ScreenPosition(Args.source); - var target = wr.ScreenPosition(Args.passiveTarget); - - for (var n = 0; n < Info.DimZaps; n++) - foreach (var z in DrawZapWandering(wr, source, target, dim)) - yield return z; - for (var n = 0; n < Info.BrightZaps; n++) - foreach (var z in DrawZapWandering(wr, source, target, bright)) - yield return z; - } - public void Tick(World world) { - if (timeUntilRemove <= 0) + if (timeUntilRemove-- <= 0) world.AddFrameEndTask(w => w.Remove(this)); - --timeUntilRemove; if (!doneDamage) { @@ -75,75 +58,10 @@ namespace OpenRA.Mods.RA.Effects { if (!initialized) { - renderables = GenerateRenderables(wr); - initialized = true; + var pos = Args.guidedTarget.IsValid ? Args.guidedTarget.CenterPosition : Args.passiveTarget; + zap = new TeslaZapRenderable(Args.source, 0, pos - Args.source, Info.Image, Info.BrightZaps, Info.DimZaps); } - - return renderables; + yield return zap; } - - static IEnumerable DrawZapWandering(WorldRenderer wr, float2 from, float2 to, Sequence s) - { - var z = float2.Zero; /* hack */ - var dist = to - from; - var norm = (1f / dist.Length) * new float2(-dist.Y, dist.X); - - var renderables = new List(); - if (Game.CosmeticRandom.Next(2) != 0) - { - var p1 = from + (1 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - var p2 = from + (2 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - - renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); - renderables.AddRange(DrawZap(wr, p1, p2, s, out p2)); - renderables.AddRange(DrawZap(wr, p2, to, s, out z)); - } - else - { - var p1 = from + (1 / 2f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - - renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); - renderables.AddRange(DrawZap(wr, p1, to, s, out z)); - } - - return renderables; - } - - static IEnumerable DrawZap(WorldRenderer wr, float2 from, float2 to, Sequence s, out float2 p) - { - var dist = to - from; - var q = new float2(-dist.Y, dist.X); - var c = -float2.Dot(from, q); - var rs = new List(); - var z = from; - - while ((to - z).X > 5 || (to - z).X < -5 || (to - z).Y > 5 || (to - z).Y < -5) - { - var step = steps.Where(t => (to - (z + new float2(t[0],t[1]))).LengthSquared < (to - z).LengthSquared ) - .OrderBy(t => Math.Abs(float2.Dot(z + new float2(t[0], t[1]), q) + c)).First(); - - rs.Add(new SpriteRenderable(s.GetSprite(step[4]), z + new float2(step[2], step[3]), - wr.Palette("effect"), (int)from.Y)); - z += new float2(step[0], step[1]); - if( rs.Count >= 1000 ) - break; - } - - p = z; - - return rs; - } - - static int[][] steps = new [] - { - new int[] { 8, 8, 4, 4, 0 }, - new int[] { -8, -8, -4, -4, 0 }, - new int[] { 8, 0, 4, 4, 1 }, - new int[] { -8, 0, -4, 4, 1 }, - new int[] { 0, 8, 4, 4, 2 }, - new int[] { 0, -8, 4, -4, 2 }, - new int[] { -8, 8, -4, 4, 3 }, - new int[] { 8, -8, 4, -4, 3 } - }; } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index bdc1ec10cf..54a3cfd217 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -462,6 +462,7 @@ + diff --git a/OpenRA.Mods.RA/TeslaZapRenderable.cs b/OpenRA.Mods.RA/TeslaZapRenderable.cs new file mode 100755 index 0000000000..0bdf0186ce --- /dev/null +++ b/OpenRA.Mods.RA/TeslaZapRenderable.cs @@ -0,0 +1,148 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 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 System.Linq; +using OpenRA.Effects; +using OpenRA.GameRules; +using OpenRA.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + struct TeslaZapRenderable : IRenderable + { + static int[][] steps = new[] + { + new int[] { 8, 8, 4, 4, 0 }, + new int[] { -8, -8, -4, -4, 0 }, + new int[] { 8, 0, 4, 4, 1 }, + new int[] { -8, 0, -4, 4, 1 }, + new int[] { 0, 8, 4, 4, 2 }, + new int[] { 0, -8, 4, -4, 2 }, + new int[] { -8, 8, -4, 4, 3 }, + new int[] { 8, -8, 4, -4, 3 } + }; + + readonly WPos pos; + readonly int zOffset; + readonly WVec length; + readonly string image; + readonly int brightZaps, dimZaps; + + WPos cachedPos; + WVec cachedLength; + IEnumerable cache; + + public TeslaZapRenderable(WPos pos, int zOffset, WVec length, string image, int brightZaps, int dimZaps) + { + this.pos = pos; + this.zOffset = zOffset; + this.length = length; + this.image = image; + this.brightZaps = brightZaps; + this.dimZaps = dimZaps; + + cachedPos = WPos.Zero; + cachedLength = WVec.Zero; + cache = new IRenderable[] { }; + } + + public WPos Pos { get { return pos; } } + public float Scale { get { return 1f; } } + public PaletteReference Palette { get { return null; } } + public int ZOffset { get { return zOffset; } } + + public IRenderable WithScale(float newScale) { return new TeslaZapRenderable(pos, zOffset, length, image, brightZaps, dimZaps); } + public IRenderable WithPalette(PaletteReference newPalette) { return new TeslaZapRenderable(pos, zOffset, length, image, brightZaps, dimZaps); } + public IRenderable WithZOffset(int newOffset) { return new TeslaZapRenderable(pos, zOffset, length, image, brightZaps, dimZaps); } + public IRenderable WithPos(WPos pos) { return new TeslaZapRenderable(pos, zOffset, length, image, brightZaps, dimZaps); } + + public void BeforeRender(WorldRenderer wr) { } + public void RenderDebugGeometry(WorldRenderer wr) { } + public void Render(WorldRenderer wr) + { + if (!cache.Any() || length != cachedLength || pos != cachedPos) + cache = GenerateRenderables(wr); + + cache.Do(c => c.Render(wr)); + } + + public IEnumerable GenerateRenderables(WorldRenderer wr) + { + var bright = SequenceProvider.GetSequence(image, "bright"); + var dim = SequenceProvider.GetSequence(image, "dim"); + + var source = wr.ScreenPosition(pos); + var target = wr.ScreenPosition(pos + length); + + for (var n = 0; n < dimZaps; n++) + foreach (var z in DrawZapWandering(wr, source, target, dim)) + yield return z; + for (var n = 0; n < brightZaps; n++) + foreach (var z in DrawZapWandering(wr, source, target, bright)) + yield return z; + } + + static IEnumerable DrawZapWandering(WorldRenderer wr, float2 from, float2 to, Sequence s) + { + var z = float2.Zero; /* hack */ + var dist = to - from; + var norm = (1f / dist.Length) * new float2(-dist.Y, dist.X); + + var renderables = new List(); + if (Game.CosmeticRandom.Next(2) != 0) + { + var p1 = from + (1 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + var p2 = from + (2 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + + renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); + renderables.AddRange(DrawZap(wr, p1, p2, s, out p2)); + renderables.AddRange(DrawZap(wr, p2, to, s, out z)); + } + else + { + var p1 = from + (1 / 2f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + + renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); + renderables.AddRange(DrawZap(wr, p1, to, s, out z)); + } + + return renderables; + } + + static IEnumerable DrawZap(WorldRenderer wr, float2 from, float2 to, Sequence s, out float2 p) + { + var dist = to - from; + var q = new float2(-dist.Y, dist.X); + var c = -float2.Dot(from, q); + var rs = new List(); + var z = from; + + while ((to - z).X > 5 || (to - z).X < -5 || (to - z).Y > 5 || (to - z).Y < -5) + { + var step = steps.Where(t => (to - (z + new float2(t[0], t[1]))).LengthSquared < (to - z).LengthSquared) + .OrderBy(t => Math.Abs(float2.Dot(z + new float2(t[0], t[1]), q) + c)).First(); + + rs.Add(new SpriteRenderable(s.GetSprite(step[4]), z + new float2(step[2], step[3]), + wr.Palette("effect"), (int)from.Y)); + + z += new float2(step[0], step[1]); + if (rs.Count >= 1000) + break; + } + + p = z; + + return rs; + } + } +} From da5c85dbac35e8c6b7f6dd3a6b95721cadc725ab Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 22:46:04 +1200 Subject: [PATCH 05/15] Rewrite GravityBomb with world coords and gravity. --- OpenRA.Mods.RA/Effects/GravityBomb.cs | 30 ++++++++++++++++----------- mods/ra/weapons.yaml | 4 +++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/OpenRA.Mods.RA/Effects/GravityBomb.cs b/OpenRA.Mods.RA/Effects/GravityBomb.cs index 58e3ffc438..96d11b5858 100755 --- a/OpenRA.Mods.RA/Effects/GravityBomb.cs +++ b/OpenRA.Mods.RA/Effects/GravityBomb.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 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, @@ -19,22 +19,26 @@ namespace OpenRA.Mods.RA.Effects public class GravityBombInfo : IProjectileInfo { public readonly string Image = null; + public readonly WRange Velocity = WRange.Zero; + public readonly WRange Acceleration = new WRange(15); + public IEffect Create(ProjectileArgs args) { return new GravityBomb(this, args); } } public class GravityBomb : IEffect { + GravityBombInfo info; Animation anim; - int2 dest; - int altitude, destAltitude; - ProjectileArgs Args; + ProjectileArgs args; + WVec velocity; + WPos pos; public GravityBomb(GravityBombInfo info, ProjectileArgs args) { - Args = args; - altitude = args.source.Z * Game.CellSize / 1024; - destAltitude = args.passiveTarget.Z * Game.CellSize / 1024; - dest = PPos.FromWPos(args.passiveTarget).ToInt2(); + this.info = info; + this.args = args; + pos = args.source; + velocity = new WVec(WRange.Zero, WRange.Zero, -info.Velocity); anim = new Animation(info.Image); if (anim.HasSequence("open")) @@ -45,10 +49,13 @@ namespace OpenRA.Mods.RA.Effects public void Tick(World world) { - if (--altitude <= destAltitude) + velocity -= new WVec(WRange.Zero, WRange.Zero, info.Acceleration); + pos += velocity; + + if (pos.Z <= args.passiveTarget.Z) { world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoImpacts(Args.passiveTarget, Args.sourceActor, Args.weapon, Args.firepowerModifier); + Combat.DoImpacts(args.passiveTarget, args.sourceActor, args.weapon, args.firepowerModifier); } anim.Tick(); @@ -56,8 +63,7 @@ namespace OpenRA.Mods.RA.Effects public IEnumerable Render(WorldRenderer wr) { - var pos = dest - new int2(0, altitude) - .5f * anim.Image.size; - yield return new SpriteRenderable(anim.Image, pos, wr.Palette("effect"), dest.Y); + return anim.Render(pos, wr.Palette("effect")); } } } diff --git a/mods/ra/weapons.yaml b/mods/ra/weapons.yaml index 5858a84859..189fe575e1 100644 --- a/mods/ra/weapons.yaml +++ b/mods/ra/weapons.yaml @@ -865,6 +865,8 @@ ParaBomb: Report: CHUTE1.AUD Projectile: GravityBomb Image: PARABOMB + Velocity: 43 + Acceleration: 0 Warhead: Spread: 6 Versus: @@ -1284,4 +1286,4 @@ Mandible: Heavy: 10% Concrete: 10% InfDeath: 1 - Damage: 60 \ No newline at end of file + Damage: 60 From 285ecb8c03576c94fd0e3d9ebee6c86bdbd6a960 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 18:40:53 +1200 Subject: [PATCH 06/15] Rewrite bullets using world coords and improved trails. --- OpenRA.Mods.RA/Effects/Bullet.cs | 191 ++++++++++++++----------------- mods/ra/weapons.yaml | 5 +- 2 files changed, 84 insertions(+), 112 deletions(-) diff --git a/OpenRA.Mods.RA/Effects/Bullet.cs b/OpenRA.Mods.RA/Effects/Bullet.cs index f6bf5276e1..082744711f 100755 --- a/OpenRA.Mods.RA/Effects/Bullet.cs +++ b/OpenRA.Mods.RA/Effects/Bullet.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -28,171 +29,145 @@ namespace OpenRA.Mods.RA.Effects public readonly string Image = null; [Desc("Check for whether an actor with Wall: trait blocks fire")] public readonly bool High = false; - public readonly int RangeLimit = 0; - public readonly int Arm = 0; public readonly bool Shadow = false; - public readonly bool Proximity = false; public readonly float Angle = 0; public readonly int TrailInterval = 2; + public readonly int TrailDelay = 1; public readonly int ContrailLength = 0; public readonly Color ContrailColor = Color.White; public readonly bool ContrailUsePlayerColor = false; public readonly int ContrailDelay = 1; - public IEffect Create(ProjectileArgs args) { return new Bullet( this, args ); } + public IEffect Create(ProjectileArgs args) { return new Bullet(this, args); } } public class Bullet : IEffect { - readonly BulletInfo Info; - readonly ProjectileArgs Args; - PPos src, dest; - int srcAltitude, destAltitude; + readonly BulletInfo info; + readonly ProjectileArgs args; - int t = 0; + ContrailRenderable trail; Animation anim; - - const int BaseBulletSpeed = 100; /* pixels / 40ms frame */ - ContrailRenderable Trail; + WAngle angle; + WPos pos, target; + int length; + int facing; + int ticks, smokeTicks; public Bullet(BulletInfo info, ProjectileArgs args) { - Info = info; - Args = args; + this.info = info; + this.args = args; + this.pos = args.source; - src = PPos.FromWPos(args.source); - srcAltitude = args.source.Z * Game.CellSize / 1024; - - dest = PPos.FromWPos(args.passiveTarget); - destAltitude = args.passiveTarget.Z * Game.CellSize / 1024; + // Convert ProjectileArg definitions to world coordinates + // TODO: Change the yaml definitions so we don't need this + var range = new WRange((int)(1024 * args.weapon.Range)); // Range in world units + var inaccuracy = new WRange((int)(info.Inaccuracy * 1024 / Game.CellSize)); // Offset in world units at max range + var speed = (int)(info.Speed * 4 * 1024 / (10 * Game.CellSize)); // Speed in world units per tick + angle = WAngle.ArcTan((int)(info.Angle * 4 * 1024), 1024); // Angle in world angle + target = args.passiveTarget; if (info.Inaccuracy > 0) { - var factor = ((dest - src).ToCVec().Length) / args.weapon.Range; - dest += (PVecInt) (info.Inaccuracy * factor * args.sourceActor.World.SharedRandom.Gauss2D(2)).ToInt2(); - Log.Write("debug", "Bullet with Inaccuracy; factor: #{0}; Projectile dest: {1}", factor, dest); + var maxOffset = inaccuracy.Range * (target - args.source).Length / range.Range; + target += WVec.FromPDF(args.sourceActor.World.SharedRandom, 2) * maxOffset / 1024; } - if (Info.Image != null) + facing = Traits.Util.GetFacing(target - args.source, 0); + length = Math.Max((target - args.source).Length / speed, 1); + + if (info.Image != null) { - anim = new Animation(Info.Image, GetEffectiveFacing); + anim = new Animation(info.Image, GetEffectiveFacing); anim.PlayRepeating("idle"); } - if (Info.ContrailLength > 0) + if (info.ContrailLength > 0) { - var color = Info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.sourceActor) : Info.ContrailColor; - Trail = new ContrailRenderable(args.sourceActor.World, color, Info.ContrailLength, Info.ContrailDelay, 0); + var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.sourceActor) : info.ContrailColor; + trail = new ContrailRenderable(args.sourceActor.World, color, info.ContrailLength, info.ContrailDelay, 0); } - } - int TotalTime() { return (dest - src).Length * BaseBulletSpeed / Info.Speed; } - - float GetAltitude() - { - var at = (float)t / TotalTime(); - return (dest - src).Length * Info.Angle * 4 * at * (1 - at); + smokeTicks = info.TrailDelay; } int GetEffectiveFacing() { - var at = (float)t / TotalTime(); - var attitude = Info.Angle * (1 - 2 * at); + var at = (float)ticks / (length - 1); + var attitude = angle.Tan() * (1 - 2 * at) / (4 * 1024); - var rawFacing = Traits.Util.GetFacing(dest - src, 0); - var u = (rawFacing % 128) / 128f; + var u = (facing % 128) / 128f; var scale = 512 * u * (1 - u); - return (int)(rawFacing < 128 - ? rawFacing - scale * attitude - : rawFacing + scale * attitude); + return (int)(facing < 128 + ? facing - scale * attitude + : facing + scale * attitude); } - int ticksToNextSmoke; - - public void Tick( World world ) + public void Tick(World world) { - t += 40; - - if (anim != null) anim.Tick(); - - if (t > TotalTime()) Explode( world ); - + // Fade the trail out gradually + if (ticks > length && info.ContrailLength > 0) { - var at = (float)t / TotalTime(); - var altitude = float2.Lerp(srcAltitude, destAltitude, at); - var pos = float2.Lerp(src.ToFloat2(), dest.ToFloat2(), at) - new float2(0, altitude); - - var highPos = (Info.High || Info.Angle > 0) - ? (pos - new float2(0, GetAltitude())) - : pos; - - if (Info.Trail != null && --ticksToNextSmoke < 0) - { - world.AddFrameEndTask(w => w.Add( - new Smoke(w, ((PPos)highPos.ToInt2()).ToWPos(0), Info.Trail))); - ticksToNextSmoke = Info.TrailInterval; - } - - if (Info.ContrailLength > 0) - { - var alt = (Info.High || Info.Angle > 0) ? GetAltitude() : 0; - Trail.Update(new PPos((int)pos.X, (int)pos.Y).ToWPos((int)alt)); - } + trail.Update(pos); + return; } - if (!Info.High) // check for hitting a wall - { - var at = (float)t / TotalTime(); - var pos = float2.Lerp(src.ToFloat2(), dest.ToFloat2(), at); - var cell = ((PPos) pos.ToInt2()).ToCPos(); + if (anim != null) + anim.Tick(); - if (world.ActorMap.GetUnitsAt(cell).Any( - a => a.HasTrait())) - { - dest = (PPos) pos.ToInt2(); - Explode(world); - } + pos = WPos.LerpQuadratic(args.source, target, angle, ticks, length); + + if (info.Trail != null && --smokeTicks < 0) + { + var delayedPos = WPos.LerpQuadratic(args.source, target, angle, ticks - info.TrailDelay, length); + world.AddFrameEndTask(w => w.Add(new Smoke(w, delayedPos, info.Trail))); + smokeTicks = info.TrailInterval; + } + + if (info.ContrailLength > 0) + trail.Update(pos); + + if (ticks++ >= length || (!info.High && world.ActorMap + .GetUnitsAt(pos.ToCPos()).Any(a => a.HasTrait()))) + { + Explode(world); } } - const float height = .1f; - public IEnumerable Render(WorldRenderer wr) { - if (Info.ContrailLength > 0) - yield return Trail; + if (info.ContrailLength > 0) + yield return trail; - if (anim != null) + if (anim == null || ticks >= length) + yield break; + + var cell = pos.ToCPos(); + if (!args.sourceActor.World.FogObscures(cell)) { - var at = (float)t / TotalTime(); - - var altitude = float2.Lerp(srcAltitude, destAltitude, at); - var pos = float2.Lerp(src.ToFloat2(), dest.ToFloat2(), at) - new float2(0, altitude); - - var cell = ((PPos)pos.ToInt2()).ToCPos(); - if (!Args.sourceActor.World.FogObscures(cell)) + if (info.Shadow) { - if (Info.High || Info.Angle > 0) - { - if (Info.Shadow) - yield return new SpriteRenderable(anim.Image, pos, wr.Palette("shadow"), (int)pos.Y); - - var highPos = pos - new float2(0, GetAltitude()); - - yield return new SpriteRenderable(anim.Image, highPos, wr.Palette("effect"), (int)pos.Y); - } - else - yield return new SpriteRenderable(anim.Image, pos, - wr.Palette(Args.weapon.Underwater ? "shadow" : "effect"), (int)pos.Y); + var shadowPos = pos - new WVec(0, 0, pos.Z); + foreach (var r in anim.Render(shadowPos, wr.Palette("shadow"))) + yield return r; } + + var palette = wr.Palette(args.weapon.Underwater ? "shadow" : "effect"); + foreach (var r in anim.Render(pos, palette)) + yield return r; } } - void Explode( World world ) + void Explode(World world) { - world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoImpacts(dest.ToWPos(destAltitude), Args.sourceActor, Args.weapon, Args.firepowerModifier); + if (info.ContrailLength > 0) + world.AddFrameEndTask(w => w.Add(new DelayedAction(info.ContrailLength, () => w.Remove(this)))); + else + world.AddFrameEndTask(w => w.Remove(this)); + + Combat.DoImpacts(target, args.sourceActor, args.weapon, args.firepowerModifier); } } } diff --git a/mods/ra/weapons.yaml b/mods/ra/weapons.yaml index 189fe575e1..3050646ba3 100644 --- a/mods/ra/weapons.yaml +++ b/mods/ra/weapons.yaml @@ -563,8 +563,6 @@ Napalm: Image: BOMBLET Speed: 5 High: yes - RangeLimit: 24 - Arm: 24 Warhead: Spread: 4 Versus: @@ -952,11 +950,10 @@ SCUD: Report: MISSILE1.AUD Projectile: Bullet Speed: 10 - Arm: 10 High: true Shadow: false - Proximity: true Trail: smokey + TrailDelay: 5 Inaccuracy: 5 Image: V2 Angle: .1 From b374816fa16cbcbbdd6137c4b4887f71411455d9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 19:42:43 +1200 Subject: [PATCH 07/15] Convert Missile to world coordinates. Fixes #3347. Closes #3434. --- OpenRA.Mods.RA/Effects/Missile.cs | 205 ++++++++++++++++-------------- OpenRA.Mods.RA/JamsMissiles.cs | 3 +- 2 files changed, 109 insertions(+), 99 deletions(-) diff --git a/OpenRA.Mods.RA/Effects/Missile.cs b/OpenRA.Mods.RA/Effects/Missile.cs index 97051ac7af..23e8c362e4 100755 --- a/OpenRA.Mods.RA/Effects/Missile.cs +++ b/OpenRA.Mods.RA/Effects/Missile.cs @@ -23,11 +23,10 @@ namespace OpenRA.Mods.RA.Effects class MissileInfo : IProjectileInfo { public readonly int Speed = 1; + public readonly WAngle MaximumPitch = WAngle.FromDegrees(30); public readonly int Arm = 0; [Desc("Check for whether an actor with Wall: trait blocks fire")] public readonly bool High = false; - public readonly bool Shadow = true; - public readonly bool Proximity = false; public readonly string Trail = null; public readonly float Inaccuracy = 0; public readonly string Image = null; @@ -48,145 +47,155 @@ namespace OpenRA.Mods.RA.Effects class Missile : IEffect { - readonly MissileInfo Info; - readonly ProjectileArgs Args; - - PVecInt offset; - public PSubPos SubPxPosition; - public PPos PxPosition { get { return SubPxPosition.ToPPos(); } } - PPos target; - int targetAltitude; - + readonly MissileInfo info; + readonly ProjectileArgs args; readonly Animation anim; - int Facing; - int t; - int Altitude; - ContrailRenderable Trail; + + ContrailRenderable trail; + WPos pos; + int facing; + + WPos target; + WVec offset; + int ticks; + bool exploded; + + readonly int speed; public Missile(MissileInfo info, ProjectileArgs args) { - Info = info; - Args = args; + this.info = info; + this.args = args; - SubPxPosition = PPos.FromWPos(Args.source).ToPSubPos(); - Altitude = args.source.Z * Game.CellSize / 1024; - Facing = Args.facing; + pos = args.source; + facing = args.facing; - target = PPos.FromWPos(Args.passiveTarget); - targetAltitude = args.passiveTarget.Z * Game.CellSize / 1024; + target = args.passiveTarget; + + // Convert ProjectileArg definitions to world coordinates + // TODO: Change the yaml definitions so we don't need this + var inaccuracy = (int)(info.Inaccuracy * 1024 / Game.CellSize); + speed = info.Speed * 1024 / (5 * Game.CellSize); if (info.Inaccuracy > 0) - offset = (PVecInt)(info.Inaccuracy * args.sourceActor.World.SharedRandom.Gauss2D(2)).ToInt2(); + offset = WVec.FromPDF(args.sourceActor.World.SharedRandom, 2) * inaccuracy / 1024; - if (Info.Image != null) + if (info.Image != null) { - anim = new Animation(Info.Image, () => Facing); + anim = new Animation(info.Image, () => facing); anim.PlayRepeating("idle"); } - if (Info.ContrailLength > 0) + if (info.ContrailLength > 0) { - var color = Info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.sourceActor) : Info.ContrailColor; - Trail = new ContrailRenderable(args.sourceActor.World, color, Info.ContrailLength, Info.ContrailDelay, 0); + var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.sourceActor) : info.ContrailColor; + trail = new ContrailRenderable(args.sourceActor.World, color, info.ContrailLength, info.ContrailDelay, 0); } } - // In pixels - const int MissileCloseEnough = 7; + static readonly WRange MissileCloseEnough = new WRange(7 * 1024 / Game.CellSize); int ticksToNextSmoke; + bool JammedBy(TraitPair tp) + { + if ((tp.Actor.CenterPosition - pos).HorizontalLengthSquared > tp.Trait.Range * tp.Trait.Range) + return false; + + if (tp.Actor.Owner.Stances[args.sourceActor.Owner] == Stance.Ally && !tp.Trait.AlliedMissiles) + return false; + + return tp.Actor.World.SharedRandom.Next(100 / tp.Trait.Chance) == 0; + } + public void Tick(World world) { - t += 40; - - // Missile tracks target - if (Args.guidedTarget.IsValid) + // Fade the trail out gradually + if (exploded && info.ContrailLength > 0) { - target = PPos.FromWPos(Args.guidedTarget.CenterPosition); - targetAltitude = Args.guidedTarget.CenterPosition.Z * Game.CellSize / 1024; - } - - // In pixels - var dist = target + offset - PxPosition; - var jammed = Info.Jammable && world.ActorsWithTrait().Any(tp => - (tp.Actor.CenterLocation - PxPosition).ToCVec().Length <= tp.Trait.Range - - && (tp.Actor.Owner.Stances[Args.sourceActor.Owner] != Stance.Ally - || (tp.Actor.Owner.Stances[Args.sourceActor.Owner] == Stance.Ally && tp.Trait.AlliedMissiles)) - - && world.SharedRandom.Next(100 / tp.Trait.Chance) == 0); - - if (!jammed) - { - Altitude += Math.Sign(targetAltitude - Altitude); - if (Args.guidedTarget.IsValid) - Facing = Traits.Util.TickFacing(Facing, - Traits.Util.GetFacing(dist, Facing), - Info.ROT); - } - else - { - Altitude += world.SharedRandom.Next(-1, 2); - Facing = Traits.Util.TickFacing(Facing, - Facing + world.SharedRandom.Next(-20, 21), - Info.ROT); + trail.Update(pos); + return; } + ticks++; anim.Tick(); - if (dist.LengthSquared < MissileCloseEnough * MissileCloseEnough) - Explode(world); + // Missile tracks target + if (args.guidedTarget.IsValid) + target = args.guidedTarget.CenterPosition; - // TODO: Replace this with a lookup table - var dir = (-float2.FromAngle((float)(Facing / 128f * Math.PI))).ToPSubVec(); + var dist = target + offset - pos; + var desiredFacing = Traits.Util.GetFacing(dist, facing); + var desiredAltitude = target.Z; + var jammed = info.Jammable && world.ActorsWithTrait().Any(j => JammedBy(j)); - var move = Info.Speed * dir; - if (targetAltitude > 0 && Info.TurboBoost) + if (jammed) + { + desiredFacing = facing + world.SharedRandom.Next(-20, 21); + desiredAltitude = world.SharedRandom.Next(-43, 86); + } + else if (!args.guidedTarget.IsValid) + desiredFacing = facing; + + facing = Traits.Util.TickFacing(facing, desiredFacing, info.ROT); + var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * speed / 1024; + if (target.Z > 0 && info.TurboBoost) move = (move * 3) / 2; - move = move / 5; - SubPxPosition += move; - - if (Info.Trail != null) + if (pos.Z != desiredAltitude) { - var sp = ((SubPxPosition - (move * 3) / 2)).ToPPos() - new PVecInt(0, Altitude); - - if (--ticksToNextSmoke < 0) - { - world.AddFrameEndTask(w => w.Add(new Smoke(w, sp.ToWPos(0), Info.Trail))); - ticksToNextSmoke = Info.TrailInterval; - } + var delta = move.HorizontalLength * info.MaximumPitch.Tan() / 1024; + var dz = (target.Z - pos.Z).Clamp(-delta, delta); + move += new WVec(0, 0, dz); } - if (Info.RangeLimit != 0 && t > Info.RangeLimit * 40) + pos += move; + + if (info.Trail != null && --ticksToNextSmoke < 0) + { + world.AddFrameEndTask(w => w.Add(new Smoke(w, pos - 3 * move / 2, info.Trail))); + ticksToNextSmoke = info.TrailInterval; + } + + if (info.ContrailLength > 0) + trail.Update(pos); + + var shouldExplode = pos.Z < 0 // Hit the ground + || dist.LengthSquared < MissileCloseEnough.Range * MissileCloseEnough.Range // Within range + || info.RangeLimit != 0 && ticks > info.RangeLimit // Ran out of fuel + || (!info.High && world.ActorMap.GetUnitsAt(pos.ToCPos()) + .Any(a => a.HasTrait())); // Hit a wall + + if (shouldExplode) Explode(world); - - if (!Info.High) // check for hitting a wall - { - var cell = PxPosition.ToCPos(); - if (world.ActorMap.GetUnitsAt(cell).Any(a => a.HasTrait())) - Explode(world); - } - - if (Info.ContrailLength > 0) - Trail.Update(PxPosition.ToWPos(Altitude)); } void Explode(World world) { - world.AddFrameEndTask(w => w.Remove(this)); - if (t > Info.Arm * 40) /* don't blow up in our launcher's face! */ - Combat.DoImpacts(PxPosition.ToWPos(Altitude), Args.sourceActor, Args.weapon, Args.firepowerModifier); + exploded = true; + + if (info.ContrailLength > 0) + world.AddFrameEndTask(w => w.Add(new DelayedAction(info.ContrailLength, () => w.Remove(this)))); + else + world.AddFrameEndTask(w => w.Remove(this)); + + // Don't blow up in our launcher's face! + if (ticks <= info.Arm) + return; + + Combat.DoImpacts(pos, args.sourceActor, args.weapon, args.firepowerModifier); } public IEnumerable Render(WorldRenderer wr) { - if (Info.ContrailLength > 0) - yield return Trail; + if (info.ContrailLength > 0) + yield return trail; - if (!Args.sourceActor.World.FogObscures(PxPosition.ToCPos())) - yield return new SpriteRenderable(anim.Image, PxPosition.ToFloat2() - new float2(0, Altitude), - wr.Palette(Args.weapon.Underwater ? "shadow" : "effect"), PxPosition.Y); + if (!args.sourceActor.World.FogObscures(pos.ToCPos())) + { + var palette = wr.Palette(args.weapon.Underwater ? "shadow" : "effect"); + foreach (var r in anim.Render(pos, palette)) + yield return r; + } } } } diff --git a/OpenRA.Mods.RA/JamsMissiles.cs b/OpenRA.Mods.RA/JamsMissiles.cs index 0f04fdd1ef..8eb3ad9710 100644 --- a/OpenRA.Mods.RA/JamsMissiles.cs +++ b/OpenRA.Mods.RA/JamsMissiles.cs @@ -26,7 +26,8 @@ namespace OpenRA.Mods.RA { readonly JamsMissilesInfo info; - public int Range { get { return info.Range; } } + // Convert cells to world units + public int Range { get { return 1024 * info.Range; } } public bool AlliedMissiles { get { return info.AlliedMissiles; } } public int Chance { get { return info.Chance; } } From bf9c737a11abf90a4336c853dbbd62733489a2bd Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 20:21:23 +1200 Subject: [PATCH 08/15] Remove obsolete Gauss1D/Gauss2D functions. --- OpenRA.Game/WorldUtils.cs | 13 ------------- OpenRA.Mods.RA/TeslaZapRenderable.cs | 6 +++--- OpenRA.Mods.RA/ThrowsParticle.cs | 2 +- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 4045c7af59..965c6d8d33 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -138,19 +138,6 @@ namespace OpenRA r.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom)); } - public static float Gauss1D(this Thirdparty.Random r, int samples) - { - return Exts.MakeArray(samples, _ => r.NextFloat() * 2 - 1f) - .Sum() / samples; - } - - // Returns a random offset in the range [-1..1,-1..1] with a separable - // Gauss distribution with 'samples' values taken for each axis - public static float2 Gauss2D(this Thirdparty.Random r, int samples) - { - return new float2(Gauss1D(r, samples), Gauss1D(r, samples)); - } - public static bool HasVoices(this Actor a) { var selectable = a.Info.Traits.GetOrDefault(); diff --git a/OpenRA.Mods.RA/TeslaZapRenderable.cs b/OpenRA.Mods.RA/TeslaZapRenderable.cs index 0bdf0186ce..0e6d883147 100755 --- a/OpenRA.Mods.RA/TeslaZapRenderable.cs +++ b/OpenRA.Mods.RA/TeslaZapRenderable.cs @@ -101,8 +101,8 @@ namespace OpenRA.Mods.RA var renderables = new List(); if (Game.CosmeticRandom.Next(2) != 0) { - var p1 = from + (1 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; - var p2 = from + (2 / 3f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + var p1 = from + (1 / 3f) * dist + WRange.FromPDF(Game.CosmeticRandom, 2).Range * dist.Length / 4096 * norm; + var p2 = from + (2 / 3f) * dist + WRange.FromPDF(Game.CosmeticRandom, 2).Range * dist.Length / 4096 * norm; renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); renderables.AddRange(DrawZap(wr, p1, p2, s, out p2)); @@ -110,7 +110,7 @@ namespace OpenRA.Mods.RA } else { - var p1 = from + (1 / 2f) * dist + Game.CosmeticRandom.Gauss1D(1) * .2f * dist.Length * norm; + var p1 = from + (1 / 2f) * dist + WRange.FromPDF(Game.CosmeticRandom, 2).Range * dist.Length / 4096 * norm; renderables.AddRange(DrawZap(wr, from, p1, s, out p1)); renderables.AddRange(DrawZap(wr, p1, to, s, out z)); diff --git a/OpenRA.Mods.RA/ThrowsParticle.cs b/OpenRA.Mods.RA/ThrowsParticle.cs index 7f7360d264..0bf3b1a36e 100644 --- a/OpenRA.Mods.RA/ThrowsParticle.cs +++ b/OpenRA.Mods.RA/ThrowsParticle.cs @@ -76,7 +76,7 @@ namespace OpenRA.Mods.RA length = (finalPos - initialPos).Length / info.Velocity; // Facing rotation - rotation = Game.CosmeticRandom.Gauss1D(2) * info.ROT; + rotation = WRange.FromPDF(Game.CosmeticRandom, 2).Range * info.ROT / 1024; var anim = new Animation(rs.GetImage(self), () => (int)facing); anim.PlayRepeating(info.Anim); From f198d7f204a21db8af898144f96c38d9c8c31b99 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 20:34:09 +1200 Subject: [PATCH 09/15] Add WVec.ToCVec() extension method. --- OpenRA.Game/CPos.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenRA.Game/CPos.cs b/OpenRA.Game/CPos.cs index b1743ea037..4a9151a269 100644 --- a/OpenRA.Game/CPos.cs +++ b/OpenRA.Game/CPos.cs @@ -72,8 +72,9 @@ namespace OpenRA public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); } } - public static class WPosExtensions + public static class WorldCoordinateExtensions { public static CPos ToCPos(this WPos a) { return new CPos(a.X / 1024, a.Y / 1024); } + public static CVec ToCVec(this WVec a) { return new CVec(a.X / 1024, a.Y / 1024); } } } \ No newline at end of file From 4a425e0fa09f4a6fd733e8a00f6161161c4a5552 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 20:34:23 +1200 Subject: [PATCH 10/15] Remove PSubVec from AttackWander. --- OpenRA.Mods.RA/Attack/AttackWander.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenRA.Mods.RA/Attack/AttackWander.cs b/OpenRA.Mods.RA/Attack/AttackWander.cs index ca68ba1716..d7614037a2 100644 --- a/OpenRA.Mods.RA/Attack/AttackWander.cs +++ b/OpenRA.Mods.RA/Attack/AttackWander.cs @@ -31,8 +31,8 @@ namespace OpenRA.Mods.RA public void TickIdle(Actor self) { - var target = (Util.SubPxVector[self.World.SharedRandom.Next(255)] * Info.MoveRadius).ToPVecInt().ToCVec() + self.Location; - self.Trait().ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = target }); + var offset = new WVec(0, -1024*Info.MoveRadius, 0).Rotate(WRot.FromFacing(self.World.SharedRandom.Next(255))).ToCVec(); + self.Trait().ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = self.Location + offset }); } } } From 3fd01cfac2c4b344830977b27bf7f516e297cd36 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 20:36:50 +1200 Subject: [PATCH 11/15] Remove obsolete PSubPos and PSubVec. --- OpenRA.Game/OpenRA.Game.csproj | 2 - OpenRA.Game/PPos.cs | 1 - OpenRA.Game/PSubPos.cs | 72 --------- OpenRA.Game/PSubVec.cs | 98 ------------- OpenRA.Game/Sync.cs | 12 -- OpenRA.Game/Traits/Util.cs | 261 --------------------------------- 6 files changed, 446 deletions(-) delete mode 100644 OpenRA.Game/PSubPos.cs delete mode 100644 OpenRA.Game/PSubVec.cs diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 33fa3179dd..e16c3456d6 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -86,8 +86,6 @@ - - diff --git a/OpenRA.Game/PPos.cs b/OpenRA.Game/PPos.cs index 4a3f45b350..d965b5191e 100644 --- a/OpenRA.Game/PPos.cs +++ b/OpenRA.Game/PPos.cs @@ -77,7 +77,6 @@ namespace OpenRA public float2 ToFloat2() { return new float2(X, Y); } public int2 ToInt2() { return new int2(X, Y); } public CPos ToCPos() { return new CPos((int)(1f / Game.CellSize * X), (int)(1f / Game.CellSize * Y)); } - public PSubPos ToPSubPos() { return new PSubPos(X * PSubPos.PerPx, Y * PSubPos.PerPx); } public PPos Clamp(Rectangle r) { diff --git a/OpenRA.Game/PSubPos.cs b/OpenRA.Game/PSubPos.cs deleted file mode 100644 index 7bd193565a..0000000000 --- a/OpenRA.Game/PSubPos.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 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.Drawing; - -namespace OpenRA -{ - /// - /// Sub-pixel coordinate position in the world (very fine). - /// - public struct PSubPos - { - public readonly int X, Y; - - public PSubPos(int x, int y) { X = x; Y = y; } - - public const int PerPx = 1024; - - public static readonly PSubPos Zero = new PSubPos(0, 0); - - public static explicit operator PSubPos(int2 a) { return new PSubPos(a.X, a.Y); } - - public static explicit operator PSubVec(PSubPos a) { return new PSubVec(a.X, a.Y); } - - public static PSubPos operator +(PSubPos a, PSubVec b) { return new PSubPos(a.X + b.X, a.Y + b.Y); } - public static PSubVec operator -(PSubPos a, PSubPos b) { return new PSubVec(a.X - b.X, a.Y - b.Y); } - public static PSubPos operator -(PSubPos a, PSubVec b) { return new PSubPos(a.X - b.X, a.Y - b.Y); } - - public static bool operator ==(PSubPos me, PSubPos other) { return (me.X == other.X && me.Y == other.Y); } - public static bool operator !=(PSubPos me, PSubPos other) { return !(me == other); } - - public static PSubPos Max(PSubPos a, PSubPos b) { return new PSubPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); } - public static PSubPos Min(PSubPos a, PSubPos b) { return new PSubPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); } - - public static PSubPos Lerp(PSubPos a, PSubPos b, int mul, int div) - { - return a + ((PSubVec)(b - a) * mul / div); - } - - public float2 ToFloat2() { return new float2(X, Y); } - public int2 ToInt2() { return new int2(X, Y); } - public PPos ToPPos() { return new PPos(X / PerPx, Y / PerPx); } - public CPos ToCPos() { return ToPPos().ToCPos(); } - - public PSubPos Clamp(Rectangle r) - { - return new PSubPos(Math.Min(r.Right, Math.Max(X, r.Left)), - Math.Min(r.Bottom, Math.Max(Y, r.Top))); - } - - public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); } - - public override bool Equals(object obj) - { - if (obj == null) - return false; - - PSubPos o = (PSubPos)obj; - return o == this; - } - - public override string ToString() { return "{0},{1}".F(X, Y); } - } -} diff --git a/OpenRA.Game/PSubVec.cs b/OpenRA.Game/PSubVec.cs deleted file mode 100644 index d461ec6333..0000000000 --- a/OpenRA.Game/PSubVec.cs +++ /dev/null @@ -1,98 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 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.Drawing; - -namespace OpenRA -{ - /// - /// Sub-pixel coordinate vector (very fine) - /// - public struct PSubVec - { - public readonly int X, Y; - - public PSubVec(int x, int y) { X = x; Y = y; } - public PSubVec(Size p) { X = p.Width; Y = p.Height; } - - public static readonly PSubVec Zero = new PSubVec(0, 0); - public static PSubVec OneCell { get { return new PSubVec(Game.CellSize, Game.CellSize); } } - - public static explicit operator PSubVec(int2 a) { return new PSubVec(a.X, a.Y); } - public static explicit operator PSubVec(float2 a) { return new PSubVec((int)a.X, (int)a.Y); } - - public static PSubVec FromRadius(int r) { return new PSubVec(r, r); } - - public static PSubVec operator +(PSubVec a, PSubVec b) { return new PSubVec(a.X + b.X, a.Y + b.Y); } - public static PSubVec operator -(PSubVec a, PSubVec b) { return new PSubVec(a.X - b.X, a.Y - b.Y); } - public static PSubVec operator *(int a, PSubVec b) { return new PSubVec(a * b.X, a * b.Y); } - public static PSubVec operator *(PSubVec b, int a) { return new PSubVec(a * b.X, a * b.Y); } - public static PSubVec operator /(PSubVec a, int b) { return new PSubVec(a.X / b, a.Y / b); } - - public static PSubVec operator -(PSubVec a) { return new PSubVec(-a.X, -a.Y); } - - public static bool operator ==(PSubVec me, PSubVec other) { return (me.X == other.X && me.Y == other.Y); } - public static bool operator !=(PSubVec me, PSubVec other) { return !(me == other); } - - public static PSubVec Max(PSubVec a, PSubVec b) { return new PSubVec(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); } - public static PSubVec Min(PSubVec a, PSubVec b) { return new PSubVec(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); } - - public static int Dot(PSubVec a, PSubVec b) { return a.X * b.X + a.Y * b.Y; } - - public PSubVec Sign() { return new PSubVec(Math.Sign(X), Math.Sign(Y)); } - public PSubVec Abs() { return new PSubVec(Math.Abs(X), Math.Abs(Y)); } - public int LengthSquared { get { return X * X + Y * Y; } } - public int Length { get { return (int)Math.Sqrt(LengthSquared); } } - - public float2 ToFloat2() { return new float2(X, Y); } - public int2 ToInt2() { return new int2(X, Y); } - public PVecInt ToPVecInt() { return new PVecInt(X / PSubPos.PerPx, Y / PSubPos.PerPx); } - - public PSubVec Clamp(Rectangle r) - { - return new PSubVec( - Math.Min(r.Right, Math.Max(X, r.Left)), - Math.Min(r.Bottom, Math.Max(Y, r.Top)) - ); - } - - public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); } - - public override bool Equals(object obj) - { - if (obj == null) - return false; - - PSubVec o = (PSubVec)obj; - return o == this; - } - - public override string ToString() { return "{0},{1}".F(X, Y); } - } - - public static class PSubVecExtensions - { - /// - /// Scales the float2 vector up to a subpixel vector. - /// - /// - /// - public static PSubVec ToPSubVec(this float2 vec) - { - return new PSubVec((int)(vec.X * PSubPos.PerPx), (int)(vec.Y * PSubPos.PerPx)); - } - - public static PSubVec ToPSubVec(this PVecInt vec) - { - return new PSubVec((vec.X * PSubPos.PerPx), (vec.Y * PSubPos.PerPx)); - } - } -} diff --git a/OpenRA.Game/Sync.cs b/OpenRA.Game/Sync.cs index 94f5a3cb32..9029849e16 100755 --- a/OpenRA.Game/Sync.cs +++ b/OpenRA.Game/Sync.cs @@ -37,8 +37,6 @@ namespace OpenRA {typeof(CVec), ((Func)hash_CVec).Method}, {typeof(PPos), ((Func)hash_PPos).Method}, {typeof(PVecInt), ((Func)hash_PVecInt).Method}, - {typeof(PSubPos), ((Func)hash_PSubPos).Method}, - {typeof(PSubVec), ((Func)hash_PSubVec).Method}, {typeof(WRange), ((Func)hash).Method}, {typeof(WPos), ((Func)hash).Method}, {typeof(WVec), ((Func)hash).Method}, @@ -126,16 +124,6 @@ namespace OpenRA return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } - public static int hash_PSubPos(PSubPos i2) - { - return ((i2.X * 5) ^ (i2.Y * 3)) / 4; - } - - public static int hash_PSubVec(PSubVec i2) - { - return ((i2.X * 5) ^ (i2.Y * 3)) / 4; - } - public static int hash_tdict(TypeDictionary d) { int ret = 0; diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index 874f84c73a..46b47613bd 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -222,266 +222,5 @@ namespace OpenRA.Traits new int2( 391, -1229 ), new int2( 199, -1305 ) }; - - - public static readonly PSubVec[] SubPxVector = - { - new PSubVec( 0, 1024 ), - new PSubVec( 25, 1023 ), - new PSubVec( 50, 1022 ), - new PSubVec( 75, 1021 ), - new PSubVec( 100, 1019 ), - new PSubVec( 125, 1016 ), - new PSubVec( 150, 1012 ), - new PSubVec( 175, 1008 ), - new PSubVec( 199, 1004 ), - new PSubVec( 224, 999 ), - new PSubVec( 248, 993 ), - new PSubVec( 273, 986 ), - new PSubVec( 297, 979 ), - new PSubVec( 321, 972 ), - new PSubVec( 344, 964 ), - new PSubVec( 368, 955 ), - new PSubVec( 391, 946 ), - new PSubVec( 414, 936 ), - new PSubVec( 437, 925 ), - new PSubVec( 460, 914 ), - new PSubVec( 482, 903 ), - new PSubVec( 504, 890 ), - new PSubVec( 526, 878 ), - new PSubVec( 547, 865 ), - new PSubVec( 568, 851 ), - new PSubVec( 589, 837 ), - new PSubVec( 609, 822 ), - new PSubVec( 629, 807 ), - new PSubVec( 649, 791 ), - new PSubVec( 668, 775 ), - new PSubVec( 687, 758 ), - new PSubVec( 706, 741 ), - new PSubVec( 724, 724 ), - new PSubVec( 741, 706 ), - new PSubVec( 758, 687 ), - new PSubVec( 775, 668 ), - new PSubVec( 791, 649 ), - new PSubVec( 807, 629 ), - new PSubVec( 822, 609 ), - new PSubVec( 837, 589 ), - new PSubVec( 851, 568 ), - new PSubVec( 865, 547 ), - new PSubVec( 878, 526 ), - new PSubVec( 890, 504 ), - new PSubVec( 903, 482 ), - new PSubVec( 914, 460 ), - new PSubVec( 925, 437 ), - new PSubVec( 936, 414 ), - new PSubVec( 946, 391 ), - new PSubVec( 955, 368 ), - new PSubVec( 964, 344 ), - new PSubVec( 972, 321 ), - new PSubVec( 979, 297 ), - new PSubVec( 986, 273 ), - new PSubVec( 993, 248 ), - new PSubVec( 999, 224 ), - new PSubVec( 1004, 199 ), - new PSubVec( 1008, 175 ), - new PSubVec( 1012, 150 ), - new PSubVec( 1016, 125 ), - new PSubVec( 1019, 100 ), - new PSubVec( 1021, 75 ), - new PSubVec( 1022, 50 ), - new PSubVec( 1023, 25 ), - new PSubVec( 1024, 0 ), - new PSubVec( 1023, -25 ), - new PSubVec( 1022, -50 ), - new PSubVec( 1021, -75 ), - new PSubVec( 1019, -100 ), - new PSubVec( 1016, -125 ), - new PSubVec( 1012, -150 ), - new PSubVec( 1008, -175 ), - new PSubVec( 1004, -199 ), - new PSubVec( 999, -224 ), - new PSubVec( 993, -248 ), - new PSubVec( 986, -273 ), - new PSubVec( 979, -297 ), - new PSubVec( 972, -321 ), - new PSubVec( 964, -344 ), - new PSubVec( 955, -368 ), - new PSubVec( 946, -391 ), - new PSubVec( 936, -414 ), - new PSubVec( 925, -437 ), - new PSubVec( 914, -460 ), - new PSubVec( 903, -482 ), - new PSubVec( 890, -504 ), - new PSubVec( 878, -526 ), - new PSubVec( 865, -547 ), - new PSubVec( 851, -568 ), - new PSubVec( 837, -589 ), - new PSubVec( 822, -609 ), - new PSubVec( 807, -629 ), - new PSubVec( 791, -649 ), - new PSubVec( 775, -668 ), - new PSubVec( 758, -687 ), - new PSubVec( 741, -706 ), - new PSubVec( 724, -724 ), - new PSubVec( 706, -741 ), - new PSubVec( 687, -758 ), - new PSubVec( 668, -775 ), - new PSubVec( 649, -791 ), - new PSubVec( 629, -807 ), - new PSubVec( 609, -822 ), - new PSubVec( 589, -837 ), - new PSubVec( 568, -851 ), - new PSubVec( 547, -865 ), - new PSubVec( 526, -878 ), - new PSubVec( 504, -890 ), - new PSubVec( 482, -903 ), - new PSubVec( 460, -914 ), - new PSubVec( 437, -925 ), - new PSubVec( 414, -936 ), - new PSubVec( 391, -946 ), - new PSubVec( 368, -955 ), - new PSubVec( 344, -964 ), - new PSubVec( 321, -972 ), - new PSubVec( 297, -979 ), - new PSubVec( 273, -986 ), - new PSubVec( 248, -993 ), - new PSubVec( 224, -999 ), - new PSubVec( 199, -1004 ), - new PSubVec( 175, -1008 ), - new PSubVec( 150, -1012 ), - new PSubVec( 125, -1016 ), - new PSubVec( 100, -1019 ), - new PSubVec( 75, -1021 ), - new PSubVec( 50, -1022 ), - new PSubVec( 25, -1023 ), - new PSubVec( 0, -1024 ), - new PSubVec( -25, -1023 ), - new PSubVec( -50, -1022 ), - new PSubVec( -75, -1021 ), - new PSubVec( -100, -1019 ), - new PSubVec( -125, -1016 ), - new PSubVec( -150, -1012 ), - new PSubVec( -175, -1008 ), - new PSubVec( -199, -1004 ), - new PSubVec( -224, -999 ), - new PSubVec( -248, -993 ), - new PSubVec( -273, -986 ), - new PSubVec( -297, -979 ), - new PSubVec( -321, -972 ), - new PSubVec( -344, -964 ), - new PSubVec( -368, -955 ), - new PSubVec( -391, -946 ), - new PSubVec( -414, -936 ), - new PSubVec( -437, -925 ), - new PSubVec( -460, -914 ), - new PSubVec( -482, -903 ), - new PSubVec( -504, -890 ), - new PSubVec( -526, -878 ), - new PSubVec( -547, -865 ), - new PSubVec( -568, -851 ), - new PSubVec( -589, -837 ), - new PSubVec( -609, -822 ), - new PSubVec( -629, -807 ), - new PSubVec( -649, -791 ), - new PSubVec( -668, -775 ), - new PSubVec( -687, -758 ), - new PSubVec( -706, -741 ), - new PSubVec( -724, -724 ), - new PSubVec( -741, -706 ), - new PSubVec( -758, -687 ), - new PSubVec( -775, -668 ), - new PSubVec( -791, -649 ), - new PSubVec( -807, -629 ), - new PSubVec( -822, -609 ), - new PSubVec( -837, -589 ), - new PSubVec( -851, -568 ), - new PSubVec( -865, -547 ), - new PSubVec( -878, -526 ), - new PSubVec( -890, -504 ), - new PSubVec( -903, -482 ), - new PSubVec( -914, -460 ), - new PSubVec( -925, -437 ), - new PSubVec( -936, -414 ), - new PSubVec( -946, -391 ), - new PSubVec( -955, -368 ), - new PSubVec( -964, -344 ), - new PSubVec( -972, -321 ), - new PSubVec( -979, -297 ), - new PSubVec( -986, -273 ), - new PSubVec( -993, -248 ), - new PSubVec( -999, -224 ), - new PSubVec( -1004, -199 ), - new PSubVec( -1008, -175 ), - new PSubVec( -1012, -150 ), - new PSubVec( -1016, -125 ), - new PSubVec( -1019, -100 ), - new PSubVec( -1021, -75 ), - new PSubVec( -1022, -50 ), - new PSubVec( -1023, -25 ), - new PSubVec( -1024, 0 ), - new PSubVec( -1023, 25 ), - new PSubVec( -1022, 50 ), - new PSubVec( -1021, 75 ), - new PSubVec( -1019, 100 ), - new PSubVec( -1016, 125 ), - new PSubVec( -1012, 150 ), - new PSubVec( -1008, 175 ), - new PSubVec( -1004, 199 ), - new PSubVec( -999, 224 ), - new PSubVec( -993, 248 ), - new PSubVec( -986, 273 ), - new PSubVec( -979, 297 ), - new PSubVec( -972, 321 ), - new PSubVec( -964, 344 ), - new PSubVec( -955, 368 ), - new PSubVec( -946, 391 ), - new PSubVec( -936, 414 ), - new PSubVec( -925, 437 ), - new PSubVec( -914, 460 ), - new PSubVec( -903, 482 ), - new PSubVec( -890, 504 ), - new PSubVec( -878, 526 ), - new PSubVec( -865, 547 ), - new PSubVec( -851, 568 ), - new PSubVec( -837, 589 ), - new PSubVec( -822, 609 ), - new PSubVec( -807, 629 ), - new PSubVec( -791, 649 ), - new PSubVec( -775, 668 ), - new PSubVec( -758, 687 ), - new PSubVec( -741, 706 ), - new PSubVec( -724, 724 ), - new PSubVec( -706, 741 ), - new PSubVec( -687, 758 ), - new PSubVec( -668, 775 ), - new PSubVec( -649, 791 ), - new PSubVec( -629, 807 ), - new PSubVec( -609, 822 ), - new PSubVec( -589, 837 ), - new PSubVec( -568, 851 ), - new PSubVec( -547, 865 ), - new PSubVec( -526, 878 ), - new PSubVec( -504, 890 ), - new PSubVec( -482, 903 ), - new PSubVec( -460, 914 ), - new PSubVec( -437, 925 ), - new PSubVec( -414, 936 ), - new PSubVec( -391, 946 ), - new PSubVec( -368, 955 ), - new PSubVec( -344, 964 ), - new PSubVec( -321, 972 ), - new PSubVec( -297, 979 ), - new PSubVec( -273, 986 ), - new PSubVec( -248, 993 ), - new PSubVec( -224, 999 ), - new PSubVec( -199, 1004 ), - new PSubVec( -175, 1008 ), - new PSubVec( -150, 1012 ), - new PSubVec( -125, 1016 ), - new PSubVec( -100, 1019 ), - new PSubVec( -75, 1021 ), - new PSubVec( -50, 1022 ), - new PSubVec( -25, 1023 ) - }; } } From e08445f762e4d8bb8188ed09725a0c0641c598cc Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 20:42:33 +1200 Subject: [PATCH 12/15] Remove obsolete functions from Traits.Util. --- OpenRA.Game/Traits/Util.cs | 25 ------------------------- OpenRA.Mods.RA/Husk.cs | 3 +-- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index 46b47613bd..a90cc02f07 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -84,31 +84,11 @@ namespace OpenRA.Traits return a / step; } - public static float2 RotateVectorByFacing(float2 v, int facing, float ecc) - { - var angle = (facing / 256f) * (2 * (float)Math.PI); - var sinAngle = (float)Math.Sin(angle); - var cosAngle = (float)Math.Cos(angle); - - return new float2( - (cosAngle * v.X + sinAngle * v.Y), - ecc * (cosAngle * v.Y - sinAngle * v.X)); - } - - public static PPos CenterOfCell(CPos loc) - { - return loc.ToPPos() + new PVecInt(Game.CellSize / 2, Game.CellSize / 2); - } - public static WPos BetweenCells(CPos from, CPos to) { return WPos.Lerp(from.CenterPosition, to.CenterPosition, 1, 2); } - public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); } - public static float2 RelOffset(this int[] offset) { return new float2(offset[0], offset[1]); } - public static float2 AbsOffset(this int[] offset) { return new float2(offset.ElementAtOrDefault(2), offset.ElementAtOrDefault(3)); } - public static Activity SequenceActivities(params Activity[] acts) { return acts.Reverse().Aggregate( @@ -133,11 +113,6 @@ namespace OpenRA.Traits return act; } - public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); } - - [Obsolete("Use ToCPos() method", true)] - public static int2 CellContaining(float2 pos) { return (1f / Game.CellSize * pos).ToInt2(); } - /* pretty crap */ public static IEnumerable Shuffle(this IEnumerable ts, Thirdparty.Random random) { diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index a46f577362..8c5a4cd27e 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -42,8 +42,7 @@ namespace OpenRA.Mods.RA this.self = init.self; TopLeft = init.Get(); - var ppos = init.Contains() ? init.Get() : Util.CenterOfCell(TopLeft); - CenterPosition = ppos.ToWPos(0); + CenterPosition = init.Contains() ? init.Get().ToWPos(0) : TopLeft.CenterPosition; Facing = init.Contains() ? init.Get() : 128; var speed = init.Contains() ? init.Get() : 0; From b50ba0bfb9b3421e4994dbc155a0250db862ebfd Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 22:11:58 +1200 Subject: [PATCH 13/15] Use WAngle.ArcTan in Traits.Util.GetFacing. --- OpenRA.FileFormats/WAngle.cs | 5 ++- OpenRA.Game/Traits/Util.cs | 71 ++++-------------------------------- 2 files changed, 11 insertions(+), 65 deletions(-) diff --git a/OpenRA.FileFormats/WAngle.cs b/OpenRA.FileFormats/WAngle.cs index dcc8bcc7fa..e3e6f860a2 100644 --- a/OpenRA.FileFormats/WAngle.cs +++ b/OpenRA.FileFormats/WAngle.cs @@ -67,7 +67,8 @@ namespace OpenRA return new WAngle(Angle - 512).Tan(); } - public static WAngle ArcTan(int y, int x) + public static WAngle ArcTan(int y, int x) { return ArcTan(y, x, 1); } + public static WAngle ArcTan(int y, int x, int stride) { if (y == 0) return new WAngle(x >= 0 ? 0 : 512); @@ -81,7 +82,7 @@ namespace OpenRA // Find the closest angle that satisfies y = x*tan(theta) var bestVal = int.MaxValue; var bestAngle = 0; - for (var i = 0; i < 256; i++) + for (var i = 0; i < 256; i+= stride) { var val = Math.Abs(1024*ay - ax*TanTable[i]); if (val < bestVal) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index a90cc02f07..cb52bd3bac 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -32,38 +32,19 @@ namespace OpenRA.Traits public static int GetFacing(WVec d, int currentFacing) { - return GetFacing(new int2(d.X, d.Y), currentFacing); - } + if (d.LengthSquared == 0) + return currentFacing; - public static int GetFacing(PVecInt d, int currentFacing) - { - return GetFacing(d.ToInt2(), currentFacing); + // OpenRA defines north as -y, so invert + var angle = WAngle.ArcTan(-d.Y, d.X, 4).Angle; + + // Convert back to a facing + return (angle / 4 - 0x40) & 0xFF; } public static int GetFacing(CVec d, int currentFacing) { - return GetFacing(d.ToInt2(), currentFacing); - } - - public static int GetFacing(int2 d, int currentFacing) - { - if (d == int2.Zero) - return currentFacing; - - int highest = -1; - int highestDot = -1; - - for( int i = 0 ; i < fvecs.Length ; i++ ) - { - int dot = int2.Dot( fvecs[ i ], d ); - if( dot > highestDot ) - { - highestDot = dot; - highest = i; - } - } - - return highest * 8; + return GetFacing(d.ToWVec(), currentFacing); } public static int GetNearestFacing( int facing, int desiredFacing ) @@ -161,41 +142,5 @@ namespace OpenRA.Traits return Util.ExpandFootprint(cells, true); } - - static int2[] fvecs = - { - new int2( 0, -1331 ), - new int2( -199, -1305 ), - new int2( -391, -1229 ), - new int2( -568, -1106 ), - new int2( -724, -941 ), - new int2( -851, -739 ), - new int2( -946, -509 ), - new int2( -1004, -259 ), - new int2( -1024, 0 ), - new int2( -1004, 259 ), - new int2( -946, 509 ), - new int2( -851, 739 ), - new int2( -724, 941 ), - new int2( -568, 1106 ), - new int2( -391, 1229 ), - new int2( -199, 1305 ), - new int2( 0, 1331 ), - new int2( 199, 1305 ), - new int2( 391, 1229 ), - new int2( 568, 1106 ), - new int2( 724, 941 ), - new int2( 851, 739 ), - new int2( 946, 509 ), - new int2( 1004, 259 ), - new int2( 1024, 0 ), - new int2( 1004, -259 ), - new int2( 946, -509 ), - new int2( 851, -739 ), - new int2( 724, -941 ), - new int2( 568, -1106 ), - new int2( 391, -1229 ), - new int2( 199, -1305 ) - }; } } From 3d1b7d6d5367d9e53b9306267cda3a0c35c4d04f Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 22:19:31 +1200 Subject: [PATCH 14/15] Fix Traits.Util style issues. --- OpenRA.Game/Traits/Util.cs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index cb52bd3bac..02f1bd4d9d 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 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, @@ -18,16 +18,16 @@ namespace OpenRA.Traits { public static class Util { - public static int TickFacing( int facing, int desiredFacing, int rot ) + public static int TickFacing(int facing, int desiredFacing, int rot) { - var leftTurn = ( facing - desiredFacing ) & 0xFF; - var rightTurn = ( desiredFacing - facing ) & 0xFF; - if( Math.Min( leftTurn, rightTurn ) < rot ) + var leftTurn = (facing - desiredFacing) & 0xFF; + var rightTurn = (desiredFacing - facing) & 0xFF; + if (Math.Min(leftTurn, rightTurn) < rot) return desiredFacing & 0xFF; - else if( rightTurn < leftTurn ) - return ( facing + rot ) & 0xFF; + else if (rightTurn < leftTurn) + return (facing + rot) & 0xFF; else - return ( facing - rot ) & 0xFF; + return (facing - rot) & 0xFF; } public static int GetFacing(WVec d, int currentFacing) @@ -47,12 +47,12 @@ namespace OpenRA.Traits return GetFacing(d.ToWVec(), currentFacing); } - public static int GetNearestFacing( int facing, int desiredFacing ) + public static int GetNearestFacing(int facing, int desiredFacing) { var turn = desiredFacing - facing; - if( turn > 128 ) + if (turn > 128) turn -= 256; - if( turn < -128 ) + if (turn < -128) turn += 256; return facing + turn; @@ -73,7 +73,7 @@ namespace OpenRA.Traits public static Activity SequenceActivities(params Activity[] acts) { return acts.Reverse().Aggregate( - (next, a) => { a.Queue( next ); return a; }); + (next, a) => { a.Queue(next); return a; }); } public static Activity RunActivity(Actor self, Activity act) @@ -91,6 +91,7 @@ namespace OpenRA.Traits if (prev == act) break; } + return act; } @@ -135,7 +136,7 @@ namespace OpenRA.Traits { var cells = target.IsActor ? target.Actor.OccupiesSpace.OccupiedCells().Select(c => c.First).ToArray() - : new CPos[] {}; + : new CPos[] { }; if (cells.Length == 0) cells = new CPos[] { target.CenterPosition.ToCPos() }; From 1ae2e55448a7bfdda5b65a580204a596a527cafe Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 22 Jul 2013 22:20:46 +1200 Subject: [PATCH 15/15] Remove obsolete PPos functions from Target. --- OpenRA.Game/Traits/Target.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 6dd8031a0a..6611dab916 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -25,7 +25,6 @@ namespace OpenRA.Traits int generation; public static Target FromPos(WPos p) { return new Target { pos = p, valid = true }; } - public static Target FromPos(PPos p) { return new Target { pos = p.ToWPos(0), valid = true }; } public static Target FromCell(CPos c) { return new Target { pos = c.CenterPosition, valid = true }; } public static Target FromOrder(Order o) { @@ -45,7 +44,6 @@ namespace OpenRA.Traits } public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && !actor.IsDead() && actor.Generation == generation)); } } - public PPos CenterLocation { get { return IsActor ? actor.CenterLocation : PPos.FromWPos(pos); } } public Actor Actor { get { return IsActor ? actor : null; } } // TODO: This should return true even if the actor is destroyed