Exemple #1
0
void CommandDrawer::DrawCommands(const CCommandAI* cai) const
{
	const CUnit* owner = cai->owner;
	const CCommandQueue& commandQue = cai->commandQue;

	lineDrawer.StartPath(owner->drawMidPos, cmdColors.start);

	if (owner->selfDCountdown != 0) {
		lineDrawer.DrawIconAtLastPos(CMD_SELFD);
	}

	CCommandQueue::const_iterator ci;
	for (ci = commandQue.begin(); ci != commandQue.end(); ++ci) {
		const int& cmdID = ci->GetID();

		switch (cmdID) {
			case CMD_ATTACK:
			case CMD_MANUALFIRE: {
				if (ci->params.size() == 1) {
					const CUnit* unit = uh->GetUnit(ci->params[0]);

					if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
						const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.attack);
					}
				} else {
					const float x = ci->params[0];
					const float z = ci->params[2];
					const float y = ground->GetHeightReal(x, z, false) + 3.0f;

					lineDrawer.DrawLineAndIcon(cmdID, float3(x, y, z), cmdColors.attack);
				}
				break;
			}
			case CMD_WAIT:{
				DrawWaitIcon(*ci);
				break;
			}
			case CMD_SELFD:{
				lineDrawer.DrawIconAtLastPos(cmdID);
				break;
			}
			default:{
				DrawDefaultCommand(*ci, owner);
				break;
			}
		}
	}

	lineDrawer.FinishPath();
}
bool CCommandAI::HasMoreMoveCommands() const
{
	if (commandQue.size() <= 1)
		return false;

	// skip the first command
	for (CCommandQueue::const_iterator i = ++commandQue.begin(); i != commandQue.end(); ++i) {
		switch (i->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:
				// 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
				if (i->IsBuildCommand())
					return true;
		}
	}

	return false;
}
Exemple #3
0
void CommandDrawer::DrawQuedBuildingSquares(const CBuilderCAI* cai) const
{
	const CCommandQueue& commandQue = cai->commandQue;
	const std::map<int, string>& buildOptions = cai->buildOptions;

	CCommandQueue::const_iterator ci;

	int buildCommands = 0;
	int underwaterCommands = 0;
	for (ci = commandQue.begin(); ci != commandQue.end(); ++ci) {
		if (buildOptions.find(ci->GetID()) != buildOptions.end()) {
			++buildCommands;
			BuildInfo bi(*ci);
			bi.pos = helper->Pos2BuildPos(bi, false);
			if (bi.pos.y < 0.f)
				++underwaterCommands;
		}
	}

	// worst case - 2 squares per building (when underwater) - 8 vertices * 3 floats
	std::vector<GLfloat> vertices_quads(buildCommands * 12);
	std::vector<GLfloat> vertices_quads_uw(buildCommands * 12); // underwater
	// 4 vertical lines
	std::vector<GLfloat> vertices_lines(underwaterCommands * 24);
	// colors for lines
	std::vector<GLfloat> colors_lines(underwaterCommands * 48);

	int quadcounter = 0;
	int uwqcounter = 0;
	int linecounter = 0;

	for (ci = commandQue.begin(); ci != commandQue.end(); ++ci) {
		if (buildOptions.find(ci->GetID()) != buildOptions.end()) {
			BuildInfo bi(*ci);
			bi.pos = helper->Pos2BuildPos(bi, false);
			const float xsize = bi.GetXSize()*4;
			const float zsize = bi.GetZSize()*4;

			const float h = bi.pos.y;
			const float x1 = bi.pos.x - xsize;
			const float z1 = bi.pos.z - zsize;
			const float x2 = bi.pos.x + xsize;
			const float z2 = bi.pos.z + zsize;

			vertices_quads[quadcounter + 0] = x1;
			vertices_quads[quadcounter + 1] = h + 1;
			vertices_quads[quadcounter + 2] = z1;
			vertices_quads[quadcounter + 3] = x1;
			vertices_quads[quadcounter + 4] = h + 1;
			vertices_quads[quadcounter + 5] = z2;
			vertices_quads[quadcounter + 6] = x2;
			vertices_quads[quadcounter + 7] = h + 1;
			vertices_quads[quadcounter + 8] = z2;
			vertices_quads[quadcounter + 9] = x2;
			vertices_quads[quadcounter +10] = h + 1;
			vertices_quads[quadcounter +11] = z1;

			quadcounter += 12;

			if (bi.pos.y < 0.0f) {
				const float col[8] = { 0.0f, 0.0f, 1.0f, 0.5f, // start color
						       0.0f, 0.5f, 1.0f, 1.0f }; // end color

				vertices_quads_uw[uwqcounter + 0] = x1;
				vertices_quads_uw[uwqcounter + 1] = 0.f;
				vertices_quads_uw[uwqcounter + 2] = z1;
				vertices_quads_uw[uwqcounter + 3] = x1;
				vertices_quads_uw[uwqcounter + 4] = 0.f;
				vertices_quads_uw[uwqcounter + 5] = z2;
				vertices_quads_uw[uwqcounter + 6] = x2;
				vertices_quads_uw[uwqcounter + 7] = 0.f;
				vertices_quads_uw[uwqcounter + 8] = z2;
				vertices_quads_uw[uwqcounter + 9] = x2;
				vertices_quads_uw[uwqcounter +10] = 0.f;
				vertices_quads_uw[uwqcounter +11] = z1;

				uwqcounter += 12;

				for (int i = 0; i<4; ++i) {
					std::copy(col, col + 8, colors_lines.begin() + linecounter * 2 + i * 8);
				}

				vertices_lines[linecounter + 0] = x1;
				vertices_lines[linecounter + 1] = h;
				vertices_lines[linecounter + 2] = z1;
				vertices_lines[linecounter + 3] = x1;
				vertices_lines[linecounter + 4] = 0;
				vertices_lines[linecounter + 5] = z1;

				vertices_lines[linecounter + 6] = x2;
				vertices_lines[linecounter + 7] = h;
				vertices_lines[linecounter + 8] = z1;
				vertices_lines[linecounter + 9] = x2;
				vertices_lines[linecounter +10] = 0;
				vertices_lines[linecounter +11] = z1;

				vertices_lines[linecounter +12] = x2;
				vertices_lines[linecounter +13] = h;
				vertices_lines[linecounter +14] = z2;
				vertices_lines[linecounter +15] = x2;
				vertices_lines[linecounter +16] = 0;
				vertices_lines[linecounter +17] = z2;

				vertices_lines[linecounter +18] = x1;
				vertices_lines[linecounter +19] = h;
				vertices_lines[linecounter +20] = z2;
				vertices_lines[linecounter +21] = x1;
				vertices_lines[linecounter +22] = 0;
				vertices_lines[linecounter +23] = z2;

				linecounter += 24;
			}
		}
	}

	if (quadcounter) {
		glEnableClientState(GL_VERTEX_ARRAY);
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINES);
		glVertexPointer(3, GL_FLOAT, 0, &vertices_quads[0]);
		glDrawArrays(GL_QUADS, 0, quadcounter/3);

		if (linecounter) {
			glPushAttrib(GL_CURRENT_BIT);
			glColor4f(0.0f, 0.5f, 1.0f, 1.0f); // same as end color of lines
			glVertexPointer(3, GL_FLOAT, 0, &vertices_quads_uw[0]);
			glDrawArrays(GL_QUADS, 0, uwqcounter/3);
			glPopAttrib();

			glEnableClientState(GL_COLOR_ARRAY);
			glColorPointer(4, GL_FLOAT, 0, &colors_lines[0]);
			glVertexPointer(3, GL_FLOAT, 0, &vertices_lines[0]);
			glDrawArrays(GL_LINES, 0, linecounter/3);
			glDisableClientState(GL_COLOR_ARRAY);
		}
		glDisableClientState(GL_VERTEX_ARRAY);
	}
}
Exemple #4
0
void CommandDrawer::DrawTransportCAICommands(const CTransportCAI* cai) const
{
	const CUnit* owner = cai->owner;
	const CCommandQueue& commandQue = cai->commandQue;

	lineDrawer.StartPath(owner->drawMidPos, cmdColors.start);

	if (owner->selfDCountdown != 0) {
		lineDrawer.DrawIconAtLastPos(CMD_SELFD);
	}

	CCommandQueue::const_iterator ci;
	for (ci = commandQue.begin(); ci != commandQue.end(); ++ci) {
		const int& cmdID = ci->GetID();

		switch (cmdID) {
			case CMD_MOVE: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.move);
				break;
			}
			case CMD_FIGHT: {
				if (ci->params.size() >= 3) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
					lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.fight);
				}
				break;
			}
			case CMD_PATROL: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.patrol);
				break;
			}
			case CMD_ATTACK: {
				if (ci->params.size() == 1) {
					const CUnit* unit = uh->GetUnit(ci->params[0]);

					if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
						const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.attack);
					}
				} else {
					const float x = ci->params[0];
					const float z = ci->params[2];
					const float y = ground->GetHeightReal(x, z, false) + 3.0f;

					lineDrawer.DrawLineAndIcon(cmdID, float3(x, y, z), cmdColors.attack);
				}
				break;
			}
			case CMD_GUARD: {
				const CUnit* unit = uh->GetUnit(ci->params[0]);
				if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
					const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
					lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.guard);
				}
				break;
			}
			case CMD_LOAD_UNITS: {
				if (ci->params.size() == 4) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);

					lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.load);
					lineDrawer.Break(endPos, cmdColors.load);
					glColor4fv(cmdColors.load);
					glSurfaceCircle(endPos, ci->params[3], 20);
					lineDrawer.RestartWithColor(cmdColors.load);
				} else {
					const CUnit* unit = uh->GetUnit(ci->params[0]);
					if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
						const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.load);
					}
				}
				break;
			}
			case CMD_UNLOAD_UNITS: {
				if (ci->params.size() == 5) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);

					lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.unload);
					lineDrawer.Break(endPos, cmdColors.unload);
					glColor4fv(cmdColors.unload);
					glSurfaceCircle(endPos, ci->params[3], 20);
					lineDrawer.RestartWithColor(cmdColors.unload);
				}
				break;
			}
			case CMD_UNLOAD_UNIT: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.unload);
				break;
			}
			case CMD_WAIT: {
				DrawWaitIcon(*ci);
				break;
			}
			case CMD_SELFD: {
				lineDrawer.DrawIconAtLastPos(cmdID);
				break;
			}
			default:
				DrawDefaultCommand(*ci, owner);
				break;
		}
	}
	lineDrawer.FinishPath();
}
Exemple #5
0
void CommandDrawer::DrawFactoryCAICommands(const CFactoryCAI* cai) const
{
	const CUnit* owner = cai->owner;
	const CCommandQueue& commandQue = cai->commandQue;
	const CCommandQueue& newUnitCommands = cai->newUnitCommands;

	lineDrawer.StartPath(owner->drawMidPos, cmdColors.start);

	if (owner->selfDCountdown != 0) {
		lineDrawer.DrawIconAtLastPos(CMD_SELFD);
	}

	if (!commandQue.empty() && (commandQue.front().GetID() == CMD_WAIT)) {
		DrawWaitIcon(commandQue.front());
	}

	CCommandQueue::const_iterator ci;
	for (ci = newUnitCommands.begin(); ci != newUnitCommands.end(); ++ci) {
		const int& cmdID = ci->GetID();

		switch (cmdID) {
			case CMD_MOVE: {
				const float3 endPos(ci->params[0], ci->params[1] + 3, ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.move);
				break;
			}
			case CMD_FIGHT: {
				const float3 endPos(ci->params[0], ci->params[1] + 3, ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.fight);
				break;
			}
			case CMD_PATROL: {
				const float3 endPos(ci->params[0], ci->params[1] + 3, ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.patrol);
				break;
			}
			case CMD_ATTACK: {
				if (ci->params.size() == 1) {
					const CUnit* unit = uh->GetUnit(ci->params[0]);

					if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
						const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.attack);
					}
				} else {
					const float x = ci->params[0];
					const float z = ci->params[2];
					const float y = ground->GetHeightReal(x, z, false) + 3.0f;

					lineDrawer.DrawLineAndIcon(cmdID, float3(x, y, z), cmdColors.attack);
				}
				break;
			}
			case CMD_GUARD: {
				const CUnit* unit = uh->GetUnit(ci->params[0]);

				if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
					const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
					lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.guard);
				}
				break;
			}
			case CMD_WAIT: {
				DrawWaitIcon(*ci);
				break;
			}
			case CMD_SELFD: {
				lineDrawer.DrawIconAtLastPos(cmdID);
				break;
			}
			default:
				DrawDefaultCommand(*ci, owner);
				break;
		}

		if ((cmdID < 0) && (ci->params.size() >= 3)) {
			BuildInfo bi;
			bi.def = unitDefHandler->GetUnitDefByID(-(cmdID));
			if (ci->params.size() == 4) {
				bi.buildFacing = int(ci->params[3]);
			}
			bi.pos = float3(ci->params[0], ci->params[1], ci->params[2]);
			bi.pos = helper->Pos2BuildPos(bi, false);

			cursorIcons.AddBuildIcon(cmdID, bi.pos, owner->team, bi.buildFacing);
			lineDrawer.DrawLine(bi.pos, cmdColors.build);

			// draw metal extraction range
			if (bi.def->extractRange > 0) {
				lineDrawer.Break(bi.pos, cmdColors.build);
				glColor4fv(cmdColors.rangeExtract);

				if (bi.def->extractSquare) {
					glSurfaceSquare(bi.pos, bi.def->extractRange, bi.def->extractRange);
				} else {
					glSurfaceCircle(bi.pos, bi.def->extractRange, 40);
				}

				lineDrawer.Restart();
			}
		}
	}
	lineDrawer.FinishPath();
}
Exemple #6
0
void CommandDrawer::DrawBuilderCAICommands(const CBuilderCAI* cai) const
{
	const CUnit* owner = cai->owner;
	const CCommandQueue& commandQue = cai->commandQue;

	lineDrawer.StartPath(owner->drawMidPos, cmdColors.start);

	if (owner->selfDCountdown != 0) {
		lineDrawer.DrawIconAtLastPos(CMD_SELFD);
	}

	CCommandQueue::const_iterator ci;
	for (ci = commandQue.begin(); ci != commandQue.end(); ++ci) {
		const int& cmdID = ci->GetID();

		if (cmdID < 0) {
			const std::map<int, string>& buildOptions = cai->buildOptions;
			const std::map<int, string>::const_iterator boi = buildOptions.find(cmdID);

			if (boi != buildOptions.end()) {
				BuildInfo bi;
				bi.def = unitDefHandler->GetUnitDefByID(-(cmdID));

				if (ci->params.size() == 4) {
					bi.buildFacing = int(abs(ci->params[3])) % NUM_FACINGS;
				}

				bi.pos = float3(ci->params[0], ci->params[1], ci->params[2]);
				bi.pos = helper->Pos2BuildPos(bi, false);

				cursorIcons.AddBuildIcon(cmdID, bi.pos, owner->team, bi.buildFacing);
				lineDrawer.DrawLine(bi.pos, cmdColors.build);

				// draw metal extraction range
				if (bi.def->extractRange > 0) {
					lineDrawer.Break(bi.pos, cmdColors.build);
					glColor4fv(cmdColors.rangeExtract);

					if (bi.def->extractSquare) {
						glSurfaceSquare(bi.pos, bi.def->extractRange, bi.def->extractRange);
					} else {
						glSurfaceCircle(bi.pos, bi.def->extractRange, 40);
					}

					lineDrawer.Restart();
				}
			}
			continue;
		}

		switch (cmdID) {
			case CMD_MOVE: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.move);
				break;
			}
			case CMD_FIGHT:{
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.fight);
				break;
			}
			case CMD_PATROL: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.patrol);
				break;
			}
			case CMD_GUARD: {
				const CUnit* unit = uh->GetUnit(ci->params[0]);

				if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
					const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
					lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.guard);
				}
				break;
			}
			case CMD_RESTORE: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.restore);
				lineDrawer.Break(endPos, cmdColors.restore);
				glColor4fv(cmdColors.restore);
				glSurfaceCircle(endPos, ci->params[3], 20);
				lineDrawer.RestartWithColor(cmdColors.restore);
				break;
			}
			case CMD_ATTACK:
			case CMD_MANUALFIRE: {
				if (ci->params.size() == 1) {
					const CUnit* unit = uh->GetUnit(ci->params[0]);

					if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
						const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(cmdID, endPos, cmdColors.attack);
					}
				} else {
					const float x = ci->params[0];
					const float z = ci->params[2];
					const float y = ground->GetHeightReal(x, z, false) + 3.0f;

					lineDrawer.DrawLineAndIcon(cmdID, float3(x, y, z), cmdColors.attack);
				}
				break;
			}
			case CMD_RECLAIM:
			case CMD_RESURRECT: {
				const float* color = (cmdID == CMD_RECLAIM) ? cmdColors.reclaim
				                                             : cmdColors.resurrect;
				if (ci->params.size() == 4) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
					lineDrawer.DrawLineAndIcon(cmdID, endPos, color);
					lineDrawer.Break(endPos, color);
					glColor4fv(color);
					glSurfaceCircle(endPos, ci->params[3], 20);
					lineDrawer.RestartWithColor(color);
				} else {
					const int signedId = (int)ci->params[0];
					if (signedId < 0) {
						LOG_L(L_WARNING, "Trying to %s a feature or unit with id < 0 (%i), aborting.",
								(cmdID == CMD_RECLAIM) ? "reclaim" : "resurrect",
								signedId);
						break;
					}

					const unsigned int id = signedId;

					if (id >= uh->MaxUnits()) {
						GML_RECMUTEX_LOCK(feat); // DrawCommands

						CFeature* feature = featureHandler->GetFeature(id - uh->MaxUnits());
						if (feature) {
							const float3 endPos = feature->midPos;
							lineDrawer.DrawLineAndIcon(cmdID, endPos, color);
						}
					} else {
						const CUnit* unit = uh->GetUnitUnsafe(id);

						if ((unit != NULL) && (unit != owner) && IsUnitTrackable(unit, owner)) {
							const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
							lineDrawer.DrawLineAndIcon(cmdID, endPos, color);
						}
					}
				}
				break;
			}
			case CMD_REPAIR:
			case CMD_CAPTURE: {
				const float* color = (ci->GetID() == CMD_REPAIR) ? cmdColors.repair
				                                            : cmdColors.capture;
				if (ci->params.size() == 4) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
					lineDrawer.DrawLineAndIcon(cmdID, endPos, color);
					lineDrawer.Break(endPos, color);
					glColor4fv(color);
					glSurfaceCircle(endPos, ci->params[3], 20);
					lineDrawer.RestartWithColor(color);
				} else {
					if (ci->params.size() >= 1) {
						const CUnit* unit = uh->GetUnit(ci->params[0]);

						if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
							const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
							lineDrawer.DrawLineAndIcon(cmdID, endPos, color);
						}
					}
				}
				break;
			}
			case CMD_LOAD_ONTO: {
				const CUnit* unit = uh->GetUnitUnsafe(ci->params[0]);
				lineDrawer.DrawLineAndIcon(cmdID, unit->pos, cmdColors.load);
				break;
			}
			case CMD_WAIT: {
				DrawWaitIcon(*ci);
				break;
			}
			case CMD_SELFD: {
				lineDrawer.DrawIconAtLastPos(ci->GetID());
				break;
			}
			default: {
				DrawDefaultCommand(*ci, owner);
				break;
			}
		}

	}
	lineDrawer.FinishPath();
}
Exemple #7
0
void CommandDrawer::DrawMobileCAICommands(const CMobileCAI* cai) const
{
	const CUnit* owner = cai->owner;
	const CCommandQueue& commandQue = cai->commandQue;

	lineDrawer.StartPath(owner->drawMidPos, cmdColors.start);

	if (owner->selfDCountdown != 0) {
		lineDrawer.DrawIconAtLastPos(CMD_SELFD);
	}

	CCommandQueue::const_iterator ci;
	for (ci = commandQue.begin(); ci != commandQue.end(); ++ci) {
		const int& cmd_id = ci->GetID();

		switch (cmd_id) {
			case CMD_MOVE: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmd_id, endPos, cmdColors.move);
				break;
			}
			case CMD_PATROL: {
				const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
				lineDrawer.DrawLineAndIcon(cmd_id, endPos, cmdColors.patrol);
				break;
			}
			case CMD_FIGHT: {
				if (ci->params.size() != 1) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
					lineDrawer.DrawLineAndIcon(cmd_id, endPos, cmdColors.fight);
					break;
				}
			}
			case CMD_ATTACK:
			case CMD_MANUALFIRE: {
				if (ci->params.size() == 1) {
					const CUnit* unit = uh->GetUnit(ci->params[0]);

					if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
						const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(cmd_id, endPos, cmdColors.attack);
					}
				}
				else if (ci->params.size() >= 3) {
					const float3 endPos(ci->params[0], ci->params[1], ci->params[2]);
					lineDrawer.DrawLineAndIcon(cmd_id, endPos, cmdColors.attack);
				}
				break;
			}
			case CMD_GUARD: {
				const CUnit* unit = uh->GetUnit(ci->params[0]);

				if ((unit != NULL) && IsUnitTrackable(unit, owner)) {
					const float3& endPos = helper->GetUnitErrorPos(unit, owner->allyteam);
					lineDrawer.DrawLineAndIcon(cmd_id, endPos, cmdColors.guard);
				}
				break;
			}
			case CMD_LOAD_ONTO: {
				const CUnit* unit = uh->GetUnitUnsafe(ci->params[0]);
				lineDrawer.DrawLineAndIcon(cmd_id, unit->pos, cmdColors.load);
				break;
			}
			case CMD_WAIT: {
				DrawWaitIcon(*ci);
				break;
			}
			case CMD_SELFD: {
				lineDrawer.DrawIconAtLastPos(cmd_id);
				break;
			}
			default: {
				DrawDefaultCommand(*ci, owner);
				break;
			}
		}
	}
	lineDrawer.FinishPath();
}