From 4c50757b1817a56e90f10593e9a5e6f041f2384d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Tue, 27 May 2014 17:14:05 +0200 Subject: [PATCH 1/3] catch trait lookup in constructor closes #5472 --- OpenRA.Mods.Cnc/ProductionAirdrop.cs | 6 +++--- OpenRA.Mods.RA/Production.cs | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/OpenRA.Mods.Cnc/ProductionAirdrop.cs b/OpenRA.Mods.Cnc/ProductionAirdrop.cs index 39bbfd6f54..61db327831 100644 --- a/OpenRA.Mods.Cnc/ProductionAirdrop.cs +++ b/OpenRA.Mods.Cnc/ProductionAirdrop.cs @@ -25,13 +25,13 @@ namespace OpenRA.Mods.Cnc [Desc("Cargo aircraft used.")] [ActorReference] public readonly string ActorType = "c17"; - public override object Create(ActorInitializer init) { return new ProductionAirdrop(this); } + public override object Create(ActorInitializer init) { return new ProductionAirdrop(this, init.self); } } class ProductionAirdrop : Production { - public ProductionAirdrop(ProductionAirdropInfo info) - : base(info) { } + public ProductionAirdrop(ProductionAirdropInfo info, Actor self) + : base(info, self) { } public override bool Produce(Actor self, ActorInfo producee) { diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index 8a03489bec..4d24f28d7c 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA [Desc("e.g. Infantry, Vehicles, Aircraft, Buildings")] public readonly string[] Produces = { }; - public virtual object Create(ActorInitializer init) { return new Production(this); } + public virtual object Create(ActorInitializer init) { return new Production(this, init.self); } } [Desc("Where the unit should leave the building. Multiples are allowed if IDs are added: Exit@2, ...")] @@ -41,10 +41,13 @@ namespace OpenRA.Mods.RA public class Production { + RallyPoint rp; + public ProductionInfo Info; - public Production(ProductionInfo info) + public Production(ProductionInfo info, Actor self) { Info = info; + rp = self.TraitOrDefault(); } public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) @@ -77,9 +80,8 @@ namespace OpenRA.Mods.RA }); } - static CPos MoveToRallyPoint(Actor self, Actor newUnit, CPos exitLocation) + CPos MoveToRallyPoint(Actor self, Actor newUnit, CPos exitLocation) { - var rp = self.TraitOrDefault(); if (rp == null) return exitLocation; From c1f8a8e3155044eeb777e8a297e1858b01381b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Wed, 28 May 2014 10:51:53 +0200 Subject: [PATCH 2/3] move RallyPoint lookup into a Lazy --- OpenRA.Mods.RA/Production.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index 4d24f28d7c..e724273ee6 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Drawing; using System.Linq; using OpenRA.Mods.RA.Move; @@ -41,13 +42,13 @@ namespace OpenRA.Mods.RA public class Production { - RallyPoint rp; + Lazy rp; public ProductionInfo Info; public Production(ProductionInfo info, Actor self) { Info = info; - rp = self.TraitOrDefault(); + rp = Exts.Lazy(() => self.TraitOrDefault()); } public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) @@ -82,15 +83,15 @@ namespace OpenRA.Mods.RA CPos MoveToRallyPoint(Actor self, Actor newUnit, CPos exitLocation) { - if (rp == null) + if (self.IsDead() || rp.Value == null) return exitLocation; var move = newUnit.TraitOrDefault(); if (move != null) { newUnit.QueueActivity(new AttackMove.AttackMoveActivity( - newUnit, move.MoveTo(rp.rallyPoint, rp.nearEnough))); - return rp.rallyPoint; + newUnit, move.MoveTo(rp.Value.rallyPoint, rp.Value.nearEnough))); + return rp.Value.rallyPoint; } return exitLocation; From a900f244667ea6797f15fca4ed93499e5f26395a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Sat, 31 May 2014 16:04:59 +0200 Subject: [PATCH 3/3] calculate exitLocation before FrameEndTask and add more null and dead checks to be safe --- OpenRA.Mods.RA/Production.cs | 43 ++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index e724273ee6..af5abf263e 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA public Production(ProductionInfo info, Actor self) { Info = info; - rp = Exts.Lazy(() => self.TraitOrDefault()); + rp = Exts.Lazy(() => self.IsDead() ? null : self.TraitOrDefault()); } public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) @@ -60,6 +60,10 @@ namespace OpenRA.Mods.RA var fi = producee.Traits.Get(); var initialFacing = exitinfo.Facing < 0 ? Util.GetFacing(to - spawn, fi.GetInitialFacing()) : exitinfo.Facing; + var exitLocation = rp.Value != null ? rp.Value.rallyPoint : exit; + var target = Target.FromCell(exitLocation); + var nearEnough = rp.Value != null ? WRange.FromCells(rp.Value.nearEnough) : WRange.Zero; + self.World.AddFrameEndTask(w => { var newUnit = self.World.CreateActor(producee.Name, new TypeDictionary @@ -70,33 +74,24 @@ namespace OpenRA.Mods.RA new FacingInit(initialFacing) }); - var move = newUnit.Trait(); - if (exitinfo.MoveIntoWorld) - newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit)); + var move = newUnit.TraitOrDefault(); + if (move != null) + { + if (exitinfo.MoveIntoWorld) + newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit)); - var target = MoveToRallyPoint(self, newUnit, exit); - newUnit.SetTargetLine(Target.FromCell(target), Color.Green, false); - foreach (var t in self.TraitsImplementing()) - t.UnitProduced(self, newUnit, exit); + newUnit.QueueActivity(new AttackMove.AttackMoveActivity( + newUnit, move.MoveWithinRange(target, nearEnough))); + } + + newUnit.SetTargetLine(target, Color.Green, false); + + if (!self.IsDead()) + foreach (var t in self.TraitsImplementing()) + t.UnitProduced(self, newUnit, exit); }); } - CPos MoveToRallyPoint(Actor self, Actor newUnit, CPos exitLocation) - { - if (self.IsDead() || rp.Value == null) - return exitLocation; - - var move = newUnit.TraitOrDefault(); - if (move != null) - { - newUnit.QueueActivity(new AttackMove.AttackMoveActivity( - newUnit, move.MoveTo(rp.Value.rallyPoint, rp.Value.nearEnough))); - return rp.Value.rallyPoint; - } - - return exitLocation; - } - public virtual bool Produce(Actor self, ActorInfo producee) { if (Reservable.IsReserved(self))