diff --git a/OpenRa.Game/Actor.cs b/OpenRa.Game/Actor.cs index 3ceeca8b09..1a0956ae35 100755 --- a/OpenRa.Game/Actor.cs +++ b/OpenRa.Game/Actor.cs @@ -71,8 +71,7 @@ namespace OpenRa.Game get { var firstSprite = Render().FirstOrDefault(); - if( firstSprite.Sprite == null ) - return new float2( 0, 0 ); + if (firstSprite.Sprite == null) return float2.Zero; return firstSprite.Sprite.size; } } diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 74d85740c5..3ea793d682 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -108,7 +108,9 @@ + + @@ -133,6 +135,8 @@ + + @@ -179,6 +183,7 @@ + diff --git a/OpenRa.Game/Traits/Activities/Circle.cs b/OpenRa.Game/Traits/Activities/Circle.cs new file mode 100644 index 0000000000..6f8eaefffd --- /dev/null +++ b/OpenRa.Game/Traits/Activities/Circle.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class Circle : IActivity + { + public IActivity NextActivity { get; set; } + bool isCanceled; + readonly int2 Cell; + + public Circle(int2 cell) { Cell = cell; } + + public IActivity Tick(Actor self) + { + if (isCanceled) return NextActivity; + var unit = self.traits.Get(); + return new Fly(Util.CenterOfCell(Cell)) + { + NextActivity = + new FlyTimed(50, 20) + { + NextActivity = this + } + }; + } + + public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/Activities/Fly.cs b/OpenRa.Game/Traits/Activities/Fly.cs index ca4a631ad6..4f7a4241f7 100644 --- a/OpenRa.Game/Traits/Activities/Fly.cs +++ b/OpenRa.Game/Traits/Activities/Fly.cs @@ -43,154 +43,4 @@ namespace OpenRa.Game.Traits.Activities public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } } - - class Land : IActivity - { - readonly float2 Pos; - bool isCanceled; - - public Land(float2 pos) { Pos = pos; } - - public IActivity NextActivity { get; set; } - - public IActivity Tick(Actor self) - { - if (isCanceled) return NextActivity; - - var d = Pos - self.CenterLocation; - if (d.LengthSquared < 50) /* close enough */ - return NextActivity; - - var unit = self.traits.Get(); - - if (unit.Altitude > 0) - --unit.Altitude; - - var desiredFacing = Util.GetFacing(d, unit.Facing); - Util.TickFacing(ref unit.Facing, desiredFacing, self.Info.ROT); - var speed = .2f * Util.GetEffectiveSpeed(self); - var angle = unit.Facing / 128f * Math.PI; - - self.CenterLocation += speed * -float2.FromAngle((float)angle); - self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); - - return this; - } - - public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } - } - - class FlyTimed : IActivity - { - public IActivity NextActivity { get; set; } - int remainingTicks; - int targetAltitude; - - public FlyTimed(int ticks, int targetAltitude) { remainingTicks = ticks; this.targetAltitude = targetAltitude; } - - public IActivity Tick(Actor self) - { - if (remainingTicks == 0) - return NextActivity; - - --remainingTicks; - - var unit = self.traits.Get(); - var speed = .2f * Util.GetEffectiveSpeed(self); - var angle = unit.Facing / 128f * Math.PI; - - self.CenterLocation += speed * -float2.FromAngle((float)angle); - self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); - - unit.Altitude += Math.Sign(targetAltitude - unit.Altitude); - return this; - } - - public void Cancel(Actor self) { remainingTicks = 0; NextActivity = null; } - } - - class Circle : IActivity - { - public IActivity NextActivity { get; set; } - bool isCanceled; - readonly int2 Cell; - - public Circle(int2 cell) { Cell = cell; } - - public IActivity Tick(Actor self) - { - if (isCanceled) return NextActivity; - var unit = self.traits.Get(); - return new Fly(Util.CenterOfCell(Cell)) - { - NextActivity = - new FlyTimed(50, 20) - { - NextActivity = this - } - }; - } - - public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } - } - - class ReturnToBase : IActivity - { - public IActivity NextActivity { get; set; } - bool isCanceled; - - readonly float2 w1, w2, w3; /* tangent points to turn circles */ - readonly float2 landPoint; - - public ReturnToBase(Actor self, float2 landPos) - { - var unit = self.traits.Get(); - var speed = .2f * Util.GetEffectiveSpeed(self); - var approachStart = landPos - new float2(unit.Altitude * speed, 0); - var turnRadius = (128f / self.Info.ROT) * speed / (float)Math.PI; - - /* work out the center points */ - var fwd = -float2.FromAngle(unit.Facing / 128f * (float)Math.PI); - var side = new float2(-fwd.Y, fwd.X); /* rotate */ - var sideTowardBase = new [] { side, -side } - .OrderBy( a => float2.Dot( a, self.CenterLocation - approachStart ) ) - .First(); - - var c1 = self.CenterLocation + turnRadius * sideTowardBase; - var c2 = approachStart + new float2(0, - turnRadius * Math.Sign( self.CenterLocation.Y - approachStart.Y )); // above or below start point - - /* work out tangent points */ - var d = c2 - c1; - var e = (turnRadius / d.Length) * d; - var f = new float2(-e.Y, e.X); /* rotate */ - - /* todo: support internal tangents, too! */ - - if (f.X > 0) f = -f; - - w1 = c1 + f; - w2 = c2 + f; - w3 = approachStart; - landPoint = landPos; - } - - public IActivity Tick(Actor self) - { - if (isCanceled) return NextActivity; - var unit = self.traits.Get(); - return new Fly(w1) - { - NextActivity = new Fly(w2) - { - NextActivity = new Fly(w3) - { - NextActivity = new Land(landPoint) - } - } - }; - } - - public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } - } } diff --git a/OpenRa.Game/Traits/Activities/FlyTimed.cs b/OpenRa.Game/Traits/Activities/FlyTimed.cs new file mode 100644 index 0000000000..c498dd008b --- /dev/null +++ b/OpenRa.Game/Traits/Activities/FlyTimed.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class FlyTimed : IActivity + { + public IActivity NextActivity { get; set; } + int remainingTicks; + int targetAltitude; + + public FlyTimed(int ticks, int targetAltitude) { remainingTicks = ticks; this.targetAltitude = targetAltitude; } + + public IActivity Tick(Actor self) + { + if (remainingTicks == 0) + return NextActivity; + + --remainingTicks; + + var unit = self.traits.Get(); + var speed = .2f * Util.GetEffectiveSpeed(self); + var angle = unit.Facing / 128f * Math.PI; + + self.CenterLocation += speed * -float2.FromAngle((float)angle); + self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); + + unit.Altitude += Math.Sign(targetAltitude - unit.Altitude); + return this; + } + + public void Cancel(Actor self) { remainingTicks = 0; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/Activities/Land.cs b/OpenRa.Game/Traits/Activities/Land.cs new file mode 100644 index 0000000000..5c4cf06ea5 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/Land.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class Land : IActivity + { + readonly float2 Pos; + bool isCanceled; + + public Land(float2 pos) { Pos = pos; } + + public IActivity NextActivity { get; set; } + + public IActivity Tick(Actor self) + { + if (isCanceled) return NextActivity; + + var d = Pos - self.CenterLocation; + if (d.LengthSquared < 50) /* close enough */ + return NextActivity; + + var unit = self.traits.Get(); + + if (unit.Altitude > 0) + --unit.Altitude; + + var desiredFacing = Util.GetFacing(d, unit.Facing); + Util.TickFacing(ref unit.Facing, desiredFacing, self.Info.ROT); + var speed = .2f * Util.GetEffectiveSpeed(self); + var angle = unit.Facing / 128f * Math.PI; + + self.CenterLocation += speed * -float2.FromAngle((float)angle); + self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); + + return this; + } + + public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/Activities/ReturnToBase.cs b/OpenRa.Game/Traits/Activities/ReturnToBase.cs new file mode 100644 index 0000000000..ee7af24ef4 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/ReturnToBase.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class ReturnToBase : IActivity + { + public IActivity NextActivity { get; set; } + bool isCanceled; + + readonly float2 w1, w2, w3; /* tangent points to turn circles */ + readonly float2 landPoint; + + public ReturnToBase(Actor self, float2 landPos) + { + var unit = self.traits.Get(); + var speed = .2f * Util.GetEffectiveSpeed(self); + var approachStart = landPos - new float2(unit.Altitude * speed, 0); + var turnRadius = (128f / self.Info.ROT) * speed / (float)Math.PI; + + /* work out the center points */ + var fwd = -float2.FromAngle(unit.Facing / 128f * (float)Math.PI); + var side = new float2(-fwd.Y, fwd.X); /* rotate */ + var sideTowardBase = new[] { side, -side } + .OrderBy(a => float2.Dot(a, self.CenterLocation - approachStart)) + .First(); + + var c1 = self.CenterLocation + turnRadius * sideTowardBase; + var c2 = approachStart + new float2(0, + turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point + + /* work out tangent points */ + var d = c2 - c1; + var e = (turnRadius / d.Length) * d; + var f = new float2(-e.Y, e.X); /* rotate */ + + /* todo: support internal tangents, too! */ + + if (f.X > 0) f = -f; + + w1 = c1 + f; + w2 = c2 + f; + w3 = approachStart; + landPoint = landPos; + } + + public IActivity Tick(Actor self) + { + if (isCanceled) return NextActivity; + var unit = self.traits.Get(); + return new Fly(w1) + { + NextActivity = new Fly(w2) + { + NextActivity = new Fly(w3) + { + NextActivity = new Land(landPoint) + } + } + }; + } + + public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/Production.cs b/OpenRa.Game/Traits/Production.cs index 640f9143d1..f916f05dc5 100755 --- a/OpenRa.Game/Traits/Production.cs +++ b/OpenRa.Game/Traits/Production.cs @@ -57,34 +57,4 @@ namespace OpenRa.Game.Traits yield return (true) ? TagType.Primary : TagType.None; } } - - class ProductionSurround : Production - { - public ProductionSurround( Actor self ) : base( self ) { } - - static int2? FindAdjacentTile(Actor a, UnitMovementType umt) - { - var tiles = Footprint.Tiles(a, a.traits.Get()); - var min = tiles.Aggregate(int2.Min) - new int2(1, 1); - var max = tiles.Aggregate(int2.Max) + new int2(1, 1); - - for (var j = min.Y; j <= max.Y; j++) - for (var i = min.X; i <= max.X; i++) - if (Game.IsCellBuildable(new int2(i, j), umt)) - return new int2(i, j); - - return null; - } - - public override int2? CreationLocation( Actor self, UnitInfo producee ) - { - return FindAdjacentTile( self, producee.WaterBound ? - UnitMovementType.Float : UnitMovementType.Wheel); /* hackety hack */ - } - - public override int CreationFacing( Actor self, Actor newUnit ) - { - return Util.GetFacing( newUnit.CenterLocation - self.CenterLocation, 128 ); - } - } } diff --git a/OpenRa.Game/Traits/ProductionSurround.cs b/OpenRa.Game/Traits/ProductionSurround.cs new file mode 100644 index 0000000000..4fb0091697 --- /dev/null +++ b/OpenRa.Game/Traits/ProductionSurround.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Game.GameRules; + +namespace OpenRa.Game.Traits +{ + class ProductionSurround : Production + { + public ProductionSurround(Actor self) : base(self) { } + + static int2? FindAdjacentTile(Actor a, UnitMovementType umt) + { + var tiles = Footprint.Tiles(a, a.traits.Get()); + var min = tiles.Aggregate(int2.Min) - new int2(1, 1); + var max = tiles.Aggregate(int2.Max) + new int2(1, 1); + + for (var j = min.Y; j <= max.Y; j++) + for (var i = min.X; i <= max.X; i++) + if (Game.IsCellBuildable(new int2(i, j), umt)) + return new int2(i, j); + + return null; + } + + public override int2? CreationLocation(Actor self, UnitInfo producee) + { + return FindAdjacentTile(self, producee.WaterBound ? + UnitMovementType.Float : UnitMovementType.Wheel); /* hackety hack */ + } + + public override int CreationFacing(Actor self, Actor newUnit) + { + return Util.GetFacing(newUnit.CenterLocation - self.CenterLocation, 128); + } + } +}