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; }
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); } } }
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); } } } }