diff --git a/OpenRa.Game/Effects/Bullet.cs b/OpenRa.Game/Effects/Bullet.cs
index 051a00bae5..1de4ed8bd1 100755
--- a/OpenRa.Game/Effects/Bullet.cs
+++ b/OpenRa.Game/Effects/Bullet.cs
@@ -66,6 +66,21 @@ namespace OpenRa.Effects
Combat.DoImpact(Dest, VisualDest - new int2( 0, DestAltitude ),
Weapon, Projectile, Warhead, FiredBy);
}
+
+ if (Projectile.Trail != null)
+ {
+ var at = (float)t / TotalTime();
+ var altitude = float2.Lerp(SrcAltitude, DestAltitude, at);
+ var pos = float2.Lerp(Src.ToFloat2(), VisualDest.ToFloat2(), at)
+ - 0.5f * anim.Image.size - new float2(0, altitude);
+
+ var highPos = (Projectile.High || Projectile.Arcing)
+ ? (pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at)))
+ : pos;
+
+ world.AddFrameEndTask(w => w.Add(
+ new Smoke(w, highPos.ToInt2(), Projectile.Trail)));
+ }
}
const float height = .1f;
@@ -83,14 +98,14 @@ namespace OpenRa.Effects
if (Projectile.High || Projectile.Arcing)
{
if (Projectile.Shadow)
- yield return new Renderable(anim.Image, pos, PaletteType.Shadow);
+ yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, PaletteType.Shadow);
var highPos = pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at));
- yield return new Renderable(anim.Image, highPos, Owner.Palette);
+ yield return new Renderable(anim.Image, highPos - .5f * anim.Image.size, Owner.Palette);
}
else
- yield return new Renderable(anim.Image, pos, Projectile.UnderWater ? PaletteType.Shadow : Owner.Palette);
+ yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, Projectile.UnderWater ? PaletteType.Shadow : Owner.Palette);
}
}
}
diff --git a/OpenRa.Game/Effects/Missile.cs b/OpenRa.Game/Effects/Missile.cs
index 8d4a63c1c8..a22cb6d7b7 100755
--- a/OpenRa.Game/Effects/Missile.cs
+++ b/OpenRa.Game/Effects/Missile.cs
@@ -77,8 +77,9 @@ namespace OpenRa.Effects
var move = speed * -float2.FromAngle((float)angle);
Pos += move;
- if (Projectile.Animates)
- world.AddFrameEndTask(w => w.Add(new Smoke(w, (Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2())));
+ if (Projectile.Trail != null)
+ world.AddFrameEndTask(w => w.Add(
+ new Smoke(w, (Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2(), Projectile.Trail)));
// todo: running out of fuel
}
diff --git a/OpenRa.Game/Effects/Smoke.cs b/OpenRa.Game/Effects/Smoke.cs
index 33a04604d7..b3b3dfd97d 100755
--- a/OpenRa.Game/Effects/Smoke.cs
+++ b/OpenRa.Game/Effects/Smoke.cs
@@ -7,11 +7,12 @@ namespace OpenRa.Effects
class Smoke : IEffect
{
readonly int2 pos;
- readonly Animation anim = new Animation("smokey");
+ readonly Animation anim;
- public Smoke(World world, int2 pos)
+ public Smoke(World world, int2 pos, string trail)
{
this.pos = pos;
+ anim = new Animation(trail);
anim.PlayThen("idle",
() => world.AddFrameEndTask(w => w.Remove(this)));
}
diff --git a/OpenRa.Game/GameRules/ProjectileInfo.cs b/OpenRa.Game/GameRules/ProjectileInfo.cs
index 70140bf598..ca71245c0c 100644
--- a/OpenRa.Game/GameRules/ProjectileInfo.cs
+++ b/OpenRa.Game/GameRules/ProjectileInfo.cs
@@ -6,7 +6,7 @@ namespace OpenRa.GameRules
public readonly bool AA = false;
public readonly bool AG = true;
public readonly bool ASW = false;
- public readonly bool Animates = false;
+ public readonly string Trail = null;
public readonly bool Arcing = false;
public readonly int Arm = 0;
public readonly bool Degenerates = false;
diff --git a/merge-ra.yaml b/mods/ra/merge-rules.yaml
similarity index 100%
rename from merge-ra.yaml
rename to mods/ra/merge-rules.yaml
diff --git a/mods/ra/rules.ini b/mods/ra/rules.ini
index b58fd7412b..b6be525c34 100644
--- a/mods/ra/rules.ini
+++ b/mods/ra/rules.ini
@@ -2232,7 +2232,7 @@ Arm=10
High=yes
Shadow=no
Proximity=yes
-Animates=yes
+Trail=smokey
Ranged=yes
Inaccurate=yes
Image=V2
@@ -2244,7 +2244,7 @@ Arm=2
High=yes
Shadow=no
Proximity=yes
-Animates=yes
+Trail=smokey
Ranged=yes
Inaccurate=yes
AA=yes
@@ -2259,7 +2259,7 @@ Arm=3
High=yes
Shadow=no
Proximity=yes
-Animates=yes
+Trail=smokey
Ranged=yes
AA=yes
Image=DRAGON
@@ -2273,7 +2273,7 @@ Arm=3
High=yes
Shadow=no
Proximity=yes
-Animates=yes
+Trail=smokey
Ranged=yes
AA=yes
AG=no
@@ -2351,7 +2351,7 @@ Frames=4
; wizard's fireball
[Fireball]
-Animates=yes
+Trail=fb2
Image=FB1
Frames=8
diff --git a/mods/ra/rules.yaml b/mods/ra/rules.yaml
index c28a57d3d4..3c93971c62 100644
--- a/mods/ra/rules.yaml
+++ b/mods/ra/rules.yaml
@@ -930,6 +930,7 @@ FTUR:
Description: Flame Turret
LongDesc: Anti-Infantry base defense.\n Strong vs Infantry\n Weak vs Aircraft
Turreted:
+ ROT: 10
Building:
Power: -20
Footprint: x
@@ -941,6 +942,7 @@ FTUR:
RenderBuilding:
AttackTurreted:
PrimaryWeapon: FireballLauncher
+ PrimaryOffset: 0,0,12,8
AutoTarget:
IronCurtainable:
diff --git a/mods/ra/sequences.xml b/mods/ra/sequences.xml
index 2b8524610e..3ac12c0a76 100644
--- a/mods/ra/sequences.xml
+++ b/mods/ra/sequences.xml
@@ -375,7 +375,7 @@
-
+
@@ -1034,4 +1034,7 @@
+
+
+
\ No newline at end of file
diff --git a/mods/ra/units.ini b/mods/ra/units.ini
index 1fdf75dc95..9f85cc2f50 100644
--- a/mods/ra/units.ini
+++ b/mods/ra/units.ini
@@ -312,6 +312,8 @@ Dimensions=1,1
Footprint=x
SelectionPriority=3
LongDesc=Anti-Infantry base defense.\n Strong vs Infantry\n Weak vs Aircraft
+PrimaryOffset=0,0,12,8
+ROT=10
[SAM]
Description=SAM Site
Traits=Building, Turreted, RenderBuildingTurreted, AttackTurreted, AutoTarget, IronCurtainable