diff --git a/OpenRA.Game/Activities/Activity.cs b/OpenRA.Game/Activities/Activity.cs
index 8c82cc43bc..36d4177765 100644
--- a/OpenRA.Game/Activities/Activity.cs
+++ b/OpenRA.Game/Activities/Activity.cs
@@ -19,122 +19,26 @@ namespace OpenRA.Activities
public enum ActivityState { Queued, Active, Canceling, Done }
/*
- * Activities are actions carried out by actors during each tick.
- *
- * Activities exist in a graph data structure built up amongst themselves. Each activity has a parent activity,
- * optionally child activities, and usually a next activity. An actor's CurrentActivity is a pointer into that graph
- * and moves through it as activities run.
- *
- *
* Things to be aware of when writing activities:
*
* - Use "return NextActivity" at least once somewhere in the tick method.
- * - Do not use "return new SomeActivity()" as that will break the graph. Queue the new activity and use "return NextActivity" instead.
- * - Do not "reuse" (with "SequenceActivities", for example) activity objects that have already finished running.
+ * - Do not use "return new SomeActivity()" as that will break the queue. Queue the new activity and use "return NextActivity" instead.
+ * - Do not "reuse" (with "SequenceActivities", for example) activity objects that have already started running.
* Queue a new instance instead.
* - Avoid calling actor.CancelActivity(). It is almost always a bug. Call activity.Cancel() instead.
- * - Do not return the Parent explicitly unless you have an extremly good reason. "return NextActivity"
- * will do the right thing in all circumstances.
- * - You do not need to care about the ChildActivity pointer advancing through the list of children,
- * the activity code already takes care of that.
- * - If you want to check whether there are any follow-up activities queued, check against "NextInQueue"
- * in favour of "NextActivity" to avoid checking against the Parent activity.
*/
public abstract class Activity
{
public ActivityState State { get; private set; }
- ///
- /// Returns the top-most activity *from the point of view of the calling activity*. Note that the root activity
- /// can and likely will have next activities of its own, which would in turn be the root for their children.
- ///
- public Activity RootActivity
- {
- get
- {
- var p = this;
- while (p.ParentActivity != null)
- p = p.ParentActivity;
-
- return p;
- }
- }
-
- Activity parentActivity;
- public Activity ParentActivity
- {
- get
- {
- return parentActivity;
- }
-
- protected set
- {
- parentActivity = value;
-
- var next = NextInQueue;
- if (next != null)
- next.ParentActivity = parentActivity;
- }
- }
-
Activity childActivity;
protected Activity ChildActivity
{
- get
- {
- return childActivity != null && childActivity.State < ActivityState.Done ? childActivity : null;
- }
-
- set
- {
- if (value == this || value == ParentActivity || value == NextInQueue)
- childActivity = null;
- else
- {
- childActivity = value;
-
- if (childActivity != null)
- childActivity.ParentActivity = this;
- }
- }
+ get { return childActivity != null && childActivity.State < ActivityState.Done ? childActivity : null; }
+ set { childActivity = value; }
}
- Activity nextActivity;
-
- ///
- /// The getter will return either the next activity or, if there is none, the parent one.
- ///
- public virtual Activity NextActivity
- {
- get
- {
- return nextActivity != null ? nextActivity : ParentActivity;
- }
-
- set
- {
- if (value == this || value == ParentActivity || (value != null && value.ParentActivity == this))
- nextActivity = null;
- else
- {
- nextActivity = value;
-
- if (nextActivity != null)
- nextActivity.ParentActivity = ParentActivity;
- }
- }
- }
-
- ///
- /// The getter will return the next activity on the same level _only_, in contrast to NextActivity.
- /// Use this to check whether there are any follow-up activities queued.
- ///
- public Activity NextInQueue
- {
- get { return nextActivity; }
- set { NextActivity = value; }
- }
+ public Activity NextActivity { get; protected set; }
public bool IsInterruptible { get; protected set; }
public bool IsCanceling { get { return State == ActivityState.Canceling; } }
@@ -156,15 +60,9 @@ namespace OpenRA.Activities
}
var ret = Tick(self);
- if (ret == null || (ret != this && ret.ParentActivity != this))
+ if (ret != this)
{
- // Make sure that the Parent's ChildActivity pointer is moved forwards as the child queue advances.
- // The Child's ParentActivity will be set automatically during assignment.
- if (ParentActivity != null && ParentActivity != ret)
- ParentActivity.ChildActivity = ret;
-
State = ActivityState.Done;
-
OnLastRun(self);
}
@@ -204,7 +102,7 @@ namespace OpenRA.Activities
public virtual void Cancel(Actor self, bool keepQueue = false)
{
if (!keepQueue)
- NextInQueue = null;
+ NextActivity = null;
if (!IsInterruptible)
return;
@@ -217,10 +115,10 @@ namespace OpenRA.Activities
public virtual void Queue(Actor self, Activity activity)
{
- if (NextInQueue != null)
- NextInQueue.Queue(self, activity);
+ if (NextActivity != null)
+ NextActivity.Queue(self, activity);
else
- NextInQueue = activity;
+ NextActivity = activity;
}
public virtual void QueueChild(Actor self, Activity activity, bool pretick = false)
@@ -232,17 +130,17 @@ namespace OpenRA.Activities
}
///
- /// Prints the activity tree, starting from the root or optionally from a given origin.
+ /// Prints the activity tree, starting from the top or optionally from a given origin.
///
/// Call this method from any place that's called during a tick, such as the Tick() method itself or
/// the Before(First|Last)Run() methods. The origin activity will be marked in the output.
///
- /// Activity from which to start traversing, and which to mark. If null, mark the calling activity, and start traversal from the root.
+ /// Activity from which to start traversing, and which to mark. If null, mark the calling activity, and start traversal from the top.
/// Initial level of indentation.
protected void PrintActivityTree(Actor self, Activity origin = null, int level = 0)
{
if (origin == null)
- RootActivity.PrintActivityTree(self, this);
+ self.CurrentActivity.PrintActivityTree(self, this);
else
{
Console.Write(new string(' ', level * 2));
@@ -254,8 +152,8 @@ namespace OpenRA.Activities
if (ChildActivity != null)
ChildActivity.PrintActivityTree(self, origin, level + 1);
- if (NextInQueue != null)
- NextInQueue.PrintActivityTree(self, origin, level);
+ if (NextActivity != null)
+ NextActivity.PrintActivityTree(self, origin, level);
}
}
diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs
index 9404259f63..2de9feacc5 100644
--- a/OpenRA.Game/Actor.cs
+++ b/OpenRA.Game/Actor.cs
@@ -222,13 +222,13 @@ namespace OpenRA
if (CurrentActivity == null)
CurrentActivity = nextActivity;
else
- CurrentActivity.RootActivity.Queue(this, nextActivity);
+ CurrentActivity.Queue(this, nextActivity);
}
public void CancelActivity()
{
if (CurrentActivity != null)
- CurrentActivity.RootActivity.Cancel(this);
+ CurrentActivity.Cancel(this);
}
public override int GetHashCode()
@@ -281,7 +281,7 @@ namespace OpenRA
// If CurrentActivity isn't null, run OnActorDisposeOuter in case some cleanups are needed.
// This should be done before the FrameEndTask to avoid dependency issues.
if (CurrentActivity != null)
- CurrentActivity.RootActivity.OnActorDisposeOuter(this);
+ CurrentActivity.OnActorDisposeOuter(this);
// Allow traits/activities to prevent a race condition when they depend on disposing the actor (e.g. Transforms)
WillDispose = true;
diff --git a/OpenRA.Game/Traits/ActivityUtils.cs b/OpenRA.Game/Traits/ActivityUtils.cs
index e0feb07456..f78c3ec24d 100644
--- a/OpenRA.Game/Traits/ActivityUtils.cs
+++ b/OpenRA.Game/Traits/ActivityUtils.cs
@@ -44,7 +44,7 @@ namespace OpenRA.Traits
else
start = current;
- if (act == prev || act == prev.ParentActivity)
+ if (act == prev)
break;
}
diff --git a/OpenRA.Mods.Common/Activities/Air/ResupplyAircraft.cs b/OpenRA.Mods.Common/Activities/Air/ResupplyAircraft.cs
index 61e5d95a19..39b219e0bd 100644
--- a/OpenRA.Mods.Common/Activities/Air/ResupplyAircraft.cs
+++ b/OpenRA.Mods.Common/Activities/Air/ResupplyAircraft.cs
@@ -32,13 +32,13 @@ namespace OpenRA.Mods.Common.Activities
{
ChildActivity = ActivityUtils.SequenceActivities(self, aircraft.GetResupplyActivities(host).ToArray());
QueueChild(self, new AllowYieldingReservation(self));
- QueueChild(self, new WaitFor(() => NextInQueue != null || aircraft.ReservedActor == null));
+ QueueChild(self, new WaitFor(() => NextActivity != null || aircraft.ReservedActor == null));
}
else
{
ChildActivity = ActivityUtils.SequenceActivities(self, aircraft.GetResupplyActivities(host).ToArray());
QueueChild(self, new AllowYieldingReservation(self));
- QueueChild(self, new TakeOff(self, (a, b, c) => NextInQueue == null && b.NextInQueue == null));
+ QueueChild(self, new TakeOff(self, (a, b, c) => NextActivity == null && b.NextActivity == null));
}
}
diff --git a/OpenRA.Mods.Common/Activities/DeliverResources.cs b/OpenRA.Mods.Common/Activities/DeliverResources.cs
index 9d0767c47d..79085c5d5b 100644
--- a/OpenRA.Mods.Common/Activities/DeliverResources.cs
+++ b/OpenRA.Mods.Common/Activities/DeliverResources.cs
@@ -35,8 +35,8 @@ namespace OpenRA.Mods.Common.Activities
public override Activity Tick(Actor self)
{
- if (NextInQueue != null)
- return NextInQueue;
+ if (NextActivity != null)
+ return NextActivity;
// Find the nearest best refinery if not explicitly ordered to a specific refinery:
if (harv.OwnerLinkedProc == null || !harv.OwnerLinkedProc.IsInWorld)
diff --git a/OpenRA.Mods.Common/Activities/FindResources.cs b/OpenRA.Mods.Common/Activities/FindResources.cs
index df68d33c29..96eea3915f 100644
--- a/OpenRA.Mods.Common/Activities/FindResources.cs
+++ b/OpenRA.Mods.Common/Activities/FindResources.cs
@@ -80,8 +80,8 @@ namespace OpenRA.Mods.Common.Activities
var randFrames = self.World.SharedRandom.Next(100, 175);
// Avoid creating an activity cycle
- var next = NextInQueue;
- NextInQueue = null;
+ var next = NextActivity;
+ NextActivity = null;
return ActivityUtils.SequenceActivities(self, next, new Wait(randFrames), this);
}
else