void CBuilderCAI::ExecuteReclaim(Command& c) { CBuilder* builder = (CBuilder*) owner; // not all builders are reclaim-capable by default if (!owner->unitDef->canReclaim) return; if (c.params.size() == 1 || c.params.size() == 5) { const int signedId = (int) c.params[0]; if (signedId < 0) { LOG_L(L_WARNING, "Trying to reclaim unit or feature with id < 0 (%i), aborting.", signedId); return; } const unsigned int uid = signedId; //FIXME add a per-unit solution to better balance the load? const bool checkForBetterTarget = (gs->frameNum % (5 * UNIT_SLOWUPDATE_RATE)) < UNIT_SLOWUPDATE_RATE; if (checkForBetterTarget && (c.options & INTERNAL_ORDER) && (c.params.size() >= 5)) { // regular check if there is a closer reclaim target CSolidObject* obj; if (uid >= uh->MaxUnits()) { obj = featureHandler->GetFeature(uid - uh->MaxUnits()); } else { obj = uh->GetUnit(uid); } if (obj) { const float3 pos(c.params[1], c.params[2], c.params[3]); const float radius = c.params[4]; const float curdist = pos.SqDistance2D(obj->pos); const bool recUnits = !!(c.options & META_KEY); const bool recEnemyOnly = (c.options & META_KEY) && (c.options & CONTROL_KEY); const bool recSpecial = !!(c.options & CONTROL_KEY); ReclaimOption recopt = REC_NORESCHECK; if (recUnits) recopt |= REC_UNITS; if (recEnemyOnly) recopt |= REC_ENEMYONLY; if (recSpecial) recopt |= REC_SPECIAL; const int rid = FindReclaimTarget(pos, radius, c.options, recopt, curdist); if ((rid > 0) && (rid != uid)) { FinishCommand(); RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); return; } } } if (uid >= uh->MaxUnits()) { // reclaim feature CFeature* feature = featureHandler->GetFeature(uid - uh->MaxUnits()); if (feature != NULL) { bool featureBeingResurrected = IsFeatureBeingResurrected(feature->id, owner); featureBeingResurrected &= (c.options & INTERNAL_ORDER) && !(c.options & CONTROL_KEY); if (featureBeingResurrected || !ReclaimObject(feature)) { StopMove(); FinishCommand(); RemoveUnitFromFeatureReclaimers(owner); } else { AddUnitToFeatureReclaimers(owner); } } else { StopMove(); FinishCommand(); RemoveUnitFromFeatureReclaimers(owner); } RemoveUnitFromReclaimers(owner); } else { // reclaim unit CUnit* unit = uh->GetUnit(uid); if (unit != NULL && c.params.size() == 5) { const float3 pos(c.params[1], c.params[2], c.params[3]); const float radius = c.params[4] + 100.0f; // do not walk too far outside reclaim area const bool outOfReclaimRange = (pos.SqDistance2D(unit->pos) > radius * radius) || (builder->curReclaim == unit && unit->isMoving && !IsInBuildRange(unit)); const bool busyAlliedBuilder = unit->unitDef->builder && !unit->commandAI->commandQue.empty() && teamHandler->Ally(owner->allyteam, unit->allyteam); if (outOfReclaimRange || busyAlliedBuilder) { StopMove(); RemoveUnitFromReclaimers(owner); FinishCommand(); RemoveUnitFromFeatureReclaimers(owner); return; } } if (unit != NULL && unit != owner && unit->unitDef->reclaimable && UpdateTargetLostTimer(unit->id) && unit->AllowedReclaim(owner)) { if (!ReclaimObject(unit)) { StopMove(); FinishCommand(); } else { AddUnitToReclaimers(owner); } } else { RemoveUnitFromReclaimers(owner); FinishCommand(); } RemoveUnitFromFeatureReclaimers(owner); } } else if (c.params.size() == 4) { // area reclaim const float3 pos = c.GetPos(0); const float radius = c.params[3]; const bool recUnits = !!(c.options & META_KEY); const bool recEnemyOnly = (c.options & META_KEY) && (c.options & CONTROL_KEY); const bool recSpecial = !!(c.options & CONTROL_KEY); RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); builder->StopBuild(); ReclaimOption recopt = REC_NORESCHECK; if (recUnits) recopt |= REC_UNITS; if (recEnemyOnly) recopt |= REC_ENEMYONLY; if (recSpecial) recopt |= REC_SPECIAL; if (FindReclaimTargetAndReclaim(pos, radius, c.options, recopt)) { inCommand = false; SlowUpdate(); return; } if(!(c.options & ALT_KEY)){ FinishCommand(); } } else { // wrong number of parameters RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); FinishCommand(); } }
void CBuilderCAI::ExecuteReclaim(Command& c) { assert(owner->unitDef->canReclaim); if(c.params.size()==1){ int id=(int) c.params[0]; if (id >= MAX_UNITS) { //reclaim feature const CFeatureSet& fset = featureHandler->GetActiveFeatures(); CFeatureSet::const_iterator it = fset.find(id - MAX_UNITS); if (it != fset.end()) { CFeature* feature = *it; if(!ReclaimObject(feature)){ StopMove(); FinishCommand(); RemoveUnitFromFeatureReclaimers(owner); } else { AddUnitToFeatureReclaimers(owner); } } else { StopMove(); FinishCommand(); RemoveUnitFromFeatureReclaimers(owner); } RemoveUnitFromReclaimers(owner); } else { //reclaim unit CUnit* unit=uh->units[id]; if(unit && unit!=owner && unit->unitDef->reclaimable && UpdateTargetLostTimer(id) && unit->AllowedReclaim(owner) ){ if(!ReclaimObject(unit)){ StopMove(); FinishCommand(); } else { AddUnitToReclaimers(owner); } } else { RemoveUnitFromReclaimers(owner); FinishCommand(); } RemoveUnitFromFeatureReclaimers(owner); } } else if(c.params.size()==4){//area reclaim float3 pos(c.params[0],c.params[1],c.params[2]); float radius=c.params[3]; const bool recAnyTeam = ((c.options & CONTROL_KEY) != 0); RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); if (FindReclaimableFeatureAndReclaim(pos, radius, c.options, true, recAnyTeam)) { inCommand=false; SlowUpdate(); return; } if(!(c.options & ALT_KEY)){ FinishCommand(); } } else { //wrong number of parameters RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); FinishCommand(); } return; }