Merge pull request #8685 from Mailaender/lint-projectile-sprites

Added projectile sprite testing to the CheckYaml lint rules
This commit is contained in:
reaperrr
2015-07-21 01:56:58 +02:00
8 changed files with 100 additions and 15 deletions

View File

@@ -31,8 +31,8 @@ namespace OpenRA.Mods.Common.Effects
[Desc("Image to display.")] [Desc("Image to display.")]
public readonly string Image = null; public readonly string Image = null;
[Desc("Loop this sequence of Image while this projectile is moving."), SequenceReference("Image")] [Desc("Loop this sequence of Image while this projectile is moving.")]
public readonly string Sequence = "idle"; [SequenceReference("Image")] public readonly string Sequence = "idle";
[Desc("The palette used to draw this projectile.")] [Desc("The palette used to draw this projectile.")]
public readonly string Palette = "effect"; public readonly string Palette = "effect";

View File

@@ -19,13 +19,19 @@ namespace OpenRA.Mods.Common.Effects
public class GravityBombInfo : IProjectileInfo public class GravityBombInfo : IProjectileInfo
{ {
public readonly string Image = null; public readonly string Image = null;
[Desc("Sequence to loop while falling.")] [Desc("Sequence to loop while falling.")]
public readonly string Sequence = "idle"; [SequenceReference("Image")] public readonly string Sequence = "idle";
[Desc("Sequence to play when launched. Skipped if null or empty.")] [Desc("Sequence to play when launched. Skipped if null or empty.")]
public readonly string OpenSequence = null; [SequenceReference("Image")] public readonly string OpenSequence = null;
public readonly string Palette = "effect"; public readonly string Palette = "effect";
public readonly bool Shadow = false; public readonly bool Shadow = false;
public readonly WDist Velocity = WDist.Zero; public readonly WDist Velocity = WDist.Zero;
[Desc("Value added to velocity every tick.")] [Desc("Value added to velocity every tick.")]
public readonly WDist Acceleration = new WDist(15); public readonly WDist Acceleration = new WDist(15);

View File

@@ -22,14 +22,20 @@ namespace OpenRA.Mods.Common.Effects
class LaserZapInfo : IProjectileInfo class LaserZapInfo : IProjectileInfo
{ {
public readonly int BeamWidth = 2; public readonly int BeamWidth = 2;
public readonly int BeamDuration = 10; public readonly int BeamDuration = 10;
public readonly bool UsePlayerColor = false; public readonly bool UsePlayerColor = false;
[Desc("Laser color in (A,)R,G,B.")] [Desc("Laser color in (A,)R,G,B.")]
public readonly Color Color = Color.Red; public readonly Color Color = Color.Red;
[Desc("Impact animation.")] [Desc("Impact animation.")]
public readonly string HitAnim = null; public readonly string HitAnim = null;
[Desc("Sequence of impact animation to use.")] [Desc("Sequence of impact animation to use.")]
public readonly string HitAnimSequence = "idle"; [SequenceReference("HitAnim")] public readonly string HitAnimSequence = "idle";
public readonly string HitAnimPalette = "effect"; public readonly string HitAnimPalette = "effect";
public IEffect Create(ProjectileArgs args) public IEffect Create(ProjectileArgs args)

View File

@@ -24,38 +24,54 @@ namespace OpenRA.Mods.Common.Effects
{ {
public readonly string Image = null; public readonly string Image = null;
[SequenceReference("Image")] public readonly string Sequence = "idle"; [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 WDist / tick")] [Desc("Projectile speed in WDist / tick")]
public readonly WDist Speed = new WDist(8); public readonly WDist Speed = new WDist(8);
[Desc("Maximum vertical pitch when changing altitude.")] [Desc("Maximum vertical pitch when changing altitude.")]
public readonly WAngle MaximumPitch = WAngle.FromDegrees(30); public readonly WAngle MaximumPitch = WAngle.FromDegrees(30);
[Desc("How many ticks before this missile is armed and can explode.")] [Desc("How many ticks before this missile is armed and can explode.")]
public readonly int Arm = 0; public readonly int Arm = 0;
[Desc("Is the missile blocked by actors with BlocksProjectiles: trait.")] [Desc("Is the missile blocked by actors with BlocksProjectiles: trait.")]
public readonly bool Blockable = true; public readonly bool Blockable = true;
[Desc("Maximum offset at the maximum range")] [Desc("Maximum offset at the maximum range")]
public readonly WDist Inaccuracy = WDist.Zero; public readonly WDist Inaccuracy = WDist.Zero;
[Desc("Probability of locking onto and following target.")] [Desc("Probability of locking onto and following target.")]
public readonly int LockOnProbability = 100; public readonly int LockOnProbability = 100;
[Desc("In n/256 per tick.")] [Desc("In n/256 per tick.")]
public readonly int RateOfTurn = 5; public readonly int RateOfTurn = 5;
[Desc("Explode when following the target longer than this many ticks.")] [Desc("Explode when following the target longer than this many ticks.")]
public readonly int RangeLimit = 0; public readonly int RangeLimit = 0;
[Desc("Trail animation.")] [Desc("Trail animation.")]
public readonly string Trail = null; public readonly string Trail = null;
[Desc("Interval in ticks between each spawned Trail animation.")] [Desc("Interval in ticks between each spawned Trail animation.")]
public readonly int TrailInterval = 2; public readonly int TrailInterval = 2;
public readonly string TrailPalette = "effect"; public readonly string TrailPalette = "effect";
public readonly bool TrailUsePlayerPalette = false; public readonly bool TrailUsePlayerPalette = false;
public readonly int ContrailLength = 0; public readonly int ContrailLength = 0;
public readonly Color ContrailColor = Color.White; public readonly Color ContrailColor = Color.White;
public readonly bool ContrailUsePlayerColor = false; public readonly bool ContrailUsePlayerColor = false;
public readonly int ContrailDelay = 1; public readonly int ContrailDelay = 1;
[Desc("Should missile targeting be thrown off by nearby actors with JamsMissiles.")] [Desc("Should missile targeting be thrown off by nearby actors with JamsMissiles.")]
public readonly bool Jammable = true; public readonly bool Jammable = true;
[Desc("Explodes when leaving the following terrain type, e.g., Water for torpedoes.")] [Desc("Explodes when leaving the following terrain type, e.g., Water for torpedoes.")]
public readonly string BoundToTerrainType = ""; public readonly string BoundToTerrainType = "";
[Desc("Explodes when inside this proximity radius to target.", [Desc("Explodes when inside this proximity radius to target.",
"Note: If this value is lower than the missile speed, this check might", "Note: If this value is lower than the missile speed, this check might",
"not trigger fast enough, causing the missile to fly past the target.")] "not trigger fast enough, causing the missile to fly past the target.")]

View File

@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using OpenRA.GameRules;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits; using OpenRA.Traits;
@@ -89,6 +90,48 @@ namespace OpenRA.Mods.Common.Lint
} }
} }
} }
foreach (var weaponInfo in map.Rules.Weapons)
{
var projectileInfo = weaponInfo.Value.Projectile;
if (projectileInfo == null)
continue;
var fields = projectileInfo.GetType().GetFields();
foreach (var field in fields)
{
if (field.HasAttribute<SequenceReferenceAttribute>())
{
var sequences = LintExts.GetFieldValues(projectileInfo, field, emitError);
foreach (var sequence in sequences)
{
if (string.IsNullOrEmpty(sequence))
continue;
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(projectileInfo, imageField, emitError))
{
if (!string.IsNullOrEmpty(imageOverride))
{
var definitions = sequenceDefinitions.FirstOrDefault(n => n.Key == imageOverride.ToLowerInvariant());
if (definitions == null)
emitWarning("Can't find sequence definition for projectile image {0} at weapon {1}.".F(imageOverride, weaponInfo.Key));
else if (!definitions.Value.Nodes.Any(n => n.Key == sequence))
emitWarning("Projectile sprite image {0} from weapon {1} does not define sequence {2} from field {3} of {4}"
.F(imageOverride, weaponInfo.Key, sequence, field.Name, projectileInfo));
}
}
}
}
}
}
}
}
} }
} }

