示例#1
0
        public Missile(MissileInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;

            pos = args.Source;
            facing = args.Facing;

            targetPosition = args.PassiveTarget;

            var world = args.SourceActor.World;

            if (world.SharedRandom.Next(100) <= info.LockOnProbability)
                lockOn = true;

            if (info.Inaccuracy.Range > 0)
            {
                var inaccuracy = OpenRA.Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Range, args.InaccuracyModifiers);
                offset = WVec.FromPDF(world.SharedRandom, 2) * inaccuracy / 1024;
            }

            if (info.Image != null)
            {
                anim = new Animation(world, info.Image, () => facing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(world, color, info.ContrailLength, info.ContrailDelay, 0);
            }
        }
示例#2
0
        public Missile(MissileInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;

            pos    = args.Source;
            facing = args.Facing;

            targetPosition = args.PassiveTarget;

            var world = args.SourceActor.World;

            if (world.SharedRandom.Next(100) <= info.LockOnProbability)
            {
                lockOn = true;
            }

            if (info.Inaccuracy.Range > 0)
            {
                var inaccuracy = OpenRA.Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Range, args.InaccuracyModifiers);
                offset = WVec.FromPDF(world.SharedRandom, 2) * inaccuracy / 1024;
            }

            if (info.Image != null)
            {
                anim = new Animation(world, info.Image, () => facing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(world, color, info.ContrailLength, info.ContrailDelay, 0);
            }
        }
示例#3
0
        public Missile(MissileInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;

            pos    = args.Source;
            facing = args.Facing;

            targetPosition = args.PassiveTarget;

            if (info.Inaccuracy.Range > 0)
            {
                offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * info.Inaccuracy.Range / 1024;
            }

            if (info.Image != null)
            {
                anim = new Animation(args.SourceActor.World, info.Image, () => facing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(args.SourceActor.World, color, info.ContrailLength, info.ContrailDelay, 0);
            }
        }
示例#4
0
        public WarheadTrailProjectileEffect(WarheadTrailProjectileInfo info, ProjectileArgs args, int lifespan, int estimatedlifespan)
        {
            this.info              = info;
            this.args              = args;
            this.lifespan          = lifespan;
            this.estimatedlifespan = estimatedlifespan;
            projectilepos          = args.Source;
            source = args.Source;

            world     = args.SourceActor.World;
            targetpos = args.PassiveTarget;
            facing    = args.Facing;

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, new Func <int>(GetEffectiveFacing));
                anim.PlayRepeating(info.Sequences.Random(world.SharedRandom));
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailWidth, info.ContrailLength, info.ContrailDelay, info.ContrailZOffset);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
            {
                trailPalette += args.SourceActor.Owner.InternalName;
            }

            smokeTicks = info.TrailDelay;
        }
示例#5
0
        public Missile(MissileInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;

            pos    = args.Source;
            facing = args.Facing;

            targetPosition = args.PassiveTarget;

            // Convert ProjectileArg definitions to world coordinates
            // TODO: Change the yaml definitions so we don't need this
            var inaccuracy = (int)(info.Inaccuracy * 1024 / Game.CellSize);

            speed = info.Speed * 1024 / (5 * Game.CellSize);

            if (info.Inaccuracy > 0)
            {
                offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * inaccuracy / 1024;
            }

            if (info.Image != null)
            {
                anim = new Animation(info.Image, () => facing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(args.SourceActor.World, color, info.ContrailLength, info.ContrailDelay, 0);
            }
        }
示例#6
0
文件: Missile.cs 项目: dnqbob/OpenRA
        public Missile(MissileInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;

            pos            = args.Source;
            hFacing        = args.Facing.Facing;
            gravity        = new WVec(0, 0, -info.Gravity);
            targetPosition = args.PassiveTarget;
            var limit = info.RangeLimit != WDist.Zero ? info.RangeLimit : args.Weapon.Range;

            rangeLimit     = new WDist(Util.ApplyPercentageModifiers(limit.Length, args.RangeModifiers));
            minLaunchSpeed = info.MinimumLaunchSpeed.Length > -1 ? info.MinimumLaunchSpeed.Length : info.Speed.Length;
            maxLaunchSpeed = info.MaximumLaunchSpeed.Length > -1 ? info.MaximumLaunchSpeed.Length : info.Speed.Length;
            maxSpeed       = info.Speed.Length;
            minLaunchAngle = info.MinimumLaunchAngle;
            maxLaunchAngle = info.MaximumLaunchAngle;

            var world = args.SourceActor.World;

            if (world.SharedRandom.Next(100) <= info.LockOnProbability)
            {
                lockOn = true;
            }

            var inaccuracy = lockOn && info.LockOnInaccuracy.Length > -1 ? info.LockOnInaccuracy.Length : info.Inaccuracy.Length;

            if (inaccuracy > 0)
            {
                var maxInaccuracyOffset = Util.GetProjectileInaccuracy(info.Inaccuracy.Length, info.InaccuracyType, args);
                offset = WVec.FromPDF(world.SharedRandom, 2) * maxInaccuracyOffset / 1024;
            }

            DetermineLaunchSpeedAndAngle(world, out speed, out vFacing);

            velocity = new WVec(0, -speed, 0)
                       .Rotate(new WRot(WAngle.FromFacing(vFacing), WAngle.Zero, WAngle.Zero))
                       .Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(hFacing)));

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, () => renderFacing);
                anim.PlayRepeating(info.Sequences.Random(world.SharedRandom));
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailWidth, info.ContrailLength, info.ContrailDelay, info.ContrailZOffset);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
            {
                trailPalette += args.SourceActor.Owner.InternalName;
            }

            shadowColor = new float3(info.ShadowColor.R, info.ShadowColor.G, info.ShadowColor.B) / 255f;
            shadowAlpha = info.ShadowColor.A;
        }
