Merge pull request #10562 from pchote/classic-facing-fudge

Implement ClassicFacingFudge for fudging classic facings.
This commit is contained in:
reaperrr
2016-01-28 23:45:48 +01:00
21 changed files with 211 additions and 32 deletions

View File

@@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.Graphics
{
static readonly WDist DefaultShadowSpriteZOffset = new WDist(-5);
readonly Sprite[] sprites;
readonly bool reverseFacings, transpose;
readonly bool reverseFacings, transpose, useClassicFacingFudge;
protected readonly ISpriteSequenceLoader Loader;
@@ -129,6 +129,8 @@ namespace OpenRA.Mods.Common.Graphics
Tick = LoadField(d, "Tick", 40);
transpose = LoadField(d, "Transpose", false);
Frames = LoadField<int[]>(d, "Frames", null);
useClassicFacingFudge = LoadField(d, "UseClassicFacingFudge", false);
var flipX = LoadField(d, "FlipX", false);
var flipY = LoadField(d, "FlipY", false);
@@ -139,6 +141,11 @@ namespace OpenRA.Mods.Common.Graphics
Facings = -Facings;
}
if (useClassicFacingFudge && Facings != 32)
throw new InvalidOperationException(
"{0}: Sequence {1}.{2}: UseClassicFacingFudge is only valid for 32 facings"
.F(info.Nodes[0].Location, sequence, animation));
var offset = LoadField(d, "Offset", float2.Zero);
var blendMode = LoadField(d, "BlendMode", BlendMode.Alpha);
@@ -237,8 +244,7 @@ namespace OpenRA.Mods.Common.Graphics
protected virtual Sprite GetSprite(int start, int frame, int facing)
{
var f = Util.QuantizeFacing(facing, Facings);
var f = Util.QuantizeFacing(facing, Facings, useClassicFacingFudge);
if (reverseFacings)
f = (Facings - f) % Facings;

View File

@@ -253,7 +253,10 @@ namespace OpenRA.Mods.Common.Traits
var localOffset = b.Offset + new WVec(-Recoil, WDist.Zero, WDist.Zero);
if (turret != null)
{
var turretOrientation = coords.QuantizeOrientation(self, turret.LocalOrientation(self));
// WorldOrientation is quantized to satisfy the *Fudges.
// Need to then convert back to a pseudo-local coordinate space, apply offsets,
// then rotate back at the end
var turretOrientation = turret.WorldOrientation(self) - bodyOrientation;
localOffset = localOffset.Rotate(turretOrientation);
localOffset += turret.Offset;
}
@@ -263,10 +266,10 @@ namespace OpenRA.Mods.Common.Traits
public WRot MuzzleOrientation(Actor self, Barrel b)
{
var orientation = self.Orientation + WRot.FromYaw(b.Yaw);
if (turret != null)
orientation += turret.LocalOrientation(self);
return orientation;
var orientation = turret != null ? turret.WorldOrientation(self) :
coords.QuantizeOrientation(self, self.Orientation);
return orientation + WRot.FromYaw(b.Yaw);
}
public Actor Actor { get { return self; } }

View File

@@ -24,6 +24,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Fudge the coordinate system angles like the early games.")]
public readonly bool UseClassicPerspectiveFudge = true;
[Desc("Fudge the coordinate system angles like the early games.")]
public readonly bool UseClassicFacingFudge = false;
public WVec LocalToWorld(WVec vec)
{
// Rotate by 90 degrees
@@ -50,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
public int QuantizeFacing(int facing, int facings)
{
return Util.QuantizeFacing(facing, facings) * (256 / facings);
return Util.QuantizeFacing(facing, facings, UseClassicFacingFudge) * (256 / facings);
}
public object Create(ActorInitializer init) { return new BodyOrientation(init, this); }

View File

@@ -90,9 +90,9 @@ namespace OpenRA.Mods.Common.Traits
{
var localOffset = Info.LocalOffset + new WVec(-armament.Recoil, WDist.Zero, WDist.Zero);
var turretOffset = turreted != null ? turreted.Position(self) : WVec.Zero;
var turretOrientation = turreted != null ? turreted.LocalOrientation(self) : WRot.Zero;
var quantizedBody = body.QuantizeOrientation(self, self.Orientation);
var turretOrientation = turreted != null ? turreted.WorldOrientation(self) - quantizedBody : WRot.Zero;
var quantizedTurret = body.QuantizeOrientation(self, turretOrientation);
return turretOffset + body.LocalToWorld(localOffset.Rotate(quantizedTurret).Rotate(quantizedBody));
}
@@ -101,7 +101,7 @@ namespace OpenRA.Mods.Common.Traits
{
var b = self.Orientation;
var qb = body.QuantizeOrientation(self, b);
yield return turreted.LocalOrientation(self) + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return turreted.WorldOrientation(self) - qb + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return qb;
}
}

View File

@@ -98,9 +98,8 @@ namespace OpenRA.Mods.Common.Traits
var recoil = arms.Aggregate(WDist.Zero, (a, b) => a + b.Recoil);
var localOffset = new WVec(-recoil, WDist.Zero, WDist.Zero);
var bodyOrientation = body.QuantizeOrientation(self, self.Orientation);
var turretOrientation = body.QuantizeOrientation(self, t.LocalOrientation(self));
return t.Position(self) + body.LocalToWorld(localOffset.Rotate(turretOrientation).Rotate(bodyOrientation));
var quantizedWorldTurret = t.WorldOrientation(self);
return t.Position(self) + body.LocalToWorld(localOffset.Rotate(quantizedWorldTurret));
}
public string NormalizeSequence(Actor self, string sequence)