View File

@@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
} }
catch (Exception e) catch (Exception e)
{ {
EmitError("{0} failed with exception: {0}".F(customPassType, e)); EmitError("{0} failed with exception: {1}".F(customPassType, e));
} }
} }
} }

View File

@@ -20,9 +20,15 @@ namespace OpenRA.Mods.RA.Effects
class TeslaZapInfo : IProjectileInfo class TeslaZapInfo : IProjectileInfo
{ {
public readonly string Image = "litning"; public readonly string Image = "litning";
[SequenceReference("Image")] public readonly string BrightSequence = "bright";
[SequenceReference("Image")] public readonly string DimSequence = "dim";
public readonly string Palette = "effect"; public readonly string Palette = "effect";
public readonly int BrightZaps = 1; public readonly int BrightZaps = 1;
public readonly int DimZaps = 2; public readonly int DimZaps = 2;
public IEffect Create(ProjectileArgs args) { return new TeslaZap(this, args); } public IEffect Create(ProjectileArgs args) { return new TeslaZap(this, args); }
} }
@@ -59,7 +65,8 @@ namespace OpenRA.Mods.RA.Effects
if (!initialized) if (!initialized)
{ {
var pos = args.GuidedTarget.IsValidFor(args.SourceActor) ? args.GuidedTarget.CenterPosition : args.PassiveTarget; var pos = args.GuidedTarget.IsValidFor(args.SourceActor) ? args.GuidedTarget.CenterPosition : args.PassiveTarget;
zap = new TeslaZapRenderable(args.Source, 0, pos - args.Source, info.Image, info.BrightZaps, info.DimZaps, info.Palette); zap = new TeslaZapRenderable(args.Source, 0, pos - args.Source,
info.Image, info.BrightSequence, info.BrightZaps, info.DimSequence, info.DimZaps, info.Palette);
} }
yield return zap; yield return zap;

