void CSelectedUnitsAI::SelectAttack(const Command& cmd, int player) { vector<int> targets; const float3 pos0(cmd.params[0], cmd.params[1], cmd.params[2]); if (cmd.params.size() == 4) { SelectCircleUnits(pos0, cmd.params[3], targets, player); } else { const float3 pos1(cmd.params[3], cmd.params[4], cmd.params[5]); SelectRectangleUnits(pos0, pos1, targets, player); } const int targetsCount = (int)targets.size(); if (targets.size() <= 0) { return; } const vector<int>& selected = selectedUnits.netSelected[player]; const int selectedCount = (int)selected.size(); if (selectedCount <= 0) { return; } Command attackCmd; attackCmd.id = CMD_ATTACK; attackCmd.options = cmd.options; attackCmd.params.push_back(0.0f); // dummy // delete the attack commands and bail for CONTROL_KEY if (cmd.options & CONTROL_KEY) { attackCmd.options |= SHIFT_KEY; for (int s = 0; s < selectedCount; s++) { CUnit* unit = uh->units[selected[s]]; if (unit == NULL) { continue; } CCommandAI* commandAI = uh->units[selected[s]]->commandAI; for (int t = 0; t < targetsCount; t++) { attackCmd.params[0] = targets[t]; if (commandAI->WillCancelQueued(attackCmd)) { commandAI->GiveCommand(attackCmd, false); } } } return; } const bool queueing = !!(cmd.options & SHIFT_KEY); // get the group center float3 midPos(0.0f, 0.0f, 0.0f); int realCount = 0; for (int s = 0; s < selectedCount; s++) { CUnit* unit = uh->units[selected[s]]; if (unit == NULL) { continue; } if (queueing) { midPos += LastQueuePosition(unit); } else { midPos += unit->midPos; } realCount++; } if (realCount <= 0) { return; } midPos /= (float)realCount; // sort the targets vector<DistInfo> distVec; int t; for (t = 0; t < targetsCount; t++) { DistInfo di; di.unitID = targets[t]; CUnit* unit = uh->units[di.unitID]; const float3 unitPos = queueing ? LastQueuePosition(unit) : float3(unit->midPos); di.dist = (unitPos - midPos).SqLength2D(); distVec.push_back(di); } sort(distVec.begin(), distVec.end()); // give the commands for (int s = 0; s < selectedCount; s++) { if (!queueing) { // clear it for the first command attackCmd.options &= ~SHIFT_KEY; } CUnit* unit = uh->units[selected[s]]; if (unit == NULL) { continue; } CCommandAI* commandAI = unit->commandAI; for (t = 0; t < targetsCount; t++) { attackCmd.params[0] = distVec[t].unitID; if (!queueing || !commandAI->WillCancelQueued(attackCmd)) { commandAI->GiveCommand(attackCmd, false); AddUnitSetMaxSpeedCommand(unit, attackCmd.options); // following commands are always queued attackCmd.options |= SHIFT_KEY; } } } }
void CSelectedUnitsHandlerAI::SelectAttack(const Command& cmd, int player) { std::vector<int> targets; if (cmd.params.size() == 4) { SelectCircleUnits(cmd.GetPos(0), cmd.params[3], player, targets); } else { SelectRectangleUnits(cmd.GetPos(0), cmd.GetPos(3), player, targets); } if (targets.empty()) return; const bool queueing = !!(cmd.options & SHIFT_KEY); const std::vector<int>& selected = selectedUnitsHandler.netSelected[player]; const unsigned int targetsCount = targets.size(); const unsigned int selectedCount = selected.size(); if (selectedCount == 0) return; Command attackCmd(CMD_ATTACK, cmd.options, 0.0f); // delete the attack commands and bail for CONTROL_KEY if (cmd.options & CONTROL_KEY) { attackCmd.options |= SHIFT_KEY; for (unsigned int s = 0; s < selectedCount; s++) { const CUnit* unit = unitHandler->GetUnit( selected[s] ); if (unit == nullptr) continue; CCommandAI* commandAI = unit->commandAI; for (unsigned int t = 0; t < targetsCount; t++) { attackCmd.params[0] = targets[t]; if (commandAI->WillCancelQueued(attackCmd)) { commandAI->GiveCommand(attackCmd, false); } } } return; } // get the group center float3 midPos; unsigned int realCount = 0; for (unsigned int s = 0; s < selectedCount; s++) { CUnit* unit = unitHandler->GetUnit(selected[s]); if (unit == nullptr) continue; if (queueing) { midPos += LastQueuePosition(unit); } else { midPos += unit->midPos; } realCount++; } if (realCount == 0) return; midPos /= realCount; // sort the targets std::vector<DistInfo> distVec; for (unsigned int t = 0; t < targetsCount; t++) { const CUnit* unit = unitHandler->GetUnit( targets[t] ); const float3 unitPos = float3(unit->midPos); DistInfo di; di.unitID = targets[t]; di.dist = (unitPos - midPos).SqLength2D(); distVec.push_back(di); } stable_sort(distVec.begin(), distVec.end()); // give the commands for (unsigned int s = 0; s < selectedCount; s++) { if (!queueing) { // clear it for the first command attackCmd.options &= ~SHIFT_KEY; } CUnit* unit = unitHandler->GetUnit(selected[s]); if (unit == nullptr) continue; CCommandAI* commandAI = unit->commandAI; for (unsigned t = 0; t < targetsCount; t++) { attackCmd.params[0] = distVec[t].unitID; if (!queueing || !commandAI->WillCancelQueued(attackCmd)) { commandAI->GiveCommand(attackCmd, false); AddUnitSetMaxSpeedCommand(unit, attackCmd.options); // following commands are always queued attackCmd.options |= SHIFT_KEY; } } } }