Convert turret facings to WAngle relative to the body.
This commit is contained in:
@@ -76,19 +76,12 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
state = PopupState.Closed;
|
||||
wsb.PlayCustomAnimationRepeating(self, info.ClosedIdleSequence);
|
||||
turret.DesiredFacing = null;
|
||||
turret.FaceTarget(self, Target.Invalid);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool CanAttack(Actor self, Target target)
|
||||
{
|
||||
if (state == PopupState.Transitioning)
|
||||
return false;
|
||||
|
||||
if (!base.CanAttack(self, target))
|
||||
return false;
|
||||
|
||||
idleTicks = 0;
|
||||
if (state == PopupState.Closed)
|
||||
{
|
||||
state = PopupState.Transitioning;
|
||||
@@ -97,9 +90,14 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
state = PopupState.Open;
|
||||
wsb.PlayCustomAnimationRepeating(self, wsb.Info.Sequence);
|
||||
});
|
||||
return false;
|
||||
|
||||
idleTicks = 0;
|
||||
}
|
||||
|
||||
if (state == PopupState.Transitioning || !base.CanAttack(self, target))
|
||||
return false;
|
||||
|
||||
idleTicks = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,17 +105,18 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
if (state == PopupState.Open && idleTicks++ > info.CloseDelay)
|
||||
{
|
||||
turret.DesiredFacing = info.DefaultFacing.Facing;
|
||||
var facingOffset = new WVec(0, -1024, 0).Rotate(WRot.FromYaw(info.DefaultFacing));
|
||||
turret.FaceTarget(self, Target.FromPos(self.CenterPosition + facingOffset));
|
||||
state = PopupState.Rotating;
|
||||
}
|
||||
else if (state == PopupState.Rotating && turret.TurretFacing == info.DefaultFacing.Facing)
|
||||
else if (state == PopupState.Rotating && turret.HasAchievedDesiredFacing)
|
||||
{
|
||||
state = PopupState.Transitioning;
|
||||
wsb.PlayCustomAnimation(self, info.ClosingSequence, () =>
|
||||
{
|
||||
state = PopupState.Closed;
|
||||
wsb.PlayCustomAnimationRepeating(self, info.ClosedIdleSequence);
|
||||
turret.DesiredFacing = null;
|
||||
turret.FaceTarget(self, Target.Invalid);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
var wsb = init.Actor.TraitInfos<WithSpriteBodyInfo>().FirstOrDefault();
|
||||
|
||||
// Show the correct turret facing
|
||||
var anim = new Animation(init.World, image, Turreted.TurretFacingFromInit(init, t));
|
||||
var anim = new Animation(init.World, image, t.WorldFacingFromInit(init));
|
||||
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), wsb.Sequence));
|
||||
|
||||
yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
|
||||
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
{
|
||||
// Turret artwork is baked into the sprite, so only the first turret makes sense.
|
||||
var turreted = self.TraitsImplementing<Turreted>().FirstOrDefault();
|
||||
return () => WAngle.FromFacing(turreted.TurretFacing);
|
||||
return () => turreted.WorldOrientation.Yaw;
|
||||
}
|
||||
|
||||
public WithEmbeddedTurretSpriteBody(ActorInitializer init, WithSpriteBodyInfo info)
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
{
|
||||
// Turret artwork is baked into the sprite, so only the first turret makes sense.
|
||||
var turreted = self.TraitsImplementing<Turreted>().FirstOrDefault();
|
||||
return () => WAngle.FromFacing(turreted.TurretFacing);
|
||||
return () => turreted.WorldOrientation.Yaw;
|
||||
}
|
||||
|
||||
public WithGunboatBody(ActorInitializer init, WithGunboatBodyInfo info)
|
||||
|
||||
@@ -84,15 +84,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
var targetPosition = self.CenterPosition + body.LocalToWorld(localOffset);
|
||||
var targetLocation = self.World.Map.CellContaining(targetPosition);
|
||||
carryall.Carryable.Trait<IPositionable>().SetPosition(carryall.Carryable, targetLocation, SubCell.FullCell);
|
||||
|
||||
// HACK: directly manipulate the turret facings to match the new orientation
|
||||
// This can eventually go away, when we make turret facings relative to the body
|
||||
var carryableFacing = carryall.Carryable.Trait<IFacing>();
|
||||
var facingDelta = facing.Facing - carryableFacing.Facing;
|
||||
foreach (var t in carryall.Carryable.TraitsImplementing<Turreted>())
|
||||
t.TurretFacing += facingDelta.Facing;
|
||||
|
||||
carryableFacing.Facing = facing.Facing;
|
||||
carryall.Carryable.Trait<IFacing>().Facing = facing.Facing;
|
||||
|
||||
// Put back into world
|
||||
self.World.AddFrameEndTask(w =>
|
||||
|
||||
@@ -374,19 +374,18 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
protected virtual WVec CalculateMuzzleOffset(Actor self, Barrel b)
|
||||
{
|
||||
var bodyOrientation = coords.QuantizeOrientation(self, self.Orientation);
|
||||
// Weapon offset in turret coordinates
|
||||
var localOffset = b.Offset + new WVec(-Recoil, WDist.Zero, WDist.Zero);
|
||||
if (turret != null)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
return coords.LocalToWorld(localOffset.Rotate(bodyOrientation));
|
||||
// Turret coordinates to body coordinates
|
||||
var bodyOrientation = coords.QuantizeOrientation(self, self.Orientation);
|
||||
if (turret != null)
|
||||
localOffset = localOffset.Rotate(turret.WorldOrientation) + turret.Offset.Rotate(bodyOrientation);
|
||||
else
|
||||
localOffset = localOffset.Rotate(bodyOrientation);
|
||||
|
||||
// Body coordinates to world coordinates
|
||||
return coords.LocalToWorld(localOffset);
|
||||
}
|
||||
|
||||
public WRot MuzzleOrientation(Actor self, Barrel b)
|
||||
@@ -396,10 +395,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
protected virtual WRot CalculateMuzzleOrientation(Actor self, Barrel b)
|
||||
{
|
||||
var orientation = turret != null ? turret.WorldOrientation(self) :
|
||||
coords.QuantizeOrientation(self, self.Orientation);
|
||||
|
||||
return orientation + WRot.FromYaw(b.Yaw);
|
||||
return WRot.FromYaw(b.Yaw).Rotate(turret != null ? turret.WorldOrientation : self.Orientation);
|
||||
}
|
||||
|
||||
public Actor Actor { get { return self; } }
|
||||
|
||||
@@ -371,9 +371,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var passengerFacing = passenger.TraitOrDefault<IFacing>();
|
||||
if (passengerFacing != null)
|
||||
passengerFacing.Facing = facing.Value.Facing + Info.PassengerFacing;
|
||||
|
||||
foreach (var t in passenger.TraitsImplementing<Turreted>())
|
||||
t.TurretFacing = (facing.Value.Facing + Info.PassengerFacing).Facing;
|
||||
}
|
||||
|
||||
public void Load(Actor self, Actor a)
|
||||
|
||||
@@ -110,9 +110,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
foreach (var b in a.Barrels)
|
||||
{
|
||||
var barrelEnd = new Barrel
|
||||
{
|
||||
Offset = b.Offset + new WVec(224, 0, 0),
|
||||
Yaw = b.Yaw
|
||||
};
|
||||
|
||||
var muzzle = self.CenterPosition + a.MuzzleOffset(self, b);
|
||||
var dirOffset = new WVec(0, -224, 0).Rotate(a.MuzzleOrientation(self, b));
|
||||
yield return new LineAnnotationRenderable(muzzle, muzzle + dirOffset, 1, Color.White);
|
||||
var endMuzzle = self.CenterPosition + a.MuzzleOffset(self, barrelEnd);
|
||||
yield return new LineAnnotationRenderable(muzzle, endMuzzle, 1, Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,11 +110,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
if (turret != null)
|
||||
{
|
||||
// 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) - quantizedBodyOrientation;
|
||||
localOffset = localOffset.Rotate(turretOrientation);
|
||||
localOffset = localOffset.Rotate(turret.LocalOrientation);
|
||||
localOffset += turret.Offset;
|
||||
}
|
||||
|
||||
@@ -123,27 +119,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public WDist DistanceFromEdge(Actor self, WPos pos)
|
||||
{
|
||||
var origin = self.CenterPosition;
|
||||
var orientation = self.Orientation;
|
||||
if (turret != null)
|
||||
{
|
||||
origin += turret.Position(self);
|
||||
orientation = turret.WorldOrientation(self);
|
||||
}
|
||||
|
||||
var origin = turret != null ? self.CenterPosition + turret.Position(self) : self.CenterPosition;
|
||||
var orientation = turret != null ? turret.WorldOrientation : self.Orientation;
|
||||
return Info.Type.DistanceFromEdge(pos, origin, orientation);
|
||||
}
|
||||
|
||||
public IEnumerable<IRenderable> RenderDebugOverlay(Actor self, WorldRenderer wr)
|
||||
{
|
||||
var origin = self.CenterPosition;
|
||||
var orientation = self.Orientation;
|
||||
if (turret != null)
|
||||
{
|
||||
origin += turret.Position(self);
|
||||
orientation = turret.WorldOrientation(self);
|
||||
}
|
||||
|
||||
var origin = turret != null ? self.CenterPosition + turret.Position(self) : self.CenterPosition;
|
||||
var orientation = turret != null ? turret.WorldOrientation : self.Orientation;
|
||||
return Info.Type.RenderDebugOverlay(wr, origin, orientation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +52,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var turreted = self.TraitsImplementing<Turreted>()
|
||||
.FirstOrDefault(t => t.Name == arm.Info.Turret);
|
||||
|
||||
// Workaround for broken ternary operators in certain versions of mono (3.10 and
|
||||
// certain versions of the 3.8 series): https://bugzilla.xamarin.com/show_bug.cgi?id=23319
|
||||
if (turreted != null)
|
||||
getFacing = () => WAngle.FromFacing(turreted.TurretFacing);
|
||||
getFacing = () => turreted.WorldOrientation.Yaw;
|
||||
else if (facing != null)
|
||||
getFacing = () => facing.Facing;
|
||||
else
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var t = init.Actor.TraitInfos<TurretedInfo>()
|
||||
.First(tt => tt.Turret == armament.Turret);
|
||||
|
||||
var turretFacing = Turreted.TurretFacingFromInit(init, t);
|
||||
var turretFacing = t.WorldFacingFromInit(init);
|
||||
var anim = new Animation(init.World, image, turretFacing);
|
||||
anim.Play(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
.First(tt => tt.Name == armament.Info.Turret);
|
||||
|
||||
rs = self.Trait<RenderSprites>();
|
||||
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => WAngle.FromFacing(turreted.TurretFacing));
|
||||
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => turreted.WorldOrientation.Yaw);
|
||||
DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence));
|
||||
rs.Add(new AnimationWithOffset(
|
||||
DefaultAnimation, () => BarrelOffset(), () => IsTraitDisabled, p => RenderUtils.ZOffsetFromCenter(self, p, 0)));
|
||||
@@ -98,21 +98,10 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
WVec BarrelOffset()
|
||||
{
|
||||
var orientation = turreted != null ? turreted.WorldOrientation : self.Orientation;
|
||||
var localOffset = Info.LocalOffset + new WVec(-armament.Recoil, WDist.Zero, WDist.Zero);
|
||||
var turretOffset = turreted != null ? turreted.Position(self) : WVec.Zero;
|
||||
var quantizedBody = body.QuantizeOrientation(self, self.Orientation);
|
||||
var turretOrientation = turreted != null ? turreted.WorldOrientation(self) - quantizedBody : WRot.None;
|
||||
|
||||
var quantizedTurret = body.QuantizeOrientation(self, turretOrientation);
|
||||
return turretOffset + body.LocalToWorld(localOffset.Rotate(quantizedTurret).Rotate(quantizedBody));
|
||||
}
|
||||
|
||||
IEnumerable<WRot> BarrelRotation()
|
||||
{
|
||||
var b = self.Orientation;
|
||||
var qb = body.QuantizeOrientation(self, b);
|
||||
yield return turreted.WorldOrientation(self) - qb + WRot.FromYaw(b.Yaw - qb.Yaw);
|
||||
yield return qb;
|
||||
var turretLocalOffset = turreted != null ? turreted.Offset : WVec.Zero;
|
||||
return body.LocalToWorld(turretLocalOffset + localOffset.Rotate(orientation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var t = init.Actor.TraitInfos<TurretedInfo>()
|
||||
.First(tt => tt.Turret == Turret);
|
||||
|
||||
var turretFacing = Turreted.TurretFacingFromInit(init, t);
|
||||
var turretFacing = t.WorldFacingFromInit(init);
|
||||
var anim = new Animation(init.World, image, turretFacing);
|
||||
anim.Play(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
arms = self.TraitsImplementing<Armament>()
|
||||
.Where(w => w.Info.Turret == info.Turret).ToArray();
|
||||
|
||||
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => WAngle.FromFacing(t.TurretFacing));
|
||||
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => t.WorldOrientation.Yaw);
|
||||
DefaultAnimation.PlayRepeating(NormalizeSequence(self, info.Sequence));
|
||||
rs.Add(new AnimationWithOffset(DefaultAnimation,
|
||||
() => TurretOffset(self),
|
||||
@@ -106,10 +106,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
if (!Info.Recoils)
|
||||
return t.Position(self);
|
||||
|
||||
var recoil = arms.Aggregate(WDist.Zero, (a, b) => a + b.Recoil);
|
||||
var localOffset = new WVec(-recoil, WDist.Zero, WDist.Zero);
|
||||
var quantizedWorldTurret = t.WorldOrientation(self);
|
||||
return t.Position(self) + body.LocalToWorld(localOffset.Rotate(quantizedWorldTurret));
|
||||
var recoilDist = arms.Aggregate(WDist.Zero, (a, b) => a + b.Recoil);
|
||||
var recoil = new WVec(-recoilDist, WDist.Zero, WDist.Zero);
|
||||
return t.Position(self) + body.LocalToWorld(recoil.Rotate(t.WorldOrientation));
|
||||
}
|
||||
|
||||
public string NormalizeSequence(Actor self, string sequence)
|
||||
|
||||
@@ -51,13 +51,11 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
var model = init.World.ModelCache.GetModelSequence(image, Sequence);
|
||||
|
||||
var turretFacing = Turreted.TurretFacingFromInit(init, t);
|
||||
Func<WRot> turretOrientation = () => body.QuantizeOrientation(WRot.FromYaw(turretFacing() - orientation().Yaw), facings);
|
||||
|
||||
Func<WRot> quantizedTurret = () => body.QuantizeOrientation(turretOrientation(), facings);
|
||||
var turretOrientation = t.PreviewOrientation(init, orientation, facings);
|
||||
Func<WRot> quantizedBody = () => body.QuantizeOrientation(orientation(), facings);
|
||||
Func<WVec> barrelOffset = () => body.LocalToWorld((t.Offset + LocalOffset.Rotate(quantizedTurret())).Rotate(quantizedBody()));
|
||||
Func<WRot> barrelOrientation = () => turretOrientation().Rotate(orientation());
|
||||
Func<WVec> barrelOffset = () => body.LocalToWorld((t.Offset + LocalOffset.Rotate(turretOrientation())).Rotate(quantizedBody()));
|
||||
Func<WRot> barrelOrientation = () => LocalOrientation.Rotate(turretOrientation()).Rotate(quantizedBody());
|
||||
|
||||
yield return new ModelAnimation(model, barrelOffset, barrelOrientation, () => false, () => 0, ShowShadow);
|
||||
}
|
||||
}
|
||||
@@ -87,21 +85,15 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
WVec BarrelOffset()
|
||||
{
|
||||
var b = self.Orientation;
|
||||
var qb = body.QuantizeOrientation(self, b);
|
||||
var orientation = turreted != null ? turreted.WorldOrientation : self.Orientation;
|
||||
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.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw) : WRot.None;
|
||||
|
||||
return body.LocalToWorld((turretLocalOffset + localOffset.Rotate(turretOrientation)).Rotate(qb));
|
||||
return body.LocalToWorld(turretLocalOffset + localOffset.Rotate(orientation));
|
||||
}
|
||||
|
||||
WRot BarrelRotation()
|
||||
{
|
||||
var b = self.Orientation;
|
||||
var qb = body.QuantizeOrientation(self, b);
|
||||
var t = turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw);
|
||||
return Info.LocalOrientation.Rotate(t).Rotate(qb);
|
||||
return Info.LocalOrientation.Rotate(turreted != null ? turreted.WorldOrientation : self.Orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,17 +37,12 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var t = init.Actor.TraitInfos<TurretedInfo>()
|
||||
.First(tt => tt.Turret == Turret);
|
||||
|
||||
var model = init.World.ModelCache.GetModelSequence(image, Sequence);
|
||||
Func<WVec> turretOffset = () => body.LocalToWorld(t.Offset.Rotate(orientation()));
|
||||
|
||||
var turretFacing = Turreted.TurretFacingFromInit(init, t);
|
||||
Func<WRot> turretOrientation = () => WRot.FromYaw(turretFacing() - orientation().Yaw)
|
||||
.Rotate(body.QuantizeOrientation(orientation(), facings));
|
||||
|
||||
var turretOffset = t.PreviewPosition(init, orientation);
|
||||
var turretOrientation = t.PreviewOrientation(init, orientation, facings);
|
||||
yield return new ModelAnimation(model, turretOffset, turretOrientation, () => false, () => 0, ShowShadow);
|
||||
}
|
||||
}
|
||||
@@ -68,15 +63,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
var rv = self.Trait<RenderVoxels>();
|
||||
rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
|
||||
() => turreted.Position(self), TurretRotation,
|
||||
() => turreted.Position(self), () => turreted.WorldOrientation,
|
||||
() => IsTraitDisabled, () => 0, info.ShowShadow));
|
||||
}
|
||||
|
||||
WRot TurretRotation()
|
||||
{
|
||||
var b = self.Orientation;
|
||||
var qb = body.QuantizeOrientation(self, b);
|
||||
return (turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw)).Rotate(qb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// TODO: Carry orientation over from the parent instead of just facing
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicFacingInit>();
|
||||
var bodyFacing = dynamicFacingInit != null ? dynamicFacingInit.Value() : init.GetValue<FacingInit, WAngle>(WAngle.Zero);
|
||||
facing = Turreted.TurretFacingFromInit(init, info, WAngle.Zero)();
|
||||
facing = TurretedInfo.WorldFacingFromInit(init, info, WAngle.Zero)();
|
||||
|
||||
// Calculate final position
|
||||
var throwRotation = WRot.FromYaw(new WAngle(Game.CosmeticRandom.Next(1024)));
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -54,36 +55,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
(actor, value) => actor.ReplaceInit(new TurretFacingInit(this, new WAngle((int)value)), this));
|
||||
}
|
||||
|
||||
public override object Create(ActorInitializer init) { return new Turreted(init, this); }
|
||||
}
|
||||
|
||||
public class Turreted : PausableConditionalTrait<TurretedInfo>, ITick, IDeathActorInitModifier, IActorPreviewInitModifier
|
||||
{
|
||||
AttackTurreted attack;
|
||||
IFacing facing;
|
||||
BodyOrientation body;
|
||||
|
||||
[Sync]
|
||||
public int QuantizedFacings = 0;
|
||||
|
||||
[Sync]
|
||||
public int TurretFacing = 0;
|
||||
|
||||
public int? DesiredFacing;
|
||||
int realignTick = 0;
|
||||
|
||||
// For subclasses that want to move the turret relative to the body
|
||||
protected WVec localOffset = WVec.Zero;
|
||||
|
||||
public WVec Offset { get { return Info.Offset + localOffset; } }
|
||||
public string Name { get { return Info.Turret; } }
|
||||
|
||||
public static Func<WAngle> TurretFacingFromInit(IActorInitializer init, TurretedInfo info)
|
||||
{
|
||||
return TurretFacingFromInit(init, info, info.InitialFacing);
|
||||
}
|
||||
|
||||
public static Func<WAngle> TurretFacingFromInit(IActorInitializer init, TraitInfo info, WAngle defaultFacing)
|
||||
public static Func<WAngle> WorldFacingFromInit(IActorInitializer init, TraitInfo info, WAngle defaultFacing)
|
||||
{
|
||||
// (Dynamic)TurretFacingInit is specified relative to the actor body.
|
||||
// We need to add the body facing to return an absolute world angle.
|
||||
@@ -102,17 +74,97 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return bodyFacing != null ? (Func<WAngle>)(() => bodyFacing() + facing) : () => facing;
|
||||
}
|
||||
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicFacingInit>();
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicTurretFacingInit>(info);
|
||||
if (dynamicFacingInit != null)
|
||||
return bodyFacing != null ? () => bodyFacing() + dynamicFacingInit.Value() : dynamicFacingInit.Value;
|
||||
|
||||
return bodyFacing ?? (Func<WAngle>)(() => defaultFacing);
|
||||
return bodyFacing ?? (() => defaultFacing);
|
||||
}
|
||||
|
||||
public Func<WAngle> WorldFacingFromInit(IActorInitializer init)
|
||||
{
|
||||
return WorldFacingFromInit(init, this, InitialFacing);
|
||||
}
|
||||
|
||||
public Func<WAngle> LocalFacingFromInit(IActorInitializer init)
|
||||
{
|
||||
var turretFacingInit = init.GetOrDefault<TurretFacingInit>(this);
|
||||
if (turretFacingInit != null)
|
||||
{
|
||||
var facing = turretFacingInit.Value;
|
||||
return () => facing;
|
||||
}
|
||||
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicTurretFacingInit>(this);
|
||||
if (dynamicFacingInit != null)
|
||||
return dynamicFacingInit.Value;
|
||||
|
||||
return () => InitialFacing;
|
||||
}
|
||||
|
||||
// Turret offset in world-space
|
||||
public Func<WVec> PreviewPosition(ActorPreviewInitializer init, Func<WRot> orientation)
|
||||
{
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
return () => body.LocalToWorld(Offset.Rotate(orientation()));
|
||||
}
|
||||
|
||||
// Orientation in world-space
|
||||
public Func<WRot> PreviewOrientation(ActorPreviewInitializer init, Func<WRot> orientation, int facings)
|
||||
{
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var turretFacing = LocalFacingFromInit(init);
|
||||
|
||||
Func<WRot> world = () => WRot.FromYaw(turretFacing()).Rotate(orientation());
|
||||
if (facings == 0)
|
||||
return world;
|
||||
|
||||
// Quantize orientation to match a rendered sprite
|
||||
// Implies no pitch or roll
|
||||
return () => WRot.FromYaw(body.QuantizeFacing(world().Yaw, facings));
|
||||
}
|
||||
|
||||
public override object Create(ActorInitializer init) { return new Turreted(init, this); }
|
||||
}
|
||||
|
||||
public class Turreted : PausableConditionalTrait<TurretedInfo>, ITick, IDeathActorInitModifier, IActorPreviewInitModifier
|
||||
{
|
||||
AttackTurreted attack;
|
||||
IFacing facing;
|
||||
BodyOrientation body;
|
||||
|
||||
[Sync]
|
||||
public int QuantizedFacings = 0;
|
||||
|
||||
WVec? desiredDirection = null;
|
||||
int realignTick = 0;
|
||||
|
||||
public WRot WorldOrientation
|
||||
{
|
||||
get
|
||||
{
|
||||
var world = facing != null ? LocalOrientation.Rotate(facing.Orientation) : LocalOrientation;
|
||||
if (QuantizedFacings == 0)
|
||||
return world;
|
||||
|
||||
// Quantize orientation to match a rendered sprite
|
||||
// Implies no pitch or roll
|
||||
return WRot.FromYaw(body.QuantizeFacing(world.Yaw, QuantizedFacings));
|
||||
}
|
||||
}
|
||||
|
||||
public WRot LocalOrientation { get; private set; }
|
||||
|
||||
// For subclasses that want to move the turret relative to the body
|
||||
protected WVec localOffset = WVec.Zero;
|
||||
|
||||
public WVec Offset { get { return Info.Offset + localOffset; } }
|
||||
public string Name { get { return Info.Turret; } }
|
||||
|
||||
public Turreted(ActorInitializer init, TurretedInfo info)
|
||||
: base(info)
|
||||
{
|
||||
TurretFacing = TurretFacingFromInit(init, Info)().Facing;
|
||||
LocalOrientation = WRot.FromYaw(info.LocalFacingFromInit(init)());
|
||||
}
|
||||
|
||||
protected override void Created(Actor self)
|
||||
@@ -143,7 +195,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (realignTick < Info.RealignDelay)
|
||||
realignTick++;
|
||||
else if (Info.RealignDelay > -1)
|
||||
DesiredFacing = null;
|
||||
desiredDirection = null;
|
||||
|
||||
MoveTurret();
|
||||
}
|
||||
@@ -154,10 +206,33 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
WAngle? DesiredLocalFacing
|
||||
{
|
||||
get
|
||||
{
|
||||
// A null value means we don't have a target
|
||||
if (!desiredDirection.HasValue)
|
||||
return null;
|
||||
|
||||
// A zero value means that we have a target, but it is on top of us
|
||||
if (desiredDirection.Value == WVec.Zero)
|
||||
return LocalOrientation.Yaw;
|
||||
|
||||
// PERF: If the turret rotation axis is vertical we can directly take the difference in facing/yaw
|
||||
var o = facing != null ? facing.Orientation : (WRot?)null;
|
||||
if (o == null || (o.Value.Pitch == WAngle.Zero && o.Value.Roll == WAngle.Zero))
|
||||
return o.HasValue ? desiredDirection.Value.Yaw - o.Value.Yaw : desiredDirection.Value.Yaw;
|
||||
|
||||
// If the turret rotation axis is not vertical we must transform the
|
||||
// target direction into the turrets local coordinate system
|
||||
return desiredDirection.Value.Rotate(-o.Value).Yaw;
|
||||
}
|
||||
}
|
||||
|
||||
void MoveTurret()
|
||||
{
|
||||
var df = DesiredFacing ?? (facing != null ? facing.Facing.Facing : TurretFacing);
|
||||
TurretFacing = Util.TickFacing(TurretFacing, df, Info.TurnSpeed.Facing);
|
||||
var desired = DesiredLocalFacing ?? Info.InitialFacing;
|
||||
LocalOrientation = LocalOrientation.WithYaw(Util.TickFacing(LocalOrientation.Yaw, desired, Info.TurnSpeed));
|
||||
}
|
||||
|
||||
public bool FaceTarget(Actor self, Target target)
|
||||
@@ -165,17 +240,27 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (IsTraitDisabled || IsTraitPaused || attack == null || attack.IsTraitDisabled || attack.IsTraitPaused)
|
||||
return false;
|
||||
|
||||
var pos = self.CenterPosition;
|
||||
var targetPos = attack.GetTargetPosition(pos, target);
|
||||
var delta = targetPos - pos;
|
||||
DesiredFacing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : TurretFacing;
|
||||
if (target.Type == TargetType.Invalid)
|
||||
{
|
||||
desiredDirection = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var turretPos = self.CenterPosition + Position(self);
|
||||
var targetPos = attack.GetTargetPosition(turretPos, target);
|
||||
desiredDirection = targetPos - turretPos;
|
||||
|
||||
MoveTurret();
|
||||
return HasAchievedDesiredFacing;
|
||||
}
|
||||
|
||||
public virtual bool HasAchievedDesiredFacing
|
||||
{
|
||||
get { return DesiredFacing == null || TurretFacing == DesiredFacing.Value; }
|
||||
get
|
||||
{
|
||||
var desired = DesiredLocalFacing;
|
||||
return !desired.HasValue || desired.Value == LocalOrientation.Yaw;
|
||||
}
|
||||
}
|
||||
|
||||
// Turret offset in world-space
|
||||
@@ -185,42 +270,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return body.LocalToWorld(Offset.Rotate(bodyOrientation));
|
||||
}
|
||||
|
||||
// Orientation in world-space
|
||||
public WRot WorldOrientation(Actor self)
|
||||
{
|
||||
// Hack: turretFacing is relative to the world, so subtract the body yaw
|
||||
var world = WRot.FromYaw(WAngle.FromFacing(TurretFacing));
|
||||
|
||||
if (QuantizedFacings == 0)
|
||||
return world;
|
||||
|
||||
// Quantize orientation to match a rendered sprite
|
||||
// Implies no pitch or yaw
|
||||
return WRot.FromYaw(body.QuantizeFacing(world.Yaw, QuantizedFacings));
|
||||
}
|
||||
|
||||
public void ModifyDeathActorInit(Actor self, TypeDictionary init)
|
||||
{
|
||||
var turretFacing = WAngle.FromFacing(TurretFacing);
|
||||
if (facing != null)
|
||||
turretFacing -= facing.Facing;
|
||||
|
||||
init.Add(new TurretFacingInit(Info, turretFacing));
|
||||
init.Add(new TurretFacingInit(Info, LocalOrientation.Yaw));
|
||||
}
|
||||
|
||||
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits)
|
||||
{
|
||||
Func<WAngle> bodyFacing = () => facing.Facing;
|
||||
var dynamicFacing = inits.GetOrDefault<DynamicFacingInit>();
|
||||
var staticFacing = inits.GetOrDefault<FacingInit>();
|
||||
if (dynamicFacing != null)
|
||||
bodyFacing = dynamicFacing.Value;
|
||||
else if (staticFacing != null)
|
||||
bodyFacing = () => staticFacing.Value;
|
||||
|
||||
// Freeze the relative turret facing to its current value
|
||||
var facingOffset = WAngle.FromFacing(TurretFacing) - bodyFacing();
|
||||
inits.Add(new DynamicTurretFacingInit(Info, () => bodyFacing() + facingOffset));
|
||||
inits.Add(new DynamicTurretFacingInit(Info, () => LocalOrientation.Yaw));
|
||||
}
|
||||
|
||||
protected override void TraitDisabled(Actor self)
|
||||
|
||||
Reference in New Issue
Block a user