View File

@@ -35,13 +35,15 @@ namespace OpenRA.Mods.RA.Graphics
readonly WVec length; readonly WVec length;
readonly string image; readonly string image;
readonly string palette; readonly string palette;
readonly string dimSequence;
readonly string brightSequence;
readonly int brightZaps, dimZaps; readonly int brightZaps, dimZaps;
WPos cachedPos; WPos cachedPos;
WVec cachedLength; WVec cachedLength;
IEnumerable<IFinalizedRenderable> cache; IEnumerable<IFinalizedRenderable> cache;
public TeslaZapRenderable(WPos pos, int zOffset, WVec length, string image, int brightZaps, int dimZaps, string palette) public TeslaZapRenderable(WPos pos, int zOffset, WVec length, string image, string brightSequence, int brightZaps, string dimSequence, int dimZaps, string palette)
{ {
this.pos = pos; this.pos = pos;
this.zOffset = zOffset; this.zOffset = zOffset;
@@ -50,6 +52,8 @@ namespace OpenRA.Mods.RA.Graphics
this.palette = palette; this.palette = palette;
this.brightZaps = brightZaps; this.brightZaps = brightZaps;
this.dimZaps = dimZaps; this.dimZaps = dimZaps;
this.dimSequence = dimSequence;
this.brightSequence = brightSequence;
cachedPos = WPos.Zero; cachedPos = WPos.Zero;
cachedLength = WVec.Zero; cachedLength = WVec.Zero;
@@ -61,17 +65,20 @@ namespace OpenRA.Mods.RA.Graphics
public int ZOffset { get { return zOffset; } } public int ZOffset { get { return zOffset; } }
public bool IsDecoration { get { return true; } } public bool IsDecoration { get { return true; } }
public IRenderable WithPalette(PaletteReference newPalette) { return new TeslaZapRenderable(pos, zOffset, length, image, brightZaps, dimZaps, palette); } public IRenderable WithPalette(PaletteReference newPalette)
public IRenderable WithZOffset(int newOffset) { return new TeslaZapRenderable(pos, zOffset, length, image, brightZaps, dimZaps, palette); } {
public IRenderable OffsetBy(WVec vec) { return new TeslaZapRenderable(pos + vec, zOffset, length, image, brightZaps, dimZaps, palette); } return new TeslaZapRenderable(pos, zOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette);
}
public IRenderable WithZOffset(int newOffset) { return new TeslaZapRenderable(pos, zOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); }
public IRenderable OffsetBy(WVec vec) { return new TeslaZapRenderable(pos + vec, zOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void RenderDebugGeometry(WorldRenderer wr) { } public void RenderDebugGeometry(WorldRenderer wr) { }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
if (wr.World.FogObscures(pos) && if (wr.World.FogObscures(pos) && wr.World.FogObscures(pos + length))
wr.World.FogObscures(pos + length))
return; return;
if (!cache.Any() || length != cachedLength || pos != cachedPos) if (!cache.Any() || length != cachedLength || pos != cachedPos)
@@ -84,8 +91,8 @@ namespace OpenRA.Mods.RA.Graphics
public IEnumerable<IFinalizedRenderable> GenerateRenderables(WorldRenderer wr) public IEnumerable<IFinalizedRenderable> GenerateRenderables(WorldRenderer wr)
{ {
var bright = wr.World.Map.SequenceProvider.GetSequence(image, "bright"); var bright = wr.World.Map.SequenceProvider.GetSequence(image, brightSequence);
var dim = wr.World.Map.SequenceProvider.GetSequence(image, "dim"); var dim = wr.World.Map.SequenceProvider.GetSequence(image, dimSequence);
var source = wr.ScreenPosition(pos); var source = wr.ScreenPosition(pos);
var target = wr.ScreenPosition(pos + length); var target = wr.ScreenPosition(pos + length);