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