#region Copyright & License Information /* * Copyright 2007-2013 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.FileFormats; using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { class WithTurretInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] public readonly string Sequence = "turret"; [Desc("Sequence name to use when prepared to fire")] public readonly string AimSequence = null; [Desc("Turreted 'Turret' key to display")] public readonly string Turret = "primary"; public object Create(ActorInitializer init) { return new WithTurret(init.self, this); } } class WithTurret : ITick { WithTurretInfo info; RenderSimple rs; AttackBase ab; Turreted t; IEnumerable arms; Animation anim; public WithTurret(Actor self, WithTurretInfo info) { this.info = info; rs = self.Trait(); ab = self.TraitOrDefault(); t = self.TraitsImplementing() .First(tt => tt.Name == info.Turret); arms = self.TraitsImplementing() .Where(w => w.Info.Turret == info.Turret); anim = new Animation(rs.GetImage(self), () => t.turretFacing); anim.Play(info.Sequence); rs.anims.Add("turret_{0}".F(info.Turret), new AnimationWithOffset( anim, wr => TurretPosition(self, wr), null) { ZOffset = 1 }); } int2 TurretPosition(Actor self, WorldRenderer wr) { var recoil = arms.Aggregate(WRange.Zero, (a,b) => a + b.Recoil); var localOffset = new WVec(-recoil, WRange.Zero, WRange.Zero); var bodyOrientation = rs.QuantizeOrientation(self, self.Orientation); var turretOrientation = rs.QuantizeOrientation(self, t.LocalOrientation(self)); var worldPos = t.Position(self) + rs.LocalToWorld(localOffset.Rotate(turretOrientation).Rotate(bodyOrientation)); return wr.ScreenPxOffset(worldPos); } public void Tick(Actor self) { if (info.AimSequence == null) return; var sequence = ab.IsAttacking ? info.AimSequence : info.Sequence; rs.anims["turret_{0}".F(info.Turret)].Animation.ReplaceAnim(sequence); } } }