示例#7
0
        public Bullet(BulletInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            pos       = args.Source;
            source    = args.Source;

            var world = args.SourceActor.World;

            if (info.LaunchAngle.Length > 1)
            {
                angle = new WAngle(world.SharedRandom.Next(info.LaunchAngle[0].Angle, info.LaunchAngle[1].Angle));
            }
            else
            {
                angle = info.LaunchAngle[0];
            }

            if (info.Speed.Length > 1)
            {
                speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length));
            }
            else
            {
                speed = info.Speed[0];
            }

            target = args.PassiveTarget;
            if (info.Inaccuracy.Length > 0)
            {
                var inaccuracy = Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers);
                var range      = Util.ApplyPercentageModifiers(args.Weapon.Range.Length, args.RangeModifiers);
                var maxOffset  = inaccuracy * (target - pos).Length / range;
                target += WVec.FromPDF(world.SharedRandom, 2) * maxOffset / 1024;
            }

            facing = (target - pos).Yaw.Facing;
            length = Math.Max((target - pos).Length / speed.Length, 1);

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, new Func <int>(GetEffectiveFacing));
                anim.PlayRepeating(info.Sequences.Random(world.SharedRandom));
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailWidth, info.ContrailLength, info.ContrailDelay, info.ContrailZOffset);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
            {
                trailPalette += args.SourceActor.Owner.InternalName;
            }

            smokeTicks       = info.TrailDelay;
            remainingBounces = info.BounceCount;
        }
        public Contrail(Actor self, ContrailInfo info)
        {
            this.info = info;

            color = info.UsePlayerColor ? ContrailRenderable.ChooseColor(self) : info.Color;
            trail = new ContrailRenderable(self.World, color, info.TrailWidth, info.TrailLength, 0, info.ZOffset);

            body = self.Trait <BodyOrientation>();
        }
示例#9
0
文件: Bullet.cs 项目: ushalin/OpenRA
        public Bullet(BulletInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            this.pos  = args.Source;

            var world = args.SourceActor.World;

            if (info.Angle.Length > 1)
            {
                angle = new WAngle(world.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle));
            }
            else
            {
                angle = info.Angle[0];
            }

            if (info.Speed.Length > 1)
            {
                speed = new WRange(world.SharedRandom.Next(info.Speed[0].Range, info.Speed[1].Range));
            }
            else
            {
                speed = info.Speed[0];
            }

            target = args.PassiveTarget;
            if (info.Inaccuracy.Range > 0)
            {
                var inaccuracy = OpenRA.Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Range, args.InaccuracyModifiers);
                var maxOffset  = inaccuracy * (target - pos).Length / args.Weapon.Range.Range;
                target += WVec.FromPDF(world.SharedRandom, 2) * maxOffset / 1024;
            }

            facing = OpenRA.Traits.Util.GetFacing(target - pos, 0);
            length = Math.Max((target - pos).Length / speed.Range, 1);

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, GetEffectiveFacing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailLength, info.ContrailDelay, 0);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
            {
                trailPalette += args.SourceActor.Owner.InternalName;
            }

            smokeTicks = info.TrailDelay;
        }
