diff --git a/OpenRA.Mods.RA/Bridge.cs b/OpenRA.Mods.RA/Bridge.cs index 3b54562b6d..206ce3bd5c 100644 --- a/OpenRA.Mods.RA/Bridge.cs +++ b/OpenRA.Mods.RA/Bridge.cs @@ -80,10 +80,12 @@ namespace OpenRA.Mods.RA readonly BridgeInfo info; readonly string type; + readonly Lazy isDangling; ushort template; Dictionary footprint; - public BridgeHut Hut { get; internal set; } + public BridgeHut Hut { get; private set; } + public bool IsDangling { get { return isDangling.Value; } } public Bridge(Actor self, BridgeInfo info) { @@ -92,6 +94,7 @@ namespace OpenRA.Mods.RA health.RemoveOnDeath = false; this.info = info; type = self.Info.Name; + isDangling = new Lazy(() => huts[0] == huts[1] && (neighbours[0] == null || neighbours[1] == null)); building = self.Trait(); } @@ -144,18 +147,24 @@ namespace OpenRA.Mods.RA } } - public BridgeHut GetHut(int index) + internal void AddHut(BridgeHut hut) { - if (huts[index] != null) - return huts[index]; // Already found - - var n = neighbours[index]; - if (n == null) - return huts[index] = Hut; // End piece - - return huts[index] = n.Hut ?? n.GetHut(index); + if (huts[0] == huts[1]) + huts[1] = hut; + if (Hut == null) + { + Hut = hut; // Assume only one until called again + if (huts[0] == null) + huts[0] = hut; // Set only first time + for (var d = 0; d <= 1; d++) + for (var b = neighbours[d]; b != null; b = b.Hut == null ? b.neighbours[d] : null) + b.huts[1 - d] = hut; + } + else + Hut = null; } + public BridgeHut GetHut(int index) { return huts[index]; } public Bridge GetNeighbor(int[] offset, BridgeLayer bridges) { if (offset == null) @@ -309,7 +318,7 @@ namespace OpenRA.Mods.RA { if (b.health.DamageState > damage) damage = b.health.DamageState; - if (b.Hut == null && b.neighbours[d] != null) + if (b.Hut == null && d >= 0 && b.neighbours[d] != null) AggregateDamageState(b.neighbours[d], d, ref damage); } diff --git a/OpenRA.Mods.RA/BridgeHut.cs b/OpenRA.Mods.RA/BridgeHut.cs index 00bdd898ab..416bc7c15b 100644 --- a/OpenRA.Mods.RA/BridgeHut.cs +++ b/OpenRA.Mods.RA/BridgeHut.cs @@ -23,18 +23,17 @@ namespace OpenRA.Mods.RA class BridgeHut : IDemolishable { - Lazy firstBridge; - int repairDirections = 0; + public readonly Bridge FirstBridge; public readonly Bridge Bridge; - public Bridge FirstBridge { get { return firstBridge.Value; } } public DamageState BridgeDamageState { get { return Bridge.AggregateDamageState(); } } public bool Repairing { get { return repairDirections > 0; } } + int repairDirections = 0; public BridgeHut(ActorInitializer init) { Bridge = init.Get().value.Trait(); - Bridge.Hut = this; - firstBridge = new Lazy(() => Bridge.Enumerate(0, true).Last()); + Bridge.AddHut(this); + FirstBridge = Bridge.Enumerate(0, true).Last(); } public void Repair(Actor repairer) diff --git a/OpenRA.Mods.RA/RepairsBridges.cs b/OpenRA.Mods.RA/RepairsBridges.cs index 7d923e06ae..48f0ca6c50 100644 --- a/OpenRA.Mods.RA/RepairsBridges.cs +++ b/OpenRA.Mods.RA/RepairsBridges.cs @@ -38,22 +38,22 @@ namespace OpenRA.Mods.RA if (order.OrderString != "RepairBridge") return null; - var bridge = order.TargetActor.TraitOrDefault(); - if (bridge == null) + var hut = order.TargetActor.TraitOrDefault(); + if (hut == null) return null; - return bridge.BridgeDamageState > DamageState.Undamaged ? "Attack" : null; + return hut.BridgeDamageState == DamageState.Undamaged || hut.Repairing || hut.Bridge.IsDangling ? null : "Attack"; } public void ResolveOrder(Actor self, Order order) { if (order.OrderString == "RepairBridge") { - var bridge = order.TargetActor.TraitOrDefault(); - if (bridge == null) + var hut = order.TargetActor.TraitOrDefault(); + if (hut == null) return; - if (bridge.BridgeDamageState == DamageState.Undamaged) + if (hut.BridgeDamageState == DamageState.Undamaged || hut.Repairing || hut.Bridge.IsDangling) return; self.SetTargetLine(Target.FromOrder(self.World, order), Color.Yellow); @@ -70,12 +70,12 @@ namespace OpenRA.Mods.RA public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - var bridge = target.TraitOrDefault(); - if (bridge == null) + var hut = target.TraitOrDefault(); + if (hut == null) return false; // Require force attack to heal partially damaged bridges to avoid unnecessary cursor noise - var damage = bridge.BridgeDamageState; + var damage = hut.BridgeDamageState; if (!modifiers.HasModifier(TargetModifiers.ForceAttack) && damage != DamageState.Dead) return false; @@ -83,8 +83,8 @@ namespace OpenRA.Mods.RA if (modifiers.HasModifier(TargetModifiers.ForceMove)) return false; - // Can't repair an undamaged bridge - if (damage == DamageState.Undamaged) + // Can't repair a bridge that is undamaged, already under repair, or dangling + if (damage == DamageState.Undamaged || hut.Repairing || hut.Bridge.IsDangling) cursor = "goldwrench-blocked"; return true; diff --git a/mods/ra/maps/intervention/map.yaml b/mods/ra/maps/intervention/map.yaml index 1629c17027..238a9a0c31 100644 --- a/mods/ra/maps/intervention/map.yaml +++ b/mods/ra/maps/intervention/map.yaml @@ -2240,7 +2240,6 @@ Rules: Inherits: E6 Buildable: Prerequisites: ~barracks - -RepairsBridges: Captures: CaptureTypes: building Sabotage: False