diff --git a/OpenRa.Game/Controller.cs b/OpenRa.Game/Controller.cs
index 1b7ea5dc03..1ea516427e 100644
--- a/OpenRa.Game/Controller.cs
+++ b/OpenRa.Game/Controller.cs
@@ -162,6 +162,7 @@ namespace OpenRa.Game
else
return Cursor.MoveBlocked;
case "Enter": return Cursor.Enter;
+ case "Infiltrate": return Cursor.Enter;
case "Capture": return Cursor.Capture;
case "Harvest": return Cursor.Attack; // TODO: special harvest cursor?
default:
diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 20ad6b77ee..8d34a4ebf1 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -198,6 +198,7 @@
+
diff --git a/OpenRa.Game/PathFinder.cs b/OpenRa.Game/PathFinder.cs
index 210613a1e6..c93b0f1f6c 100644
--- a/OpenRa.Game/PathFinder.cs
+++ b/OpenRa.Game/PathFinder.cs
@@ -49,7 +49,7 @@ namespace OpenRa.Game
}
}
- Func AvoidUnitsNear(int2 p, int dist)
+ public Func AvoidUnitsNear(int2 p, int dist)
{
return q =>
p != q &&
diff --git a/OpenRa.Game/PathSearch.cs b/OpenRa.Game/PathSearch.cs
index 983634cbdf..931733726a 100755
--- a/OpenRa.Game/PathSearch.cs
+++ b/OpenRa.Game/PathSearch.cs
@@ -15,6 +15,7 @@ namespace OpenRa.Game
Func customBlock;
public bool checkForBlocked;
public bool ignoreTerrain;
+ public Actor ignoreBuilding;
public PathSearch()
{
@@ -28,6 +29,12 @@ namespace OpenRa.Game
return this;
}
+ public PathSearch WithIgnoredBuilding(Actor b)
+ {
+ ignoreBuilding = b;
+ return this;
+ }
+
public int2 Expand( float[][ , ] passableCost )
{
var p = queue.Pop();
@@ -49,7 +56,8 @@ namespace OpenRa.Game
{
if (passableCost[(int)umt][newHere.X, newHere.Y] == float.PositiveInfinity)
continue;
- if (!Game.BuildingInfluence.CanMoveHere(newHere))
+ if (!Game.BuildingInfluence.CanMoveHere(newHere) &&
+ Game.BuildingInfluence.GetBuildingAt(newHere) != ignoreBuilding)
continue;
if (Rules.Map.IsOverlaySolid(newHere))
continue;
diff --git a/OpenRa.Game/Traits/Activities/Move.cs b/OpenRa.Game/Traits/Activities/Move.cs
index e92863fea2..ebab176413 100755
--- a/OpenRa.Game/Traits/Activities/Move.cs
+++ b/OpenRa.Game/Traits/Activities/Move.cs
@@ -14,6 +14,7 @@ namespace OpenRa.Game.Traits.Activities
int nearEnough;
public List path;
Func> getPath;
+ public Actor ignoreBuilding;
MovePart move;
@@ -26,6 +27,18 @@ namespace OpenRa.Game.Traits.Activities
this.nearEnough = nearEnough;
}
+ public Move(int2 destination, Actor ignoreBuilding)
+ {
+ this.getPath = (self, mobile) =>
+ Game.PathFinder.FindPath(
+ PathSearch.FromPoint( self.Location, destination, mobile.GetMovementType(), false )
+ .WithCustomBlocker( Game.PathFinder.AvoidUnitsNear( self.Location, 4 )).WithIgnoredBuilding( ignoreBuilding ));
+
+ this.destination = destination;
+ this.nearEnough = 0;
+ this.ignoreBuilding = ignoreBuilding;
+ }
+
public Move( Actor target, int range )
{
this.getPath = ( self, mobile ) => Game.PathFinder.FindUnitPathToRange(
@@ -42,9 +55,11 @@ namespace OpenRa.Game.Traits.Activities
this.nearEnough = 0;
}
- static bool CanEnterCell( int2 c, Actor self )
+ bool CanEnterCell( int2 c, Actor self )
{
- if (!Game.BuildingInfluence.CanMoveHere(c)) return false;
+ if (!Game.BuildingInfluence.CanMoveHere(c)
+ && Game.BuildingInfluence.GetBuildingAt(c) != ignoreBuilding)
+ return false;
// Cannot enter a cell if any unit inside is uncrushable
// This will need to be updated for multiple-infantry-in-a-cell
diff --git a/OpenRa.Game/Traits/EngineerCapture.cs b/OpenRa.Game/Traits/EngineerCapture.cs
index 5703d0c59c..5a31ff027d 100644
--- a/OpenRa.Game/Traits/EngineerCapture.cs
+++ b/OpenRa.Game/Traits/EngineerCapture.cs
@@ -16,13 +16,13 @@ namespace OpenRa.Game.Traits
// todo: other bits
- return new Order(underCursor.Health <= EngineerDamage ? "Capture" : "Enter",
+ return new Order(underCursor.Health <= EngineerDamage ? "Capture" : "Infiltrate",
self, underCursor, int2.Zero, null);
}
public void ResolveOrder(Actor self, Order order)
{
- if (order.OrderString == "Enter" || order.OrderString == "Capture")
+ if (order.OrderString == "Infiltrate" || order.OrderString == "Capture")
{
self.CancelActivity();
self.QueueActivity(new Move(order.TargetActor, 1));
diff --git a/OpenRa.Game/Traits/Repairable.cs b/OpenRa.Game/Traits/Repairable.cs
new file mode 100644
index 0000000000..b5cafac857
--- /dev/null
+++ b/OpenRa.Game/Traits/Repairable.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using OpenRa.Game.Traits.Activities;
+
+namespace OpenRa.Game.Traits
+{
+ class Repairable : IOrder
+ {
+ IDisposable reservation;
+ public Repairable(Actor self) { }
+
+ public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
+ {
+ if (mi.Button != MouseButton.Right) return null;
+ if (underCursor == null) return null;
+
+ if (underCursor.Info == Rules.UnitInfo["FIX"]
+ && underCursor.Owner == self.Owner
+ && !Reservable.IsReserved(underCursor))
+ return new Order("Enter", self, underCursor, int2.Zero, null);
+
+ return null;
+ }
+
+ public void ResolveOrder(Actor self, Order order)
+ {
+ if (reservation != null)
+ {
+ reservation.Dispose();
+ reservation = null;
+ }
+
+ if (order.OrderString == "Enter")
+ {
+ if (Reservable.IsReserved(order.TargetActor))
+ return;
+
+ var res = order.TargetActor.traits.GetOrDefault();
+ if (res != null) reservation = res.Reserve(self);
+
+ self.CancelActivity();
+ self.QueueActivity(new Move(((1 / 24f) * order.TargetActor.CenterLocation).ToInt2(), order.TargetActor));
+ self.QueueActivity(new Rearm());
+ self.QueueActivity(new Repair());
+ }
+ }
+ }
+}
diff --git a/doc/progress.txt b/doc/progress.txt
index 0013085c6c..bcc268c1fb 100644
--- a/doc/progress.txt
+++ b/doc/progress.txt
@@ -22,7 +22,7 @@ All tracked vehicles
Light vehicles
V2RL Works
APC Cargo doesn't work
-MNLY Can't reload at FIX
+MNLY Works
MGG No gap
MRJ No radar
JEEP Works
@@ -31,15 +31,15 @@ HARV Works
ARTY Works
Helicopters
- - Repair as FIX doesn't work
+ - Return to base after attack doesnt work
TRAN Cargo doesn't work
-HELI Weapon offsets wrong
-HIND Weapon offsets wrong
+HELI Works
+HIND Works
-Planes
- - Repair at FIX doesn't work [fix doesn't work?]
-YAK Ammo/ROF are funky
-MIG Ammo/ROF are funky
+Planes
+ - Ammo/ROF are funky
+YAK Works
+MIG Works
Ships
diff --git a/units.ini b/units.ini
index b6eb87044c..6d8a795165 100644
--- a/units.ini
+++ b/units.ini
@@ -16,47 +16,47 @@ MNLY.AT
[V2RL]
Description=V2 Rocket
-Traits=Unit, Mobile, AttackBase, RenderUnitReload, AutoTarget
+Traits=Unit, Mobile, AttackBase, RenderUnitReload, AutoTarget, Repairable
Voice=VehicleVoice
LongDesc=Long-range rocket artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
[1TNK]
Description=Light Tank
-Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
+Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
Recoil=2
Voice=VehicleVoice
LongDesc=Light Tank, good for scouting.\n Strong vs Light Vehicles\n Weak vs Tanks, Aircraft
[2TNK]
Description=Medium Tank
-Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
+Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
Recoil=3
Voice=VehicleVoice
LongDesc=Allied Main Battle Tank.\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
[3TNK]
Description=Heavy Tank
-Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
+Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
Recoil=3
Voice=VehicleVoice
LongDesc=Soviet Main Battle Tank, with dual cannons\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft
[4TNK]
Description=Mammoth Tank
-Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
+Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
Voice=VehicleVoice
LongDesc=Big and slow tank, with anti-air capability.\n Strong vs Tanks, Aircraft\n Weak vs Infantry
[ARTY]
Description=Artillery
-Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget
+Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable
Voice=VehicleVoice
LongDesc=Long-range artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
[JEEP]
Description=Ranger
-Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
+Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
PrimaryOffset=0,0,0,-2
MuzzleFlash=yes
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
+Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash, AutoTarget, Repairable
PrimaryOffset=0,0,0,-4
MuzzleFlash=yes
Voice=VehicleVoice
@@ -65,40 +65,40 @@ LongDesc=Tough infantry transport.\n Strong vs Infantry, Light Vehicles\n Weak
;; non-combat vehicles
[MRJ]
Description=Radar Jammer
-Traits=Unit, Mobile, RenderUnitSpinner
+Traits=Unit, Mobile, RenderUnitSpinner, Repairable
PrimaryOffset=0,4,0,-6
SelectionPriority=3
Voice=VehicleVoice
LongDesc=Hides nearby units on the enemy's minimap.\n Unarmed
[MGG]
Description=Mobile Gap Generator
-Traits=Unit, Mobile, RenderUnitSpinner
+Traits=Unit, Mobile, RenderUnitSpinner, Repairable
PrimaryOffset=0,6,0,-3
SelectionPriority=3
Voice=VehicleVoice
LongDesc=Regenerates Fog of War in a small area \naround the unit.\n Unarmed
[HARV]
Description=Ore Truck
-Traits=Harvester, Unit, Mobile, RenderUnit
+Traits=Harvester, Unit, Mobile, RenderUnit, Repairable
SelectionPriority=7
Voice=VehicleVoice
LongDesc=Collects Ore and Gems for processing.\n Unarmed
[MCV]
Description=Mobile Construction Vehicle
-Traits=Unit, Mobile, McvDeploy, RenderUnit
+Traits=Unit, Mobile, McvDeploy, RenderUnit, Repairable
SelectionPriority=3
Voice=VehicleVoice
LongDesc=Deploys into another Construction Yard.\n Unarmed
[MNLY.AP]
Description=Minelayer (Anti-Personnel)
-Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune
+Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable
Voice=VehicleVoice
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
Primary=MINP ;; temporary hack
[MNLY.AT]
Description=Minelayer (Anti-Tank)
-Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune
+Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable
Voice=VehicleVoice
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
Primary=MINV ;; temporary hack