check for missing sequence entries using lint

This commit is contained in:
Matthias Mailänder
2015-05-24 14:24:09 +02:00
parent 7424f32b2f
commit 7faebe874a
59 changed files with 273 additions and 84 deletions

View File

@@ -25,4 +25,16 @@ namespace OpenRA.Traits
[AttributeUsage(AttributeTargets.Field)] [AttributeUsage(AttributeTargets.Field)]
public sealed class VoiceReferenceAttribute : Attribute { } 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;
}
}
} }

View File

@@ -27,6 +27,7 @@ namespace OpenRA.Mods.Common.Effects
[Desc("Maximum offset at the maximum range.")] [Desc("Maximum offset at the maximum range.")]
public readonly WRange Inaccuracy = WRange.Zero; public readonly WRange Inaccuracy = WRange.Zero;
public readonly string Image = null; public readonly string Image = null;
[SequenceReference("Image")] public readonly string Sequence = "idle";
public readonly string Palette = "effect"; public readonly string Palette = "effect";
public readonly bool Shadow = false; public readonly bool Shadow = false;
[Desc("Trail animation.")] [Desc("Trail animation.")]
@@ -138,7 +139,7 @@ namespace OpenRA.Mods.Common.Effects
if (!string.IsNullOrEmpty(info.Trail) && --smokeTicks < 0) if (!string.IsNullOrEmpty(info.Trail) && --smokeTicks < 0)
{ {
var delayedPos = WPos.LerpQuadratic(args.Source, target, angle, ticks - info.TrailDelay, length); 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; smokeTicks = info.TrailInterval;
} }

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Mods.Common.Effects
class MissileInfo : IProjectileInfo class MissileInfo : IProjectileInfo
{ {
public readonly string Image = null; public readonly string Image = null;
[SequenceReference("Image")] public readonly string Sequence = "idle";
public readonly string Palette = "effect"; public readonly string Palette = "effect";
public readonly bool Shadow = false; public readonly bool Shadow = false;
[Desc("Projectile speed in WRange / tick")] [Desc("Projectile speed in WRange / tick")]
@@ -171,7 +172,7 @@ namespace OpenRA.Mods.Common.Effects
if (!string.IsNullOrEmpty(info.Trail) && --ticksToNextSmoke < 0) 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; ticksToNextSmoke = info.TrailInterval;
} }

View File

@@ -40,14 +40,14 @@ namespace OpenRA.Mods.Common.Effects
if (parachuteSprite != null) if (parachuteSprite != null)
{ {
parachute = new Animation(cargo.World, parachuteSprite); 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; var shadowSprite = parachutableInfo != null ? parachutableInfo.ShadowSequence : null;
if (shadowSprite != null) if (shadowSprite != null)
{ {
shadow = new Animation(cargo.World, shadowSprite); shadow = new Animation(cargo.World, shadowSprite);
shadow.PlayRepeating("idle"); shadow.PlayRepeating(parachutableInfo.ParachuteIdleSequence);
} }
if (parachutableInfo != null) if (parachutableInfo != null)

View File

@@ -21,14 +21,14 @@ namespace OpenRA.Mods.Common.Effects
readonly Animation anim; readonly Animation anim;
readonly string palette; 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.world = world;
this.pos = pos; this.pos = pos;
this.palette = palette; this.palette = palette;
anim = new Animation(world, trail); anim = new Animation(world, trail);
anim.PlayThen("idle", anim.PlayThen(sequence,
() => world.AddFrameEndTask(w => w.Remove(this))); () => world.AddFrameEndTask(w => w.Remove(this)));
} }

View File

@@ -9,7 +9,9 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits; using OpenRA.Traits;
@@ -17,9 +19,17 @@ namespace OpenRA.Mods.Common.Lint
{ {
class CheckSequences : ILintPass class CheckSequences : ILintPass
{ {
Action<string> emitWarning;
List<MiniYamlNode> sequenceDefinitions;
public void Run(Action<string> emitError, Action<string> emitWarning, Map map) public void Run(Action<string> emitError, Action<string> 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<CountryInfo>().Select(c => c.Race); var races = map.Rules.Actors["world"].Traits.WithInterface<CountryInfo>().Select(c => c.Race);
foreach (var actorInfo in map.Rules.Actors) foreach (var actorInfo in map.Rules.Actors)
@@ -29,11 +39,76 @@ namespace OpenRA.Mods.Common.Lint
foreach (var race in races) foreach (var race in races)
{ {
var image = renderInfo.GetImage(actorInfo.Value, map.Rules.Sequences[map.Tileset], race); 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." 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)); .F(image, actorInfo.Value.Name, map.Tileset, race));
} }
} }
foreach (var traitInfo in actorInfo.Value.Traits.WithInterface<ITraitInfo>())
{
var fields = traitInfo.GetType().GetFields();
foreach (var field in fields)
{
if (field.HasAttribute<SequenceReferenceAttribute>())
{
var sequences = LintExts.GetFieldValues(traitInfo, field, emitError);
foreach (var sequence in sequences)
{
if (string.IsNullOrEmpty(sequence))
continue;
var renderInfo = actorInfo.Value.Traits.WithInterface<RenderSpritesInfo>().FirstOrDefault();
if (renderInfo == null)
continue;
foreach (var race in races)
{
var sequenceReference = field.GetCustomAttributes<SequenceReferenceAttribute>(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<string, ActorInfo> 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));
}
} }
} }
} }

