Add top and bottom offsets to HitShapes

This commit is contained in:
reaperrr
2016-01-02 16:11:14 +01:00
parent fb53890636
commit 72c580b708
3 changed files with 105 additions and 19 deletions

View File

@@ -11,8 +11,10 @@
using System;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.HitShapes
{
@@ -28,6 +30,12 @@ namespace OpenRA.Mods.Common.HitShapes
public readonly WDist Radius = new WDist(426);
[Desc("Defines the top offset relative to the actor's target point.")]
public readonly int VerticalTopOffset = 0;
[Desc("Defines the bottom offset relative to the actor's target point.")]
public readonly int VerticalBottomOffset = 0;
int2 ab;
int abLenSq;
@@ -48,6 +56,9 @@ namespace OpenRA.Mods.Common.HitShapes
if (abLenSq == 0)
throw new YamlException("This Capsule describes a circle. Use a Circle HitShape instead.");
if (VerticalTopOffset < VerticalBottomOffset)
throw new YamlException("VerticalTopOffset must be equal to or higher than VerticalBottomOffset.");
OuterRadius = Radius + new WDist(Math.Max(PointA.Length, PointB.Length));
}
@@ -73,22 +84,41 @@ namespace OpenRA.Mods.Common.HitShapes
public WDist DistanceFromEdge(WPos pos, Actor actor)
{
return DistanceFromEdge((pos - actor.CenterPosition).Rotate(-actor.Orientation));
var actorPos = actor.CenterPosition;
if (pos.Z > actorPos.Z + VerticalTopOffset)
return DistanceFromEdge((pos - (actorPos + new WVec(0, 0, VerticalTopOffset))).Rotate(-actor.Orientation));
if (pos.Z < actorPos.Z + VerticalBottomOffset)
return DistanceFromEdge((pos - (actorPos + new WVec(0, 0, VerticalBottomOffset))).Rotate(-actor.Orientation));
return DistanceFromEdge((pos - new WPos(actorPos.X, actorPos.Y, pos.Z)).Rotate(-actor.Orientation));
}
public void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor)
{
var a = actor.CenterPosition + new WVec(PointA.X, PointA.Y, 0).Rotate(actor.Orientation);
var b = actor.CenterPosition + new WVec(PointB.X, PointB.Y, 0).Rotate(actor.Orientation);
var actorPos = actor.CenterPosition;
var offset = new WVec(a.Y - b.Y, b.X - a.X, 0);
offset = offset * Radius.Length / offset.Length;
var a = actorPos + new WVec(PointA.X, PointA.Y, VerticalTopOffset).Rotate(actor.Orientation);
var b = actorPos + new WVec(PointB.X, PointB.Y, VerticalTopOffset).Rotate(actor.Orientation);
var aa = actorPos + new WVec(PointA.X, PointA.Y, VerticalBottomOffset).Rotate(actor.Orientation);
var bb = actorPos + new WVec(PointB.X, PointB.Y, VerticalBottomOffset).Rotate(actor.Orientation);
var offset1 = new WVec(a.Y - b.Y, b.X - a.X, 0);
offset1 = offset1 * Radius.Length / offset1.Length;
var offset2 = new WVec(aa.Y - bb.Y, bb.X - aa.X, 0);
offset2 = offset2 * Radius.Length / offset2.Length;
var c = Color.Yellow;
RangeCircleRenderable.DrawRangeCircle(wr, a, Radius, 1, c, 0, c);
RangeCircleRenderable.DrawRangeCircle(wr, b, Radius, 1, c, 0, c);
wcr.DrawLine(new[] { wr.ScreenPosition(a - offset), wr.ScreenPosition(b - offset) }, 1, c);
wcr.DrawLine(new[] { wr.ScreenPosition(a + offset), wr.ScreenPosition(b + offset) }, 1, c);
wcr.DrawLine(new[] { wr.ScreenPosition(a - offset1), wr.ScreenPosition(b - offset1) }, 1, c);
wcr.DrawLine(new[] { wr.ScreenPosition(a + offset1), wr.ScreenPosition(b + offset1) }, 1, c);
RangeCircleRenderable.DrawRangeCircle(wr, aa, Radius, 1, c, 0, c);
RangeCircleRenderable.DrawRangeCircle(wr, bb, Radius, 1, c, 0, c);
wcr.DrawLine(new[] { wr.ScreenPosition(aa - offset2), wr.ScreenPosition(bb - offset2) }, 1, c);
wcr.DrawLine(new[] { wr.ScreenPosition(aa + offset2), wr.ScreenPosition(bb + offset2) }, 1, c);
}
}
}

View File

