diff --git a/OpenRA.Game/Traits/BodyOrientation.cs b/OpenRA.Game/Traits/BodyOrientation.cs index 061112e2e3..37d506930d 100755 --- a/OpenRA.Game/Traits/BodyOrientation.cs +++ b/OpenRA.Game/Traits/BodyOrientation.cs @@ -8,56 +8,76 @@ */ #endregion +using System; + namespace OpenRA.Traits { public class BodyOrientationInfo : ITraitInfo, IBodyOrientationInfo { - [Desc("Number of facings for gameplay calculations. -1 indiciates auto-detection from sequence")] + [Desc("Number of facings for gameplay calculations. -1 indicates auto-detection from another trait")] public readonly int QuantizedFacings = -1; [Desc("Camera pitch for rotation calculations")] public readonly WAngle CameraPitch = WAngle.FromDegrees(40); + + public WVec LocalToWorld(WVec vec) + { + // RA's 2d perspective doesn't correspond to an orthonormal 3D + // coordinate system, so fudge the y axis to make things look good + return new WVec(vec.Y, -CameraPitch.Sin() * vec.X / 1024, vec.Z); + } + + public WRot QuantizeOrientation(WRot orientation, int facings) + { + // Quantization disabled + if (facings == 0) + return orientation; + + // Map yaw to the closest facing + var facing = Util.QuantizeFacing(orientation.Yaw.Angle / 4, facings) * (256 / facings); + + // Roll and pitch are always zero if yaw is quantized + return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)); + } + public object Create(ActorInitializer init) { return new BodyOrientation(init.self, this); } } public class BodyOrientation : IBodyOrientation { - [Sync] public int QuantizedFacings { get; private set; } - BodyOrientationInfo info; + readonly BodyOrientationInfo info; + readonly Lazy quantizedFacings; + + [Sync] public int QuantizedFacings { get { return quantizedFacings.Value; } } public BodyOrientation(Actor self, BodyOrientationInfo info) { this.info = info; - if (info.QuantizedFacings > 0) - QuantizedFacings = info.QuantizedFacings; + + quantizedFacings = Exts.Lazy(() => + { + // Override value is set + if (info.QuantizedFacings >= 0) + return info.QuantizedFacings; + + var qboi = self.Info.Traits.GetOrDefault(); + if (qboi == null) + throw new InvalidOperationException("Actor type '" + self.Info.Name + "' does not define a quantized body orientation."); + + return qboi.QuantizedBodyFacings(self.World.Map.SequenceProvider, self.Info); + }); } public WAngle CameraPitch { get { return info.CameraPitch; } } public WVec LocalToWorld(WVec vec) { - // RA's 2d perspective doesn't correspond to an orthonormal 3D - // coordinate system, so fudge the y axis to make things look good - return new WVec(vec.Y, -info.CameraPitch.Sin()*vec.X/1024, vec.Z); + return info.LocalToWorld(vec); } public WRot QuantizeOrientation(Actor self, WRot orientation) { - // Quantization disabled - if (QuantizedFacings == 0) - return orientation; - - // Map yaw to the closest facing - var facing = Util.QuantizeFacing(orientation.Yaw.Angle / 4, QuantizedFacings) * (256 / QuantizedFacings); - - // Roll and pitch are always zero if yaw is quantized - return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)); - } - - public void SetAutodetectedFacings(int facings) - { - if (info.QuantizedFacings < 0) - QuantizedFacings = facings; + return info.QuantizeOrientation(orientation, quantizedFacings.Value); } } } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 990e85eb2b..712f79acea 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -227,15 +227,22 @@ namespace OpenRA.Traits public interface IRenderShroud { void RenderShroud(WorldRenderer wr, Shroud shroud); } public interface IPostRenderSelection { IEnumerable RenderAfterWorld(WorldRenderer wr); } + public interface IBodyOrientation { WAngle CameraPitch { get; } int QuantizedFacings { get; } WVec LocalToWorld(WVec vec); WRot QuantizeOrientation(Actor self, WRot orientation); - void SetAutodetectedFacings(int facings); } - public interface IBodyOrientationInfo : ITraitInfo { } + + public interface IBodyOrientationInfo : ITraitInfo + { + WVec LocalToWorld(WVec vec); + WRot QuantizeOrientation(WRot orientation, int facings); + } + + public interface IQuantizeBodyOrientationInfo { int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai); } public interface ITargetableInfo { diff --git a/OpenRA.Mods.Cnc/RenderGunboat.cs b/OpenRA.Mods.Cnc/RenderGunboat.cs index 29159b846e..a1e825531b 100644 --- a/OpenRA.Mods.Cnc/RenderGunboat.cs +++ b/OpenRA.Mods.Cnc/RenderGunboat.cs @@ -14,7 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - class RenderGunboatInfo : RenderSpritesInfo, Requires + class RenderGunboatInfo : RenderSpritesInfo, IQuantizeBodyOrientationInfo, Requires { [Desc("Turreted 'Turret' key to display")] public readonly string Turret = "primary"; @@ -25,6 +25,11 @@ namespace OpenRA.Mods.RA.Render public readonly string WakeRightSequence = "wake-right"; public override object Create(ActorInitializer init) { return new RenderGunboat(init.self, this); } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) + { + return 2; + } } class RenderGunboat : RenderSprites, INotifyDamageStateChanged @@ -54,8 +59,6 @@ namespace OpenRA.Mods.RA.Render var rightWake = new Animation(self.World, name); rightWake.Play(info.WakeRightSequence); Add(info.WakeRightSequence, new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87)); - - self.Trait().SetAutodetectedFacings(2); } public void DamageStateChanged(Actor self, AttackInfo e) diff --git a/OpenRA.Mods.RA/Graphics/ActorPreview.cs b/OpenRA.Mods.RA/Graphics/ActorPreview.cs new file mode 100644 index 0000000000..f33977deba --- /dev/null +++ b/OpenRA.Mods.RA/Graphics/ActorPreview.cs @@ -0,0 +1,45 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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 OpenRA.Graphics; +using OpenRA.Primitives; + +namespace OpenRA.Mods.RA.Graphics +{ + public interface IActorPreview + { + void Tick(); + IEnumerable Render(WorldRenderer wr, WPos pos); + } + + public class ActorPreviewInitializer + { + public readonly ActorInfo Actor; + public readonly Player Owner; + public readonly WorldRenderer WorldRenderer; + public World World { get { return WorldRenderer.world; } } + + readonly TypeDictionary dict; + + public ActorPreviewInitializer(ActorInfo actor, Player owner, WorldRenderer worldRenderer, TypeDictionary dict) + { + Actor = actor; + Owner = owner; + WorldRenderer = worldRenderer; + this.dict = dict; + } + + public T Get() where T : IActorInit { return dict.Get(); } + public U Get() where T : IActorInit { return dict.Get().Value(World); } + public bool Contains() where T : IActorInit { return dict.Contains(); } + } +} diff --git a/OpenRA.Mods.RA/Graphics/SpriteActorPreview.cs b/OpenRA.Mods.RA/Graphics/SpriteActorPreview.cs new file mode 100644 index 0000000000..a8066af1d3 --- /dev/null +++ b/OpenRA.Mods.RA/Graphics/SpriteActorPreview.cs @@ -0,0 +1,42 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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 OpenRA.Graphics; +using OpenRA.Primitives; + +namespace OpenRA.Mods.RA.Graphics +{ + public class SpriteActorPreview : IActorPreview + { + readonly Animation animation; + readonly WVec offset; + readonly int zOffset; + readonly PaletteReference pr; + readonly float scale; + + public SpriteActorPreview(Animation animation, WVec offset, int zOffset, PaletteReference pr, float scale) + { + this.animation = animation; + this.offset = offset; + this.zOffset = zOffset; + this.pr = pr; + this.scale = scale; + } + + public void Tick() { animation.Tick(); } + + public IEnumerable Render(WorldRenderer wr, WPos pos) + { + return animation.Render(pos, offset, zOffset, pr, scale); + } + } +} diff --git a/OpenRA.Mods.RA/Graphics/VoxelActorPreview.cs b/OpenRA.Mods.RA/Graphics/VoxelActorPreview.cs new file mode 100644 index 0000000000..75f4abeae2 --- /dev/null +++ b/OpenRA.Mods.RA/Graphics/VoxelActorPreview.cs @@ -0,0 +1,58 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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 OpenRA.Graphics; +using OpenRA.Mods.RA.Render; +using OpenRA.Primitives; + +namespace OpenRA.Mods.RA.Graphics +{ + public class VoxelPreview : IActorPreview + { + readonly VoxelAnimation[] components; + readonly RenderVoxelsInfo rvi; + readonly WRot lightSource; + readonly WRot camera; + + readonly PaletteReference colorPalette; + readonly PaletteReference normalsPalette; + readonly PaletteReference shadowPalette; + + readonly WVec offset; + readonly int zOffset; + + public VoxelPreview(VoxelAnimation[] components, WVec offset, int zOffset, RenderVoxelsInfo rvi, WAngle cameraPitch, + PaletteReference colorPalette, PaletteReference normalsPalette, PaletteReference shadowPalette) + { + this.components = components; + this.rvi = rvi; + lightSource = new WRot(WAngle.Zero,new WAngle(256) - rvi.LightPitch, rvi.LightYaw); + camera = new WRot(WAngle.Zero, cameraPitch - new WAngle(256), new WAngle(256)); + + this.colorPalette = colorPalette; + this.normalsPalette = normalsPalette; + this.shadowPalette = shadowPalette; + + this.offset = offset; + this.zOffset = zOffset; + } + + public void Tick() { /* not supported */ } + + public IEnumerable Render(WorldRenderer wr, WPos pos) + { + yield return new VoxelRenderable(components, pos + offset, zOffset, camera, rvi.Scale, + lightSource, rvi.LightAmbientColor, rvi.LightDiffuseColor, + colorPalette, normalsPalette, shadowPalette); + } + } +} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 3a0809d7d3..1148e35b16 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -545,6 +545,9 @@ + + + diff --git a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs index 3d23129501..48aeae7a1c 100644 --- a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs @@ -13,8 +13,10 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Graphics; using OpenRA.Mods.RA.Render; using OpenRA.Traits; +using OpenRA.Primitives; namespace OpenRA.Mods.RA.Orders { @@ -23,8 +25,8 @@ namespace OpenRA.Mods.RA.Orders readonly Actor Producer; readonly string Building; readonly BuildingInfo BuildingInfo; + IActorPreview[] preview; - IEnumerable preview; Sprite buildOk, buildBlocked; bool initialized = false; @@ -79,7 +81,15 @@ namespace OpenRA.Mods.RA.Orders } } - public void Tick(World world) {} + public void Tick(World world) + { + if (preview == null) + return; + + foreach (var p in preview) + p.Tick(); + } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public IEnumerable RenderAfterWorld(WorldRenderer wr, World world) { @@ -108,23 +118,22 @@ namespace OpenRA.Mods.RA.Orders { if (!initialized) { - var rbi = rules.Actors[Building].Traits.GetOrDefault(); - if (rbi == null) - preview = new IRenderable[0]; - else - { - var palette = rbi.Palette ?? (Producer.Owner != null ? - rbi.PlayerPalette + Producer.Owner.InternalName : null); - - preview = rbi.RenderPreview(world, rules.Actors[Building], wr.Palette(palette)); - } + var init = new ActorPreviewInitializer(rules.Actors[Building], Producer.Owner, wr, new TypeDictionary()); + preview = rules.Actors[Building].Traits.WithInterface() + .SelectMany(rpi => rpi.RenderPreview(init)) + .ToArray(); initialized = true; } - var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, BuildingInfo) - WPos.Zero; - foreach (var r in preview) - yield return r.OffsetBy(offset); + var comparer = new RenderableComparer(wr); + var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, BuildingInfo); + var previewRenderables = preview + .SelectMany(p => p.Render(wr, offset)) + .OrderBy(r => r, comparer); + + foreach (var r in previewRenderables) + yield return r; var res = world.WorldActor.Trait(); var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft); diff --git a/OpenRA.Mods.RA/Render/RenderBuilding.cs b/OpenRA.Mods.RA/Render/RenderBuilding.cs index 416866cc84..c5973152f2 100755 --- a/OpenRA.Mods.RA/Render/RenderBuilding.cs +++ b/OpenRA.Mods.RA/Render/RenderBuilding.cs @@ -49,8 +49,6 @@ namespace OpenRA.Mods.RA.Render this.info = info; DefaultAnimation.PlayRepeating(NormalizeSequence(self, "idle")); - - self.Trait().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings); } public virtual void BuildingComplete(Actor self) diff --git a/OpenRA.Mods.RA/Render/RenderBuildingTurreted.cs b/OpenRA.Mods.RA/Render/RenderBuildingTurreted.cs index 0c14873c40..a95173f5d6 100644 --- a/OpenRA.Mods.RA/Render/RenderBuildingTurreted.cs +++ b/OpenRA.Mods.RA/Render/RenderBuildingTurreted.cs @@ -9,14 +9,29 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; +using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { class RenderBuildingTurretedInfo : RenderBuildingInfo, Requires { - public override object Create(ActorInitializer init) { return new RenderBuildingTurreted( init, this ); } + public override object Create(ActorInitializer init) { return new RenderBuildingTurreted(init, this); } + + public override IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var t = init.Actor.Traits.WithInterface() + .FirstOrDefault(); + + // Show the correct turret facing + var anim = new Animation(init.World, image, () => t.InitialFacing); + anim.PlayRepeating("idle"); + + yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); + } } class RenderBuildingTurreted : RenderBuilding diff --git a/OpenRA.Mods.RA/Render/RenderBuildingWall.cs b/OpenRA.Mods.RA/Render/RenderBuildingWall.cs index f6152f8112..343206fac6 100644 --- a/OpenRA.Mods.RA/Render/RenderBuildingWall.cs +++ b/OpenRA.Mods.RA/Render/RenderBuildingWall.cs @@ -8,7 +8,10 @@ */ #endregion +using System.Collections.Generic; using System.Linq; +using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render @@ -19,6 +22,15 @@ namespace OpenRA.Mods.RA.Render public readonly string Sequence = "idle"; public override object Create(ActorInitializer init) { return new RenderBuildingWall(init, this); } + + public override IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + // Show a static frame instead of animating all of the wall states + var anim = new Animation(init.World, image, () => 0); + anim.PlayFetchIndex("idle", () => 0); + + yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); + } } class RenderBuildingWall : RenderBuilding, INotifyAddedToWorld, INotifyRemovedFromWorld diff --git a/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs b/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs index 204426465d..5b9265bde4 100755 --- a/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs +++ b/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs @@ -12,27 +12,27 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { class RenderBuildingWarFactoryInfo : RenderBuildingInfo { - public override object Create(ActorInitializer init) { return new RenderBuildingWarFactory( init, this ); } + public override object Create(ActorInitializer init) { return new RenderBuildingWarFactory(init, this); } - /* get around unverifiability */ - IEnumerable BaseBuildingPreview(World world, ActorInfo building, PaletteReference pr) + public override IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) { - return base.RenderPreview(world, building, pr); - } + foreach (var orig in base.RenderPreviewSprites(init, rs, image, facings, p)) + yield return orig; - public override IEnumerable RenderPreview(World world, ActorInfo building, PaletteReference pr) - { - var p = BaseBuildingPreview(world, building, pr); - var anim = new Animation(world, RenderSprites.GetImage(building), () => 0); + // Show additional roof overlay + var anim = new Animation(init.World, image, () => 0); anim.PlayRepeating("idle-top"); - return p.Concat(anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale)); + var bi = init.Actor.Traits.Get(); + var offset = FootprintUtils.CenterOffset(init.World, bi).Y + 512; + yield return new SpriteActorPreview(anim, WVec.Zero, offset, p, rs.Scale); } } diff --git a/OpenRA.Mods.RA/Render/RenderInfantry.cs b/OpenRA.Mods.RA/Render/RenderInfantry.cs index cbf5cc21a4..7399fcec9b 100644 --- a/OpenRA.Mods.RA/Render/RenderInfantry.cs +++ b/OpenRA.Mods.RA/Render/RenderInfantry.cs @@ -8,7 +8,11 @@ */ #endregion +using System.Collections.Generic; +using System.Linq; using OpenRA.Mods.RA.Effects; +using OpenRA.Mods.RA.Graphics; +using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render @@ -25,6 +29,23 @@ namespace OpenRA.Mods.RA.Render public readonly string[] StandAnimations = { "stand" }; public override object Create(ActorInitializer init) { return new RenderInfantry(init.self, this); } + + public override IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var facing = 0; + var ifacing = init.Actor.Traits.GetOrDefault(); + if (ifacing != null) + facing = init.Contains() ? init.Get() : ifacing.GetInitialFacing(); + + var anim = new Animation(init.World, image, () => facing); + anim.PlayRepeating(StandAnimations.First()); + yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); + } + + public override int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) + { + return sequenceProvider.GetSequence(RenderSprites.GetImage(ai), StandAnimations.First()).Facings; + } } public class RenderInfantry : RenderSimple, INotifyAttack, INotifyKilled, INotifyIdle @@ -64,8 +85,6 @@ namespace OpenRA.Mods.RA.Render DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandAnimations.Random(Game.CosmeticRandom)), () => 0); State = AnimationState.Waiting; move = self.Trait(); - - self.Trait().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings); } public void Attacking(Actor self, Target target) diff --git a/OpenRA.Mods.RA/Render/RenderSimple.cs b/OpenRA.Mods.RA/Render/RenderSimple.cs index 14a640692e..567cedc97e 100644 --- a/OpenRA.Mods.RA/Render/RenderSimple.cs +++ b/OpenRA.Mods.RA/Render/RenderSimple.cs @@ -11,20 +11,28 @@ using System; using System.Collections.Generic; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class RenderSimpleInfo : RenderSpritesInfo, ILegacyEditorRenderInfo, Requires + public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, ILegacyEditorRenderInfo, Requires { public override object Create(ActorInitializer init) { return new RenderSimple(init.self); } - public virtual IEnumerable RenderPreview(World world, ActorInfo ai, PaletteReference pr) + public virtual IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) { - var anim = new Animation(world, RenderSimple.GetImage(ai), () => 0); - anim.PlayRepeating("idle"); + var ifacing = init.Actor.Traits.GetOrDefault(); + var facing = ifacing != null ? init.Contains() ? init.Get() : ifacing.GetInitialFacing() : 0; - return anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale); + var anim = new Animation(init.World, image, () => facing); + anim.PlayRepeating("idle"); + yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); + } + + public virtual int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) + { + return sequenceProvider.GetSequence(RenderSprites.GetImage(ai), "idle").Facings; } public string EditorPalette { get { return Palette; } } @@ -46,7 +54,6 @@ namespace OpenRA.Mods.RA.Render : this(self, MakeFacingFunc(self)) { DefaultAnimation.PlayRepeating(NormalizeSequence(self, "idle")); - self.Trait().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings); } public int2 SelectionSize(Actor self) { return AutoSelectionSize(self); } diff --git a/OpenRA.Mods.RA/Render/RenderSprites.cs b/OpenRA.Mods.RA/Render/RenderSprites.cs index f93507498b..6f9eef80b2 100644 --- a/OpenRA.Mods.RA/Render/RenderSprites.cs +++ b/OpenRA.Mods.RA/Render/RenderSprites.cs @@ -12,12 +12,15 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; using OpenRA.Primitives; namespace OpenRA.Mods.RA.Render { - public class RenderSpritesInfo : ITraitInfo + public interface IRenderActorPreviewSpritesInfo { IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p); } + + public class RenderSpritesInfo : IRenderActorPreviewInfo, ITraitInfo { [Desc("Defaults to the actor name.")] public readonly string Image = null; @@ -30,6 +33,23 @@ namespace OpenRA.Mods.RA.Render public readonly float Scale = 1f; public virtual object Create(ActorInitializer init) { return new RenderSprites(init.self); } + + public IEnumerable RenderPreview(ActorPreviewInitializer init) + { + var sequenceProvider = init.World.Map.SequenceProvider; + var image = RenderSprites.GetImage(init.Actor); + var palette = init.WorldRenderer.Palette(Palette ?? (init.Owner != null ? PlayerPalette + init.Owner.InternalName : null)); + + var facings = 0; + var body = init.Actor.Traits.GetOrDefault(); + if (body != null) + facings = body.QuantizedFacings == -1 ? init.Actor.Traits.Get().QuantizedBodyFacings(sequenceProvider, init.Actor) : body.QuantizedFacings; + + foreach (var spi in init.Actor.Traits.WithInterface()) + foreach (var preview in spi.RenderPreviewSprites(init, this, image, facings, palette)) + yield return preview; + } + } public class RenderSprites : IRender, ITick, INotifyOwnerChanged, INotifyEffectiveOwnerChanged @@ -89,7 +109,7 @@ namespace OpenRA.Mods.RA.Render public static string GetImage(ActorInfo actor) { var Info = actor.Traits.Get(); - return Info.Image ?? actor.Name; + return (Info.Image ?? actor.Name).ToLowerInvariant(); } public string GetImage(Actor self) diff --git a/OpenRA.Mods.RA/Render/RenderVoxels.cs b/OpenRA.Mods.RA/Render/RenderVoxels.cs index 6b466817ff..eb07ff6d8e 100755 --- a/OpenRA.Mods.RA/Render/RenderVoxels.cs +++ b/OpenRA.Mods.RA/Render/RenderVoxels.cs @@ -9,13 +9,16 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.Graphics; -using OpenRA.Traits; using OpenRA.Mods.RA.Graphics; +using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class RenderVoxelsInfo : ITraitInfo, Requires + public interface IRenderActorPreviewVoxelsInfo { IEnumerable RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p); } + + public class RenderVoxelsInfo : ITraitInfo, IRenderActorPreviewInfo, Requires { [Desc("Defaults to the actor name.")] public readonly string Image = null; @@ -34,7 +37,27 @@ namespace OpenRA.Mods.RA.Render public readonly WAngle LightYaw = WAngle.FromDegrees(240); public readonly float[] LightAmbientColor = new float[] {0.6f, 0.6f, 0.6f}; public readonly float[] LightDiffuseColor = new float[] {0.4f, 0.4f, 0.4f}; + public virtual object Create(ActorInitializer init) { return new RenderVoxels(init.self, this); } + + public virtual IEnumerable RenderPreview(ActorPreviewInitializer init) + { + var body = init.Actor.Traits.Get(); + var sequenceProvider = init.World.Map.SequenceProvider; + var image = Image ?? init.Actor.Name; + var facings = body.QuantizedFacings == -1 ? init.Actor.Traits.Get().QuantizedBodyFacings(sequenceProvider, init.Actor) : body.QuantizedFacings; + var palette = init.WorldRenderer.Palette(Palette ?? (init.Owner != null ? PlayerPalette + init.Owner.InternalName : null)); + + var facing = init.Contains() ? init.Get() : 0; + var orientation = WRot.FromFacing(facing); + var components = init.Actor.Traits.WithInterface() + .SelectMany(rvpi => rvpi.RenderPreviewVoxels(init, this, image, orientation, facings, palette)) + .ToArray(); + + yield return new VoxelPreview(components, WVec.Zero, 0, this, body.CameraPitch, palette, + init.WorldRenderer.Palette(NormalsPalette), init.WorldRenderer.Palette("shadow")); + } + } public class RenderVoxels : IRender, INotifyOwnerChanged diff --git a/OpenRA.Mods.RA/Render/WithIdleOverlay.cs b/OpenRA.Mods.RA/Render/WithIdleOverlay.cs index 089e4109c7..b4e1eb2012 100644 --- a/OpenRA.Mods.RA/Render/WithIdleOverlay.cs +++ b/OpenRA.Mods.RA/Render/WithIdleOverlay.cs @@ -8,15 +8,17 @@ */ #endregion +using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { [Desc("Renders a decorative animation on units and buildings.")] - public class WithIdleOverlayInfo : ITraitInfo, Requires, Requires + public class WithIdleOverlayInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires { [Desc("Sequence name to use")] public readonly string Sequence = "idle-overlay"; @@ -33,6 +35,18 @@ namespace OpenRA.Mods.RA.Render public readonly bool PauseOnLowPower = false; public object Create(ActorInitializer init) { return new WithIdleOverlay(init.self, this); } + + public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var facing = init.Contains() ? init.Get() : 0; + var anim = new Animation(init.World, image, () => facing); + anim.PlayRepeating(Sequence); + + var orientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)), facings); + var offset = body.LocalToWorld(Offset.Rotate(orientation)); + yield return new SpriteActorPreview(anim, offset, offset.Y + offset.Z + 1, p, rs.Scale); + } } public class WithIdleOverlay : INotifyDamageStateChanged, INotifyBuildComplete, INotifySold diff --git a/OpenRA.Mods.RA/Render/WithRotor.cs b/OpenRA.Mods.RA/Render/WithRotor.cs index 31e196bd14..25b8559e84 100755 --- a/OpenRA.Mods.RA/Render/WithRotor.cs +++ b/OpenRA.Mods.RA/Render/WithRotor.cs @@ -8,13 +8,16 @@ */ #endregion +using System; +using System.Collections.Generic; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { [Desc("Displays a helicopter rotor overlay.")] - public class WithRotorInfo : ITraitInfo, Requires, Requires + public class WithRotorInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires { [Desc("Sequence name to use when flying")] public readonly string Sequence = "rotor"; @@ -29,6 +32,18 @@ namespace OpenRA.Mods.RA.Render public readonly string Id = "rotor"; public object Create(ActorInitializer init) { return new WithRotor(init.self, this); } + + public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var facing = init.Contains() ? init.Get() : 0; + var anim = new Animation(init.World, image, () => facing); + anim.PlayRepeating(Sequence); + + var orientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)), facings); + var offset = body.LocalToWorld(Offset.Rotate(orientation)); + yield return new SpriteActorPreview(anim, offset, offset.Y + offset.Z + 1, p, rs.Scale); + } } public class WithRotor : ITick diff --git a/OpenRA.Mods.RA/Render/WithTurret.cs b/OpenRA.Mods.RA/Render/WithTurret.cs index 5de395019c..6541640c43 100755 --- a/OpenRA.Mods.RA/Render/WithTurret.cs +++ b/OpenRA.Mods.RA/Render/WithTurret.cs @@ -11,12 +11,13 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { [Desc("Renders barrels for units with the Turreted trait.")] - class WithTurretInfo : ITraitInfo, Requires, Requires, Requires + class WithTurretInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires, Requires { [Desc("Sequence name to use")] public readonly string Sequence = "turret"; @@ -31,6 +32,20 @@ namespace OpenRA.Mods.RA.Render public readonly bool Recoils = true; public object Create(ActorInitializer init) { return new WithTurret(init.self, this); } + + public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var t = init.Actor.Traits.WithInterface() + .First(tt => tt.Turret == Turret); + + var anim = new Animation(init.World, image, () => t.InitialFacing); + anim.Play(Sequence); + + var orientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(t.InitialFacing)), facings); + var offset = body.LocalToWorld(t.Offset.Rotate(orientation)); + yield return new SpriteActorPreview(anim, offset, offset.Y + offset.Z + 1, p, rs.Scale); + } } class WithTurret : ITick diff --git a/OpenRA.Mods.RA/Render/WithVoxelBarrel.cs b/OpenRA.Mods.RA/Render/WithVoxelBarrel.cs index adbe829e89..046be7ff1f 100755 --- a/OpenRA.Mods.RA/Render/WithVoxelBarrel.cs +++ b/OpenRA.Mods.RA/Render/WithVoxelBarrel.cs @@ -11,11 +11,12 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class WithVoxelBarrelInfo : ITraitInfo, Requires + public class WithVoxelBarrelInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires { [Desc("Voxel sequence name to use")] public readonly string Sequence = "barrel"; @@ -25,6 +26,22 @@ namespace OpenRA.Mods.RA.Render public readonly WVec LocalOffset = WVec.Zero; public object Create(ActorInitializer init) { return new WithVoxelBarrel(init.self, this); } + + public IEnumerable RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var armament = init.Actor.Traits.WithInterface() + .First(a => a.Name == Armament); + var t = init.Actor.Traits.WithInterface() + .First(tt => tt.Turret == armament.Turret); + + var voxel = VoxelProvider.GetVoxel(image, Sequence); + var turretOrientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(t.InitialFacing) - orientation.Yaw), facings); + var turretOffset = body.LocalToWorld(t.Offset.Rotate(orientation)); + + yield return new VoxelAnimation(voxel, () => turretOffset, () => new [] { turretOrientation, orientation }, + () => false, () => 0); + } } public class WithVoxelBarrel diff --git a/OpenRA.Mods.RA/Render/WithVoxelBody.cs b/OpenRA.Mods.RA/Render/WithVoxelBody.cs old mode 100755 new mode 100644 index af28a54528..430f4fb723 --- a/OpenRA.Mods.RA/Render/WithVoxelBody.cs +++ b/OpenRA.Mods.RA/Render/WithVoxelBody.cs @@ -9,18 +9,32 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { [Desc("Also returns a default selection size that is calculated automatically from the voxel dimensions.")] - public class WithVoxelBodyInfo : ITraitInfo, Requires + public class WithVoxelBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewVoxelsInfo, Requires { public readonly string Sequence = "idle"; public object Create(ActorInitializer init) { return new WithVoxelBody(init.self, this); } + + public IEnumerable RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var voxel = VoxelProvider.GetVoxel(image, "idle"); + var bodyOrientation = new[] { body.QuantizeOrientation(orientation, facings) }; + yield return new VoxelAnimation(voxel, () => WVec.Zero, + () => bodyOrientation, + () => false, () => 0); + } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) { return 0; } } public class WithVoxelBody : IAutoSelectionSize diff --git a/OpenRA.Mods.RA/Render/WithVoxelTurret.cs b/OpenRA.Mods.RA/Render/WithVoxelTurret.cs index 8adfd5c2ac..2568073b95 100755 --- a/OpenRA.Mods.RA/Render/WithVoxelTurret.cs +++ b/OpenRA.Mods.RA/Render/WithVoxelTurret.cs @@ -11,11 +11,12 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class WithVoxelTurretInfo : ITraitInfo, Requires + public class WithVoxelTurretInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires, Requires { [Desc("Voxel sequence name to use")] public readonly string Sequence = "turret"; @@ -24,6 +25,20 @@ namespace OpenRA.Mods.RA.Render public readonly string Turret = "primary"; public object Create(ActorInitializer init) { return new WithVoxelTurret(init.self, this); } + + public IEnumerable RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var t = init.Actor.Traits.WithInterface() + .First(tt => tt.Turret == Turret); + + var voxel = VoxelProvider.GetVoxel(image, Sequence); + var turretOffset = body.LocalToWorld(t.Offset.Rotate(orientation)); + + var turretBodyOrientation = new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(t.InitialFacing) - orientation.Yaw); + var turretOrientation = new[] { turretBodyOrientation, body.QuantizeOrientation(orientation, facings) }; + yield return new VoxelAnimation(voxel, () => turretOffset, () => turretOrientation, () => false, () => 0); + } } public class WithVoxelTurret diff --git a/OpenRA.Mods.RA/TraitsInterfaces.cs b/OpenRA.Mods.RA/TraitsInterfaces.cs index 3ec75b1301..50deaa7f60 100755 --- a/OpenRA.Mods.RA/TraitsInterfaces.cs +++ b/OpenRA.Mods.RA/TraitsInterfaces.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using OpenRA.Mods.RA.Activities; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA @@ -50,4 +51,5 @@ namespace OpenRA.Mods.RA public interface INotifyTransform { void BeforeTransform(Actor self); void OnTransform(Actor self); void AfterTransform(Actor toActor); } public interface INotifyAttack { void Attacking(Actor self, Target target, Armament a, Barrel barrel); } public interface INotifyChat { bool OnChat(string from, string message); } + public interface IRenderActorPreviewInfo { IEnumerable RenderPreview(ActorPreviewInitializer init); } } diff --git a/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs b/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs index 5109661dec..b230d39ab4 100755 --- a/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs +++ b/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs @@ -12,11 +12,12 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; +using OpenRA.Mods.RA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class WithVoxelUnloadBodyInfo : ITraitInfo, Requires + public class WithVoxelUnloadBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewVoxelsInfo, Requires { [Desc("Voxel sequence name to use when docked to a refinery.")] public readonly string UnloadSequence = "unload"; @@ -25,6 +26,17 @@ namespace OpenRA.Mods.RA.Render public readonly string IdleSequence = "idle"; public object Create(ActorInitializer init) { return new WithVoxelUnloadBody(init.self, this); } + + public IEnumerable RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) + { + var body = init.Actor.Traits.Get(); + var voxel = VoxelProvider.GetVoxel(image, "idle"); + yield return new VoxelAnimation(voxel, () => WVec.Zero, + () => new[]{ body.QuantizeOrientation(orientation, facings) }, + () => false, () => 0); + } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) { return 0; } } public class WithVoxelUnloadBody : IAutoSelectionSize diff --git a/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs b/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs index 90e8373c6e..8210f7f8d9 100644 --- a/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs +++ b/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs @@ -15,10 +15,12 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class WithVoxelWalkerBodyInfo : ITraitInfo, Requires, Requires + public class WithVoxelWalkerBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, Requires, Requires { public readonly int TickRate = 5; public object Create(ActorInitializer init) { return new WithVoxelWalkerBody(init.self, this); } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) { return 0; } } public class WithVoxelWalkerBody : IAutoSelectionSize, ITick diff --git a/mods/d2k/rules/atreides.yaml b/mods/d2k/rules/atreides.yaml index 8af2dcdd44..77871ddf1f 100644 --- a/mods/d2k/rules/atreides.yaml +++ b/mods/d2k/rules/atreides.yaml @@ -25,8 +25,6 @@ REFA: Inherits: ^REFINERY Buildable: Owner: atreides - RenderBuildingWarFactory: - Image: REFA BARRA: Inherits: ^BARRACKS @@ -76,15 +74,11 @@ LIGHTA: Inherits: ^LIGHT Buildable: Owner: atreides - RenderBuildingWarFactory: - Image: LIGHTA HEAVYA: Inherits: ^HEAVY Buildable: Owner: atreides - RenderBuildingWarFactory: - Image: HEAVYA RADARA: Inherits: ^RADAR diff --git a/mods/d2k/rules/harkonnen.yaml b/mods/d2k/rules/harkonnen.yaml index 93caf01a52..a919c07789 100644 --- a/mods/d2k/rules/harkonnen.yaml +++ b/mods/d2k/rules/harkonnen.yaml @@ -25,8 +25,6 @@ REFH: Inherits: ^REFINERY Buildable: Owner: harkonnen - RenderBuildingWarFactory: - Image: REFH BARRH: Inherits: ^BARRACKS @@ -53,15 +51,11 @@ LIGHTH: Inherits: ^LIGHT Buildable: Owner: harkonnen - RenderBuildingWarFactory: - Image: LIGHTH HEAVYH: Inherits: ^HEAVY Buildable: Owner: harkonnen - RenderBuildingWarFactory: - Image: HEAVYH RADARH: Inherits: ^RADAR diff --git a/mods/d2k/rules/ordos.yaml b/mods/d2k/rules/ordos.yaml index 2e8a17f450..2f7924d08e 100644 --- a/mods/d2k/rules/ordos.yaml +++ b/mods/d2k/rules/ordos.yaml @@ -25,8 +25,6 @@ REFO: Inherits: ^REFINERY Buildable: Owner: ordos - RenderBuildingWarFactory: - Image: REFO BARRO: Inherits: ^BARRACKS @@ -52,15 +50,11 @@ LIGHTO: Inherits: ^LIGHT Buildable: Owner: ordos - RenderBuildingWarFactory: - Image: LIGHTO HEAVYO: Inherits: ^HEAVY Buildable: Owner: ordos - RenderBuildingWarFactory: - Image: HEAVYO RADARO: Inherits: ^RADAR diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index 870c82dbc2..ce4fa51046 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -173,7 +173,6 @@ CONCRETEB: Type: Wood RevealsShroud: Range: 6c0 - -RenderBuilding: OreRefinery: DockOffset: 2,1 DockAngle: 160 @@ -195,6 +194,8 @@ CONCRETEB: Sequence: smoke Power: Amount: -30 + WithIdleOverlay@TOP: + Sequence: idle-top ^SILO: Inherits: ^Building @@ -251,7 +252,6 @@ CONCRETEB: Type: Wood RevealsShroud: Range: 4c0 - -RenderBuilding: RallyPoint: RallyPoint: 2,2 Exit@1: @@ -265,6 +265,8 @@ CONCRETEB: Prerequisite: Light WithProductionOverlay@WELDING: Sequence: production-welding + WithIdleOverlay@TOP: + Sequence: idle-top Power: Amount: -20 @@ -291,7 +293,6 @@ CONCRETEB: Type: Wood RevealsShroud: Range: 4c0 - -RenderBuilding: RallyPoint: RallyPoint: 0,3 Exit@1: @@ -305,6 +306,8 @@ CONCRETEB: Prerequisite: Heavy WithProductionOverlay@WELDING: Sequence: production-welding + WithIdleOverlay@TOP: + Sequence: idle-top Power: Amount: -30 @@ -724,8 +727,6 @@ PALACEC: HEAVYC: Inherits: ^HEAVY -Buildable: - RenderBuildingWarFactory: - Image: HEAVYC CONYARD: Tooltip: diff --git a/mods/d2k/sequences/structures.yaml b/mods/d2k/sequences/structures.yaml index 598f9ca001..6f1bf2a411 100644 --- a/mods/d2k/sequences/structures.yaml +++ b/mods/d2k/sequences/structures.yaml @@ -693,14 +693,6 @@ lighta: damaged-idle: DATA Start: 2673 Offset: -48,64 - build-top: DATA - Start: 2674 - Length: 1 - Offset: -48,64 - damaged-build-top: DATA - Start: 2675 - Length: 1 - Offset: -48,64 idle-top: DATA Start: 2674 Offset: -48,64 @@ -742,14 +734,6 @@ heavya: damaged-idle: DATA Start: 2518 Offset: -48,80 - build-top: DATA - Start: 2519 - Length: 1 - Offset: -48,80 - damaged-build-top: DATA - Start: 2520 - Length: 1 - Offset: -48,80 idle-top: DATA Start: 2519 Offset: -48,80 @@ -1104,14 +1088,6 @@ lighth: damaged-idle: DATA Start: 2833 Offset: -48,64 - build-top: DATA - Start: 2834 - Length: 1 - Offset: -48,64 - damaged-build-top: DATA - Start: 2835 - Length: 1 - Offset: -48,64 idle-top: DATA Start: 2834 Offset: -48,64 @@ -1153,14 +1129,6 @@ heavyh: damaged-idle: DATA Start: 2678 Offset: -48,80 - build-top: DATA - Start: 2679 - Length: 1 - Offset: -48,80 - damaged-build-top: DATA - Start: 2680 - Length: 1 - Offset: -48,80 idle-top: DATA Start: 2679 Offset: -48,80 @@ -1508,14 +1476,6 @@ lighto: damaged-idle: DATA Start: 2993 Offset: -48,64 - build-top: DATA - Start: 2994 - Length: 1 - Offset: -48,64 - damaged-build-top: DATA - Start: 2995 - Length: 1 - Offset: -48,64 idle-top: DATA Start: 2994 Offset: -48,64 @@ -1557,14 +1517,6 @@ heavyo: damaged-idle: DATA Start: 2838 Offset: -48,80 - build-top: DATA - Start: 2839 - Length: 1 - Offset: -48,80 - damaged-build-top: DATA - Start: 2840 - Length: 1 - Offset: -48,80 idle-top: DATA Start: 2839 Offset: -48,80 @@ -1677,14 +1629,6 @@ heavyc: # TODO: unused damaged-idle: DATA Start: 3001 Offset: -48,64 - build-top: DATA - Start: 3002 - Length: 1 - Offset: -48,64 - damaged-build-top: DATA - Start: 3003 - Length: 1 - Offset: -48,64 idle-top: DATA Start: 3002 Offset: -48,64