View File

@@ -24,6 +24,8 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Chance (out of 100) the unit has to enter panic mode when attacked.")] [Desc("Chance (out of 100) the unit has to enter panic mode when attacked.")]
public readonly int AttackPanicChance = 20; public readonly int AttackPanicChance = 20;
[SequenceReference(null, true)] public readonly string PanicSequencePrefix = "panic-";
public object Create(ActorInitializer init) { return new ScaredyCat(init.Self, this); } 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; } } bool Panicking { get { return panicStartedTick > 0; } }
public bool IsModifyingSequence { get { return Panicking; } } 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) public ScaredyCat(Actor self, ScaredyCatInfo info)
{ {

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits
public readonly WVec ProneOffset = new WVec(85, 0, -171); 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); } public override object Create(ActorInitializer init) { return new TakeCover(init, this); }

View File

@@ -19,16 +19,20 @@ namespace OpenRA.Mods.Common.Traits
[Desc("If we land on invalid terrain for my actor type should we be killed?")] [Desc("If we land on invalid terrain for my actor type should we be killed?")]
public readonly bool KilledOnImpassableTerrain = true; 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 GroundImpactSound = null;
public readonly string GroundCorpseSequence = "corpse"; [SequenceReference("CorpseSequenceCollection")] public readonly string GroundCorpseSequence = "corpse";
public readonly string GroundCorpsePalette = "effect"; public readonly string GroundCorpsePalette = "effect";
public readonly string WaterImpactSound = null; public readonly string WaterImpactSound = null;
public readonly string WaterCorpseSequence = "small_splash"; [SequenceReference("CorpseSequenceCollection")] public readonly string WaterCorpseSequence = null;
public readonly string WaterCorpsePalette = "effect"; public readonly string WaterCorpsePalette = "effect";
[Desc("Requires the sub-sequences \"open\" and \"idle\".")]
public readonly string ParachuteSequence = null; 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.")] [Desc("Optional, otherwise defaults to the palette the actor is using.")]
public readonly string ParachutePalette = null; public readonly string ParachutePalette = null;

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits
public class RenderBuildingChargeInfo : RenderBuildingInfo public class RenderBuildingChargeInfo : RenderBuildingInfo
{ {
[Desc("Sequence to use for building charge animation.")] [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); } public override object Create(ActorInitializer init) { return new RenderBuildingCharge(init, this); }
} }

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
public readonly string[] ImagesByFullness = { "harv" }; 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); } public override object Create(ActorInitializer init) { return new RenderHarvester(init, this); }
} }

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Basic render trait for immobile actors. Deprecated, use RenderSprites + WithSpriteBody instead.")] [Desc("Basic render trait for immobile actors. Deprecated, use RenderSprites + WithSpriteBody instead.")]
public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, Requires<IBodyOrientationInfo> public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, Requires<IBodyOrientationInfo>
{ {
public readonly string Sequence = "idle"; [SequenceReference] public readonly string Sequence = "idle";
public override object Create(ActorInitializer init) { return new RenderSimple(init, this); } public override object Create(ActorInitializer init) { return new RenderSimple(init, this); }

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits
public string GetImage(ActorInfo actor, SequenceProvider sequenceProvider, string race) public string GetImage(ActorInfo actor, SequenceProvider sequenceProvider, string race)
{ {
if (RaceImages != null) if (RaceImages != null && !string.IsNullOrEmpty(race))
{ {
string raceImage = null; string raceImage = null;
if (RaceImages.TryGetValue(race, out raceImage) && sequenceProvider.HasSequence(raceImage)) if (RaceImages.TryGetValue(race, out raceImage) && sequenceProvider.HasSequence(raceImage))

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithActiveAnimationInfo : ITraitInfo, Requires<RenderBuildingInfo> public class WithActiveAnimationInfo : ITraitInfo, Requires<RenderBuildingInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "active"; [SequenceReference] public readonly string Sequence = "active";
public readonly int Interval = 750; public readonly int Interval = 750;

View File

@@ -20,13 +20,13 @@ namespace OpenRA.Mods.RA.Traits
public readonly string Armament = "primary"; public readonly string Armament = "primary";
[Desc("Displayed while attacking.")] [Desc("Displayed while attacking.")]
public readonly string AttackSequence = null; [SequenceReference] public readonly string AttackSequence = null;
[Desc("Displayed while targeting.")] [Desc("Displayed while targeting.")]
public readonly string AimSequence = null; [SequenceReference] public readonly string AimSequence = null;
[Desc("Shown while reloading.")] [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); } public object Create(ActorInitializer init) { return new WithAttackAnimation(init, this); }
} }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits
class WithBarrelInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> class WithBarrelInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "barrel"; [SequenceReference] public readonly string Sequence = "barrel";
[Desc("Armament to use for recoil")] [Desc("Armament to use for recoil")]
public readonly string Armament = "primary"; public readonly string Armament = "primary";

View File

@@ -18,8 +18,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Display explosions over the building footprint when it is destroyed.")] [Desc("Display explosions over the building footprint when it is destroyed.")]
class WithBuildingExplosionInfo : ITraitInfo, Requires<BuildingInfo> class WithBuildingExplosionInfo : ITraitInfo, Requires<BuildingInfo>
{ {
[Desc("Group where Sequence is looked up.")]
public readonly string SequenceCollection = "explosion";
[Desc("Explosion sequence name to use")] [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.")] [Desc("Delay the explosions by this many ticks.")]
public readonly int Delay = 0; public readonly int Delay = 0;

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithBuildingPlacedAnimationInfo : ITraitInfo, Requires<RenderSimpleInfo> public class WithBuildingPlacedAnimationInfo : ITraitInfo, Requires<RenderSimpleInfo>
{ {
[Desc("Sequence name to use")] [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); } public object Create(ActorInitializer init) { return new WithBuildingPlacedAnimation(init.Self, this); }
} }

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithBuildingPlacedOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithBuildingPlacedOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "crane-overlay"; [SequenceReference] public readonly string Sequence = "crane-overlay";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithChargeOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo> public class WithChargeOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "active"; [SequenceReference] public readonly string Sequence = "active";
[Desc("Custom palette name")] [Desc("Custom palette name")]
public readonly string Palette = null; public readonly string Palette = null;

View File

@@ -23,12 +23,16 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Easteregg sequences to use in december.")] [Desc("Easteregg sequences to use in december.")]
public readonly string[] XmasImages = { }; 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 object Create(ActorInitializer init) { return new WithCrateBody(init.Self, this); }
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
{ {
var anim = new Animation(init.World, rs.Image, () => 0); 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); yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
} }
@@ -39,22 +43,27 @@ namespace OpenRA.Mods.Common.Traits
{ {
readonly Actor self; readonly Actor self;
readonly Animation anim; readonly Animation anim;
readonly WithCrateBodyInfo info;
public WithCrateBody(Actor self, WithCrateBodyInfo info) public WithCrateBody(Actor self, WithCrateBodyInfo info)
{ {
this.self = self; this.self = self;
this.info = info;
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var image = rs.GetImage(self); var image = rs.GetImage(self);
var images = info.XmasImages.Any() && DateTime.Today.Month == 12 ? info.XmasImages : new[] { image }; var images = info.XmasImages.Any() && DateTime.Today.Month == 12 ? info.XmasImages : new[] { image };
anim = new Animation(self.World, images.Random(Game.CosmeticRandom)); anim = new Animation(self.World, images.Random(Game.CosmeticRandom));
anim.Play("idle"); anim.Play(info.IdleSequence);
rs.Add(anim); rs.Add(anim);
} }
public void OnLanded() public void OnLanded()
{ {
var seq = self.World.Map.GetTerrainInfo(self.Location).IsWater ? "water" : "land"; var sequence = self.World.Map.GetTerrainInfo(self.Location).IsWater ? info.WaterSequence : info.LandSequence;
anim.PlayRepeating(seq); if (!string.IsNullOrEmpty(sequence))
anim.PlayRepeating(sequence);
} }
} }
} }

View File

@@ -19,8 +19,8 @@ namespace OpenRA.Mods.Common.Traits
[Desc("This actor has a death animation.")] [Desc("This actor has a death animation.")]
public class WithDeathAnimationInfo : ITraitInfo, Requires<RenderSpritesInfo> public class WithDeathAnimationInfo : ITraitInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Sequence to play when this actor is killed by a warhead.")] [Desc("Sequence prefix to play when this actor is killed by a warhead.")]
public readonly string DeathSequence = "die"; [SequenceReference(null, true)] public readonly string DeathSequence = "die";
[Desc("The palette used for `DeathSequence`.")] [Desc("The palette used for `DeathSequence`.")]
public readonly string DeathSequencePalette = "player"; public readonly string DeathSequencePalette = "player";
@@ -29,10 +29,10 @@ namespace OpenRA.Mods.Common.Traits
public readonly bool DeathPaletteIsPlayerPalette = true; public readonly bool DeathPaletteIsPlayerPalette = true;
[Desc("Should DeathType-specific sequences be used (sequence name = DeathSequence + DeathType).")] [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.")] [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`.")] [Desc("The palette used for `CrushedSequence`.")]
public readonly string CrushedSequencePalette = "effect"; public readonly string CrushedSequencePalette = "effect";

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithDockingOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithDockingOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "docking-overlay"; [SequenceReference] public readonly string Sequence = "docking-overlay";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits
class WithHarvestAnimationInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> class WithHarvestAnimationInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "harvest"; [SequenceReference] public readonly string Sequence = "harvest";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithIdleOverlayInfo : UpgradableTraitInfo, ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithIdleOverlayInfo : UpgradableTraitInfo, ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "idle-overlay"; [SequenceReference] public readonly string Sequence = "idle-overlay";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -21,10 +21,11 @@ namespace OpenRA.Mods.Common.Traits
{ {
public readonly int MinIdleWaitTicks = 30; public readonly int MinIdleWaitTicks = 30;
public readonly int MaxIdleWaitTicks = 110; public readonly int MaxIdleWaitTicks = 110;
public readonly string MoveSequence = "run";
public readonly string AttackSequence = "shoot"; [SequenceReference] public readonly string MoveSequence = "run";
public readonly string[] IdleSequences = { }; [SequenceReference] public readonly string AttackSequence = null;
public readonly string[] StandSequences = { "stand" }; [SequenceReference] public readonly string[] IdleSequences = { };
[SequenceReference] public readonly string[] StandSequences = { "stand" };
public virtual object Create(ActorInitializer init) { return new WithInfantryBody(init, this); } 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) public void Attacking(Actor self, Target target)
{ {
state = AnimationState.Attacking; if (!string.IsNullOrEmpty(Info.AttackSequence) && DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, Info.AttackSequence)))
if (DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, Info.AttackSequence))) {
state = AnimationState.Attacking;
DefaultAnimation.PlayThen(NormalizeInfantrySequence(self, Info.AttackSequence), () => state = AnimationState.Idle); DefaultAnimation.PlayThen(NormalizeInfantrySequence(self, Info.AttackSequence), () => state = AnimationState.Idle);
}
} }
public void Attacking(Actor self, Target target, Armament a, Barrel barrel) public void Attacking(Actor self, Target target, Armament a, Barrel barrel)

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithMakeAnimationInfo : ITraitInfo, Requires<BuildingInfo>, Requires<RenderBuildingInfo> public class WithMakeAnimationInfo : ITraitInfo, Requires<BuildingInfo>, Requires<RenderBuildingInfo>
{ {
[Desc("Sequence name to use")] [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); } public object Create(ActorInitializer init) { return new WithMakeAnimation(init, this); }
} }

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithMoveAnimationInfo : ITraitInfo, Requires<WithFacingSpriteBodyInfo>, Requires<IMoveInfo> public class WithMoveAnimationInfo : ITraitInfo, Requires<WithFacingSpriteBodyInfo>, Requires<IMoveInfo>
{ {
[Desc("Displayed while moving.")] [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); } public object Create(ActorInitializer init) { return new WithMoveAnimation(init, this); }
} }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithProductionOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithProductionOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "production-overlay"; [SequenceReference] public readonly string Sequence = "production-overlay";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithRepairAnimationInfo : ITraitInfo, Requires<RenderBuildingInfo> public class WithRepairAnimationInfo : ITraitInfo, Requires<RenderBuildingInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "active"; [SequenceReference] public readonly string Sequence = "active";
public readonly bool PauseOnLowPower = false; public readonly bool PauseOnLowPower = false;

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
public class WithRepairOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithRepairOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "active"; [SequenceReference] public readonly string Sequence = "active";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits
class WithResourcesInfo : ITraitInfo, Requires<RenderSimpleInfo> class WithResourcesInfo : ITraitInfo, Requires<RenderSimpleInfo>
{ {
[Desc("Sequence name to use")] [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); } public object Create(ActorInitializer init) { return new WithResources(init.Self, this); }
} }

