void CBuilderCAI::ExecuteResurrect(Command& c) { // not all builders are resurrect-capable by default if (!owner->unitDef->canResurrect) return; if (c.params.size() == 1) { unsigned int id = (unsigned int) c.params[0]; if (id >= unitHandler->MaxUnits()) { // resurrect feature CFeature* feature = featureHandler->GetFeature(id - unitHandler->MaxUnits()); if (feature && feature->udef != NULL) { if (((c.options & INTERNAL_ORDER) && !(c.options & CONTROL_KEY) && IsFeatureBeingReclaimed(feature->id, owner)) || !ResurrectObject(feature)) { StopMove(); RemoveUnitFromResurrecters(owner); FinishCommand(); } else { AddUnitToResurrecters(owner); } } else { RemoveUnitFromResurrecters(owner); if (ownerBuilder->lastResurrected && unitHandler->GetUnitUnsafe(ownerBuilder->lastResurrected) != NULL && owner->unitDef->canRepair) { // resurrection finished, start repair (by overwriting the current order) c = Command(CMD_REPAIR, c.options | INTERNAL_ORDER, ownerBuilder->lastResurrected); ownerBuilder->lastResurrected = 0; inCommand = false; SlowUpdate(); return; } StopMove(); FinishCommand(); } } else { // resurrect unit RemoveUnitFromResurrecters(owner); FinishCommand(); } } else if (c.params.size() == 4) { // area resurrect const float3 pos = c.GetPos(0); const float radius = c.params[3]; if (FindResurrectableFeatureAndResurrect(pos, radius, c.options, (c.options & META_KEY))) { inCommand = false; SlowUpdate(); return; } if (!(c.options & ALT_KEY)) { FinishCommand(); } } else { // wrong number of parameters RemoveUnitFromResurrecters(owner); FinishCommand(); } }
bool CBuilderCAI::FindResurrectableFeatureAndResurrect(const float3& pos, float radius, unsigned char options, bool freshOnly) { const std::vector<CFeature*> &features = qf->GetFeaturesExact(pos, radius); const CFeature* best = NULL; float bestDist = 1.0e30f; for (std::vector<CFeature*>::const_iterator fi = features.begin(); fi != features.end(); ++fi) { const CFeature* f = *fi; if (f->def->destructable && f->udef != NULL) { if (!f->IsInLosForAllyTeam(owner->allyteam)) { continue; } if (freshOnly && f->reclaimLeft < 1.0f && f->resurrectProgress <= 0.0f) { continue; } float dist = f3SqDist(f->pos, owner->pos); if (dist < bestDist) { // dont lock-on to units outside of our reach (for immobile builders) if (owner->immobile && !IsInBuildRange(f)) { continue; } if(!(options & CONTROL_KEY) && IsFeatureBeingReclaimed(f->id, owner)) { continue; } bestDist = dist; best = f; } } } if (best) { Command c2(CMD_RESURRECT, options | INTERNAL_ORDER); c2.params.push_back(uh->MaxUnits() + best->id); commandQue.push_front(c2); return true; } return false; }