diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index f0977e2ca8..ee9401be26 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -208,6 +208,8 @@
+
+
diff --git a/OpenRa.Game/Traits/Crate.cs b/OpenRa.Game/Traits/Crate.cs
new file mode 100644
index 0000000000..34074a3fa5
--- /dev/null
+++ b/OpenRa.Game/Traits/Crate.cs
@@ -0,0 +1,52 @@
+using System.Collections.Generic;
+using System.Linq;
+using OpenRa.Effects;
+using OpenRa.Traits;
+
+namespace OpenRa.Traits
+{
+ class CrateInfo : ITraitInfo
+ {
+ public readonly int Lifetime = 5; // Seconds
+ public object Create(Actor self) { return new Crate(self); }
+ }
+
+ class Crate : ICrushable, IOccupySpace, ITick
+ {
+ readonly Actor self;
+ int ticks;
+ public Crate(Actor self)
+ {
+ this.self = self;
+ self.World.UnitInfluence.Add(self, this);
+ }
+
+ public void OnCrush(Actor crusher)
+ {
+ // TODO: Do Stuff
+
+
+ self.World.AddFrameEndTask(w => w.Remove(self));
+ }
+
+ public bool IsPathableCrush(UnitMovementType umt, Player player)
+ {
+ return true;
+ }
+
+ public bool IsCrushableBy(UnitMovementType umt, Player player)
+ {
+ return true;
+ }
+
+ public IEnumerable OccupiedCells() { yield return self.Location; }
+
+ public void Tick(Actor self)
+ {
+ if (++ticks >= self.Info.Traits.Get().Lifetime * 25)
+ {
+ self.World.AddFrameEndTask(w => w.Remove(self));
+ }
+ }
+ }
+}
diff --git a/OpenRa.Game/Traits/CrateSpawnPower.cs b/OpenRa.Game/Traits/CrateSpawnPower.cs
new file mode 100644
index 0000000000..244d71c132
--- /dev/null
+++ b/OpenRa.Game/Traits/CrateSpawnPower.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using OpenRa.Orders;
+
+namespace OpenRa.Traits
+{
+ class CrateSpawnPowerInfo : SupportPowerInfo
+ {
+ public readonly float Duration = 0f;
+ public override object Create(Actor self) { return new CrateSpawnPower(self, this); }
+ }
+
+ class CrateSpawnPower : SupportPower, IResolveOrder
+ {
+ public CrateSpawnPower(Actor self, CrateSpawnPowerInfo info) : base(self, info) { }
+
+ protected override void OnBeginCharging() {}
+ protected override void OnFinishCharging() {}
+ protected override void OnActivate()
+ {
+ Game.controller.orderGenerator = new SelectTarget();
+ }
+
+ public void ResolveOrder(Actor self, Order order)
+ {
+ if (order.OrderString == "SpawnCrate")
+ {
+ self.World.AddFrameEndTask(
+ w => w.CreateActor("crate", order.TargetLocation, self.Owner));
+
+ Game.controller.CancelInputMode();
+ FinishActivate();
+ }
+ }
+
+ class SelectTarget : IOrderGenerator
+ {
+ public SelectTarget() { }
+
+ public IEnumerable Order(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Right)
+ Game.controller.CancelInputMode();
+
+ return OrderInner(world, xy, mi);
+ }
+
+ IEnumerable OrderInner(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Left)
+ {
+ var loc = mi.Location + Game.viewport.Location;
+ var underCursor = world.FindUnits(loc, loc).FirstOrDefault();
+
+ if (underCursor == null)
+ yield return new Order("SpawnCrate", world.LocalPlayer.PlayerActor, xy);
+ }
+
+ yield break;
+ }
+
+ public void Tick(World world) { }
+
+ public void Render(World world) { }
+
+ public Cursor GetCursor(World world, int2 xy, MouseInput mi)
+ {
+ mi.Button = MouseButton.Left;
+ return OrderInner(world, xy, mi).Any()
+ ? Cursor.Ability : Cursor.MoveBlocked;
+ }
+ }
+ }
+}
diff --git a/mods/ra/merge-rules.yaml b/mods/ra/merge-rules.yaml
index 0be4beb212..8aea030be9 100644
--- a/mods/ra/merge-rules.yaml
+++ b/mods/ra/merge-rules.yaml
@@ -49,7 +49,13 @@ Player:
TechLevel: 5
GivenAuto: no
OneShot: yes
-
+ CrateSpawnPower:
+ Image: 4tnkicon
+ ChargeTime: 0.001
+ Description: Spawn Crate
+ LongDesc: Spawns a crate at a target location
+ Prerequisites: POWR
+ TechLevel: 12
World:
WaterPaletteRotation:
ChronoshiftPaletteEffect:
@@ -126,3 +132,10 @@ AGUN:
DOME:
RequiresPower:
CanPowerDown:
+
+CRATE:
+ Crate:
+ Unit:
+ HP: 1
+ RenderUnit:
+ BelowUnits:
diff --git a/mods/ra/rules.yaml b/mods/ra/rules.yaml
index 41a6489841..e39cf74022 100644
--- a/mods/ra/rules.yaml
+++ b/mods/ra/rules.yaml
@@ -49,6 +49,13 @@ Player:
TechLevel: 5
GivenAuto: no
OneShot: yes
+ CrateSpawnPower:
+ Image: 4tnkicon
+ ChargeTime: 0.001
+ Description: Spawn Crate
+ LongDesc: Spawns a crate at a target location
+ Prerequisites: POWR
+ TechLevel: 12
World:
WaterPaletteRotation:
@@ -415,6 +422,13 @@ DOME:
ProvidesRadar:
IronCurtainable:
+CRATE:
+ Crate:
+ Unit:
+ HP: 1
+ RenderUnit:
+ BelowUnits:
+
V2RL:
Inherits: ^Vehicle
Buildable:
diff --git a/mods/ra/sequences.xml b/mods/ra/sequences.xml
index 82bc9ecbc5..37b81b126e 100644
--- a/mods/ra/sequences.xml
+++ b/mods/ra/sequences.xml
@@ -1041,4 +1041,7 @@
+
+
+
\ No newline at end of file