View File

@@ -20,10 +20,10 @@ namespace OpenRA.Mods.Common.Traits
public class WithRotorInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithRotorInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use when flying")] [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")] [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")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -16,19 +16,26 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Renders an overlay when the actor is taking heavy damage.")] [Desc("Renders an overlay when the actor is taking heavy damage.")]
public class WithSmokeInfo : ITraitInfo, Requires<RenderSpritesInfo> public class WithSmokeInfo : ITraitInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Needs to define \"idle\", \"loop\" and \"end\" sub-sequences.")]
public readonly string Sequence = "smoke_m"; 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 object Create(ActorInitializer init) { return new WithSmoke(init.Self, this); }
} }
public class WithSmoke : INotifyDamage public class WithSmoke : INotifyDamage
{ {
readonly WithSmokeInfo info;
readonly Animation anim;
bool isSmoking; bool isSmoking;
Animation anim;
public WithSmoke(Actor self, WithSmokeInfo info) public WithSmoke(Actor self, WithSmokeInfo info)
{ {
this.info = info;
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
anim = new Animation(self.World, info.Sequence); anim = new Animation(self.World, info.Sequence);
@@ -42,9 +49,9 @@ namespace OpenRA.Mods.Common.Traits
if (e.DamageState < DamageState.Heavy) return; if (e.DamageState < DamageState.Heavy) return;
isSmoking = true; isSmoking = true;
anim.PlayThen("idle", anim.PlayThen(info.IdleSequence,
() => anim.PlayThen("loop", () => anim.PlayThen(info.LoopSequence,
() => anim.PlayBackwardsThen("end", () => anim.PlayBackwardsThen(info.EndSequence,
() => isSmoking = false))); () => isSmoking = false)));
} }
} }

