diff --git a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj index 94b7de4d18..ee7d98b092 100644 --- a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj +++ b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj @@ -72,7 +72,7 @@ - + diff --git a/OpenRA.Mods.D2k/Traits/Carryable.cs b/OpenRA.Mods.D2k/Traits/Carryable.cs index fea29f56dd..4b22004407 100644 --- a/OpenRA.Mods.D2k/Traits/Carryable.cs +++ b/OpenRA.Mods.D2k/Traits/Carryable.cs @@ -7,16 +7,15 @@ * see COPYING. */ #endregion -using System; + using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; -using OpenRA.Mods.D2k.Activities; using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { - [Desc("Can be carried by units with the trait `AutoCarryall`.")] + [Desc("Can be carried by units with the trait `Carryall`.")] public class CarryableInfo : ITraitInfo { [Desc("Required distance away from destination before requesting a pickup.")] @@ -32,7 +31,7 @@ namespace OpenRA.Mods.D2k.Traits public bool Reserved { get; private set; } - // If we're locked there isnt much we can do. We'll have to wait for the carrier to finish with us. We should not move or get new orders! + // If we're locked there isn't much we can do. We'll have to wait for the carrier to finish with us. We should not move or get new orders! bool locked; public bool WantsTransport { get; private set; } @@ -62,15 +61,14 @@ namespace OpenRA.Mods.D2k.Traits Destination = destination; this.afterLandActivity = afterLandActivity; + WantsTransport = true; if (locked || Reserved) return; - WantsTransport = true; - // Inform all idle carriers - var carriers = self.World.ActorsWithTrait() - .Where(c => !c.Trait.Busy && !c.Actor.IsDead && c.Actor.Owner == self.Owner) + var carriers = self.World.ActorsWithTrait() + .Where(c => !c.Trait.IsBusy && !c.Actor.IsDead && c.Actor.Owner == self.Owner && c.Actor.IsInWorld) .OrderBy(p => (self.Location - p.Actor.Location).LengthSquared); foreach (var carrier in carriers) @@ -90,7 +88,7 @@ namespace OpenRA.Mods.D2k.Traits WantsTransport = false; afterLandActivity = null; - // TODO: We could implement something like a carrier.Trait().CancelTransportNotify(self) and call it here + // TODO: We could implement something like a carrier.Trait().CancelTransportNotify(self) and call it here } // We do not handle Harvested notification @@ -99,8 +97,8 @@ namespace OpenRA.Mods.D2k.Traits public Actor GetClosestIdleCarrier() { // Find carriers - var carriers = self.World.ActorsWithTrait() - .Where(p => p.Actor.Owner == self.Owner && !p.Trait.Busy) + var carriers = self.World.ActorsWithTrait() + .Where(p => p.Actor.Owner == self.Owner && !p.Trait.IsBusy && p.Actor.IsInWorld) .Select(h => h.Actor); return WorldUtils.ClosestTo(carriers, self); diff --git a/OpenRA.Mods.D2k/Traits/AutoCarryall.cs b/OpenRA.Mods.D2k/Traits/Carryall.cs similarity index 63% rename from OpenRA.Mods.D2k/Traits/AutoCarryall.cs rename to OpenRA.Mods.D2k/Traits/Carryall.cs index 7952689267..3129e086d9 100644 --- a/OpenRA.Mods.D2k/Traits/AutoCarryall.cs +++ b/OpenRA.Mods.D2k/Traits/Carryall.cs @@ -7,57 +7,63 @@ * see COPYING. */ #endregion -using System; + using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Traits; -using OpenRA.Mods.D2k.Activities; -using OpenRA.Mods.RA; -using OpenRA.Mods.RA.Traits; using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { - [Desc("Automatically transports harvesters with the Carryable trait between resource fields and refineries")] - public class AutoCarryallInfo : ITraitInfo, Requires + [Desc("Automatically transports harvesters with the Carryable trait between resource fields and refineries.")] + public class CarryallInfo : ITraitInfo, Requires { - public object Create(ActorInitializer init) { return new AutoCarryall(init.Self, this); } + [Desc("Set to false when the carryall should not automatically get new jobs.")] + public readonly bool Automatic = true; + + public object Create(ActorInitializer init) { return new Carryall(init.Self, this); } } - public class AutoCarryall : INotifyBecomingIdle, INotifyKilled, ISync, IRender + public class Carryall : INotifyBecomingIdle, INotifyKilled, ISync, IRender { readonly Actor self; readonly WRange carryHeight; + readonly CarryallInfo info; // The actor we are currently carrying. - [Sync] Actor carrying; - bool isCarrying; + [Sync] public Actor Carrying { get; internal set; } + public bool IsCarrying { get; internal set; } // TODO: Use ActorPreviews so that this can support actors with multiple sprites Animation anim; - public bool Busy { get; internal set; } + public bool IsBusy { get; internal set; } - public AutoCarryall(Actor self, AutoCarryallInfo info) + public Carryall(Actor self, CarryallInfo info) { this.self = self; + this.info = info; + + IsBusy = false; + IsCarrying = false; carryHeight = self.Trait().Info.LandAltitude; } public void OnBecomingIdle(Actor self) { - FindCarryableForTransport(); + if (info.Automatic) + FindCarryableForTransport(); - if (!Busy) + if (!IsBusy) self.QueueActivity(new HeliFlyCircle(self)); } // A carryable notifying us that he'd like to be carried public bool RequestTransportNotify(Actor carryable) { - if (Busy) + if (IsBusy || !info.Automatic) return false; if (ReserveCarryable(carryable)) @@ -71,29 +77,32 @@ namespace OpenRA.Mods.D2k.Traits void FindCarryableForTransport() { - // get all carryables who want transport + if (!self.IsInWorld) + return; + + // Get all carryables who want transport var carryables = self.World.ActorsWithTrait() .Where(p => - { - var actor = p.Actor; - if (actor == null) - return false; + { + var actor = p.Actor; + if (actor == null) + return false; - if (actor.Owner != self.Owner) - return false; + if (actor.Owner != self.Owner) + return false; - if (actor.IsDead) - return false; + if (actor.IsDead) + return false; - var trait = p.Trait; - if (trait.Reserved) - return false; + var trait = p.Trait; + if (trait.Reserved) + return false; - if (!trait.WantsTransport) - return false; + if (!trait.WantsTransport) + return false; - return true; - }) + return true; + }) .OrderBy(p => (self.Location - p.Actor.Location).LengthSquared); foreach (var p in carryables) @@ -112,8 +121,8 @@ namespace OpenRA.Mods.D2k.Traits { if (carryable.Trait().Reserve(self)) { - carrying = carryable; - Busy = true; + Carrying = carryable; + IsBusy = true; return true; } @@ -123,24 +132,26 @@ namespace OpenRA.Mods.D2k.Traits // Unreserve the carryable public void UnreserveCarryable() { - if (carrying != null) + if (Carrying != null) { - if (carrying.IsInWorld && !carrying.IsDead) - carrying.Trait().UnReserve(self); + if (Carrying.IsInWorld && !Carrying.IsDead) + Carrying.Trait().UnReserve(self); - carrying = null; + Carrying = null; } - Busy = false; + IsBusy = false; } // INotifyKilled public void Killed(Actor self, AttackInfo e) { - if (carrying != null) + if (Carrying != null) { - if (isCarrying && carrying.IsInWorld && !carrying.IsDead) - carrying.Kill(e.Attacker); + if (IsCarrying && Carrying.IsInWorld && !Carrying.IsDead) + Carrying.Kill(e.Attacker); + + Carrying = null; } UnreserveCarryable(); @@ -149,7 +160,9 @@ namespace OpenRA.Mods.D2k.Traits // Called when carryable is inside. public void AttachCarryable(Actor carryable) { - isCarrying = true; + IsBusy = true; + IsCarrying = true; + Carrying = carryable; // Create a new animation for our carryable unit var rs = carryable.Trait(); @@ -161,7 +174,7 @@ namespace OpenRA.Mods.D2k.Traits // Called when released public void CarryableReleased() { - isCarrying = false; + IsCarrying = false; anim = null; } @@ -171,7 +184,8 @@ namespace OpenRA.Mods.D2k.Traits if (anim != null && !self.World.FogObscures(self)) { anim.Tick(); - var renderables = anim.Render(self.CenterPosition + new WVec(0, 0, -carryHeight.Range), wr.Palette("player" + carrying.Owner.InternalName)); + var renderables = anim.Render(self.CenterPosition + new WVec(0, 0, -carryHeight.Range), + wr.Palette("player" + Carrying.Owner.InternalName)); foreach (var rr in renderables) yield return rr; diff --git a/mods/d2k/rules/aircraft.yaml b/mods/d2k/rules/aircraft.yaml index e3858bd7d7..9e3504c579 100644 --- a/mods/d2k/rules/aircraft.yaml +++ b/mods/d2k/rules/aircraft.yaml @@ -29,7 +29,7 @@ carryall.scripted: carryall: Inherits: carryall.scripted - AutoCarryall: + Carryall: Buildable: Queue: Aircraft BuildPaletteOrder: 120