示例#10
0
        public Missile(MissileInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;

            pos            = args.Source;
            hFacing        = args.Facing;
            gravity        = new WVec(0, 0, -info.Gravity);
            targetPosition = args.PassiveTarget;

            var world = args.SourceActor.World;

            if (info.Inaccuracy.Length > 0)
            {
                var inaccuracy = Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers);
                offset = WVec.FromPDF(world.SharedRandom, 2) * inaccuracy / 1024;
            }

            DetermineLaunchSpeedAndAngle(world, out speed, out vFacing);

            velocity = new WVec(0, -speed, 0)
                       .Rotate(new WRot(WAngle.FromFacing(vFacing), WAngle.Zero, WAngle.Zero))
                       .Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(hFacing)));

            if (world.SharedRandom.Next(100) <= info.LockOnProbability)
            {
                lockOn = true;
            }

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, () => renderFacing);
                anim.PlayRepeating(info.Sequence);
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailWidth, info.ContrailLength, info.ContrailDelay, info.ContrailZOffset);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
            {
                trailPalette += args.SourceActor.Owner.InternalName;
            }
        }
示例#11
0
        public Bullet(BulletInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            this.pos  = args.Source;

            var world = args.SourceActor.World;

            if (info.Angle.Length > 1 && info.Speed.Length > 1)
            {
                angle = new WAngle(args.SourceActor.World.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle));
                speed = new WRange(args.SourceActor.World.SharedRandom.Next(info.Speed[0].Range, info.Speed[1].Range));
            }
            else
            {
                angle = info.Angle[0];
                speed = info.Speed[0];
            }

            target = args.PassiveTarget;
            if (info.Inaccuracy.Range > 0)
            {
                var maxOffset = info.Inaccuracy.Range * (target - pos).Length / args.Weapon.Range.Range;
                target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024;
            }

            facing = Traits.Util.GetFacing(target - pos, 0);
            length = Math.Max((target - pos).Length / speed.Range, 1);

            if (info.Image != null)
            {
                anim = new Animation(world, info.Image, GetEffectiveFacing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(args.SourceActor.World, color, info.ContrailLength, info.ContrailDelay, 0);
            }

            smokeTicks = info.TrailDelay;
        }
示例#12
0
        public Bullet(BulletInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            this.pos  = args.Source;

            // Convert ProjectileArg definitions to world coordinates
            // TODO: Change the yaml definitions so we don't need this
            var range      = new WRange((int)(1024 * args.Weapon.Range));               // Range in world units
            var inaccuracy = new WRange((int)(info.Inaccuracy * 1024 / Game.CellSize)); // Offset in world units at max range
            var speed      = (int)(info.Speed * 4 * 1024 / (10 * Game.CellSize));       // Speed in world units per tick

            angle = WAngle.ArcTan((int)(info.Angle * 4 * 1024), 1024);                  // Angle in world angle

            target = args.PassiveTarget;
            if (info.Inaccuracy > 0)
            {
                var maxOffset = inaccuracy.Range * (target - pos).Length / range.Range;
                target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024;
            }

            facing = Traits.Util.GetFacing(target - pos, 0);
            length = Math.Max((target - pos).Length / speed, 1);

            if (info.Image != null)
            {
                anim = new Animation(info.Image, GetEffectiveFacing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(args.SourceActor.World, color, info.ContrailLength, info.ContrailDelay, 0);
            }

            smokeTicks = info.TrailDelay;
        }
示例#13
0
 public ContrailFader(WPos pos, ContrailRenderable trail)
 {
     this.pos   = pos;
     this.trail = trail;
 }
示例#14
0
        public BulletCA(BulletCAInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            pos       = args.Source;
            source    = args.Source;

            var world = args.SourceActor.World;

            if (info.LaunchAngle.Length > 1)
            {
                angle = new WAngle(world.SharedRandom.Next(info.LaunchAngle[0].Angle, info.LaunchAngle[1].Angle));
            }
            else
            {
                angle = info.LaunchAngle[0];
            }

            if (info.Speed.Length > 1)
            {
                speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length));
            }
            else
            {
                speed = info.Speed[0];
            }

            target = args.PassiveTarget;
            if (info.Inaccuracy.Length > 0)
            {
                var maxInaccuracyOffset = Common.Util.GetProjectileInaccuracy(info.Inaccuracy.Length, info.InaccuracyType, args);
                target += WVec.FromPDF(world.SharedRandom, 2) * maxInaccuracyOffset / 1024;
            }

            if (info.AirburstAltitude > WDist.Zero)
            {
                target += new WVec(WDist.Zero, WDist.Zero, info.AirburstAltitude);
            }

            facing = (target - pos).Yaw;
            length = Math.Max((target - pos).Length / speed.Length, 1);

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, new Func <WAngle>(GetEffectiveFacing));
                anim.PlayRepeating(info.Sequences.Random(world.SharedRandom));
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailWidth, info.ContrailLength, info.ContrailDelay, info.ContrailZOffset);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
            {
                trailPalette += args.SourceActor.Owner.InternalName;
            }

            smokeTicks       = info.TrailDelay;
            remainingBounces = info.BounceCount;
        }
