bool CTransportCAI::AllowedCommand(const Command& c, bool fromSynced)
{
	if (!CMobileCAI::AllowedCommand(c, fromSynced)) {
		return false;
	}

	switch (c.GetID()) {
		case CMD_UNLOAD_UNIT:
		case CMD_UNLOAD_UNITS: {
			const CTransportUnit* transport = static_cast<CTransportUnit*>(owner);
			const std::list<CTransportUnit::TransportedUnit>& transportees = transport->GetTransportedUnits();

			// allow unloading empty transports for easier setup of transport bridges
			if (transportees.empty())
				return true;

			if (c.GetParamsCount() == 5) {
				if (fromSynced) {
					// point transported buildings (...) in their wanted direction after unloading
					for (auto it = transportees.begin(); it != transportees.end(); ++it) {
						CBuilding* building = dynamic_cast<CBuilding*>(it->unit);

						if (building == NULL)
							continue;

						building->buildFacing = std::abs(int(c.GetParam(4))) % NUM_FACINGS;
					}
				}
			}

			if (c.GetParamsCount() >= 4) {
				// find unload positions for transportees (WHY can this run in unsynced context?)
				for (auto it = transportees.begin(); it != transportees.end(); ++it) {
					CUnit* u = it->unit;

					const float radius = (c.GetID() == CMD_UNLOAD_UNITS)? c.GetParam(3): 0.0f;
					const float spread = u->radius * transport->unitDef->unloadSpread;

					float3 foundPos;

					if (FindEmptySpot(c.GetPos(0), radius, spread, foundPos, u, fromSynced)) {
						return true;
					}
					 // FIXME: support arbitrary unloading order for other unload types also
					if (unloadType != UNLOAD_LAND) {
						return false;
					}
				}

				// no empty spot found for any transported unit
				return false;
			}

			break;
		}
	}

	return true;
}
bool TextFormulaNode::UndoRemoveItem(NodeEvent& nodeEvent)
{
	Command* command = any_cast<Command*>(nodeEvent["command"]);
	bool right = any_cast<bool>(nodeEvent["right"]);
	SharedCaretState c = any_cast<SharedCaretState>(nodeEvent["caretState"]);
	int pos = c->GetPos();
	QString str = any_cast<QString>(command->GetParam(this, "str"));
	QString text = GetText();
	
	text = text.left(pos) + str + text.right(text.length() - pos);
	SetText(text);
	
	return true;
}
bool TextFormulaNode::UndoInsertText(NodeEvent& nodeEvent)
{
	Command* command = any_cast<Command*>(nodeEvent["command"]);
	int pos = any_cast<int>(command->GetParam(this, "pos"));
	QString str = any_cast<QString>(nodeEvent["text"]);
	QString text = GetText();
	SharedCaretState c = any_cast<SharedCaretState>(nodeEvent["caretState"]);

	//update the item	
	text = text.left(pos) + text.right(text.length() - pos - str.length());
	SetText(text);
	
	c->SetToNode(this, pos);
	
	return true;
}
Exemple #4
0
void CUnitHandler::BuildTaskCreate(int id) {
	const UnitDef* newUnitDef = ai->cb->GetUnitDef(id);
	const UnitCategory category = ai->ut->GetCategory(id);
	const float3 pos = ai->cb->GetUnitPos(id);

	if ((!newUnitDef->movedata || category == CAT_DEFENCE) && !newUnitDef->canfly && category != CAT_LAST) {
		// this needs to change, so that it can make more stuff
		if (category >= CAT_LAST) {
			return;
		}

		BuildTask bt;
		bt.id = -1;

		std::list<TaskPlan>::iterator i;

		for (i = TaskPlans[category].begin(); i != TaskPlans[category].end(); i++) {
			if (pos.distance2D(i->pos) < 1.0f && newUnitDef == i->def) {
				bt.category = category;
				bt.id       = id;
				bt.pos      = i->pos;
				bt.def      = newUnitDef;

				std::list<BuilderTracker*> moveList;

				for (std::list<BuilderTracker*>::iterator builder = i->builderTrackers.begin(); builder != i->builderTrackers.end(); builder++) {
					moveList.push_back(*builder);
				}

				for (std::list<BuilderTracker*>::iterator builder = moveList.begin(); builder != moveList.end(); builder++) {
					TaskPlanRemove(*builder);
					BuildTaskAddBuilder(&bt, *builder);
				}

				// there can not be more than one found TaskPlan
				break;
			}
		}

		if (bt.id == -1) {
			// buildtask creation error (can happen if builder manages
			// to restart a dead building, or a human has taken control),
			// make one anyway
			std::stringstream msg;
				msg << "[CUnitHandler::BuildTaskCreate()][frame=" << ai->cb->GetCurrentFrame() << "]\n";
				msg << "\tBuildTask Creation Error for task with ID " << id << "\n";
			ai->GetLogger()->Log(msg.str());

			if (category == CAT_DEFENCE) {
				ai->dm->AddDefense(pos, newUnitDef);
			}

			bt.category = category;
			bt.id = id;
			bt.pos = pos;
			bt.def = newUnitDef;

			// if we have any friendly builders
			for (std::list<BuilderTracker*>::iterator i = BuilderTrackers.begin(); i != BuilderTrackers.end(); i++) {
				BuilderTracker* builderTracker = *i;

				// check what builder is doing
				const CCommandQueue* cq = ai->cb->GetCurrentUnitCommands(builderTracker->builderID);

				if (!cq->empty()) {
					Command c = cq->front();

					const bool b0 = (c.GetID() == -newUnitDef->id && c.GetParam(0) == pos.x && c.GetParam(2) == pos.z); // at this pos
					const bool b1 = (c.GetID() == CMD_REPAIR && c.GetParam(0) == id); // at this unit (id)
					const bool b2 = (c.GetID() == CMD_GUARD  && c.GetParam(0) == id); // at this unit (id)
					const bool b3 = b0 || b1 || b2;

					if (b3) {
						if (builderTracker->buildTaskId != 0) {
							BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);

							if (buildTask->builderTrackers.size() > 1) {
								BuildTaskRemove(builderTracker);
							} else {
								// only builder of this thing, and now idle
								BuildTaskRemove(builderTracker);
							}
						}

						if (builderTracker->taskPlanId != 0) {
							GetTaskPlan(builderTracker->taskPlanId);
							TaskPlanRemove(builderTracker);
						}
						if (builderTracker->factoryId != 0) {
							FactoryBuilderRemove(builderTracker);
						}

						// this builder is now free
						if (builderTracker->idleStartFrame == -2) {
							IdleUnitRemove(builderTracker->builderID);
						}

						// add it to this task
						BuildTaskAddBuilder(&bt, builderTracker);

						msg.str("");
							msg << "\tadded builder " << builderTracker->builderID << " to";
							msg << " build-task with ID " << builderTracker->buildTaskId << "\n";
						ai->GetLogger()->Log(msg.str());
					}
				}
			}

			// add the task anyway
			BuildTasks[category].push_back(bt);
		}
		else {
			if (category == CAT_DEFENCE)
				ai->dm->AddDefense(pos,newUnitDef);

			BuildTasks[category].push_back(bt);
		}
	}
}
Exemple #5
0
void CSelectedUnitsHandlerAI::GiveCommandNet(Command &c, int player)
{
	const std::vector<int>& netSelected = selectedUnitsHandler.netSelected[player];
	std::vector<int>::const_iterator ui;

	const int nbrOfSelectedUnits = netSelected.size();
	const int cmd_id = c.GetID();

	if (nbrOfSelectedUnits < 1) {
		// no units to command
	}
	else if ((cmd_id == CMD_ATTACK) && (
			(c.GetParamsCount() == 6) ||
			((c.GetParamsCount() == 4) && (c.GetParam(3) > 0.001f))
		))
	{
		SelectAttack(c, player);
	}
	else if (nbrOfSelectedUnits == 1) {
		// a single unit selected
		CUnit* unit = unitHandler->GetUnit(*netSelected.begin());

		if (unit != nullptr) {
			unit->commandAI->GiveCommand(c, true);

			if (MayRequireSetMaxSpeedCommand(c))
				AddUnitSetMaxSpeedCommand(unit, c.options);

			if (cmd_id == CMD_WAIT) {
				if (player == gu->myPlayerNum) {
					waitCommandsAI.AcknowledgeCommand(c);
				}
			}
		}
	}

	// User Move Front Command:
	//
	//   CTRL:      Group Front/Speed  command
	//
	// User Move Command:
	//
	//   ALT:       Group Front        command
	//   ALT+CTRL:  Group Front/Speed  command
	//   CTRL:      Group Locked/Speed command  (maintain relative positions)
	//
	// User Patrol and Fight Commands:
	//
	//   CTRL:      Group Locked/Speed command  (maintain relative positions)
	//   ALT+CTRL:  Group Locked       command  (maintain relative positions)
	//

	else if (((cmd_id == CMD_MOVE) || (cmd_id == CMD_FIGHT)) && (c.GetParamsCount() == 6)) {
		CalculateGroupData(player, !!(c.options & SHIFT_KEY));

		MakeFrontMove(&c, player);

		const bool groupSpeed = !!(c.options & CONTROL_KEY);
		for (ui = netSelected.begin(); ui != netSelected.end(); ++ui) {
			CUnit* unit = unitHandler->GetUnit(*ui);

			if (unit != nullptr) {
				if (groupSpeed) {
					AddGroupSetMaxSpeedCommand(unit, c.options);
				} else {
					AddUnitSetMaxSpeedCommand(unit, c.options);
				}
			}
		}
	}
	else if ((cmd_id == CMD_MOVE) && (c.options & ALT_KEY)) {
		CalculateGroupData(player, !!(c.options & SHIFT_KEY));

		// use the vector from the middle of group to new pos as forward dir
		const float3 pos(c.GetParam(0), c.GetParam(1), c.GetParam(2));
		float3 frontdir = pos - centerCoor;
		frontdir.y = 0.0f;
		frontdir.ANormalize();
		const float3 sideDir = frontdir.cross(UpVector);

		// calculate so that the units form in an aproximate square
		float length = 100.0f + (math::sqrt((float)nbrOfSelectedUnits) * 32.0f);

		// push back some extra params so it confer with a front move
		c.PushPos(pos + (sideDir * length));

		MakeFrontMove(&c, player);

		const bool groupSpeed = !!(c.options & CONTROL_KEY);
		for (ui = netSelected.begin(); ui != netSelected.end(); ++ui) {
			CUnit* unit = unitHandler->GetUnit(*ui);

			if (unit != nullptr) {
				if (groupSpeed) {
					AddGroupSetMaxSpeedCommand(unit, c.options);
				} else {
					AddUnitSetMaxSpeedCommand(unit, c.options);
				}
			}
		}
	}
	else if ((c.options & CONTROL_KEY) &&
	         ((cmd_id == CMD_MOVE) || (cmd_id == CMD_PATROL) || (cmd_id == CMD_FIGHT))) {
		CalculateGroupData(player, !!(c.options & SHIFT_KEY));

		const bool groupSpeed = !(c.options & ALT_KEY);

		for (ui = netSelected.begin(); ui != netSelected.end(); ++ui) {
			CUnit* unit = unitHandler->GetUnit(*ui);

			if (unit != nullptr) {
				// Modifying the destination relative to the center of the group
				Command uc = c;
				float3 midPos;
				if (c.options & SHIFT_KEY) {
					midPos = LastQueuePosition(unit);
				} else {
					midPos = unit->midPos;
				}
				uc.params[CMDPARAM_MOVE_X] += midPos.x - centerCoor.x;
				uc.params[CMDPARAM_MOVE_Y] += midPos.y - centerCoor.y;
				uc.params[CMDPARAM_MOVE_Z] += midPos.z - centerCoor.z;
				unit->commandAI->GiveCommand(uc, false);

				if (groupSpeed) {
					AddGroupSetMaxSpeedCommand(unit, c.options);
				} else {
					AddUnitSetMaxSpeedCommand(unit, c.options);
				}
			}
		}
	}
	else {
		for (ui = netSelected.begin(); ui != netSelected.end(); ++ui) {
			CUnit* unit = unitHandler->GetUnit(*ui);

			if (unit != nullptr) {
				// appending a CMD_SET_WANTED_MAX_SPEED command to
				// every command is a little bit wasteful, n'est pas?
				unit->commandAI->GiveCommand(c, false);
				if (MayRequireSetMaxSpeedCommand(c)) {
					AddUnitSetMaxSpeedCommand(unit, c.options);
				}
			}
		}
		if (cmd_id == CMD_WAIT) {
			if (player == gu->myPlayerNum) {
				waitCommandsAI.AcknowledgeCommand(c);
			}
		}
	}
}