#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.Collections.Generic; using System.Linq; using OpenRA.Mods.RA.Render; using OpenRA.FileFormats; using OpenRA.Traits; namespace OpenRA.Mods.RA { public class TurretedInfo : ITraitInfo, UsesInit { public readonly string Turret = "primary"; [Desc("Rate of Turning")] public readonly int ROT = 255; public readonly int InitialFacing = 128; public readonly bool AlignWhenIdle = false; [Desc("Muzzle position relative to turret or body. (forward, right, up) triples")] public readonly WVec Offset = WVec.Zero; public virtual object Create(ActorInitializer init) { return new Turreted(init, this); } } public class Turreted : ITick, ISync, IResolveOrder { [Sync] public int turretFacing = 0; public int? desiredFacing; TurretedInfo info; IFacing facing; // 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 int GetInitialTurretFacing(ActorInitializer init, int def) { if (init.Contains()) return init.Get(); if (init.Contains()) return init.Get(); return def; } public Turreted(ActorInitializer init, TurretedInfo info) { this.info = info; turretFacing = GetInitialTurretFacing(init, info.InitialFacing); facing = init.self.TraitOrDefault(); } public virtual void Tick(Actor self) { var df = desiredFacing ?? ( facing != null ? facing.Facing : turretFacing ); turretFacing = Util.TickFacing(turretFacing, df, info.ROT); } public bool FaceTarget(Actor self, Target target) { desiredFacing = Util.GetFacing(target.CenterLocation - self.CenterLocation, turretFacing); return turretFacing == desiredFacing; } public virtual void ResolveOrder(Actor self, Order order) { if (info.AlignWhenIdle && order.OrderString != "Attack" && order.OrderString != "AttackHold") desiredFacing = null; } // Turret offset in world-space public WVec Position(Actor self) { var coords = self.Trait(); var bodyOrientation = coords.QuantizeOrientation(self, self.Orientation); return coords.LocalToWorld(Offset.Rotate(bodyOrientation)); } // Orientation in unit-space public WRot LocalOrientation(Actor self) { // Hack: turretFacing is relative to the world, so subtract the body yaw return WRot.FromYaw(WAngle.FromFacing(turretFacing) - self.Orientation.Yaw); } } }