diff --git a/OpenRa.Game/Traits/AcceptsOre.cs b/OpenRa.Game/Traits/AcceptsOre.cs index 7b0db686f1..dad718450c 100644 --- a/OpenRa.Game/Traits/AcceptsOre.cs +++ b/OpenRa.Game/Traits/AcceptsOre.cs @@ -16,7 +16,7 @@ namespace OpenRa.Game.Traits var harvester = new Actor("harv", self.Location + new int2(1, 2), self.Owner); var mobile = harvester.traits.Get(); mobile.facing = 64; - mobile.InternalSetActivity(new Harvest()); + mobile.QueueActivity(new Harvest()); w.Add(harvester); }); } diff --git a/OpenRa.Game/Traits/Activities/Attack.cs b/OpenRa.Game/Traits/Activities/Attack.cs index 545233dd35..31db0f3ce9 100644 --- a/OpenRa.Game/Traits/Activities/Attack.cs +++ b/OpenRa.Game/Traits/Activities/Attack.cs @@ -19,20 +19,13 @@ namespace OpenRa.Game.Traits.Activities public IActivity NextActivity { get; set; } - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { - if (Target.IsDead) - { - mobile.InternalSetActivity(NextActivity); - return; - } + if (Target == null || Target.IsDead) + return NextActivity; if ((Target.Location - self.Location).LengthSquared >= Range * Range) - { - mobile.InternalSetActivity(new Move(Target, Range)); - mobile.QueueActivity(this); - return; - } + return new Move( Target, Range ) { NextActivity = this }; var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0); var renderUnit = self.traits.WithInterface().First(); @@ -40,19 +33,18 @@ namespace OpenRa.Game.Traits.Activities if (Util.QuantizeFacing(mobile.facing, renderUnit.anim.CurrentSequence.Length) != Util.QuantizeFacing(desiredFacing, renderUnit.anim.CurrentSequence.Length)) { - mobile.InternalSetActivity(new Turn(desiredFacing)); - mobile.QueueActivity(this); - return; + return new Turn( desiredFacing ) { NextActivity = this }; } var attack = self.traits.WithInterface().First(); attack.target = Target; attack.DoAttack(self); + return null; } public void Cancel(Actor self, Mobile mobile) { - mobile.InternalSetActivity(null); + Target = null; } } } diff --git a/OpenRa.Game/Traits/Activities/DeliverOre.cs b/OpenRa.Game/Traits/Activities/DeliverOre.cs index a928fde85a..4bec3e9966 100644 --- a/OpenRa.Game/Traits/Activities/DeliverOre.cs +++ b/OpenRa.Game/Traits/Activities/DeliverOre.cs @@ -21,20 +21,14 @@ namespace OpenRa.Game.Traits.Activities static readonly int2 refineryDeliverOffset = new int2( 1, 2 ); - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { if( isDone ) { - var harv = self.traits.Get(); - - harv.Deliver( self ); - - if( NextActivity == null ) - NextActivity = new Harvest(); - mobile.InternalSetActivity( NextActivity ); - return; + self.traits.Get().Deliver( self ); + return NextActivity ?? new Harvest(); } - else if( refinery == null || refinery.IsDead ) + else if( refinery == null || refinery.IsDead || self.Location != refinery.Location + refineryDeliverOffset ) { var search = new PathSearch { @@ -51,34 +45,26 @@ namespace OpenRa.Game.Traits.Activities if( path.Count != 0 ) { refinery = refineries.FirstOrDefault( x => x.Location + refineryDeliverOffset == path[ 0 ] ); - var move = new Move( () => path ); - mobile.InternalSetActivity( move ); - mobile.QueueActivity( this ); - move.Tick( self, mobile ); - return; + return new Move( () => path ) { NextActivity = this }; } else // no refineries reachable? - return; + return null; } else if( mobile.facing != 64 ) - { - var turn = new Turn( 64 ); - mobile.InternalSetActivity( turn ); - mobile.QueueActivity( this ); - turn.Tick( self, mobile ); - return; - } + return new Turn( 64 ) { NextActivity = this }; var renderUnit = self.traits.WithInterface().First(); if( renderUnit.anim.CurrentSequence.Name != "empty" ) renderUnit.PlayCustomAnimation( self, "empty", () => isDone = true ); + + return null; } public void Cancel(Actor self, Mobile mobile) { - mobile.InternalSetActivity(null); + // TODO: allow canceling of deliver orders? } } } diff --git a/OpenRa.Game/Traits/Activities/DeployMcv.cs b/OpenRa.Game/Traits/Activities/DeployMcv.cs index def708eed5..02ae60be48 100755 --- a/OpenRa.Game/Traits/Activities/DeployMcv.cs +++ b/OpenRa.Game/Traits/Activities/DeployMcv.cs @@ -9,13 +9,14 @@ namespace OpenRa.Game.Traits.Activities { public IActivity NextActivity { get; set; } - public void Tick( Actor self, Mobile mobile ) + public IActivity Tick( Actor self, Mobile mobile ) { Game.world.AddFrameEndTask( _ => { Game.world.Remove( self ); Game.world.Add( new Actor( "fact", self.Location - new int2( 1, 1 ), self.Owner ) ); } ); + return null; } public void Cancel( Actor self, Mobile mobile ) diff --git a/OpenRa.Game/Traits/Activities/Follow.cs b/OpenRa.Game/Traits/Activities/Follow.cs index 9b19c7aea4..18e4304a6b 100644 --- a/OpenRa.Game/Traits/Activities/Follow.cs +++ b/OpenRa.Game/Traits/Activities/Follow.cs @@ -18,24 +18,20 @@ namespace OpenRa.Game.Traits.Activities public IActivity NextActivity { get; set; } - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { - if (Target.IsDead) - { - mobile.InternalSetActivity(NextActivity); - return; - } + if (Target == null || Target.IsDead) + return NextActivity; - if ((Target.Location - self.Location).LengthSquared >= Range * Range) - { - mobile.InternalSetActivity(new Move(Target, Range)); - mobile.QueueActivity(this); - } + if( ( Target.Location - self.Location ).LengthSquared >= Range * Range ) + return new Move( Target, Range ) { NextActivity = this }; + + return null; } public void Cancel(Actor self, Mobile mobile) { - mobile.InternalSetActivity(null); + Target = null; } } } diff --git a/OpenRa.Game/Traits/Activities/Harvest.cs b/OpenRa.Game/Traits/Activities/Harvest.cs index 925e1949ce..44c271062c 100644 --- a/OpenRa.Game/Traits/Activities/Harvest.cs +++ b/OpenRa.Game/Traits/Activities/Harvest.cs @@ -10,59 +10,49 @@ namespace OpenRa.Game.Traits.Activities public IActivity NextActivity { get; set; } bool isHarvesting = false; - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { - if( isHarvesting ) return; + if( isHarvesting ) return null; if( NextActivity != null ) - { - mobile.InternalSetActivity( NextActivity ); - NextActivity.Tick( self, mobile ); - return; - } + return NextActivity; var harv = self.traits.Get(); if( harv.IsFull ) - { - mobile.QueueActivity( new DeliverOre() ); - mobile.InternalSetActivity( NextActivity ); - } + return new DeliverOre { NextActivity = NextActivity }; var isGem = false; - if (Game.map.ContainsResource(self.Location) && - Game.map.Harvest(self.Location, out isGem)) + if( Game.map.ContainsResource( self.Location ) && + Game.map.Harvest( self.Location, out isGem ) ) { - var harvestAnim = "harvest" + Util.QuantizeFacing(mobile.facing, 8); + var harvestAnim = "harvest" + Util.QuantizeFacing( mobile.facing, 8 ); var renderUnit = self.traits.WithInterface().First(); /* better have one of these! */ if( harvestAnim != renderUnit.anim.CurrentSequence.Name ) { isHarvesting = true; renderUnit.PlayCustomAnimation( self, harvestAnim, () => isHarvesting = false ); } - harv.AcceptResource(isGem); - return; + harv.AcceptResource( isGem ); + return null; } - - PlanMoreHarvesting( self, mobile ); - } - - void PlanMoreHarvesting(Actor self, Mobile mobile) - { - mobile.QueueActivity(new Move( - () => - { - var search = new PathSearch + else + { + mobile.QueueActivity( new Move( + () => { - heuristic = loc => (Game.map.ContainsResource(loc) ? 0 : 1), - umt = UnitMovementType.Wheel, - checkForBlocked = true - }; - search.AddInitialCell(self.Location); - return Game.PathFinder.FindPath(search); - })); - mobile.QueueActivity(new Harvest()); - mobile.InternalSetActivity( NextActivity ); + var search = new PathSearch + { + heuristic = loc => ( Game.map.ContainsResource( loc ) ? 0 : 1 ), + umt = UnitMovementType.Wheel, + checkForBlocked = true + }; + search.AddInitialCell( self.Location ); + return Game.PathFinder.FindPath( search ); + } ) ); + mobile.QueueActivity( new Harvest() ); + return NextActivity; + } } public void Cancel(Actor self, Mobile mobile) { } diff --git a/OpenRa.Game/Traits/Activities/IActivity.cs b/OpenRa.Game/Traits/Activities/IActivity.cs index 53eb5ace06..2ec4556871 100644 --- a/OpenRa.Game/Traits/Activities/IActivity.cs +++ b/OpenRa.Game/Traits/Activities/IActivity.cs @@ -8,7 +8,7 @@ namespace OpenRa.Game.Traits.Activities interface IActivity { IActivity NextActivity { get; set; } - void Tick( Actor self, Mobile mobile ); + IActivity Tick( Actor self, Mobile mobile ); void Cancel( Actor self, Mobile mobile ); } } diff --git a/OpenRa.Game/Traits/Activities/Move.cs b/OpenRa.Game/Traits/Activities/Move.cs index bb90417c65..554447b490 100755 --- a/OpenRa.Game/Traits/Activities/Move.cs +++ b/OpenRa.Game/Traits/Activities/Move.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using OpenRa.Game.GameRules; +using System.Diagnostics; namespace OpenRa.Game.Traits.Activities { @@ -48,43 +49,42 @@ namespace OpenRa.Game.Traits.Activities return (u == null || u == self); } - public void Tick( Actor self, Mobile mobile ) + public IActivity Tick( Actor self, Mobile mobile ) { if( move != null ) { move.TickMove( self, mobile, this ); - return; + return null; } if( destination == self.Location ) - { - mobile.InternalSetActivity( NextActivity ); - return; - } + return NextActivity; - if( path == null ) path = getPath( self, mobile ).TakeWhile( a => a != self.Location ).ToList(); + if( path == null ) + { + path = getPath( self, mobile ).TakeWhile( a => a != self.Location ).ToList(); + SanityCheckPath( mobile ); + } if( path.Count == 0 ) { destination = mobile.toCell; - return; + return null; } destination = path[ 0 ]; var nextCell = PopPath( self, mobile ); if( nextCell == null ) - return; + return null; int2 dir = nextCell.Value - mobile.fromCell; var firstFacing = Util.GetFacing( dir, mobile.facing ); if( firstFacing != mobile.facing ) { - var t = new Turn( firstFacing ) { NextActivity = this }; - mobile.InternalSetActivity( t ); path.Add( nextCell.Value ); - t.Tick( self, mobile ); + return new Turn( firstFacing ) { NextActivity = this }; } else { @@ -99,9 +99,19 @@ namespace OpenRa.Game.Traits.Activities Game.UnitInfluence.Update( mobile ); move.TickMove( self, mobile, this ); + + return null; } } + [Conditional( "SANITY_CHECKS")] + void SanityCheckPath( Mobile mobile ) + { + var d = path[path.Count-1] - mobile.toCell; + if( d.LengthSquared > 2 ) + throw new InvalidOperationException( "(Move) Sanity check failed" ); + } + int2? PopPath( Actor self, Mobile mobile ) { if( path.Count == 0 ) return null; diff --git a/OpenRa.Game/Traits/Activities/Turn.cs b/OpenRa.Game/Traits/Activities/Turn.cs index f36285101a..5b607ee4c1 100755 --- a/OpenRa.Game/Traits/Activities/Turn.cs +++ b/OpenRa.Game/Traits/Activities/Turn.cs @@ -16,16 +16,13 @@ namespace OpenRa.Game.Traits.Activities this.desiredFacing = desiredFacing; } - public void Tick( Actor self, Mobile mobile ) + public IActivity Tick( Actor self, Mobile mobile ) { if( desiredFacing == mobile.facing ) - { - mobile.InternalSetActivity( NextActivity ); - if( NextActivity != null ) - NextActivity.Tick( self, mobile ); - return; - } + return NextActivity; + Util.TickFacing( ref mobile.facing, desiredFacing, self.unitInfo.ROT ); + return null; } public void Cancel( Actor self, Mobile mobile ) diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index 73bfe0103b..f31410a6e8 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -42,17 +42,20 @@ namespace OpenRa.Game.Traits act.NextActivity = nextActivity; } - public void InternalSetActivity( IActivity activity ) - { - currentActivity = activity; - } - public void Tick(Actor self) { - if( currentActivity != null ) - currentActivity.Tick( self, this ); - else + if( currentActivity == null ) + { fromCell = toCell; + return; + } + + var nextActivity = currentActivity; + while( nextActivity != null ) + { + currentActivity = nextActivity; + nextActivity = nextActivity.Tick( self, this ); + } } public Order Order(Actor self, int2 xy, bool lmb, Actor underCursor)