View File

@@ -21,10 +21,10 @@ namespace OpenRA.Mods.Common.Traits
Requires<RenderSpritesInfo> Requires<RenderSpritesInfo>
{ {
[Desc("Animation to play when the actor is created.")] [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.")] [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); } public virtual object Create(ActorInitializer init) { return new WithSpriteBody(init, this); }

View File

@@ -21,10 +21,10 @@ namespace OpenRA.Mods.Common.Traits
Requires<RenderSpritesInfo>, Requires<TurretedInfo>, Requires<IBodyOrientationInfo> Requires<RenderSpritesInfo>, Requires<TurretedInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [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")] [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")] [Desc("Turreted 'Turret' key to display")]
public readonly string Turret = "primary"; public readonly string Turret = "primary";

View File

@@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Traits
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;
public readonly int Interval = 3; public readonly int Interval = 3;
public readonly string Sprite = "smokey"; public readonly string Sprite = "smokey";
[SequenceReference("Sprite")] public readonly string Sequence = "idle";
public readonly string Palette = "effect"; public readonly string Palette = "effect";
public readonly DamageState MinDamage = DamageState.Heavy; 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 offset = info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation));
var pos = position + body.LocalToWorld(offset); 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; ticks = info.Interval;

View File

@@ -28,6 +28,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Sprite sequence name")] [Desc("Sprite sequence name")]
public readonly string SmokeType = "smoke_m"; public readonly string SmokeType = "smoke_m";
[SequenceReference("SmokeType")] public readonly string SmokeSequence = "idle";
public readonly string SmokePalette = "effect"; public readonly string SmokePalette = "effect";
@@ -99,7 +100,7 @@ namespace OpenRA.Mods.Common.Traits
public void AddSmudge(CPos loc) public void AddSmudge(CPos loc)
{ {
if (Game.CosmeticRandom.Next(0, 100) <= Info.SmokePercentage) 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)) if (!dirty.ContainsKey(loc) && !tiles.ContainsKey(loc))
{ {

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.D2k.Traits
public class WithAttackOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo> public class WithAttackOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = null; [SequenceReference] public readonly string Sequence = null;
[Desc("Custom palette name")] [Desc("Custom palette name")]
public readonly string Palette = null; public readonly string Palette = null;

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.D2k.Traits
public class WithCrumbleOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo> public class WithCrumbleOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "crumble-overlay"; [SequenceReference] public readonly string Sequence = "crumble-overlay";
[Desc("Custom palette name")] [Desc("Custom palette name")]
public readonly string Palette = null; public readonly string Palette = null;

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.D2k.Traits
public class WithDeliveryOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo> public class WithDeliveryOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{ {
[Desc("Sequence name to use")] [Desc("Sequence name to use")]
public readonly string Sequence = "active"; [SequenceReference] public readonly string Sequence = "active";
[Desc("Position relative to body")] [Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero; public readonly WVec Offset = WVec.Zero;

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Traits
{ {
class MadTankInfo : ITraitInfo, Requires<ExplodesInfo>, Requires<WithFacingSpriteBodyInfo> class MadTankInfo : ITraitInfo, Requires<ExplodesInfo>, Requires<WithFacingSpriteBodyInfo>
{ {
public readonly string ThumpSequence = "piston"; [SequenceReference] public readonly string ThumpSequence = "piston";
public readonly int ThumpInterval = 8; public readonly int ThumpInterval = 8;
[WeaponReference] [WeaponReference]
public readonly string ThumpDamageWeapon = "MADTankThump"; public readonly string ThumpDamageWeapon = "MADTankThump";

View File

@@ -17,8 +17,8 @@ namespace OpenRA.Mods.RA.Traits
public class RenderLandingCraftInfo : RenderUnitInfo, Requires<IMoveInfo>, Requires<CargoInfo> public class RenderLandingCraftInfo : RenderUnitInfo, Requires<IMoveInfo>, Requires<CargoInfo>
{ {
public readonly string[] OpenTerrainTypes = { "Clear" }; public readonly string[] OpenTerrainTypes = { "Clear" };
public readonly string OpenAnim = "open"; [SequenceReference] public readonly string OpenAnim = "open";
public readonly string UnloadAnim = "unload"; [SequenceReference] public readonly string UnloadAnim = "unload";
public override object Create(ActorInitializer init) { return new RenderLandingCraft(init, this); } public override object Create(ActorInitializer init) { return new RenderLandingCraft(init, this); }
} }

View File

@@ -199,6 +199,7 @@
ExplosionDeath: 4 ExplosionDeath: 4
FireDeath: 5 FireDeath: 5
TiberiumDeath: 6 TiberiumDeath: 6
CrushedSequence: die-crushed
AttackMove: AttackMove:
Passenger: Passenger:
CargoType: Infantry CargoType: Infantry
@@ -273,6 +274,8 @@
CrushSound: squish2.aud CrushSound: squish2.aud
Voiced: Voiced:
VoiceSet: CivilianMaleVoice VoiceSet: CivilianMaleVoice
WithInfantryBody:
AttackSequence: shoot
^DINO: ^DINO:
AppearsOnRadar: AppearsOnRadar:
@@ -309,6 +312,7 @@
HiddenUnderFog: HiddenUnderFog:
GivesExperience: GivesExperience:
WithInfantryBody: WithInfantryBody:
AttackSequence: attack
WithDeathAnimation: WithDeathAnimation:
UseDeathTypeSuffix: false UseDeathTypeSuffix: false
EditorAppearance: EditorAppearance:

View File

@@ -19,6 +19,7 @@ E1:
WithInfantryBody: WithInfantryBody:
IdleSequences: idle1,idle2,idle3,idle4 IdleSequences: idle1,idle2,idle3,idle4
StandSequences: stand, stand2 StandSequences: stand, stand2
AttackSequence: shoot
E2: E2:
Inherits: ^Infantry Inherits: ^Infantry
@@ -42,6 +43,7 @@ E2:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: throw
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand, stand2 StandSequences: stand, stand2
Explodes: Explodes:
@@ -72,6 +74,7 @@ E3:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand, stand2 StandSequences: stand, stand2
@@ -101,6 +104,7 @@ E4:
SplitFacings: true SplitFacings: true
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand, stand2 StandSequences: stand, stand2
@@ -138,6 +142,7 @@ E5:
WithInfantryBody: WithInfantryBody:
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand, stand2 StandSequences: stand, stand2
AttackSequence: shoot
E6: E6:
Inherits: ^Infantry Inherits: ^Infantry
@@ -202,6 +207,7 @@ RMBO:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2,idle3 IdleSequences: idle1,idle2,idle3
StandSequences: stand, stand2 StandSequences: stand, stand2
AnnounceOnBuild: AnnounceOnBuild:

View File

@@ -8,7 +8,7 @@ steg:
Start: 16 Start: 16
Length: 8 Length: 8
Facings: 8 Facings: 8
shoot: attack:
Start: 80 Start: 80
Length: 12 Length: 12
Facings: 8 Facings: 8
@@ -27,7 +27,7 @@ trex:
Start: 16 Start: 16
Length: 8 Length: 8
Facings: 8 Facings: 8
shoot: attack:
Start: 80 Start: 80
Length: 8 Length: 8
Facings: 8 Facings: 8
@@ -46,7 +46,7 @@ tric:
Start: 16 Start: 16
Length: 8 Length: 8
Facings: 8 Facings: 8
shoot: attack:
Start: 80 Start: 80
Length: 12 Length: 12
Facings: 8 Facings: 8
@@ -65,7 +65,7 @@ rapt:
Start: 16 Start: 16
Length: 8 Length: 8
Facings: 8 Facings: 8
shoot: attack:
Start: 80 Start: 80
Length: 8 Length: 8
Facings: 8 Facings: 8

View File

@@ -165,7 +165,7 @@ e2:
Length: 6 Length: 6
Facings: 8 Facings: 8
Tick: 100 Tick: 100
shoot: throw:
Start: 64 Start: 64
Length: 20 Length: 20
Facings: 8 Facings: 8
@@ -188,7 +188,7 @@ e2:
Length: 4 Length: 4
Facings: 8 Facings: 8
Tick: 100 Tick: 100
prone-shoot: prone-throw:
Start: 288 Start: 288
Length: 12 Length: 12
Facings: 8 Facings: 8

View File

@@ -231,6 +231,7 @@
SoundDeath: 2 SoundDeath: 2
SmallExplosionDeath: 3 SmallExplosionDeath: 3
BulletDeath: 4 BulletDeath: 4
CrushedSequence: die-crushed
AutoTarget: AutoTarget:
AttackMove: AttackMove:
Passenger: Passenger:

View File

@@ -17,6 +17,7 @@ rifle:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
AttractsWorms: AttractsWorms:
Intensity: 120 Intensity: 120
@@ -71,6 +72,7 @@ bazooka:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
AttractsWorms: AttractsWorms:
Intensity: 180 Intensity: 180
@@ -133,6 +135,7 @@ fremen:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
Cloak: Cloak:
InitialDelay: 250 InitialDelay: 250
CloakDelay: 250 CloakDelay: 250
@@ -164,6 +167,7 @@ grenadier:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: throw
IdleSequences: idle IdleSequences: idle
Explodes: Explodes:
Weapon: UnitExplodeSmall Weapon: UnitExplodeSmall
@@ -190,6 +194,7 @@ sardaukar:
Range: 6c0 Range: 6c0
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
Armament@PRIMARY: Armament@PRIMARY:
Weapon: Vulcan Weapon: Vulcan
Armament@SECONDARY: Armament@SECONDARY:

View File

@@ -427,7 +427,7 @@ grenadier: # 2502 - 2749 in 1.06 DATA.R8
Length: 6 Length: 6
Facings: 8 Facings: 8
Tick: 120 Tick: 120
shoot: grenadier.shp throw: grenadier.shp
Start: 56 Start: 56
Length: 6 Length: 6
Facings: 8 Facings: 8
@@ -458,7 +458,7 @@ grenadier: # 2502 - 2749 in 1.06 DATA.R8
Length: 4 Length: 4
Facings: 8 Facings: 8
Tick: 120 Tick: 120
prone-shoot: grenadier.shp prone-throw: grenadier.shp
Start: 136 Start: 136
Length: 5 Length: 5
Facings: 8 Facings: 8

View File

@@ -150,6 +150,8 @@
ParachuteOffset: 0,0,200 ParachuteOffset: 0,0,200
KilledOnImpassableTerrain: true KilledOnImpassableTerrain: true
ParachuteSequence: parach ParachuteSequence: parach
ParachuteOpenSequence: open
ParachuteIdleSequence: idle
ShadowSequence: ShadowSequence:
GroundCorpseSequence: GroundCorpseSequence:
GroundCorpsePalette: GroundCorpsePalette:
@@ -199,6 +201,7 @@
ExplosionDeath: 4 ExplosionDeath: 4
FireDeath: 5 FireDeath: 5
ElectricityDeath: 6 ElectricityDeath: 6
CrushedSequence: die-crushed
AutoTarget: AutoTarget:
AttackMove: AttackMove:
Passenger: Passenger:
@@ -238,9 +241,12 @@
ParachuteOffset: 0,0,427 ParachuteOffset: 0,0,427
KilledOnImpassableTerrain: true KilledOnImpassableTerrain: true
ParachuteSequence: parach ParachuteSequence: parach
ParachuteOpenSequence: open
ParachuteIdleSequence: idle
ShadowSequence: parach-shadow ShadowSequence: parach-shadow
GroundImpactSound: squishy2.aud GroundImpactSound: squishy2.aud
WaterImpactSound: splash9.aud WaterImpactSound: splash9.aud
WaterCorpseSequence: small_splash
Cloneable: Cloneable:
Types: Infantry Types: Infantry
MustBeDestroyed: MustBeDestroyed:
@@ -666,9 +672,16 @@
Image: scrate Image: scrate
WithCrateBody: WithCrateBody:
XmasImages: xcratea, xcrateb, xcratec, xcrated XmasImages: xcratea, xcrateb, xcratec, xcrated
LandSequence: land
WaterSequence: water
Selectable:
Selectable: false
Bounds: 15,15,-1,-1
Parachutable: Parachutable:
KilledOnImpassableTerrain: false KilledOnImpassableTerrain: false
ParachuteSequence: parach ParachuteSequence: parach
ParachuteOpenSequence: open
ParachuteIdleSequence: idle
Passenger: Passenger:
CustomSelectionSize: CustomSelectionSize:
CustomBounds: 16,16 CustomBounds: 16,16

View File

@@ -35,12 +35,14 @@ DOG:
TargetableUnit: TargetableUnit:
TargetTypes: Ground, Infantry TargetTypes: Ground, Infantry
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
IgnoresDisguise: IgnoresDisguise:
DetectCloaked: DetectCloaked:
Range: 5 Range: 5
Voiced: Voiced:
VoiceSet: DogVoice VoiceSet: DogVoice
-TakeCover:
E1: E1:
Inherits: ^Infantry Inherits: ^Infantry
@@ -67,6 +69,7 @@ E1:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
@@ -97,6 +100,7 @@ E2:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: throw
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
Explodes: Explodes:
@@ -131,6 +135,7 @@ E3:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
@@ -160,6 +165,7 @@ E4:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
@@ -226,6 +232,7 @@ SPY:
-AutoTarget: -AutoTarget:
-WithInfantryBody: -WithInfantryBody:
WithDisguisingInfantryBody: WithDisguisingInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
Armament: Armament:
@@ -288,6 +295,7 @@ E7:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
AnnounceOnBuild: AnnounceOnBuild:
AnnounceOnKill: AnnounceOnKill:
@@ -363,7 +371,7 @@ MECH:
-AutoTarget: -AutoTarget:
WithInfantryBody: WithInfantryBody:
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
AttackSequence: heal AttackSequence: repair
Voiced: Voiced:
VoiceSet: MechanicVoice VoiceSet: MechanicVoice
@@ -434,6 +442,7 @@ GNRL:
Voice: Move Voice: Move
Voiced: Voiced:
VoiceSet: StavrosVoice VoiceSet: StavrosVoice
-ScaredyCat:
THF: THF:
Inherits: ^Infantry Inherits: ^Infantry
@@ -519,6 +528,7 @@ SHOK:
Voice: Move Voice: Move
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
Voiced: Voiced:
@@ -555,6 +565,7 @@ SNIPER:
AttackFrontal: AttackFrontal:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
StandSequences: stand,stand2 StandSequences: stand,stand2
Cloak: Cloak:
@@ -585,10 +596,13 @@ Zombie:
AutoTarget: AutoTarget:
ScanRadius: 5 ScanRadius: 5
AttackFrontal: AttackFrontal:
WithInfantryBody:
AttackSequence: bite
Armament: Armament:
Weapon: claw Weapon: claw
Voiced: Voiced:
VoiceSet: AntVoice VoiceSet: AntVoice
-TakeCover:
Ant: Ant:
Inherits: ^Infantry Inherits: ^Infantry
@@ -615,6 +629,8 @@ Ant:
AutoTarget: AutoTarget:
ScanRadius: 5 ScanRadius: 5
AttackFrontal: AttackFrontal:
WithInfantryBody:
AttackSequence: bite
Armament: Armament:
Weapon: mandible Weapon: mandible
TargetableUnit: TargetableUnit:
@@ -623,4 +639,5 @@ Ant:
UseDeathTypeSuffix: false UseDeathTypeSuffix: false
Voiced: Voiced:
VoiceSet: AntVoice VoiceSet: AntVoice
-TakeCover:

View File

@@ -355,7 +355,7 @@ mech:
Length: 6 Length: 6
Facings: 8 Facings: 8
Tick: 100 Tick: 100
heal: repair:
Start: 56 Start: 56
Length: 58 Length: 58
Tick: 120 Tick: 120
@@ -422,7 +422,7 @@ e2:
Length: 6 Length: 6
Facings: 8 Facings: 8
Tick: 80 Tick: 80
shoot: throw:
Start: 64 Start: 64
Length: 20 Length: 20
Facings: 8 Facings: 8
@@ -472,7 +472,7 @@ e2:
Length: 4 Length: 4
Facings: 8 Facings: 8
Tick: 80 Tick: 80
prone-shoot: prone-throw:
Start: 288 Start: 288
Length: 12 Length: 12
Facings: 8 Facings: 8
@@ -1278,7 +1278,7 @@ zombie:
Start: 16 Start: 16
Length: 6 Length: 6
Facings: 8 Facings: 8
shoot: bite:
Start: 64 Start: 64
Length: 4 Length: 4
Facings: 8 Facings: 8
@@ -1327,7 +1327,7 @@ ant:
Start: 8 Start: 8
Length: 8 Length: 8
Facings: 8 Facings: 8
shoot: bite:
Start: 72 Start: 72
Length: 4 Length: 4
Facings: 8 Facings: 8

View File

@@ -43,6 +43,7 @@ UMAGON:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
CHAMSPY: CHAMSPY:
@@ -91,6 +92,7 @@ MUTANT:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
MWMN: MWMN:
@@ -115,6 +117,7 @@ MWMN:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
MUTANT3: MUTANT3:
@@ -139,6 +142,7 @@ MUTANT3:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
TRATOS: TRATOS:
@@ -160,6 +164,7 @@ TRATOS:
TakeCover: TakeCover:
-AutoTarget: -AutoTarget:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
OXANNA: OXANNA:
@@ -179,6 +184,7 @@ OXANNA:
TakeCover: TakeCover:
-AutoTarget: -AutoTarget:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
SLAV: SLAV:
@@ -198,6 +204,7 @@ SLAV:
TakeCover: TakeCover:
-AutoTarget: -AutoTarget:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
DOGGIE: DOGGIE:
@@ -228,6 +235,7 @@ DOGGIE:
WanderMoveRadius: 2 WanderMoveRadius: 2
MinMoveDelayInTicks: 25 MinMoveDelayInTicks: 25
MaxMoveDelayInTicks: 45 MaxMoveDelayInTicks: 45
-TakeCover:
VISSML: VISSML:
Inherits: ^Viceroid Inherits: ^Viceroid
@@ -264,6 +272,8 @@ VISLRG:
CIV1: CIV1:
Inherits: ^CivilianInfantry Inherits: ^CivilianInfantry
WithInfantryBody:
AttackSequence: shoot
Armament: Armament:
Weapon: Pistola Weapon: Pistola
AttackFrontal: AttackFrontal:
@@ -275,6 +285,8 @@ CIV2:
CIV3: CIV3:
Inherits: ^CivilianInfantry Inherits: ^CivilianInfantry
WithInfantryBody:
AttackSequence: shoot
Armament: Armament:
Weapon: Pistola Weapon: Pistola
AttackFrontal: AttackFrontal:

View File

@@ -301,6 +301,8 @@
Types: CivilianInfantry Types: CivilianInfantry
-TakeCover: -TakeCover:
WithInfantryBody: WithInfantryBody:
WithDeathAnimation:
CrushedSequence: die-crushed
ScaredyCat: ScaredyCat:
-MustBeDestroyed: -MustBeDestroyed:

View File

@@ -83,6 +83,7 @@ JUMPJET:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
GHOST: GHOST:
Inherits: ^Infantry Inherits: ^Infantry
@@ -119,5 +120,6 @@ GHOST:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2

View File

@@ -22,6 +22,7 @@ E3:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
CYBORG: CYBORG:
@@ -56,10 +57,12 @@ CYBORG:
AttackFrontal: AttackFrontal:
Voice: Attack Voice: Attack
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
WithPermanentInjury: WithPermanentInjury:
SelectionDecorations: SelectionDecorations:
VisualBounds: 16,31,0,-10 VisualBounds: 16,31,0,-10
-TakeCover:
CYC2: CYC2:
Inherits: ^Infantry Inherits: ^Infantry
@@ -95,10 +98,12 @@ CYC2:
AttackFrontal: AttackFrontal:
Voice: Attack Voice: Attack
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
WithPermanentInjury: WithPermanentInjury:
SelectionDecorations: SelectionDecorations:
VisualBounds: 16,32,-1,-12 VisualBounds: 16,32,-1,-12
-TakeCover:
MHIJACK: MHIJACK:
Inherits: ^Infantry Inherits: ^Infantry
@@ -126,5 +131,6 @@ MHIJACK:
-AutoTarget: -AutoTarget:
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2

View File

@@ -26,6 +26,7 @@ E1:
Voice: Attack Voice: Attack
TakeCover: TakeCover:
WithInfantryBody: WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2 IdleSequences: idle1,idle2
ENGINEER: ENGINEER:

View File

@@ -111,12 +111,13 @@ e2:
ShadowStart: 451 ShadowStart: 451
Tick: 800 Tick: 800
ZOffset: -511 ZOffset: -511
shoot: throw:
Start: 164 Start: 164
Length: 6 Length: 6
Facings: 8 Facings: 8
ShadowStart: 456 ShadowStart: 456
prone-shoot: prone-throw:
Tick: 80
Start: 212 Start: 212
Length: 6 Length: 6
Facings: 8 Facings: 8