示例#15
0
 public ContrailFader(WPos pos, ContrailRenderable trail)
 {
     this.pos = pos;
     this.trail = trail;
 }
示例#16
0
 void INotifyAddedToWorld.AddedToWorld(Actor self)
 {
     trail = new ContrailRenderable(self.World, color, info.TrailWidth, info.TrailLength, 0, info.ZOffset);
 }
示例#17
0
		public Missile(MissileInfo info, ProjectileArgs args)
		{
			this.info = info;
			this.args = args;

			pos = args.Source;
			hFacing = args.Facing;
			targetPosition = args.PassiveTarget;

			var world = args.SourceActor.World;

			if (info.Inaccuracy.Length > 0)
			{
				var inaccuracy = OpenRA.Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers);
				offset = WVec.FromPDF(world.SharedRandom, 2) * inaccuracy / 1024;
			}

			DetermineLaunchSpeedAndAngle(world, out speed, out vFacing);

			velocity = new WVec(0, -speed, 0)
				.Rotate(new WRot(WAngle.FromFacing(vFacing), WAngle.Zero, WAngle.Zero))
				.Rotate(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(hFacing)));

			if (world.SharedRandom.Next(100) <= info.LockOnProbability)
				lockOn = true;

			if (!string.IsNullOrEmpty(info.Image))
			{
				anim = new Animation(world, info.Image, () => renderFacing);
				anim.PlayRepeating(info.Sequence);
			}

			if (info.ContrailLength > 0)
			{
				var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
				contrail = new ContrailRenderable(world, color, info.ContrailLength, info.ContrailDelay, 0);
			}

			trailPalette = info.TrailPalette;
			if (info.TrailUsePlayerPalette)
				trailPalette += args.SourceActor.Owner.InternalName;
		}
示例#18
0
        public Bullet(BulletInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            this.pos = args.Source;

            var world = args.SourceActor.World;

            if (info.Angle.Length > 1)
                angle = new WAngle(world.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle));
            else
                angle = info.Angle[0];

            if (info.Speed.Length > 1)
                speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length));
            else
                speed = info.Speed[0];

            target = args.PassiveTarget;
            if (info.Inaccuracy.Length > 0)
            {
                var inaccuracy = OpenRA.Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers);
                var maxOffset = inaccuracy * (target - pos).Length / args.Weapon.Range.Length;
                target += WVec.FromPDF(world.SharedRandom, 2) * maxOffset / 1024;
            }

            facing = OpenRA.Traits.Util.GetFacing(target - pos, 0);
            length = Math.Max((target - pos).Length / speed.Length, 1);

            if (!string.IsNullOrEmpty(info.Image))
            {
                anim = new Animation(world, info.Image, GetEffectiveFacing);
                anim.PlayRepeating(info.Sequence);
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                contrail = new ContrailRenderable(world, color, info.ContrailLength, info.ContrailDelay, 0);
            }

            trailPalette = info.TrailPalette;
            if (info.TrailUsePlayerPalette)
                trailPalette += args.SourceActor.Owner.InternalName;

            smokeTicks = info.TrailDelay;
        }
示例#19
0
        public Bullet(BulletInfo info, ProjectileArgs args)
        {
            this.info = info;
            this.args = args;
            this.pos = args.Source;

            var world = args.SourceActor.World;

            if (info.Angle.Length > 1 && info.Speed.Length > 1)
            {
                angle = new WAngle(world.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle));
                speed = new WRange(world.SharedRandom.Next(info.Speed[0].Range, info.Speed[1].Range));
            }
            else
            {
                angle = info.Angle[0];
                speed = info.Speed[0];
            }

            target = args.PassiveTarget;
            if (info.Inaccuracy.Range > 0)
            {
                var inaccuracy = OpenRA.Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Range, args.InaccuracyModifiers);
                var maxOffset = inaccuracy * (target - pos).Length / args.Weapon.Range.Range;
                target += WVec.FromPDF(world.SharedRandom, 2) * maxOffset / 1024;
            }

            facing = OpenRA.Traits.Util.GetFacing(target - pos, 0);
            length = Math.Max((target - pos).Length / speed.Range, 1);

            if (info.Image != null)
            {
                anim = new Animation(world, info.Image, GetEffectiveFacing);
                anim.PlayRepeating("idle");
            }

            if (info.ContrailLength > 0)
            {
                var color = info.ContrailUsePlayerColor ? ContrailRenderable.ChooseColor(args.SourceActor) : info.ContrailColor;
                trail = new ContrailRenderable(world, color, info.ContrailLength, info.ContrailDelay, 0);
            }

            smokeTicks = info.TrailDelay;
        }