diff --git a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj
index 39acd08bc9..0a64324e53 100644
--- a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj
+++ b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj
@@ -92,6 +92,7 @@
+
diff --git a/OpenRA.Mods.D2k/Traits/SpiceBloom.cs b/OpenRA.Mods.D2k/Traits/SpiceBloom.cs
new file mode 100644
index 0000000000..aec763cc9d
--- /dev/null
+++ b/OpenRA.Mods.D2k/Traits/SpiceBloom.cs
@@ -0,0 +1,148 @@
+#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.Linq;
+using OpenRA.Effects;
+using OpenRA.GameRules;
+using OpenRA.Graphics;
+using OpenRA.Mods.Common.Traits;
+using OpenRA.Primitives;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.D2k.Traits
+{
+ [Desc("Seeds resources by explosive eruptions after accumulation times.")]
+ public class SpiceBloomInfo : ITraitInfo, Requires
+ {
+ [SequenceReference]
+ public readonly string[] GrowthSequences = { "grow1", "grow2", "grow3" };
+
+ [Desc("The range of time (in ticks) that the spicebloom will take to respawn.")]
+ public readonly int[] RespawnDelay = { 1500, 2500 };
+
+ [Desc("The range of time (in ticks) that the spicebloom will take to grow.")]
+ public readonly int[] GrowthDelay = { 1000, 1500 };
+
+ public readonly string ResourceType = "Spice";
+
+ [Desc("The weapon to use for spice creation.")]
+ [WeaponReference]
+ public readonly string Weapon = "SpiceExplosion";
+
+ [Desc("The amount of spice to expel.")]
+ public readonly int[] Pieces = { 3, 10 };
+
+ [Desc("The maximum distance in cells that spice may be expelled.")]
+ public readonly int Range = 5;
+
+ public object Create(ActorInitializer init) { return new SpiceBloom(init, this); }
+ }
+
+ public class SpiceBloom : ITick, INotifyKilled
+ {
+ readonly Actor self;
+ readonly SpiceBloomInfo info;
+ readonly ResourceType resType;
+ readonly ResourceLayer resLayer;
+ readonly AnimationWithOffset anim;
+
+ readonly int respawnTicks;
+ readonly int growTicks;
+ int ticks;
+
+ public SpiceBloom(ActorInitializer init, SpiceBloomInfo info)
+ {
+ this.info = info;
+ self = init.Self;
+
+ resLayer = self.World.WorldActor.Trait();
+ resType = self.World.WorldActor.TraitsImplementing().First(t => t.Info.Name == info.ResourceType);
+
+ var render = self.Trait();
+ anim = new AnimationWithOffset(new Animation(init.Self.World, render.GetImage(self)), null, () => self.IsDead);
+ render.Add(anim);
+
+ respawnTicks = self.World.SharedRandom.Next(info.RespawnDelay[0], info.RespawnDelay[1]);
+ growTicks = self.World.SharedRandom.Next(info.GrowthDelay[0], info.GrowthDelay[1]);
+ anim.Animation.Play(info.GrowthSequences[0]);
+ }
+
+ public void Tick(Actor self)
+ {
+ ticks++;
+
+ if (ticks >= growTicks)
+ self.Kill(self);
+ else
+ {
+ var index = info.GrowthSequences.Length * ticks / growTicks;
+ anim.Animation.Play(info.GrowthSequences[index]);
+ }
+ }
+
+ public void Killed(Actor self, AttackInfo e)
+ {
+ var args = new ProjectileArgs
+ {
+ Weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()],
+ Facing = 0,
+
+ DamageModifiers = self.TraitsImplementing()
+ .Select(a => a.GetFirepowerModifier()).ToArray(),
+
+ InaccuracyModifiers = self.TraitsImplementing()
+ .Select(a => a.GetInaccuracyModifier()).ToArray(),
+
+ Source = self.CenterPosition,
+ SourceActor = self,
+ };
+
+ var pieces = self.World.SharedRandom.Next(info.Pieces[0], info.Pieces[1]) * ticks / growTicks;
+ for (var i = 0; pieces > i; i++)
+ {
+ var cells = OpenRA.Traits.Util.RandomWalk(self.Location, self.World.SharedRandom);
+ var cell = cells.Take(info.Range).SkipWhile(p => resLayer.GetResource(p) == resType && resLayer.IsFull(p)).Cast().RandomOrDefault(self.World.SharedRandom);
+ if (cell == null)
+ cell = cells.Take(info.Range).Random(self.World.SharedRandom);
+
+ args.PassiveTarget = self.World.Map.CenterOfCell(cell.Value);
+
+ self.World.AddFrameEndTask(_ =>
+ {
+ if (args.Weapon.Projectile != null)
+ {
+ var projectile = args.Weapon.Projectile.Create(args);
+ if (projectile != null)
+ self.World.Add(projectile);
+
+ if (args.Weapon.Report != null && args.Weapon.Report.Any())
+ Game.Sound.Play(args.Weapon.Report.Random(self.World.SharedRandom), self.CenterPosition);
+ }
+ });
+ }
+
+ self.World.AddFrameEndTask(t => t.Add(new DelayedAction(respawnTicks, () =>
+ {
+ var td = new TypeDictionary
+ {
+ new ParentActorInit(self),
+ new LocationInit(self.Location),
+ new CenterPositionInit(self.CenterPosition),
+ new OwnerInit(self.Owner),
+ new FactionInit(self.Owner.Faction.InternalName),
+ new SkipMakeAnimsInit()
+ };
+ self.World.CreateActor(self.Info.Name, td);
+ })));
+ }
+ }
+}
diff --git a/mods/d2k/bits/spicebloom.shp b/mods/d2k/bits/spicebloom.shp
deleted file mode 100644
index 0e0bb76d3f..0000000000
Binary files a/mods/d2k/bits/spicebloom.shp and /dev/null differ
diff --git a/mods/d2k/rules/arrakis.yaml b/mods/d2k/rules/arrakis.yaml
index fafde1bb88..f03cc2aa6a 100644
--- a/mods/d2k/rules/arrakis.yaml
+++ b/mods/d2k/rules/arrakis.yaml
@@ -1,20 +1,29 @@
spicebloom:
- Inherits@1: ^SpriteActor
HiddenUnderShroud:
- WithSpriteBody:
- Building:
- Footprint: x
- Dimensions: 1,1
+ BodyOrientation:
+ QuantizedFacings: 1
+ AutoSelectionSize:
+ RenderSprites:
AppearsOnRadar:
+ UseLocation: yes
Tooltip:
Name: Spice Bloom
- SeedsResource:
- ResourceType: Spice
- Interval: 75
- WithActiveAnimation:
+ SpiceBloom:
+ Weapon: SpiceExplosion
+ Crushable:
+ CrushClasses: spicebloom
+ CrushedByFriendlies: true
RadarColorFromTerrain:
Terrain: Spice
- WithMakeAnimation:
+ Immobile:
+ Health:
+ HP: 1
+ Radius: 512
+ Targetable:
+ TargetTypes: Ground
+ RequiresForceFire: yes
+ Armor:
+ Type: None
sandworm:
Inherits@1: ^SpriteActor
diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml
index 5d618528d9..b3ab29fe3c 100644
--- a/mods/d2k/rules/defaults.yaml
+++ b/mods/d2k/rules/defaults.yaml
@@ -58,7 +58,7 @@
Inherits@2: ^GainsExperience
Inherits@3: ^SpriteActor
Mobile:
- Crushes: crate
+ Crushes: crate, spicebloom
TerrainSpeeds:
Sand: 100
Rock: 100
@@ -99,7 +99,7 @@
^Tank:
Inherits: ^Vehicle
Mobile:
- Crushes: crate, infantry
+ Crushes: crate, infantry, spicebloom
^Husk:
Inherits@1: ^SpriteActor
@@ -165,7 +165,7 @@
RevealsShroud:
Range: 6c0
Mobile:
- Crushes: crate
+ Crushes: crate, spicebloom
SharesCell: true
TerrainSpeeds:
Sand: 100
diff --git a/mods/d2k/rules/vehicles.yaml b/mods/d2k/rules/vehicles.yaml
index f6dffa3d99..d36e7bcd54 100644
--- a/mods/d2k/rules/vehicles.yaml
+++ b/mods/d2k/rules/vehicles.yaml
@@ -20,7 +20,7 @@ mcv:
Type: light
Mobile:
Speed: 31
- Crushes: crate, infantry
+ Crushes: crate, infantry, spicebloom
RevealsShroud:
Range: 8c0
MustBeDestroyed:
@@ -73,7 +73,7 @@ harvester:
Type: harvester
Mobile:
Speed: 43
- Crushes: crate, infantry
+ Crushes: crate, infantry, spicebloom
RevealsShroud:
Range: 4c0
Explodes:
@@ -184,7 +184,6 @@ siege_tank:
Mobile:
Speed: 43
ROT: 3
- Crushes: crate, infantry
RevealsShroud:
Range: 8c0
Turreted:
@@ -304,7 +303,6 @@ devastator:
Mobile:
ROT: 3
Speed: 31
- Crushes: crate, infantry
RevealsShroud:
Range: 7c0
Armament:
@@ -440,7 +438,6 @@ deviator:
Mobile:
Speed: 75
ROT: 5
- Crushes: crate, infantry
RevealsShroud:
Range: 8c0
Turreted:
@@ -499,7 +496,6 @@ combat_tank_o:
Mobile:
Speed: 85
ROT: 5
- Crushes: crate, infantry
Health:
HP: 1800
SpawnActorOnDeath:
diff --git a/mods/d2k/sequences/misc.yaml b/mods/d2k/sequences/misc.yaml
index 1b3c5ec0b0..756bf5dba3 100644
--- a/mods/d2k/sequences/misc.yaml
+++ b/mods/d2k/sequences/misc.yaml
@@ -327,19 +327,20 @@ crate:
ZOffset: -511
Offset: -16,-16
-# TODO: keep the redundant spicebloom.shp for now for the awful WinForms maps editor
spicebloom:
- make: DATA.R8
+ grow1: DATA.R8
Start: 107
- Length: 3
+ Length: 1
ZOffset: -1023
Offset: -16,-16
- active: DATA.R8
- Start: 109
+ grow2: DATA.R8
+ Start: 108
+ Length: 1
ZOffset: -1023
Offset: -16,-16
- idle: DATA.R8
+ grow3: DATA.R8
Start: 109
+ Length: 1
ZOffset: -1023
Offset: -16,-16
diff --git a/mods/d2k/weapons.yaml b/mods/d2k/weapons.yaml
index 85e50dd447..9ec67da457 100644
--- a/mods/d2k/weapons.yaml
+++ b/mods/d2k/weapons.yaml
@@ -829,6 +829,13 @@ SardDeath:
ImpactSound: EXPLSML2.WAV
SpiceExplosion:
+ Report: EXPLMD1.WAV
+ Projectile: Bullet
+ Speed: 50, 75
+ High: true
+ Angle: 91, 264
+ Trail: large_trail
+ Image: null
Warhead@1Dam: SpreadDamage
Spread: 480
Falloff: 100, 100, 100, 95, 60, 25, 0