View File

@@ -84,20 +84,20 @@ namespace OpenRA.Mods.Common.Traits
WVec BarrelOffset()
{
var b = self.Orientation;
var qb = body.QuantizeOrientation(self, b);
var localOffset = Info.LocalOffset + new WVec(-armament.Recoil, WDist.Zero, WDist.Zero);
var turretLocalOffset = turreted != null ? turreted.Offset : WVec.Zero;
var turretOrientation = turreted != null ? turreted.LocalOrientation(self) : WRot.Zero;
var turretOrientation = turreted != null ? turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw) : WRot.Zero;
var quantizedBody = body.QuantizeOrientation(self, self.Orientation);
var quantizedTurret = body.QuantizeOrientation(self, turretOrientation);
return body.LocalToWorld((turretLocalOffset + localOffset.Rotate(quantizedTurret)).Rotate(quantizedBody));
return body.LocalToWorld((turretLocalOffset + localOffset.Rotate(turretOrientation)).Rotate(qb));
}
IEnumerable<WRot> BarrelRotation()
{
var b = self.Orientation;
var qb = body.QuantizeOrientation(self, b);
yield return turreted.LocalOrientation(self) + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return qb;
}

View File

@@ -73,7 +73,7 @@ namespace OpenRA.Mods.Common.Traits
{
var b = self.Orientation;
var qb = body.QuantizeOrientation(self, b);
yield return turreted.LocalOrientation(self) + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return qb;
}

View File

@@ -122,18 +122,18 @@ namespace OpenRA.Mods.Common.Traits
return body.LocalToWorld(Offset.Rotate(bodyOrientation));
}
// Orientation in unit-space
public WRot LocalOrientation(Actor self)
// Orientation in world-space
public WRot WorldOrientation(Actor self)
{
// Hack: turretFacing is relative to the world, so subtract the body yaw
var local = WRot.FromYaw(WAngle.FromFacing(TurretFacing) - self.Orientation.Yaw);
var world = WRot.FromYaw(WAngle.FromFacing(TurretFacing));
if (QuantizedFacings == 0)
return local;
return world;
// Quantize orientation to match a rendered sprite
// Implies no pitch or yaw
var facing = body.QuantizeFacing(local.Yaw.Angle / 4, QuantizedFacings);
var facing = body.QuantizeFacing(world.Yaw.Angle / 4, QuantizedFacings);
return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing));
}

View File

@@ -48,6 +48,30 @@ namespace OpenRA.Mods.Common
return a / step;
}
public static int QuantizeFacing(int facing, int numFrames, bool useClassicFacingFudge)
{
if (!useClassicFacingFudge || numFrames != 32)
return Util.QuantizeFacing(facing, numFrames);
// TD and RA divided the facing artwork into 3 frames from (north|south) to (north|south)-(east|west)
// and then 5 frames from (north|south)-(east|west) to (east|west)
var quadrant = ((facing + 31) & 0xFF) / 64;
if (quadrant == 0 || quadrant == 2)
{
var frame = Util.QuantizeFacing(facing, 24);
if (frame > 18)
return frame + 6;
if (frame > 4)
return frame + 3;
return frame;
}
else
{
var frame = Util.QuantizeFacing(facing, 40);
return frame < 20 ? frame - 3 : frame - 8;
}
}
public static WPos BetweenCells(World w, CPos from, CPos to)
{
return WPos.Lerp(w.Map.CenterOfCell(from), w.Map.CenterOfCell(to), 1, 2);