diff --git a/OpenRA.Game/Traits/LintAttributes.cs b/OpenRA.Game/Traits/LintAttributes.cs index 5a72b07a82..e65029bef7 100644 --- a/OpenRA.Game/Traits/LintAttributes.cs +++ b/OpenRA.Game/Traits/LintAttributes.cs @@ -25,4 +25,16 @@ namespace OpenRA.Traits [AttributeUsage(AttributeTargets.Field)] public sealed class VoiceReferenceAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Field)] + public sealed class SequenceReferenceAttribute : Attribute + { + public readonly string ImageReference; // the field name in the same trait info that contains the image name + public readonly bool Prefix; + public SequenceReferenceAttribute(string imageReference = null, bool prefix = false) + { + ImageReference = imageReference; + Prefix = prefix; + } + } } diff --git a/OpenRA.Mods.Common/Effects/Bullet.cs b/OpenRA.Mods.Common/Effects/Bullet.cs index 2a80aaca12..8ba7ae0186 100644 --- a/OpenRA.Mods.Common/Effects/Bullet.cs +++ b/OpenRA.Mods.Common/Effects/Bullet.cs @@ -27,6 +27,7 @@ namespace OpenRA.Mods.Common.Effects [Desc("Maximum offset at the maximum range.")] public readonly WRange Inaccuracy = WRange.Zero; public readonly string Image = null; + [SequenceReference("Image")] public readonly string Sequence = "idle"; public readonly string Palette = "effect"; public readonly bool Shadow = false; [Desc("Trail animation.")] @@ -138,7 +139,7 @@ namespace OpenRA.Mods.Common.Effects if (!string.IsNullOrEmpty(info.Trail) && --smokeTicks < 0) { var delayedPos = WPos.LerpQuadratic(args.Source, target, angle, ticks - info.TrailDelay, length); - world.AddFrameEndTask(w => w.Add(new Smoke(w, delayedPos, info.Trail, trailPalette))); + world.AddFrameEndTask(w => w.Add(new Smoke(w, delayedPos, info.Trail, trailPalette, info.Sequence))); smokeTicks = info.TrailInterval; } diff --git a/OpenRA.Mods.Common/Effects/Missile.cs b/OpenRA.Mods.Common/Effects/Missile.cs index 92dece6c26..cde08689ac 100644 --- a/OpenRA.Mods.Common/Effects/Missile.cs +++ b/OpenRA.Mods.Common/Effects/Missile.cs @@ -23,6 +23,7 @@ namespace OpenRA.Mods.Common.Effects class MissileInfo : IProjectileInfo { public readonly string Image = null; + [SequenceReference("Image")] public readonly string Sequence = "idle"; public readonly string Palette = "effect"; public readonly bool Shadow = false; [Desc("Projectile speed in WRange / tick")] @@ -171,7 +172,7 @@ namespace OpenRA.Mods.Common.Effects if (!string.IsNullOrEmpty(info.Trail) && --ticksToNextSmoke < 0) { - world.AddFrameEndTask(w => w.Add(new Smoke(w, pos - 3 * move / 2, info.Trail, trailPalette))); + world.AddFrameEndTask(w => w.Add(new Smoke(w, pos - 3 * move / 2, info.Trail, trailPalette, info.Sequence))); ticksToNextSmoke = info.TrailInterval; } diff --git a/OpenRA.Mods.Common/Effects/Parachute.cs b/OpenRA.Mods.Common/Effects/Parachute.cs index d58cbe57a3..526ef9a8a1 100644 --- a/OpenRA.Mods.Common/Effects/Parachute.cs +++ b/OpenRA.Mods.Common/Effects/Parachute.cs @@ -40,14 +40,14 @@ namespace OpenRA.Mods.Common.Effects if (parachuteSprite != null) { parachute = new Animation(cargo.World, parachuteSprite); - parachute.PlayThen("open", () => parachute.PlayRepeating("idle")); + parachute.PlayThen(parachutableInfo.ParachuteOpenSequence, () => parachute.PlayRepeating(parachutableInfo.ParachuteIdleSequence)); } var shadowSprite = parachutableInfo != null ? parachutableInfo.ShadowSequence : null; if (shadowSprite != null) { shadow = new Animation(cargo.World, shadowSprite); - shadow.PlayRepeating("idle"); + shadow.PlayRepeating(parachutableInfo.ParachuteIdleSequence); } if (parachutableInfo != null) diff --git a/OpenRA.Mods.Common/Effects/Smoke.cs b/OpenRA.Mods.Common/Effects/Smoke.cs index 65c4cec7ae..0f81ed1b33 100644 --- a/OpenRA.Mods.Common/Effects/Smoke.cs +++ b/OpenRA.Mods.Common/Effects/Smoke.cs @@ -21,14 +21,14 @@ namespace OpenRA.Mods.Common.Effects readonly Animation anim; readonly string palette; - public Smoke(World world, WPos pos, string trail, string palette) + public Smoke(World world, WPos pos, string trail, string palette, string sequence) { this.world = world; this.pos = pos; this.palette = palette; anim = new Animation(world, trail); - anim.PlayThen("idle", + anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this))); } diff --git a/OpenRA.Mods.Common/Lint/CheckSequences.cs b/OpenRA.Mods.Common/Lint/CheckSequences.cs index 41add1abcc..979c3219c9 100644 --- a/OpenRA.Mods.Common/Lint/CheckSequences.cs +++ b/OpenRA.Mods.Common/Lint/CheckSequences.cs @@ -9,7 +9,9 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; +using System.Reflection; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; @@ -17,9 +19,17 @@ namespace OpenRA.Mods.Common.Lint { class CheckSequences : ILintPass { + Action emitWarning; + + List sequenceDefinitions; + public void Run(Action emitError, Action emitWarning, Map map) { - var sequences = MiniYaml.MergeLiberal(map.SequenceDefinitions, Game.ModData.Manifest.Sequences.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); + this.emitWarning = emitWarning; + + sequenceDefinitions = MiniYaml.MergeLiberal(map.SequenceDefinitions, + Game.ModData.Manifest.Sequences.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); + var races = map.Rules.Actors["world"].Traits.WithInterface().Select(c => c.Race); foreach (var actorInfo in map.Rules.Actors) @@ -29,11 +39,76 @@ namespace OpenRA.Mods.Common.Lint foreach (var race in races) { var image = renderInfo.GetImage(actorInfo.Value, map.Rules.Sequences[map.Tileset], race); - if (!sequences.Any(s => s.Key == image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^")) + if (!sequenceDefinitions.Any(s => s.Key == image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^")) emitWarning("Sprite image {0} from actor {1} on tileset {2} using race {3} has no sequence definition." .F(image, actorInfo.Value.Name, map.Tileset, race)); } } + + foreach (var traitInfo in actorInfo.Value.Traits.WithInterface()) + { + var fields = traitInfo.GetType().GetFields(); + foreach (var field in fields) + { + if (field.HasAttribute()) + { + var sequences = LintExts.GetFieldValues(traitInfo, field, emitError); + foreach (var sequence in sequences) + { + if (string.IsNullOrEmpty(sequence)) + continue; + + var renderInfo = actorInfo.Value.Traits.WithInterface().FirstOrDefault(); + if (renderInfo == null) + continue; + + foreach (var race in races) + { + var sequenceReference = field.GetCustomAttributes(true).FirstOrDefault(); + if (sequenceReference != null && !string.IsNullOrEmpty(sequenceReference.ImageReference)) + { + var imageField = fields.FirstOrDefault(f => f.Name == sequenceReference.ImageReference); + if (imageField != null) + { + foreach (var imageOverride in LintExts.GetFieldValues(traitInfo, imageField, emitError)) + { + if (!string.IsNullOrEmpty(imageOverride) && !sequenceDefinitions.Any(s => s.Key == imageOverride.ToLowerInvariant())) + emitWarning("Custom sprite image {0} from actor {1} has no sequence definition.".F(imageOverride, actorInfo.Value.Name)); + else + CheckDefintions(imageOverride, sequenceReference, actorInfo, sequence, race, field, traitInfo); + } + } + } + else + { + var image = renderInfo.GetImage(actorInfo.Value, map.SequenceProvider, race); + CheckDefintions(image, sequenceReference, actorInfo, sequence, race, field, traitInfo); + } + } + } + } + } + } + } + } + + void CheckDefintions(string image, SequenceReferenceAttribute sequenceReference, + KeyValuePair actorInfo, string sequence, string race, FieldInfo field, ITraitInfo traitInfo) + { + var definitions = sequenceDefinitions.FirstOrDefault(n => n.Key == image.ToLowerInvariant()); + if (definitions != null) + { + if (sequenceReference != null && sequenceReference.Prefix) + { + if (!definitions.Value.Nodes.Any(n => n.Key.StartsWith(sequence))) + emitWarning("Sprite image {0} from actor {1} of faction {2} does not define sequence prefix {3} from field {4} of {5}" + .F(image, actorInfo.Value.Name, race, sequence, field.Name, traitInfo)); + } + else if (!definitions.Value.Nodes.Any(n => n.Key == sequence)) + { + emitWarning("Sprite image {0} from actor {1} of faction {2} does not define sequence {3} from field {4} of {5}" + .F(image, actorInfo.Value.Name, race, sequence, field.Name, traitInfo)); + } } } } diff --git a/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs b/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs index a54b1af6e0..6fdbbe743d 100644 --- a/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs +++ b/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs @@ -24,6 +24,8 @@ namespace OpenRA.Mods.Common.Traits [Desc("Chance (out of 100) the unit has to enter panic mode when attacked.")] public readonly int AttackPanicChance = 20; + [SequenceReference(null, true)] public readonly string PanicSequencePrefix = "panic-"; + public object Create(ActorInitializer init) { return new ScaredyCat(init.Self, this); } } @@ -36,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits bool Panicking { get { return panicStartedTick > 0; } } public bool IsModifyingSequence { get { return Panicking; } } - public string SequencePrefix { get { return "panic-"; } } + public string SequencePrefix { get { return info.PanicSequencePrefix; } } public ScaredyCat(Actor self, ScaredyCatInfo info) { diff --git a/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs b/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs index 8adf37a504..46e95ac595 100644 --- a/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs +++ b/OpenRA.Mods.Common/Traits/Infantry/TakeCover.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits public readonly WVec ProneOffset = new WVec(85, 0, -171); - public readonly string ProneSequencePrefix = "prone-"; + [SequenceReference(null, true)] public readonly string ProneSequencePrefix = "prone-"; public override object Create(ActorInitializer init) { return new TakeCover(init, this); } diff --git a/OpenRA.Mods.Common/Traits/Parachutable.cs b/OpenRA.Mods.Common/Traits/Parachutable.cs index 56d20afae1..f4e1213b95 100644 --- a/OpenRA.Mods.Common/Traits/Parachutable.cs +++ b/OpenRA.Mods.Common/Traits/Parachutable.cs @@ -19,16 +19,20 @@ namespace OpenRA.Mods.Common.Traits [Desc("If we land on invalid terrain for my actor type should we be killed?")] public readonly bool KilledOnImpassableTerrain = true; + [Desc("Group where Ground/WaterCorpseSequence is looked up.")] + public readonly string CorpseSequenceCollection = "explosion"; + public readonly string GroundImpactSound = null; - public readonly string GroundCorpseSequence = "corpse"; + [SequenceReference("CorpseSequenceCollection")] public readonly string GroundCorpseSequence = "corpse"; public readonly string GroundCorpsePalette = "effect"; public readonly string WaterImpactSound = null; - public readonly string WaterCorpseSequence = "small_splash"; + [SequenceReference("CorpseSequenceCollection")] public readonly string WaterCorpseSequence = null; public readonly string WaterCorpsePalette = "effect"; - [Desc("Requires the sub-sequences \"open\" and \"idle\".")] public readonly string ParachuteSequence = null; + [SequenceReference("ParachuteSequence")] public readonly string ParachuteOpenSequence = null; + [SequenceReference("ParachuteSequence")] public readonly string ParachuteIdleSequence = null; [Desc("Optional, otherwise defaults to the palette the actor is using.")] public readonly string ParachutePalette = null; diff --git a/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs b/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs index 932de424fc..f1f5104620 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs @@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits public class RenderBuildingChargeInfo : RenderBuildingInfo { [Desc("Sequence to use for building charge animation.")] - public readonly string ChargeSequence = "active"; + [SequenceReference] public readonly string ChargeSequence = "active"; public override object Create(ActorInitializer init) { return new RenderBuildingCharge(init, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/RenderHarvester.cs b/OpenRA.Mods.Common/Traits/Render/RenderHarvester.cs index ce47c21e2b..a3f8ca054c 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderHarvester.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderHarvester.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits { public readonly string[] ImagesByFullness = { "harv" }; - public readonly string HarvestSequence = "harvest"; + [SequenceReference("ImagesByFullness")] public readonly string HarvestSequence = "harvest"; public override object Create(ActorInitializer init) { return new RenderHarvester(init, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs b/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs index 249a34ca34..e53470d01a 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Basic render trait for immobile actors. Deprecated, use RenderSprites + WithSpriteBody instead.")] public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, Requires { - public readonly string Sequence = "idle"; + [SequenceReference] public readonly string Sequence = "idle"; public override object Create(ActorInitializer init) { return new RenderSimple(init, this); } diff --git a/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs b/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs index ac31eaa169..21470ded30 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs @@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits public string GetImage(ActorInfo actor, SequenceProvider sequenceProvider, string race) { - if (RaceImages != null) + if (RaceImages != null && !string.IsNullOrEmpty(race)) { string raceImage = null; if (RaceImages.TryGetValue(race, out raceImage) && sequenceProvider.HasSequence(raceImage)) diff --git a/OpenRA.Mods.Common/Traits/Render/WithActiveAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithActiveAnimation.cs index 6a4d93cd75..da1c054ff8 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithActiveAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithActiveAnimation.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits public class WithActiveAnimationInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "active"; + [SequenceReference] public readonly string Sequence = "active"; public readonly int Interval = 750; diff --git a/OpenRA.Mods.Common/Traits/Render/WithAttackAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithAttackAnimation.cs index b6c9958969..5e65c5d15c 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithAttackAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithAttackAnimation.cs @@ -20,13 +20,13 @@ namespace OpenRA.Mods.RA.Traits public readonly string Armament = "primary"; [Desc("Displayed while attacking.")] - public readonly string AttackSequence = null; + [SequenceReference] public readonly string AttackSequence = null; [Desc("Displayed while targeting.")] - public readonly string AimSequence = null; + [SequenceReference] public readonly string AimSequence = null; [Desc("Shown while reloading.")] - public readonly string ReloadPrefix = null; + [SequenceReference(null, true)] public readonly string ReloadPrefix = null; public object Create(ActorInitializer init) { return new WithAttackAnimation(init, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithBarrel.cs b/OpenRA.Mods.Common/Traits/Render/WithBarrel.cs index 123c13097f..fe11cab00a 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBarrel.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBarrel.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits class WithBarrelInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "barrel"; + [SequenceReference] public readonly string Sequence = "barrel"; [Desc("Armament to use for recoil")] public readonly string Armament = "primary"; diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs index 3e76028aa4..c5f90e386b 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingExplosion.cs @@ -18,8 +18,11 @@ namespace OpenRA.Mods.Common.Traits [Desc("Display explosions over the building footprint when it is destroyed.")] class WithBuildingExplosionInfo : ITraitInfo, Requires { + [Desc("Group where Sequence is looked up.")] + public readonly string SequenceCollection = "explosion"; + [Desc("Explosion sequence name to use")] - public readonly string Sequence = "building"; + [SequenceReference("SequenceCollection")] public readonly string Sequence = "building"; [Desc("Delay the explosions by this many ticks.")] public readonly int Delay = 0; diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs index feac110c32..783a3c6a4b 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs @@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits public class WithBuildingPlacedAnimationInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "build"; + [SequenceReference] public readonly string Sequence = "build"; public object Create(ActorInitializer init) { return new WithBuildingPlacedAnimation(init.Self, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs index e8e4deadae..f886e826a7 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits public class WithBuildingPlacedOverlayInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "crane-overlay"; + [SequenceReference] public readonly string Sequence = "crane-overlay"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs index a06554aebf..ce5a9eb6fa 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits public class WithChargeOverlayInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "active"; + [SequenceReference] public readonly string Sequence = "active"; [Desc("Custom palette name")] public readonly string Palette = null; diff --git a/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs b/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs index 0ea8683ebd..a44c17e0aa 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs @@ -23,12 +23,16 @@ namespace OpenRA.Mods.Common.Traits [Desc("Easteregg sequences to use in december.")] public readonly string[] XmasImages = { }; + [SequenceReference] public readonly string IdleSequence = "idle"; + public readonly string WaterSequence = null; + public readonly string LandSequence = null; + public object Create(ActorInitializer init) { return new WithCrateBody(init.Self, this); } public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) { var anim = new Animation(init.World, rs.Image, () => 0); - anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), "idle")); + anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), IdleSequence)); yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); } @@ -39,22 +43,27 @@ namespace OpenRA.Mods.Common.Traits { readonly Actor self; readonly Animation anim; + readonly WithCrateBodyInfo info; public WithCrateBody(Actor self, WithCrateBodyInfo info) { this.self = self; + this.info = info; + var rs = self.Trait(); var image = rs.GetImage(self); var images = info.XmasImages.Any() && DateTime.Today.Month == 12 ? info.XmasImages : new[] { image }; + anim = new Animation(self.World, images.Random(Game.CosmeticRandom)); - anim.Play("idle"); + anim.Play(info.IdleSequence); rs.Add(anim); } public void OnLanded() { - var seq = self.World.Map.GetTerrainInfo(self.Location).IsWater ? "water" : "land"; - anim.PlayRepeating(seq); + var sequence = self.World.Map.GetTerrainInfo(self.Location).IsWater ? info.WaterSequence : info.LandSequence; + if (!string.IsNullOrEmpty(sequence)) + anim.PlayRepeating(sequence); } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs index 2b5943620c..6be98a8294 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs @@ -19,8 +19,8 @@ namespace OpenRA.Mods.Common.Traits [Desc("This actor has a death animation.")] public class WithDeathAnimationInfo : ITraitInfo, Requires { - [Desc("Sequence to play when this actor is killed by a warhead.")] - public readonly string DeathSequence = "die"; + [Desc("Sequence prefix to play when this actor is killed by a warhead.")] + [SequenceReference(null, true)] public readonly string DeathSequence = "die"; [Desc("The palette used for `DeathSequence`.")] public readonly string DeathSequencePalette = "player"; @@ -29,10 +29,10 @@ namespace OpenRA.Mods.Common.Traits public readonly bool DeathPaletteIsPlayerPalette = true; [Desc("Should DeathType-specific sequences be used (sequence name = DeathSequence + DeathType).")] - public readonly bool UseDeathTypeSuffix = true; + public readonly bool UseDeathTypeSuffix = true; // TODO: check the complete sequence with lint rules [Desc("Sequence to play when this actor is crushed.")] - public readonly string CrushedSequence = "die-crushed"; + [SequenceReference] public readonly string CrushedSequence = null; [Desc("The palette used for `CrushedSequence`.")] public readonly string CrushedSequencePalette = "effect"; diff --git a/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs index c059a21351..7f9c155bcc 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits public class WithDockingOverlayInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "docking-overlay"; + [SequenceReference] public readonly string Sequence = "docking-overlay"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs index 7e03eb43fb..b8c494ed74 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits class WithHarvestAnimationInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "harvest"; + [SequenceReference] public readonly string Sequence = "harvest"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs index 4aa424ac43..2ad7cb7af5 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits public class WithIdleOverlayInfo : UpgradableTraitInfo, ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "idle-overlay"; + [SequenceReference] public readonly string Sequence = "idle-overlay"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs b/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs index 56dfdaec86..4ba8c30ea3 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs @@ -21,10 +21,11 @@ namespace OpenRA.Mods.Common.Traits { public readonly int MinIdleWaitTicks = 30; public readonly int MaxIdleWaitTicks = 110; - public readonly string MoveSequence = "run"; - public readonly string AttackSequence = "shoot"; - public readonly string[] IdleSequences = { }; - public readonly string[] StandSequences = { "stand" }; + + [SequenceReference] public readonly string MoveSequence = "run"; + [SequenceReference] public readonly string AttackSequence = null; + [SequenceReference] public readonly string[] IdleSequences = { }; + [SequenceReference] public readonly string[] StandSequences = { "stand" }; public virtual object Create(ActorInitializer init) { return new WithInfantryBody(init, this); } @@ -93,9 +94,11 @@ namespace OpenRA.Mods.Common.Traits public void Attacking(Actor self, Target target) { - state = AnimationState.Attacking; - if (DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, Info.AttackSequence))) + if (!string.IsNullOrEmpty(Info.AttackSequence) && DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, Info.AttackSequence))) + { + state = AnimationState.Attacking; DefaultAnimation.PlayThen(NormalizeInfantrySequence(self, Info.AttackSequence), () => state = AnimationState.Idle); + } } public void Attacking(Actor self, Target target, Armament a, Barrel barrel) diff --git a/OpenRA.Mods.Common/Traits/Render/WithMakeAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithMakeAnimation.cs index 367382dc5c..e12da66ff4 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithMakeAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithMakeAnimation.cs @@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Traits public class WithMakeAnimationInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "make"; + [SequenceReference] public readonly string Sequence = "make"; public object Create(ActorInitializer init) { return new WithMakeAnimation(init, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithMoveAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithMoveAnimation.cs index 67b391ef23..70f3fdc396 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithMoveAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithMoveAnimation.cs @@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits public class WithMoveAnimationInfo : ITraitInfo, Requires, Requires { [Desc("Displayed while moving.")] - public readonly string MoveSequence = "move"; + [SequenceReference] public readonly string MoveSequence = "move"; public object Create(ActorInitializer init) { return new WithMoveAnimation(init, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs index 311874126a..2bf8988f92 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits public class WithProductionOverlayInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "production-overlay"; + [SequenceReference] public readonly string Sequence = "production-overlay"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithRepairAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithRepairAnimation.cs index d38612c4f6..7e4eecd030 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithRepairAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithRepairAnimation.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits public class WithRepairAnimationInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "active"; + [SequenceReference] public readonly string Sequence = "active"; public readonly bool PauseOnLowPower = false; diff --git a/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs index 36efd06a7f..bb3d8b9b9b 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits public class WithRepairOverlayInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "active"; + [SequenceReference] public readonly string Sequence = "active"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithResources.cs b/OpenRA.Mods.Common/Traits/Render/WithResources.cs index ce9f984931..8f5540b957 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithResources.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithResources.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits class WithResourcesInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "resources"; + [SequenceReference] public readonly string Sequence = "resources"; public object Create(ActorInitializer init) { return new WithResources(init.Self, this); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithRotor.cs b/OpenRA.Mods.Common/Traits/Render/WithRotor.cs index a14ca751b6..8db1df98a1 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithRotor.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithRotor.cs @@ -20,10 +20,10 @@ namespace OpenRA.Mods.Common.Traits public class WithRotorInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires { [Desc("Sequence name to use when flying")] - public readonly string Sequence = "rotor"; + [SequenceReference] public readonly string Sequence = "rotor"; [Desc("Sequence name to use when landed")] - public readonly string GroundSequence = "slow-rotor"; + [SequenceReference] public readonly string GroundSequence = "slow-rotor"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.Common/Traits/Render/WithSmoke.cs b/OpenRA.Mods.Common/Traits/Render/WithSmoke.cs index 35e4d3fba9..deca3b6326 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSmoke.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSmoke.cs @@ -16,19 +16,26 @@ namespace OpenRA.Mods.Common.Traits [Desc("Renders an overlay when the actor is taking heavy damage.")] public class WithSmokeInfo : ITraitInfo, Requires { - [Desc("Needs to define \"idle\", \"loop\" and \"end\" sub-sequences.")] public readonly string Sequence = "smoke_m"; + [SequenceReference("Sequence")] public readonly string IdleSequence = "idle"; + [SequenceReference("Sequence")] public readonly string LoopSequence = "loop"; + [SequenceReference("Sequence")] public readonly string EndSequence = "end"; + public object Create(ActorInitializer init) { return new WithSmoke(init.Self, this); } } public class WithSmoke : INotifyDamage { + readonly WithSmokeInfo info; + readonly Animation anim; + bool isSmoking; - Animation anim; public WithSmoke(Actor self, WithSmokeInfo info) { + this.info = info; + var rs = self.Trait(); anim = new Animation(self.World, info.Sequence); @@ -42,9 +49,9 @@ namespace OpenRA.Mods.Common.Traits if (e.DamageState < DamageState.Heavy) return; isSmoking = true; - anim.PlayThen("idle", - () => anim.PlayThen("loop", - () => anim.PlayBackwardsThen("end", + anim.PlayThen(info.IdleSequence, + () => anim.PlayThen(info.LoopSequence, + () => anim.PlayBackwardsThen(info.EndSequence, () => isSmoking = false))); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs index 1aa72e50de..830c5154c4 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs @@ -21,10 +21,10 @@ namespace OpenRA.Mods.Common.Traits Requires { [Desc("Animation to play when the actor is created.")] - public readonly string StartSequence = null; + [SequenceReference] public readonly string StartSequence = null; [Desc("Animation to play when the actor is idle.")] - public readonly string Sequence = "idle"; + [SequenceReference] public readonly string Sequence = "idle"; public virtual object Create(ActorInitializer init) { return new WithSpriteBody(init, this); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithTurret.cs b/OpenRA.Mods.Common/Traits/Render/WithTurret.cs index 4859059000..ec2c8af1c8 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithTurret.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithTurret.cs @@ -21,10 +21,10 @@ namespace OpenRA.Mods.Common.Traits Requires, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "turret"; + [SequenceReference] public readonly string Sequence = "turret"; [Desc("Sequence name to use when prepared to fire")] - public readonly string AimSequence = null; + [SequenceReference] public readonly string AimSequence = null; [Desc("Turreted 'Turret' key to display")] public readonly string Turret = "primary"; diff --git a/OpenRA.Mods.Common/Traits/SmokeTrailWhenDamaged.cs b/OpenRA.Mods.Common/Traits/SmokeTrailWhenDamaged.cs index fb7736ad54..a62020d088 100644 --- a/OpenRA.Mods.Common/Traits/SmokeTrailWhenDamaged.cs +++ b/OpenRA.Mods.Common/Traits/SmokeTrailWhenDamaged.cs @@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Traits public readonly WVec Offset = WVec.Zero; public readonly int Interval = 3; public readonly string Sprite = "smokey"; + [SequenceReference("Sprite")] public readonly string Sequence = "idle"; public readonly string Palette = "effect"; public readonly DamageState MinDamage = DamageState.Heavy; @@ -46,7 +47,7 @@ namespace OpenRA.Mods.Common.Traits { var offset = info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation)); var pos = position + body.LocalToWorld(offset); - self.World.AddFrameEndTask(w => w.Add(new Smoke(w, pos, info.Sprite, info.Palette))); + self.World.AddFrameEndTask(w => w.Add(new Smoke(w, pos, info.Sprite, info.Palette, info.Sequence))); } ticks = info.Interval; diff --git a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs index 0711a7f1c2..7edf0ad3c5 100644 --- a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs @@ -28,6 +28,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Sprite sequence name")] public readonly string SmokeType = "smoke_m"; + [SequenceReference("SmokeType")] public readonly string SmokeSequence = "idle"; public readonly string SmokePalette = "effect"; @@ -99,7 +100,7 @@ namespace OpenRA.Mods.Common.Traits public void AddSmudge(CPos loc) { if (Game.CosmeticRandom.Next(0, 100) <= Info.SmokePercentage) - world.AddFrameEndTask(w => w.Add(new Smoke(w, world.Map.CenterOfCell(loc), Info.SmokeType, Info.SmokePalette))); + world.AddFrameEndTask(w => w.Add(new Smoke(w, world.Map.CenterOfCell(loc), Info.SmokeType, Info.SmokePalette, Info.SmokeSequence))); if (!dirty.ContainsKey(loc) && !tiles.ContainsKey(loc)) { diff --git a/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs index 671e572158..bb6c7c450d 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithAttackOverlay.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.D2k.Traits public class WithAttackOverlayInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = null; + [SequenceReference] public readonly string Sequence = null; [Desc("Custom palette name")] public readonly string Palette = null; diff --git a/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs index d53e8f5d88..dcdb7c914a 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.D2k.Traits public class WithCrumbleOverlayInfo : ITraitInfo, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "crumble-overlay"; + [SequenceReference] public readonly string Sequence = "crumble-overlay"; [Desc("Custom palette name")] public readonly string Palette = null; diff --git a/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs index a0da9af257..b150eff70a 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.D2k.Traits public class WithDeliveryOverlayInfo : ITraitInfo, Requires, Requires { [Desc("Sequence name to use")] - public readonly string Sequence = "active"; + [SequenceReference] public readonly string Sequence = "active"; [Desc("Position relative to body")] public readonly WVec Offset = WVec.Zero; diff --git a/OpenRA.Mods.RA/Traits/MadTank.cs b/OpenRA.Mods.RA/Traits/MadTank.cs index 886b08384d..e015a38ea9 100644 --- a/OpenRA.Mods.RA/Traits/MadTank.cs +++ b/OpenRA.Mods.RA/Traits/MadTank.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Traits { class MadTankInfo : ITraitInfo, Requires, Requires { - public readonly string ThumpSequence = "piston"; + [SequenceReference] public readonly string ThumpSequence = "piston"; public readonly int ThumpInterval = 8; [WeaponReference] public readonly string ThumpDamageWeapon = "MADTankThump"; diff --git a/OpenRA.Mods.RA/Traits/Render/RenderLandingCraft.cs b/OpenRA.Mods.RA/Traits/Render/RenderLandingCraft.cs index b7ac4b2fc1..27ed41eef2 100644 --- a/OpenRA.Mods.RA/Traits/Render/RenderLandingCraft.cs +++ b/OpenRA.Mods.RA/Traits/Render/RenderLandingCraft.cs @@ -17,8 +17,8 @@ namespace OpenRA.Mods.RA.Traits public class RenderLandingCraftInfo : RenderUnitInfo, Requires, Requires { public readonly string[] OpenTerrainTypes = { "Clear" }; - public readonly string OpenAnim = "open"; - public readonly string UnloadAnim = "unload"; + [SequenceReference] public readonly string OpenAnim = "open"; + [SequenceReference] public readonly string UnloadAnim = "unload"; public override object Create(ActorInitializer init) { return new RenderLandingCraft(init, this); } } diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index eda347fe1b..cf9a2db8fa 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -199,6 +199,7 @@ ExplosionDeath: 4 FireDeath: 5 TiberiumDeath: 6 + CrushedSequence: die-crushed AttackMove: Passenger: CargoType: Infantry @@ -273,6 +274,8 @@ CrushSound: squish2.aud Voiced: VoiceSet: CivilianMaleVoice + WithInfantryBody: + AttackSequence: shoot ^DINO: AppearsOnRadar: @@ -309,6 +312,7 @@ HiddenUnderFog: GivesExperience: WithInfantryBody: + AttackSequence: attack WithDeathAnimation: UseDeathTypeSuffix: false EditorAppearance: diff --git a/mods/cnc/rules/infantry.yaml b/mods/cnc/rules/infantry.yaml index 29bb40ef5b..5cabc2ed66 100644 --- a/mods/cnc/rules/infantry.yaml +++ b/mods/cnc/rules/infantry.yaml @@ -19,6 +19,7 @@ E1: WithInfantryBody: IdleSequences: idle1,idle2,idle3,idle4 StandSequences: stand, stand2 + AttackSequence: shoot E2: Inherits: ^Infantry @@ -42,6 +43,7 @@ E2: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: throw IdleSequences: idle1,idle2 StandSequences: stand, stand2 Explodes: @@ -72,6 +74,7 @@ E3: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand, stand2 @@ -101,6 +104,7 @@ E4: SplitFacings: true TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand, stand2 @@ -138,6 +142,7 @@ E5: WithInfantryBody: IdleSequences: idle1,idle2 StandSequences: stand, stand2 + AttackSequence: shoot E6: Inherits: ^Infantry @@ -202,6 +207,7 @@ RMBO: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2,idle3 StandSequences: stand, stand2 AnnounceOnBuild: diff --git a/mods/cnc/sequences/funpark.yaml b/mods/cnc/sequences/funpark.yaml index 5587e05364..33f376d2d5 100644 --- a/mods/cnc/sequences/funpark.yaml +++ b/mods/cnc/sequences/funpark.yaml @@ -8,7 +8,7 @@ steg: Start: 16 Length: 8 Facings: 8 - shoot: + attack: Start: 80 Length: 12 Facings: 8 @@ -27,7 +27,7 @@ trex: Start: 16 Length: 8 Facings: 8 - shoot: + attack: Start: 80 Length: 8 Facings: 8 @@ -46,7 +46,7 @@ tric: Start: 16 Length: 8 Facings: 8 - shoot: + attack: Start: 80 Length: 12 Facings: 8 @@ -65,7 +65,7 @@ rapt: Start: 16 Length: 8 Facings: 8 - shoot: + attack: Start: 80 Length: 8 Facings: 8 diff --git a/mods/cnc/sequences/infantry.yaml b/mods/cnc/sequences/infantry.yaml index 78a9313daf..1c4f513d00 100644 --- a/mods/cnc/sequences/infantry.yaml +++ b/mods/cnc/sequences/infantry.yaml @@ -165,7 +165,7 @@ e2: Length: 6 Facings: 8 Tick: 100 - shoot: + throw: Start: 64 Length: 20 Facings: 8 @@ -188,7 +188,7 @@ e2: Length: 4 Facings: 8 Tick: 100 - prone-shoot: + prone-throw: Start: 288 Length: 12 Facings: 8 diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index d87eee569d..7a0eb7d4e1 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -231,6 +231,7 @@ SoundDeath: 2 SmallExplosionDeath: 3 BulletDeath: 4 + CrushedSequence: die-crushed AutoTarget: AttackMove: Passenger: diff --git a/mods/d2k/rules/infantry.yaml b/mods/d2k/rules/infantry.yaml index 3b8124d976..2bd06f559b 100644 --- a/mods/d2k/rules/infantry.yaml +++ b/mods/d2k/rules/infantry.yaml @@ -17,6 +17,7 @@ rifle: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot AttractsWorms: Intensity: 120 @@ -71,6 +72,7 @@ bazooka: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot AttractsWorms: Intensity: 180 @@ -133,6 +135,7 @@ fremen: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot Cloak: InitialDelay: 250 CloakDelay: 250 @@ -164,6 +167,7 @@ grenadier: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: throw IdleSequences: idle Explodes: Weapon: UnitExplodeSmall @@ -190,6 +194,7 @@ sardaukar: Range: 6c0 TakeCover: WithInfantryBody: + AttackSequence: shoot Armament@PRIMARY: Weapon: Vulcan Armament@SECONDARY: diff --git a/mods/d2k/sequences/infantry.yaml b/mods/d2k/sequences/infantry.yaml index ae052c362f..92ae95cffe 100644 --- a/mods/d2k/sequences/infantry.yaml +++ b/mods/d2k/sequences/infantry.yaml @@ -427,7 +427,7 @@ grenadier: # 2502 - 2749 in 1.06 DATA.R8 Length: 6 Facings: 8 Tick: 120 - shoot: grenadier.shp + throw: grenadier.shp Start: 56 Length: 6 Facings: 8 @@ -458,7 +458,7 @@ grenadier: # 2502 - 2749 in 1.06 DATA.R8 Length: 4 Facings: 8 Tick: 120 - prone-shoot: grenadier.shp + prone-throw: grenadier.shp Start: 136 Length: 5 Facings: 8 diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 77ed4c8a75..faddb3dc78 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -150,6 +150,8 @@ ParachuteOffset: 0,0,200 KilledOnImpassableTerrain: true ParachuteSequence: parach + ParachuteOpenSequence: open + ParachuteIdleSequence: idle ShadowSequence: GroundCorpseSequence: GroundCorpsePalette: @@ -199,6 +201,7 @@ ExplosionDeath: 4 FireDeath: 5 ElectricityDeath: 6 + CrushedSequence: die-crushed AutoTarget: AttackMove: Passenger: @@ -238,9 +241,12 @@ ParachuteOffset: 0,0,427 KilledOnImpassableTerrain: true ParachuteSequence: parach + ParachuteOpenSequence: open + ParachuteIdleSequence: idle ShadowSequence: parach-shadow GroundImpactSound: squishy2.aud WaterImpactSound: splash9.aud + WaterCorpseSequence: small_splash Cloneable: Types: Infantry MustBeDestroyed: @@ -666,9 +672,16 @@ Image: scrate WithCrateBody: XmasImages: xcratea, xcrateb, xcratec, xcrated + LandSequence: land + WaterSequence: water + Selectable: + Selectable: false + Bounds: 15,15,-1,-1 Parachutable: KilledOnImpassableTerrain: false ParachuteSequence: parach + ParachuteOpenSequence: open + ParachuteIdleSequence: idle Passenger: CustomSelectionSize: CustomBounds: 16,16 diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index d0b4c516d9..3fc6b8faf4 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -35,12 +35,14 @@ DOG: TargetableUnit: TargetTypes: Ground, Infantry WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 IgnoresDisguise: DetectCloaked: Range: 5 Voiced: VoiceSet: DogVoice + -TakeCover: E1: Inherits: ^Infantry @@ -67,6 +69,7 @@ E1: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand,stand2 @@ -97,6 +100,7 @@ E2: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: throw IdleSequences: idle1,idle2 StandSequences: stand,stand2 Explodes: @@ -131,6 +135,7 @@ E3: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand,stand2 @@ -160,6 +165,7 @@ E4: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand,stand2 @@ -226,6 +232,7 @@ SPY: -AutoTarget: -WithInfantryBody: WithDisguisingInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand,stand2 Armament: @@ -288,6 +295,7 @@ E7: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 AnnounceOnBuild: AnnounceOnKill: @@ -363,7 +371,7 @@ MECH: -AutoTarget: WithInfantryBody: IdleSequences: idle1,idle2 - AttackSequence: heal + AttackSequence: repair Voiced: VoiceSet: MechanicVoice @@ -434,6 +442,7 @@ GNRL: Voice: Move Voiced: VoiceSet: StavrosVoice + -ScaredyCat: THF: Inherits: ^Infantry @@ -519,6 +528,7 @@ SHOK: Voice: Move TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand,stand2 Voiced: @@ -555,6 +565,7 @@ SNIPER: AttackFrontal: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 StandSequences: stand,stand2 Cloak: @@ -585,10 +596,13 @@ Zombie: AutoTarget: ScanRadius: 5 AttackFrontal: + WithInfantryBody: + AttackSequence: bite Armament: Weapon: claw Voiced: VoiceSet: AntVoice + -TakeCover: Ant: Inherits: ^Infantry @@ -615,6 +629,8 @@ Ant: AutoTarget: ScanRadius: 5 AttackFrontal: + WithInfantryBody: + AttackSequence: bite Armament: Weapon: mandible TargetableUnit: @@ -623,4 +639,5 @@ Ant: UseDeathTypeSuffix: false Voiced: VoiceSet: AntVoice + -TakeCover: diff --git a/mods/ra/sequences/infantry.yaml b/mods/ra/sequences/infantry.yaml index 151823d0d1..18aad29ebf 100644 --- a/mods/ra/sequences/infantry.yaml +++ b/mods/ra/sequences/infantry.yaml @@ -355,7 +355,7 @@ mech: Length: 6 Facings: 8 Tick: 100 - heal: + repair: Start: 56 Length: 58 Tick: 120 @@ -422,7 +422,7 @@ e2: Length: 6 Facings: 8 Tick: 80 - shoot: + throw: Start: 64 Length: 20 Facings: 8 @@ -472,7 +472,7 @@ e2: Length: 4 Facings: 8 Tick: 80 - prone-shoot: + prone-throw: Start: 288 Length: 12 Facings: 8 @@ -1278,7 +1278,7 @@ zombie: Start: 16 Length: 6 Facings: 8 - shoot: + bite: Start: 64 Length: 4 Facings: 8 @@ -1327,7 +1327,7 @@ ant: Start: 8 Length: 8 Facings: 8 - shoot: + bite: Start: 72 Length: 4 Facings: 8 diff --git a/mods/ts/rules/civilian-infantry.yaml b/mods/ts/rules/civilian-infantry.yaml index 45f1d34060..d00f51ed02 100644 --- a/mods/ts/rules/civilian-infantry.yaml +++ b/mods/ts/rules/civilian-infantry.yaml @@ -43,6 +43,7 @@ UMAGON: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 CHAMSPY: @@ -91,6 +92,7 @@ MUTANT: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 MWMN: @@ -115,6 +117,7 @@ MWMN: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 MUTANT3: @@ -139,6 +142,7 @@ MUTANT3: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 TRATOS: @@ -160,6 +164,7 @@ TRATOS: TakeCover: -AutoTarget: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 OXANNA: @@ -179,6 +184,7 @@ OXANNA: TakeCover: -AutoTarget: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 SLAV: @@ -198,6 +204,7 @@ SLAV: TakeCover: -AutoTarget: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 DOGGIE: @@ -228,6 +235,7 @@ DOGGIE: WanderMoveRadius: 2 MinMoveDelayInTicks: 25 MaxMoveDelayInTicks: 45 + -TakeCover: VISSML: Inherits: ^Viceroid @@ -264,6 +272,8 @@ VISLRG: CIV1: Inherits: ^CivilianInfantry + WithInfantryBody: + AttackSequence: shoot Armament: Weapon: Pistola AttackFrontal: @@ -275,6 +285,8 @@ CIV2: CIV3: Inherits: ^CivilianInfantry + WithInfantryBody: + AttackSequence: shoot Armament: Weapon: Pistola AttackFrontal: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index b4b0a5f050..b737f7abb8 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -301,6 +301,8 @@ Types: CivilianInfantry -TakeCover: WithInfantryBody: + WithDeathAnimation: + CrushedSequence: die-crushed ScaredyCat: -MustBeDestroyed: diff --git a/mods/ts/rules/gdi-infantry.yaml b/mods/ts/rules/gdi-infantry.yaml index cf8aa68a23..8349380f0b 100644 --- a/mods/ts/rules/gdi-infantry.yaml +++ b/mods/ts/rules/gdi-infantry.yaml @@ -83,6 +83,7 @@ JUMPJET: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot GHOST: Inherits: ^Infantry @@ -119,5 +120,6 @@ GHOST: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 diff --git a/mods/ts/rules/nod-infantry.yaml b/mods/ts/rules/nod-infantry.yaml index 79c386922e..67fee77475 100644 --- a/mods/ts/rules/nod-infantry.yaml +++ b/mods/ts/rules/nod-infantry.yaml @@ -22,6 +22,7 @@ E3: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 CYBORG: @@ -56,10 +57,12 @@ CYBORG: AttackFrontal: Voice: Attack WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 WithPermanentInjury: SelectionDecorations: VisualBounds: 16,31,0,-10 + -TakeCover: CYC2: Inherits: ^Infantry @@ -95,10 +98,12 @@ CYC2: AttackFrontal: Voice: Attack WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 WithPermanentInjury: SelectionDecorations: VisualBounds: 16,32,-1,-12 + -TakeCover: MHIJACK: Inherits: ^Infantry @@ -126,5 +131,6 @@ MHIJACK: -AutoTarget: TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 diff --git a/mods/ts/rules/shared-infantry.yaml b/mods/ts/rules/shared-infantry.yaml index c21a6731bd..af286f2e41 100644 --- a/mods/ts/rules/shared-infantry.yaml +++ b/mods/ts/rules/shared-infantry.yaml @@ -26,6 +26,7 @@ E1: Voice: Attack TakeCover: WithInfantryBody: + AttackSequence: shoot IdleSequences: idle1,idle2 ENGINEER: diff --git a/mods/ts/sequences/infantry.yaml b/mods/ts/sequences/infantry.yaml index 878c2b7e1b..975c3c861c 100644 --- a/mods/ts/sequences/infantry.yaml +++ b/mods/ts/sequences/infantry.yaml @@ -111,12 +111,13 @@ e2: ShadowStart: 451 Tick: 800 ZOffset: -511 - shoot: + throw: Start: 164 Length: 6 Facings: 8 ShadowStart: 456 - prone-shoot: + prone-throw: + Tick: 80 Start: 212 Length: 6 Facings: 8