diff --git a/OpenRa.Game/GameRules/UnitInfo.cs b/OpenRa.Game/GameRules/UnitInfo.cs
index 8401ae04ef..a1dc335a46 100755
--- a/OpenRa.Game/GameRules/UnitInfo.cs
+++ b/OpenRa.Game/GameRules/UnitInfo.cs
@@ -55,13 +55,14 @@ namespace OpenRa.Game.GameRules
public readonly int OrePips = 0;
public readonly string Icon = null;
public readonly int[] SelectionSize = null;
+ public readonly int Passengers = 0;
+ public readonly int UnloadFacing = 0;
public UnitInfo(string name) { Name = name; }
}
public class MobileInfo : UnitInfo
{
- public readonly int Passengers = 0;
public readonly int Speed = 0;
public readonly bool NoMovingFire = false;
public readonly string Voice = "GenericVoice";
diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 72f4caec37..ef9bea264e 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -185,6 +185,7 @@
+
@@ -198,6 +199,7 @@
+
diff --git a/OpenRa.Game/Traits/Activities/UnloadCargo.cs b/OpenRa.Game/Traits/Activities/UnloadCargo.cs
new file mode 100644
index 0000000000..3a620f8ab4
--- /dev/null
+++ b/OpenRa.Game/Traits/Activities/UnloadCargo.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OpenRa.Game.Traits.Activities
+{
+ class UnloadCargo : IActivity
+ {
+ public IActivity NextActivity { get; set; }
+ bool isCanceled;
+
+ public IActivity Tick(Actor self)
+ {
+ if (isCanceled) return NextActivity;
+
+ // if we're a thing that can turn, turn to the
+ // right facing for the unload animation
+ var unit = self.traits.GetOrDefault();
+ if (unit != null && unit.Facing != self.Info.UnloadFacing)
+ return Util.SequenceActivities(new Turn(self.Info.UnloadFacing), this);
+
+ // todo: play the `open` anim (or the `close` anim backwards)
+ // todo: unload all the cargo
+ // todo: play the `close` anim (or the `open` anim backwards)
+
+ // as for open/close... the westwood guys suck at being consistent.
+
+ return this;
+ }
+
+ public void Cancel(Actor self) { NextActivity = null; isCanceled = true; }
+ }
+}
diff --git a/OpenRa.Game/Traits/Cargo.cs b/OpenRa.Game/Traits/Cargo.cs
new file mode 100644
index 0000000000..a1202b5440
--- /dev/null
+++ b/OpenRa.Game/Traits/Cargo.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using OpenRa.Game.GameRules;
+
+namespace OpenRa.Game.Traits
+{
+ class Cargo : IPips, IOrder
+ {
+ List cargo = new List();
+
+ public Cargo(Actor self) { }
+
+ public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
+ {
+ // todo: check if there is an unoccupied `land` tile adjacent
+ if (mi.Button == MouseButton.Right && underCursor == self && cargo.Count > 0)
+ return new Order("Deploy", self, null, int2.Zero, null);
+
+ return null;
+ }
+
+ public void ResolveOrder(Actor self, Order order)
+ {
+ if (order.OrderString == "Deploy")
+ {
+ // todo: eject the units
+ self.CancelActivity();
+ }
+ }
+
+ public bool IsFull(Actor self)
+ {
+ return cargo.Count == self.Info.Passengers;
+ }
+
+ public IEnumerable GetPips( Actor self )
+ {
+ for (var i = 0; i < self.Info.Passengers; i++)
+ if (i >= cargo.Count)
+ yield return PipType.Transparent;
+ else
+ yield return GetPipForPassenger(cargo[i]);
+ }
+
+ static PipType GetPipForPassenger(Actor a)
+ {
+ // probably not actually right yet; fix to match real-ra
+
+ if (a.traits.Contains())
+ return PipType.Yellow;
+ if (!a.traits.WithInterface().Any())
+ return PipType.Yellow; // noncombat [E6,SPY,THF]
+ if (a.traits.Contains())
+ return PipType.Red; // E7
+
+ return PipType.Green;
+ }
+ }
+}
diff --git a/sequences.xml b/sequences.xml
index f659cf186a..a56029f90d 100644
--- a/sequences.xml
+++ b/sequences.xml
@@ -283,6 +283,8 @@
+
+
@@ -376,7 +378,7 @@
-
+
@@ -536,6 +538,8 @@
+
+
@@ -572,6 +576,8 @@
+
+
@@ -1008,8 +1014,8 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/units.ini b/units.ini
index 5b0d90121e..76c9ac4a54 100644
--- a/units.ini
+++ b/units.ini
@@ -56,7 +56,7 @@ Voice=VehicleVoice
LongDesc=Fast scout & anti-infantry vehicle.\n Strong vs Infantry\n Weak vs Tanks, Aircraft
[APC]
Description=Armored Personnel Carrier
-Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash, AutoTarget, Repairable, Chronoshiftable
+Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash, AutoTarget, Repairable, Chronoshiftable, Cargo
PrimaryOffset=0,0,0,-4
MuzzleFlash=yes
Voice=VehicleVoice
@@ -138,7 +138,7 @@ Recoil=3
[LST]
Description=Transport
WaterBound=yes
-Traits=Unit, Mobile, RenderUnit
+Traits=Unit, Mobile, RenderUnit, Cargo
LongDesc=General-purpose naval transport.\nCan carry infantry and tanks.\n Unarmed
[PT]
Description=Gunboat
@@ -179,7 +179,7 @@ Description=Transport Helicopter
RotorOffset=0,14,0,-4
RotorOffset2=0,-14,0,-2
BuiltAt=hpad
-Traits=Unit, Helicopter, RenderUnitRotor, WithShadow
+Traits=Unit, Helicopter, RenderUnitRotor, WithShadow, Cargo
InitialFacing=20
LongDesc=Fast Infantry Transport Helicopter.\n Unarmed
[HELI]