@@ -11,8 +11,10 @@
using System;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.HitShapes
{
@@ -23,11 +25,21 @@ namespace OpenRA.Mods.Common.HitShapes
[FieldLoader.Require]
public readonly WDist Radius = new WDist(426);
[Desc("Defines the top offset relative to the actor's target point.")]
public readonly int VerticalTopOffset = 0;
[Desc("Defines the bottom offset relative to the actor's target point.")]
public readonly int VerticalBottomOffset = 0;
public CircleShape() { }
public CircleShape(WDist radius) { Radius = radius; }
public void Initialize() { }
public void Initialize()
{
if (VerticalTopOffset < VerticalBottomOffset)
throw new YamlException("VerticalTopOffset must be equal to or higher than VerticalBottomOffset.");
}
public WDist DistanceFromEdge(WVec v)
{
@@ -36,12 +48,25 @@ namespace OpenRA.Mods.Common.HitShapes
public WDist DistanceFromEdge(WPos pos, Actor actor)
{
return DistanceFromEdge(pos - actor.CenterPosition);
var actorPos = actor.CenterPosition;
if (pos.Z > actorPos.Z + VerticalTopOffset)
return DistanceFromEdge(pos - (actorPos + new WVec(0, 0, VerticalTopOffset)));
if (pos.Z < actorPos.Z + VerticalBottomOffset)
return DistanceFromEdge(pos - (actorPos + new WVec(0, 0, VerticalBottomOffset)));
return DistanceFromEdge(pos - new WPos(actorPos.X, actorPos.Y, pos.Z));
}
public void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor)
{
RangeCircleRenderable.DrawRangeCircle(wr, actor.CenterPosition, Radius, 1, Color.Yellow, 0, Color.Yellow);
var actorPos = actor.CenterPosition;
RangeCircleRenderable.DrawRangeCircle(
wr, actorPos + new WVec(0, 0, VerticalTopOffset), Radius, 1, Color.Yellow, 0, Color.Yellow);
RangeCircleRenderable.DrawRangeCircle(
wr, actorPos + new WVec(0, 0, VerticalBottomOffset), Radius, 1, Color.Yellow, 0, Color.Yellow);
}
}
}

View File

@@ -13,6 +13,7 @@ using System;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.HitShapes
{
@@ -26,10 +27,17 @@ namespace OpenRA.Mods.Common.HitShapes
[FieldLoader.Require]
public readonly int2 BottomRight;
[Desc("Defines the top offset relative to the actor's target point.")]
public readonly int VerticalTopOffset = 0;
[Desc("Defines the bottom offset relative to the actor's target point.")]
public readonly int VerticalBottomOffset = 0;
int2 quadrantSize;
int2 center;
WVec[] combatOverlayVerts;
WVec[] combatOverlayVertsTop;
WVec[] combatOverlayVertsBottom;
public RectangleShape() { }
@@ -44,17 +52,28 @@ namespace OpenRA.Mods.Common.HitShapes
if (TopLeft.X >= BottomRight.X || TopLeft.Y >= BottomRight.Y)
throw new YamlException("TopLeft and BottomRight points are invalid.");
if (VerticalTopOffset < VerticalBottomOffset)
throw new YamlException("VerticalTopOffset must be equal to or higher than VerticalBottomOffset.");
quadrantSize = (BottomRight - TopLeft) / 2;
center = TopLeft + quadrantSize;
OuterRadius = new WDist(Math.Max(TopLeft.Length, BottomRight.Length));
combatOverlayVerts = new WVec[]
combatOverlayVertsTop = new WVec[]
{
new WVec(TopLeft.X, TopLeft.Y, 0),
new WVec(BottomRight.X, TopLeft.Y, 0),
new WVec(BottomRight.X, BottomRight.Y, 0),
new WVec(TopLeft.X, BottomRight.Y, 0)
new WVec(TopLeft.X, TopLeft.Y, VerticalTopOffset),
new WVec(BottomRight.X, TopLeft.Y, VerticalTopOffset),
new WVec(BottomRight.X, BottomRight.Y, VerticalTopOffset),
new WVec(TopLeft.X, BottomRight.Y, VerticalTopOffset)
};
combatOverlayVertsBottom = new WVec[]
{
new WVec(TopLeft.X, TopLeft.Y, VerticalBottomOffset),
new WVec(BottomRight.X, TopLeft.Y, VerticalBottomOffset),
new WVec(BottomRight.X, BottomRight.Y, VerticalBottomOffset),
new WVec(TopLeft.X, BottomRight.Y, VerticalBottomOffset)
};
}
@@ -69,13 +88,25 @@ namespace OpenRA.Mods.Common.HitShapes
public WDist DistanceFromEdge(WPos pos, Actor actor)
{
return DistanceFromEdge((pos - actor.CenterPosition).Rotate(-actor.Orientation));
var actorPos = actor.CenterPosition;
if (pos.Z > actorPos.Z + VerticalTopOffset)
return DistanceFromEdge((pos - (actorPos + new WVec(0, 0, VerticalTopOffset))).Rotate(-actor.Orientation));
if (pos.Z < actorPos.Z + VerticalBottomOffset)
return DistanceFromEdge((pos - (actorPos + new WVec(0, 0, VerticalBottomOffset))).Rotate(-actor.Orientation));
return DistanceFromEdge((pos - new WPos(actorPos.X, actorPos.Y, pos.Z)).Rotate(-actor.Orientation));
}
public void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor)
{
var verts = combatOverlayVerts.Select(v => wr.ScreenPosition(actor.CenterPosition + v.Rotate(actor.Orientation)));
wcr.DrawPolygon(verts.ToArray(), 1, Color.Yellow);
var actorPos = actor.CenterPosition;
var vertsTop = combatOverlayVertsTop.Select(v => wr.ScreenPosition(actorPos + v.Rotate(actor.Orientation)));
var vertsBottom = combatOverlayVertsBottom.Select(v => wr.ScreenPosition(actorPos + v.Rotate(actor.Orientation)));
wcr.DrawPolygon(vertsTop.ToArray(), 1, Color.Yellow);
wcr.DrawPolygon(vertsBottom.ToArray(), 1, Color.Yellow);
}
}
}