diff --git a/OpenRA.Mods.Common/Effects/Shrapnel.cs b/OpenRA.Mods.Common/Effects/Shrapnel.cs new file mode 100644 index 0000000000..10e0b2b1a4 --- /dev/null +++ b/OpenRA.Mods.Common/Effects/Shrapnel.cs @@ -0,0 +1,147 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.Effects; +using OpenRA.GameRules; +using OpenRA.Graphics; +using OpenRA.Mods.Common.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Effects +{ + public class ShrapnelInfo : IProjectileInfo + { + [Desc("Projectile speed in WDist / tick, two values indicate variable velocity.")] + public readonly WDist[] Speed = { new WDist(17) }; + + [Desc("Image to display.")] + public readonly string Image = null; + + [Desc("Loop these sequences of Image while this projectile is moving.")] + [SequenceReference("Image")] public readonly string[] Sequences = { "idle" }; + + [Desc("The palette used to draw this projectile.")] + public readonly string Palette = "effect"; + + [Desc("Does this projectile have a shadow?")] + public readonly bool Shadow = false; + + [Desc("Palette to use for this projectile's shadow if Shadow is true.")] + public readonly string ShadowPalette = "shadow"; + + [Desc("Arc in WAngles, two values indicate variable arc.")] + public readonly WAngle[] Angle = { WAngle.Zero }; + + public IEffect Create(ProjectileArgs args) { return new Shrapnel(this, args); } + } + + public class Shrapnel : IEffect, ISync + { + readonly ShrapnelInfo info; + readonly ProjectileArgs args; + readonly Animation anim; + [Sync] readonly WAngle angle; + [Sync] readonly WDist speed; + + [Sync] WPos pos, target; + [Sync] int length; + [Sync] int facing; + [Sync] int ticks; + + [Sync] public Actor SourceActor { get { return args.SourceActor; } } + + public Shrapnel(ShrapnelInfo 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; + + 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.Sequences.Random(world.SharedRandom)); + } + } + + int GetEffectiveFacing() + { + var at = (float)ticks / (length - 1); + var attitude = angle.Tan() * (1 - 2 * at) / (4 * 1024); + + var u = (facing % 128) / 128f; + var scale = 512 * u * (1 - u); + + return (int)(facing < 128 + ? facing - scale * attitude + : facing + scale * attitude); + } + + public void Tick(World world) + { + if (anim != null) + anim.Tick(); + + pos = WPos.LerpQuadratic(args.Source, target, angle, ticks, length); + + if (ticks++ >= length) + Explode(world); + } + + public IEnumerable Render(WorldRenderer wr) + { + if (anim == null || ticks >= length) + yield break; + + var world = args.SourceActor.World; + if (!world.FogObscures(pos)) + { + if (info.Shadow) + { + var dat = world.Map.DistanceAboveTerrain(pos); + var shadowPos = pos - new WVec(0, 0, dat.Length); + foreach (var r in anim.Render(shadowPos, wr.Palette(info.ShadowPalette))) + yield return r; + } + + var palette = wr.Palette(info.Palette); + foreach (var r in anim.Render(pos, palette)) + yield return r; + } + } + + void Explode(World world) + { + world.AddFrameEndTask(w => w.Remove(this)); + + args.Weapon.Impact(Target.FromPos(pos), args.SourceActor, args.DamageModifiers); + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 9bf8805b53..c1452e132e 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -163,6 +163,7 @@ + diff --git a/mods/d2k/weapons.yaml b/mods/d2k/weapons.yaml index c45d119b9f..e5b8fdb7dd 100644 --- a/mods/d2k/weapons.yaml +++ b/mods/d2k/weapons.yaml @@ -695,11 +695,10 @@ Shrapnel: ReloadDelay: 60 Range: 4c0 Report: - Projectile: Bullet + Projectile: Shrapnel Speed: 50, 125 Blockable: false Angle: 91, 264 - Inaccuracy: 416 Image: shrapnel Warhead@1Dam: SpreadDamage Spread: 192 diff --git a/mods/ts/sequences/misc.yaml b/mods/ts/sequences/misc.yaml index 37a3c11188..59e72f9033 100644 --- a/mods/ts/sequences/misc.yaml +++ b/mods/ts/sequences/misc.yaml @@ -402,76 +402,48 @@ srock05: UseTilesetExtension: true Offset: 0, -12 -dbris1sm: - idle: +dbrissm: + 1: dbris1sm + Length:* + 2: dbris2sm + Length:* + 3: dbris3sm + Length:* + 4: dbris4sm + Length:* + 5: dbris5sm + Length:* + 6: dbris6sm + Length:* + 7: dbris7sm + Length:* + 8: dbris8sm + Length:* + 9: dbris9sm + Length:* + 10: dbrs10sm Length:* -dbris2sm: - idle: +dbrislg: + 1: dbris1lg Length:* - -dbris3sm: - idle: + 2: dbris2lg Length:* - -dbris4sm: - idle: + 3: dbris3lg Length:* - -dbris5sm: - idle: + 4: dbris4lg Length:* - -dbris6sm: - idle: + 5: dbris5lg Length:* - -dbris7sm: - idle: + 6: dbris6lg Length:* - -dbris8sm: - idle: + 7: dbris7lg Length:* - -dbris9sm: - idle: + 8: dbris8lg Length:* - -dbris1lg: - idle: + 9: dbris9lg Length:* - -dbris2lg: - idle: - Length:* - -dbris3lg: - idle: - Length:* - -dbris4lg: - idle: - Length:* - -dbris5lg: - idle: - Length:* - -dbris6lg: - idle: - Length:* - -dbris7lg: - idle: - Length:* - -dbris8lg: - idle: - Length:* - -dbris9lg: - idle: + 10: dbrs10lg Length:* crat01: @@ -512,3 +484,4 @@ palet03: palet04: idle: + diff --git a/mods/ts/weapons/explosions.yaml b/mods/ts/weapons/explosions.yaml index 38bba9332e..5453bd3a44 100644 --- a/mods/ts/weapons/explosions.yaml +++ b/mods/ts/weapons/explosions.yaml @@ -48,20 +48,20 @@ SmallDebris: ReloadDelay: 60 Range: 4c0 Report: - Projectile: Bullet + Projectile: Shrapnel Speed: 50, 125 - Blockable: false Angle: 91, 264 - Inaccuracy: 416 - Image: dbris1sm # TODO: add some variation + Image: dbrissm + Sequences: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + Shadow: true LargeDebris: ReloadDelay: 60 Range: 4c0 Report: - Projectile: Bullet + Projectile: Shrapnel Speed: 50, 125 - Blockable: false Angle: 91, 264 - Inaccuracy: 416 - Image: dbris1lg # TODO: add some variation \ No newline at end of file + Image: dbrislg + Sequences: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + Shadow: true