1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef COMMAND_H
#define COMMAND_H
#include <string>
#include <climits> // INT_MAX
#include <cstring> // memset
#include "System/creg/creg_cond.h"
#include "System/float3.h"
// ID's lower than 0 are reserved for build options (cmd -x = unitdefs[x])
#define CMD_STOP 0
#define CMD_INSERT 1
#define CMD_REMOVE 2
#define CMD_WAIT 5
#define CMD_TIMEWAIT 6
#define CMD_DEATHWAIT 7
#define CMD_SQUADWAIT 8
#define CMD_GATHERWAIT 9
#define CMD_MOVE 10
#define CMD_PATROL 15
#define CMD_FIGHT 16
#define CMD_ATTACK 20
#define CMD_AREA_ATTACK 21
#define CMD_GUARD 25
#define CMD_AISELECT 30 //FIXME REMOVE
#define CMD_GROUPSELECT 35
#define CMD_GROUPADD 36
#define CMD_GROUPCLEAR 37
#define CMD_REPAIR 40
#define CMD_FIRE_STATE 45
#define CMD_MOVE_STATE 50
#define CMD_SETBASE 55
#define CMD_INTERNAL 60
#define CMD_SELFD 65
#define CMD_LOAD_UNITS 75
#define CMD_LOAD_ONTO 76
#define CMD_UNLOAD_UNITS 80
#define CMD_UNLOAD_UNIT 81
#define CMD_ONOFF 85
#define CMD_RECLAIM 90
#define CMD_CLOAK 95
#define CMD_STOCKPILE 100
#define CMD_MANUALFIRE 105
#define CMD_RESTORE 110
#define CMD_REPEAT 115
#define CMD_TRAJECTORY 120
#define CMD_RESURRECT 125
#define CMD_CAPTURE 130
#define CMD_AUTOREPAIRLEVEL 135
#define CMD_IDLEMODE 145
#define CMD_FAILED 150
#define CMDTYPE_ICON 0 // expect 0 parameters in return
#define CMDTYPE_ICON_MODE 5 // expect 1 parameter in return (number selected mode)
#define CMDTYPE_ICON_MAP 10 // expect 3 parameters in return (mappos)
#define CMDTYPE_ICON_AREA 11 // expect 4 parameters in return (mappos+radius)
#define CMDTYPE_ICON_UNIT 12 // expect 1 parameters in return (unitid)
#define CMDTYPE_ICON_UNIT_OR_MAP 13 // expect 1 parameters in return (unitid) or 3 parameters in return (mappos)
#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)
#define CMDTYPE_ICON_UNIT_OR_AREA 16 // expect 1 parameter in return (unitid) or 4 parameters in return (mappos+radius)
#define CMDTYPE_NEXT 17 // used with CMD_INTERNAL
#define CMDTYPE_PREV 18 // used with CMD_INTERNAL
#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)
#define CMDTYPE_ICON_BUILDING 20 // expect 3 parameters in return (mappos)
#define CMDTYPE_CUSTOM 21 // used with CMD_INTERNAL
#define CMDTYPE_ICON_UNIT_OR_RECTANGLE 22 // expect 1 parameter in return (unitid)
// or 3 parameters in return (mappos)
// or 6 parameters in return (startpos+endpos)
#define CMDTYPE_NUMBER 23 // expect 1 parameter in return (number)
// wait codes
#define CMD_WAITCODE_TIMEWAIT 1.0f
#define CMD_WAITCODE_DEATHWAIT 2.0f
#define CMD_WAITCODE_SQUADWAIT 3.0f
#define CMD_WAITCODE_GATHERWAIT 4.0f
// bits for the option field of Command
// NOTE:
// these names are misleading, eg. the SHIFT_KEY bit
// really means that an order gets queued instead of
// executed immediately (a better name for it would
// be QUEUED_ORDER), ALT_KEY in most contexts means
// OVERRIDE_QUEUED_ORDER, etc.
//
#define META_KEY (1 << 2) // 4
#define INTERNAL_ORDER (1 << 3) // 8
#define RIGHT_MOUSE_KEY (1 << 4) // 16
#define SHIFT_KEY (1 << 5) // 32
#define CONTROL_KEY (1 << 6) // 64
#define ALT_KEY (1 << 7) // 128
// maximum number of inline parameters for any (default and custom) command type
#define MAX_COMMAND_PARAMS 8
#if defined(BUILDING_AI)
#define CMD_DGUN CMD_MANUALFIRE
#endif
enum {
MOVESTATE_NONE = -1,
MOVESTATE_HOLDPOS = 0,
MOVESTATE_MANEUVER = 1,
MOVESTATE_ROAM = 2,
};
enum {
FIRESTATE_NONE = -1,
FIRESTATE_HOLDFIRE = 0,
FIRESTATE_RETURNFIRE = 1,
FIRESTATE_FIREATWILL = 2,
FIRESTATE_FIREATNEUTRAL = 3,
};
#if (defined(__cplusplus))
extern "C" {
#endif
// this must have C linkage
struct RawCommand {
int id[2];
int timeOut;
unsigned int pageIndex;
unsigned int numParams;
/// unique id within a CCommandQueue
unsigned int tag;
/// option bits (RIGHT_MOUSE_KEY, ...)
unsigned char options;
/// command parameters
float* params;
};
#if (defined(__cplusplus))
// extern "C"
};
#endif
struct Command {
private:
CR_DECLARE_STRUCT(Command)
public:
Command() {
memset(¶ms[0], 0, sizeof(params));
SetFlags(INT_MAX, 0, 0);
}
Command(const Command& c) {
*this = c;
}
Command& operator = (const Command& c) {
memcpy(&id[0], &c.id[0], sizeof(id));
SetFlags(c.timeOut, c.tag, c.options);
CopyParams(c);
return *this;
}
Command(const float3& pos) {
memset(¶ms[0], 0, sizeof(params));
PushPos(pos);
SetFlags(INT_MAX, 0, 0);
}
Command(int cmdID) {
memcpy(&id[0], &cmdID, sizeof(cmdID));
memset(¶ms[0], 0, sizeof(params));
SetFlags(INT_MAX, 0, 0);
}
Command(int cmdID, const float3& pos) {
memcpy(&id[0], &cmdID, sizeof(cmdID));
memset(¶ms[0], 0, sizeof(params));
PushPos(pos);
SetFlags(INT_MAX, 0, 0);
}
Command(int cmdID, unsigned char cmdOptions) {
memcpy(&id[0], &cmdID, sizeof(cmdID));
memset(¶ms[0], 0, sizeof(params));
SetFlags(INT_MAX, 0, cmdOptions);
}
Command(int cmdID, unsigned char cmdOptions, float param) {
memcpy(&id[0], &cmdID, sizeof(cmdID));
memset(¶ms[0], 0, sizeof(params));
PushParam(param);
SetFlags(INT_MAX, 0, cmdOptions);
}
Command(int cmdID, unsigned char cmdOptions, const float3& pos) {
memcpy(&id[0], &cmdID, sizeof(cmdID));
memset(¶ms[0], 0, sizeof(params));
PushPos(pos);
SetFlags(INT_MAX, 0, cmdOptions);
}
Command(int cmdID, unsigned char cmdOptions, float param, const float3& pos) {
memcpy(&id[0], &cmdID, sizeof(cmdID));
memset(¶ms[0], 0, sizeof(params));
PushParam(param);
PushPos(pos);
SetFlags(INT_MAX, 0, cmdOptions);
}
~Command();
RawCommand ToRawCommand() {
RawCommand rc;
rc.id[0] = id[0];
rc.id[1] = id[1];
rc.timeOut = timeOut;
rc.pageIndex = pageIndex;
rc.numParams = numParams;
rc.tag = tag;
rc.options = options;
rc.params = const_cast<float*>(GetParams());
return rc;
}
void FromRawCommand(const RawCommand& rc) {
pageIndex = rc.pageIndex;
numParams = rc.numParams;
memcpy(&id[0], &rc.id[0], sizeof(id));
memset(¶ms[0], 0, sizeof(params));
SetFlags(rc.timeOut, rc.tag, rc.options);
if (IsPooledCommand()) {
// actual params should still be in pool, original command exists on AI side
assert(numParams > MAX_COMMAND_PARAMS);
return;
}
assert(numParams <= MAX_COMMAND_PARAMS);
memcpy(¶ms[0], &rc.params[0], rc.numParams);
}
// returns true if the command references another object and
// in this case also returns the param index of the object in cpos
bool IsObjectCommand(int& cpos) const {
switch (GetID()) {
case CMD_ATTACK:
case CMD_FIGHT:
case CMD_MANUALFIRE:
cpos = 0;
return (1 <= numParams && numParams < 3);
case CMD_GUARD:
case CMD_LOAD_ONTO:
cpos = 0;
return (numParams >= 1);
case CMD_CAPTURE:
case CMD_LOAD_UNITS:
case CMD_RECLAIM:
case CMD_REPAIR:
case CMD_RESURRECT:
cpos = 0;
return (1 <= numParams && numParams < 4);
case CMD_UNLOAD_UNIT:
cpos = 3;
return (numParams >= 4);
case CMD_INSERT: {
if (numParams < 3)
return false;
Command icmd(static_cast<int>(GetParam(1)), static_cast<unsigned char>(GetParam(2)));
for (unsigned int p = 3; p < numParams; p++) {
icmd.PushParam(GetParam(p));
}
if (!icmd.IsObjectCommand(cpos))
return false;
cpos += 3;
return true;
}
}
return false;
}
bool IsMoveCommand() const {
switch (GetID()) {
case CMD_AREA_ATTACK:
case CMD_ATTACK:
case CMD_CAPTURE:
case CMD_FIGHT:
case CMD_GUARD:
case CMD_LOAD_UNITS:
case CMD_MANUALFIRE:
case CMD_MOVE:
case CMD_PATROL:
case CMD_RECLAIM:
case CMD_REPAIR:
case CMD_RESTORE:
case CMD_RESURRECT:
case CMD_UNLOAD_UNIT:
case CMD_UNLOAD_UNITS:
return true;
case CMD_DEATHWAIT:
case CMD_GATHERWAIT:
case CMD_SELFD:
case CMD_SQUADWAIT:
case CMD_STOP:
case CMD_TIMEWAIT:
case CMD_WAIT:
return false;
default: break;
}
// build commands are no different from reclaim or repair commands
// in that they can require a unit to move, so return true when we
// have one
return IsBuildCommand();
}
bool IsAttackCommand() const {
return (GetID() == CMD_ATTACK || GetID() == CMD_AREA_ATTACK || GetID() == CMD_FIGHT);
}
bool IsAreaCommand() const {
switch (GetID()) {
case CMD_CAPTURE:
case CMD_LOAD_UNITS:
case CMD_RECLAIM:
case CMD_REPAIR:
case CMD_RESURRECT:
// params[0..2] always holds the position, params[3] the radius
return (numParams == 4);
case CMD_UNLOAD_UNITS:
return (numParams == 5);
case CMD_AREA_ATTACK:
return true;
default: break;
}
return false;
}
bool IsBuildCommand() const { return (GetID() < 0); }
bool IsEmptyCommand() const { return (numParams == 0); }
bool IsPooledCommand() const { return (pageIndex != -1u); } // implies numParams > MAX_COMMAND_PARAMS
bool IsInternalOrder() const { return ((options & INTERNAL_ORDER) != 0); }
int GetID(bool idx = false) const { return id[idx]; }
int GetTimeOut() const { return timeOut; }
unsigned int GetpageIndex() const { return pageIndex; }
unsigned int GetNumParams() const { return numParams; }
unsigned int GetTag() const { return tag; }
unsigned char GetOpts() const { return options; }
const float* GetParams(unsigned int idx = 0) const;
float GetParam (unsigned int idx ) const;
bool SetParam(unsigned int idx, float param);
bool PushParam(float param);
bool PushPos(const float3& pos) { return (PushPos(&pos.x)); }
bool PushPos(const float* pos) {
PushParam(pos[0]);
PushParam(pos[1]);
PushParam(pos[2]);
return true;
}
float3 GetPos(unsigned int idx) const {
float3 p;
p.x = GetParam(idx + 0);
p.y = GetParam(idx + 1);
p.z = GetParam(idx + 2);
return p;
}
bool SetPos(unsigned int idx, const float3& p) {
SetParam(idx + 0, p.x);
SetParam(idx + 1, p.y);
SetParam(idx + 2, p.z);
return true;
}
void SetAICmdID(int cmdID) { id[1] = cmdID; }
void SetTimeOut(int cmdTimeOut) { timeOut = cmdTimeOut; }
void SetTag(unsigned int cmdTag) { tag = cmdTag; }
void SetOpts(unsigned char cmdOpts) { options = cmdOpts; }
void SetFlags(int cmdTimeOut, unsigned int cmdTag, unsigned char cmdOpts) {
SetTimeOut(cmdTimeOut);
SetTag(cmdTag);
SetOpts(cmdOpts);
}
void CopyParams(const Command& c);
void Serialize(creg::ISerializer* s);
private:
/// [0] := CMD_xxx code (custom codes can also be used)
/// [1] := AI Command callback id (passed in on handleCommand, returned in CommandFinished event)
int id[2] = {0, -1};
/**
* Remove this command after this frame (absolute).
* Mostly used for internal temporary orders, also
* exposed to Lua.
* Examples:
* - 0
* - MAX_INT
* - currenFrame + 60
*/
int timeOut = INT_MAX;
/// page-index for cmdParamsPool, valid iff numParams > MAX_COMMAND_PARAMS
unsigned int pageIndex = -1u;
unsigned int numParams = 0;
/// unique id within a CCommandQueue
unsigned int tag = 0;
/// option bits (RIGHT_MOUSE_KEY, ...)
unsigned char options = 0;
/// inline command parameters, used if numParams <= MAX_COMMAND_PARAMS
float params[MAX_COMMAND_PARAMS];
};
#endif // COMMAND_H
|