1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef COMMAND_H
4 #define COMMAND_H
5 
6 #include <string>
7 #include <climits> // for INT_MAX
8 
9 #include "System/creg/creg_cond.h"
10 #include "System/float3.h"
11 #include "System/SafeVector.h"
12 
13 // ID's lower than 0 are reserved for build options (cmd -x = unitdefs[x])
14 #define CMD_STOP                   0
15 #define CMD_INSERT                 1
16 #define CMD_REMOVE                 2
17 #define CMD_WAIT                   5
18 #define CMD_TIMEWAIT               6
19 #define CMD_DEATHWAIT              7
20 #define CMD_SQUADWAIT              8
21 #define CMD_GATHERWAIT             9
22 #define CMD_MOVE                  10
23 #define CMD_PATROL                15
24 #define CMD_FIGHT                 16
25 #define CMD_ATTACK                20
26 #define CMD_AREA_ATTACK           21
27 #define CMD_GUARD                 25
28 #define CMD_AISELECT              30 //FIXME REMOVE
29 #define CMD_GROUPSELECT           35
30 #define CMD_GROUPADD              36
31 #define CMD_GROUPCLEAR            37
32 #define CMD_REPAIR                40
33 #define CMD_FIRE_STATE            45
34 #define CMD_MOVE_STATE            50
35 #define CMD_SETBASE               55
36 #define CMD_INTERNAL              60
37 #define CMD_SELFD                 65
38 #define CMD_SET_WANTED_MAX_SPEED  70
39 #define CMD_LOAD_UNITS            75
40 #define CMD_LOAD_ONTO             76
41 #define CMD_UNLOAD_UNITS          80
42 #define CMD_UNLOAD_UNIT           81
43 #define CMD_ONOFF                 85
44 #define CMD_RECLAIM               90
45 #define CMD_CLOAK                 95
46 #define CMD_STOCKPILE            100
47 #define CMD_MANUALFIRE           105
48 #define CMD_RESTORE              110
49 #define CMD_REPEAT               115
50 #define CMD_TRAJECTORY           120
51 #define CMD_RESURRECT            125
52 #define CMD_CAPTURE              130
53 #define CMD_AUTOREPAIRLEVEL      135
54 #define CMD_IDLEMODE             145
55 #define CMD_FAILED               150
56 
57 #define CMDTYPE_ICON                        0  // expect 0 parameters in return
58 #define CMDTYPE_ICON_MODE                   5  // expect 1 parameter in return (number selected mode)
59 #define CMDTYPE_ICON_MAP                   10  // expect 3 parameters in return (mappos)
60 #define CMDTYPE_ICON_AREA                  11  // expect 4 parameters in return (mappos+radius)
61 #define CMDTYPE_ICON_UNIT                  12  // expect 1 parameters in return (unitid)
62 #define CMDTYPE_ICON_UNIT_OR_MAP           13  // expect 1 parameters in return (unitid) or 3 parameters in return (mappos)
63 #define CMDTYPE_ICON_FRONT                 14  // expect 3 or 6 parameters in return (middle of front and right side of front if a front was defined)
64 #define CMDTYPE_COMBO_BOX                  15  // expect 1 parameter in return (number selected option)
65 #define CMDTYPE_ICON_UNIT_OR_AREA          16  // expect 1 parameter in return (unitid) or 4 parameters in return (mappos+radius)
66 #define CMDTYPE_NEXT                       17  // used with CMD_INTERNAL
67 #define CMDTYPE_PREV                       18  // used with CMD_INTERNAL
68 #define CMDTYPE_ICON_UNIT_FEATURE_OR_AREA  19  // expect 1 parameter in return (unitid or featureid+unitHandler->MaxUnits() (id>unitHandler->MaxUnits()=feature)) or 4 parameters in return (mappos+radius)
69 #define CMDTYPE_ICON_BUILDING              20  // expect 3 parameters in return (mappos)
70 #define CMDTYPE_CUSTOM                     21  // used with CMD_INTERNAL
71 #define CMDTYPE_ICON_UNIT_OR_RECTANGLE     22  // expect 1 parameter in return (unitid)
72                                                //     or 3 parameters in return (mappos)
73                                                //     or 6 parameters in return (startpos+endpos)
74 #define CMDTYPE_NUMBER                     23  // expect 1 parameter in return (number)
75 
76 
77 // wait codes
78 #define CMD_WAITCODE_TIMEWAIT    1.0f
79 #define CMD_WAITCODE_DEATHWAIT   2.0f
80 #define CMD_WAITCODE_SQUADWAIT   3.0f
81 #define CMD_WAITCODE_GATHERWAIT  4.0f
82 
83 
84 // bits for the option field of Command
85 // NOTE:
86 //   these names are misleading, eg. the SHIFT_KEY bit
87 //   really means that an order gets queued instead of
88 //   executed immediately (a better name for it would
89 //   be QUEUED_ORDER), ALT_KEY in most contexts means
90 //   OVERRIDE_QUEUED_ORDER, etc.
91 //
92 #define META_KEY        (1 << 2) //   4
93 #define INTERNAL_ORDER  (1 << 3) //   8
94 #define RIGHT_MOUSE_KEY (1 << 4) //  16
95 #define SHIFT_KEY       (1 << 5) //  32
96 #define CONTROL_KEY     (1 << 6) //  64
97 #define ALT_KEY         (1 << 7) // 128
98 
99 enum {
100 	MOVESTATE_NONE     = -1,
101 	MOVESTATE_HOLDPOS  =  0,
102 	MOVESTATE_MANEUVER =  1,
103 	MOVESTATE_ROAM     =  2,
104 };
105 enum {
106 	FIRESTATE_NONE       = -1,
107 	FIRESTATE_HOLDFIRE   =  0,
108 	FIRESTATE_RETURNFIRE =  1,
109 	FIRESTATE_FIREATWILL =  2,
110 };
111 
112 struct Command
113 {
114 private:
CR_DECLARE_STRUCTCommand115 	CR_DECLARE_STRUCT(Command)
116 /*
117 	TODO check if usage of System/MemPool.h for this struct improves performance
118 */
119 
120 public:
121 	Command()
122 		: aiCommandId(-1)
123 		, options(0)
124 		, tag(0)
125 		, timeOut(INT_MAX)
126 		, id(0)
127 	{}
128 
CommandCommand129 	Command(const Command& c) {
130 		*this = c;
131 	}
132 
133 	Command& operator = (const Command& c) {
134 		id = c.id;
135 		aiCommandId = c.aiCommandId;
136 		options = c.options;
137 		tag = c.tag;
138 		timeOut = c.timeOut;
139 		params = c.params;
140 		return *this;
141 	}
142 
CommandCommand143 	Command(const float3& pos)
144 		: aiCommandId(-1)
145 		, options(0)
146 		, tag(0)
147 		, timeOut(INT_MAX)
148 		, id(0)
149 	{
150 		PushPos(pos);
151 	}
152 
CommandCommand153 	Command(const int cmdID)
154 		: aiCommandId(-1)
155 		, options(0)
156 		, tag(0)
157 		, timeOut(INT_MAX)
158 		, id(cmdID)
159 	{}
160 
CommandCommand161 	Command(const int cmdID, const float3& pos)
162 		: aiCommandId(-1)
163 		, options(0)
164 		, tag(0)
165 		, timeOut(INT_MAX)
166 		, id(cmdID)
167 	{
168 		PushPos(pos);
169 	}
170 
CommandCommand171 	Command(const int cmdID, const unsigned char cmdOptions)
172 		: aiCommandId(-1)
173 		, options(cmdOptions)
174 		, tag(0)
175 		, timeOut(INT_MAX)
176 		, id(cmdID)
177 	{}
178 
CommandCommand179 	Command(const int cmdID, const unsigned char cmdOptions, const float param)
180 		: aiCommandId(-1)
181 		, options(cmdOptions)
182 		, tag(0)
183 		, timeOut(INT_MAX)
184 		, id(cmdID)
185 	{
186 		PushParam(param);
187 	}
188 
CommandCommand189 	Command(const int cmdID, const unsigned char cmdOptions, const float3& pos)
190 		: aiCommandId(-1)
191 		, options(cmdOptions)
192 		, tag(0)
193 		, timeOut(INT_MAX)
194 		, id(cmdID)
195 	{
196 		PushPos(pos);
197 	}
198 
CommandCommand199 	Command(const int cmdID, const unsigned char cmdOptions, const float param, const float3& pos)
200 		: aiCommandId(-1)
201 		, options(cmdOptions)
202 		, tag(0)
203 		, timeOut(INT_MAX)
204 		, id(cmdID)
205 	{
206 		PushParam(param);
207 		PushPos(pos);
208 	}
209 
~CommandCommand210 	~Command() { params.clear(); }
211 
212 	// returns true if the command references another object and
213 	// in this case also returns the param index of the object in cpos
IsObjectCommandCommand214 	bool IsObjectCommand(int& cpos) const {
215 		const int psize = params.size();
216 
217 		switch (id) {
218 			case CMD_ATTACK:
219 			case CMD_FIGHT:
220 			case CMD_MANUALFIRE:
221 				cpos = 0;
222 				return (1 <= psize && psize < 3);
223 			case CMD_GUARD:
224 			case CMD_LOAD_ONTO:
225 				cpos = 0;
226 				return (psize >= 1);
227 			case CMD_CAPTURE:
228 			case CMD_LOAD_UNITS:
229 			case CMD_RECLAIM:
230 			case CMD_REPAIR:
231 			case CMD_RESURRECT:
232 				cpos = 0;
233 				return (1 <= psize && psize < 4);
234 			case CMD_UNLOAD_UNIT:
235 				cpos = 3;
236 				return (psize >= 4);
237 			case CMD_INSERT: {
238 				if (psize < 3)
239 					return false;
240 
241 				Command icmd((int)params[1], (unsigned char)params[2]);
242 
243 				for (int p = 3; p < (int)psize; p++)
244 					icmd.params.push_back(params[p]);
245 
246 				if (!icmd.IsObjectCommand(cpos))
247 					return false;
248 
249 				cpos += 3;
250 				return true;
251 			}
252 		}
253 		return false;
254 	}
255 
IsAreaCommandCommand256 	bool IsAreaCommand() const {
257 		switch (id) {
258 			case CMD_CAPTURE:
259 			case CMD_LOAD_UNITS:
260 			case CMD_RECLAIM:
261 			case CMD_REPAIR:
262 			case CMD_RESURRECT:
263 				// params[0..2] always holds the position, params[3] the radius
264 				return (params.size() == 4);
265 			case CMD_UNLOAD_UNITS:
266 				return (params.size() == 5);
267 			case CMD_AREA_ATTACK:
268 				return true;
269 		}
270 		return false;
271 	}
IsBuildCommandCommand272 	bool IsBuildCommand() const { return (id < 0); }
273 
PushParamCommand274 	void PushParam(float par) { params.push_back(par); }
GetParamCommand275 	const float& GetParam(size_t idx) const { return params[idx]; }
276 
277 	/// const safe_vector<float>& GetParams() const { return params; }
GetParamsCountCommand278 	const size_t GetParamsCount() const { return params.size(); }
279 
SetIDCommand280 	void SetID(int id)
281 #ifndef _MSC_VER
282 		__attribute__ ((deprecated))
283 #endif
284 		{ this->id = id; params.clear(); }
GetIDCommand285 	const int& GetID() const { return id; }
286 
PushPosCommand287 	void PushPos(const float3& pos)
288 	{
289 		params.push_back(pos.x);
290 		params.push_back(pos.y);
291 		params.push_back(pos.z);
292 	}
293 
PushPosCommand294 	void PushPos(const float* pos)
295 	{
296 		params.push_back(pos[0]);
297 		params.push_back(pos[1]);
298 		params.push_back(pos[2]);
299 	}
300 
GetPosCommand301 	float3 GetPos(const int idx) const {
302 		float3 p;
303 		p.x = params[idx    ];
304 		p.y = params[idx + 1];
305 		p.z = params[idx + 2];
306 		return p;
307 	}
308 
SetPosCommand309 	void SetPos(const int idx, const float3& p) {
310 		params[idx    ] = p.x;
311 		params[idx + 1] = p.y;
312 		params[idx + 2] = p.z;
313 	}
314 
315 public:
316 	/**
317 	 * AI Command callback id (passed in on handleCommand, returned
318 	 * in CommandFinished event)
319 	 */
320 	int aiCommandId;
321 
322 	/// option bits (RIGHT_MOUSE_KEY, ...)
323 	unsigned char options;
324 
325 	/// command parameters
326 	safe_vector<float> params;
327 
328 	/// unique id within a CCommandQueue
329 	unsigned int tag;
330 
331 	/**
332 	 * Remove this command after this frame (absolute).
333 	 * This can only be set locally and is not sent over the network.
334 	 * (used for temporary orders)
335 	 * Examples:
336 	 * - 0
337 	 * - MAX_INT
338 	 * - currenFrame + 60
339 	 */
340 	int timeOut;
341 
342 private:
343 	/// CMD_xxx code  (custom codes can also be used)
344 	int id;
345 };
346 
347 
348 struct CommandDescription {
349 private:
CR_DECLARE_STRUCTCommandDescription350 	CR_DECLARE_STRUCT(CommandDescription)
351 
352 public:
353 	CommandDescription():
354 		id(0),
355 		type(CMDTYPE_ICON),
356 		hidden(false),
357 		disabled(false),
358 		showUnique(false),
359 		onlyTexture(false) {}
360 
361 	/// CMD_xxx code (custom codes can also be used)
362 	int id;
363 	/// CMDTYPE_xxx code
364 	int type;
365 
366 	/// command name
367 	std::string name;
368 	/// the associated command action binding name
369 	std::string action;
370 	/// button texture
371 	std::string iconname;
372 	/// mouse cursor
373 	std::string mouseicon;
374 	/// tooltip text
375 	std::string tooltip;
376 
377 	/// if true dont show a button for the command
378 	bool hidden;
379 	/// for greying-out commands
380 	bool disabled;
381 	/// command only applies to single units
382 	bool showUnique;
383 	/// do not draw the name if the texture is available
384 	bool onlyTexture;
385 
386 	std::vector<std::string> params;
387 };
388 
389 
390 #endif // COMMAND_H
391