1 #region Copyright & License Information
2 /*
3  * Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
4  * This file is part of OpenRA, which is free software. It is made
5  * available to you under the terms of the GNU General Public License
6  * as published by the Free Software Foundation, either version 3 of
7  * the License, or (at your option) any later version. For more
8  * information, see COPYING.
9  */
10 #endregion
11 
12 using System;
13 using System.Collections.Generic;
14 using OpenRA.Activities;
15 using OpenRA.Mods.Common.Traits;
16 using OpenRA.Primitives;
17 using OpenRA.Traits;
18 
19 namespace OpenRA.Mods.Common.Activities
20 {
21 	public abstract class HarvesterDockSequence : Activity
22 	{
23 		protected enum DockingState { Wait, Turn, Dock, Loop, Undock, Complete }
24 
25 		protected readonly Actor Refinery;
26 		protected readonly Harvester Harv;
27 		protected readonly int DockAngle;
28 		protected readonly bool IsDragRequired;
29 		protected readonly WVec DragOffset;
30 		protected readonly int DragLength;
31 		protected readonly WPos StartDrag;
32 		protected readonly WPos EndDrag;
33 
34 		protected DockingState dockingState;
35 
HarvesterDockSequence(Actor self, Actor refinery, int dockAngle, bool isDragRequired, WVec dragOffset, int dragLength)36 		public HarvesterDockSequence(Actor self, Actor refinery, int dockAngle, bool isDragRequired, WVec dragOffset, int dragLength)
37 		{
38 			dockingState = DockingState.Turn;
39 			Refinery = refinery;
40 			DockAngle = dockAngle;
41 			IsDragRequired = isDragRequired;
42 			DragOffset = dragOffset;
43 			DragLength = dragLength;
44 			Harv = self.Trait<Harvester>();
45 			StartDrag = self.CenterPosition;
46 			EndDrag = refinery.CenterPosition + DragOffset;
47 		}
48 
Tick(Actor self)49 		public override bool Tick(Actor self)
50 		{
51 			switch (dockingState)
52 			{
53 				case DockingState.Wait:
54 					return false;
55 
56 				case DockingState.Turn:
57 					dockingState = DockingState.Dock;
58 					QueueChild(new Turn(self, DockAngle));
59 					if (IsDragRequired)
60 						QueueChild(new Drag(self, StartDrag, EndDrag, DragLength));
61 					return false;
62 
63 				case DockingState.Dock:
64 					if (Refinery.IsInWorld && !Refinery.IsDead)
65 						foreach (var nd in Refinery.TraitsImplementing<INotifyDocking>())
66 							nd.Docked(Refinery, self);
67 
68 					OnStateDock(self);
69 					return false;
70 
71 				case DockingState.Loop:
72 					if (!Refinery.IsInWorld || Refinery.IsDead || Harv.TickUnload(self, Refinery))
73 						dockingState = DockingState.Undock;
74 
75 					return false;
76 
77 				case DockingState.Undock:
78 					OnStateUndock(self);
79 					return false;
80 
81 				case DockingState.Complete:
82 					if (Refinery.IsInWorld && !Refinery.IsDead)
83 						foreach (var nd in Refinery.TraitsImplementing<INotifyDocking>())
84 							nd.Undocked(Refinery, self);
85 
86 					Harv.LastLinkedProc = Harv.LinkedProc;
87 					Harv.LinkProc(self, null);
88 					if (IsDragRequired)
89 						QueueChild(new Drag(self, EndDrag, StartDrag, DragLength));
90 
91 					return true;
92 			}
93 
94 			throw new InvalidOperationException("Invalid harvester dock state");
95 		}
96 
Cancel(Actor self, bool keepQueue = false)97 		public override void Cancel(Actor self, bool keepQueue = false)
98 		{
99 			dockingState = DockingState.Undock;
100 			base.Cancel(self);
101 		}
102 
GetTargets(Actor self)103 		public override IEnumerable<Target> GetTargets(Actor self)
104 		{
105 			yield return Target.FromActor(Refinery);
106 		}
107 
TargetLineNodes(Actor self)108 		public override IEnumerable<TargetLineNode> TargetLineNodes(Actor self)
109 		{
110 			yield return new TargetLineNode(Target.FromActor(Refinery), Color.Green);
111 		}
112 
OnStateDock(Actor self)113 		public abstract void OnStateDock(Actor self);
114 
OnStateUndock(Actor self)115 		public abstract void OnStateUndock(Actor self);
116 	}
117 }
118