void CBuilderCAI::ExecuteReclaim(Command &c) { assert(owner->unitDef->canReclaim); CBuilder* fac=(CBuilder*)owner; if(c.params.size()==1){ int id=(int) c.params[0]; if(id>=MAX_UNITS){ //reclaim feature CFeature* feature=featureHandler->features[id-MAX_UNITS]; if(feature){ if(!ReclaimObject(feature)){ StopMove(); FinishCommand(); } } else { StopMove(); FinishCommand(); } } else { //reclaim unit CUnit* unit=uh->units[id]; if(unit && unit!=owner && unit->unitDef->reclaimable && UpdateTargetLostTimer(id)){ if(!ReclaimObject(unit)){ StopMove(); FinishCommand(); } } else { FinishCommand(); } } } else if(c.params.size()==4){//area reclaim float3 pos(c.params[0],c.params[1],c.params[2]); float radius=c.params[3]; if(FindReclaimableFeatureAndReclaim(pos,radius,c.options,true)){ inCommand=false; SlowUpdate(); return; } if(!(c.options & ALT_KEY)){ FinishCommand(); } } else { //wrong number of parameters FinishCommand(); } return; }
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::ExecuteGuard(Command& c) { if (!owner->unitDef->canGuard) return; CBuilder* builder = (CBuilder*) owner; CUnit* guardee = uh->GetUnit(c.params[0]); if (guardee == NULL) { FinishCommand(); return; } if (guardee == owner) { FinishCommand(); return; } if (UpdateTargetLostTimer(guardee->id) == 0) { FinishCommand(); return; } if (guardee->outOfMapTime > (GAME_SPEED * 5)) { FinishCommand(); return; } if (CBuilder* b = dynamic_cast<CBuilder*>(guardee)) { if (b->terraforming) { if (MoveInBuildRange(b->terraformCenter, b->terraformRadius * 0.7f)) { builder->HelpTerraform(b); } else { StopSlowGuard(); } return; } else if (b->curReclaim && owner->unitDef->canReclaim) { StopSlowGuard(); if (!ReclaimObject(b->curReclaim)) { StopMove(); } return; } else if (b->curResurrect && owner->unitDef->canResurrect) { StopSlowGuard(); if (!ResurrectObject(b->curResurrect)) { StopMove(); } return; } else { builder->StopBuild(); } const bool pushRepairCommand = ( b->curBuild != NULL) && ( b->curBuild->soloBuilder == NULL || b->curBuild->soloBuilder == owner) && (( b->curBuild->beingBuilt && owner->unitDef->canAssist) || ( !b->curBuild->beingBuilt && owner->unitDef->canRepair)); if (pushRepairCommand) { StopSlowGuard(); Command nc(CMD_REPAIR, c.options); nc.params.push_back(b->curBuild->id); commandQue.push_front(nc); inCommand = false; SlowUpdate(); return; } } if (CFactory* fac = dynamic_cast<CFactory*>(guardee)) { const bool pushRepairCommand = ( fac->curBuild != NULL) && ( fac->curBuild->soloBuilder == NULL || fac->curBuild->soloBuilder == owner) && (( fac->curBuild->beingBuilt && owner->unitDef->canAssist) || (!fac->curBuild->beingBuilt && owner->unitDef->canRepair)); if (pushRepairCommand) { StopSlowGuard(); Command nc(CMD_REPAIR, c.options); nc.params.push_back(fac->curBuild->id); commandQue.push_front(nc); inCommand = false; // SlowUpdate(); return; } } if (!(c.options & CONTROL_KEY) && IsUnitBeingReclaimed(guardee, owner)) return; const float3 pos = guardee->pos; const float radius = (guardee->immobile) ? guardee->radius : guardee->radius * 0.8f; // in case of mobile units reduce radius a bit if (MoveInBuildRange(pos, radius)) { StartSlowGuard(guardee->moveType->GetMaxSpeed()); const bool pushRepairCommand = ( guardee->health < guardee->maxHealth) && ( guardee->soloBuilder == NULL || guardee->soloBuilder == owner) && (( guardee->beingBuilt && owner->unitDef->canAssist) || (!guardee->beingBuilt && owner->unitDef->canRepair)); if (pushRepairCommand) { StopSlowGuard(); Command nc(CMD_REPAIR, c.options); nc.params.push_back(guardee->id); commandQue.push_front(nc); inCommand = false; return; } else { NonMoving(); } } else { StopSlowGuard(); } }
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; }
void CBuilderCAI::ExecuteGuard(Command& c) { assert(owner->unitDef->canGuard); CBuilder* fac=(CBuilder*)owner; CUnit* guarded=uh->units[(int)c.params[0]]; if (guarded && guarded!=owner && UpdateTargetLostTimer((int)c.params[0])) { if (CBuilder* b=dynamic_cast<CBuilder*>(guarded)) { if (b->terraforming) { if (f3SqDist(fac->pos, b->terraformCenter) < Square((fac->buildDistance * 0.8f) + (b->terraformRadius * 0.7f))) { StopMove(); owner->moveType->KeepPointingTo(b->terraformCenter, fac->buildDistance*0.9f, false); fac->HelpTerraform(b); } else { StopSlowGuard(); SetGoal(b->terraformCenter,fac->pos,fac->buildDistance*0.7f+b->terraformRadius*0.6f); } return; } else if (b->curReclaim && owner->unitDef->canReclaim){ StopSlowGuard(); if(!ReclaimObject(b->curReclaim)){ StopMove(); } return; } else { fac->StopBuild(); } if (b->curBuild && (!b->curBuild->soloBuilder || (b->curBuild->soloBuilder == owner)) && (( b->curBuild->beingBuilt && owner->unitDef->canAssist) || (!b->curBuild->beingBuilt && owner->unitDef->canRepair))) { StopSlowGuard(); Command nc; nc.id=CMD_REPAIR; nc.options=c.options; nc.params.push_back(b->curBuild->id); commandQue.push_front(nc); inCommand=false; SlowUpdate(); return; } } if(CFactory* f=dynamic_cast<CFactory*>(guarded)){ if (f->curBuild && (!f->curBuild->soloBuilder || (f->curBuild->soloBuilder == owner)) && (( f->curBuild->beingBuilt && owner->unitDef->canAssist) || (!f->curBuild->beingBuilt && owner->unitDef->canRepair))) { StopSlowGuard(); Command nc; nc.id=CMD_REPAIR; nc.options=c.options; nc.params.push_back(f->curBuild->id); commandQue.push_front(nc); inCommand=false; // SlowUpdate(); return; } } if (IsUnitBeingReclaimedByFriend(guarded)) return; float3 curPos = owner->pos; float3 dif = guarded->pos - curPos; dif.Normalize(); float3 goal = guarded->pos - dif * (fac->buildDistance * 0.5f); if (f3SqLen(guarded->pos - curPos) > (fac->buildDistance*1.1f + guarded->radius) * (fac->buildDistance*1.1f + guarded->radius)) { StopSlowGuard(); } if (f3SqLen(guarded->pos - curPos) < (fac->buildDistance*0.9f + guarded->radius) * (fac->buildDistance*0.9f + guarded->radius)) { StartSlowGuard(guarded->maxSpeed); StopMove(); // logOutput.Print("should point with type 3?"); owner->moveType->KeepPointingTo(guarded->pos, fac->buildDistance*0.9f+guarded->radius, false); if ((guarded->health < guarded->maxHealth) && (!guarded->soloBuilder || (guarded->soloBuilder == owner)) && (( guarded->beingBuilt && owner->unitDef->canAssist) || (!guarded->beingBuilt && owner->unitDef->canRepair))) { StopSlowGuard(); Command nc; nc.id=CMD_REPAIR; nc.options=c.options; nc.params.push_back(guarded->id); commandQue.push_front(nc); inCommand=false; return; } else { NonMoving(); } } else { if (f3SqLen(goalPos - goal) > 4000 || f3SqLen(goalPos - owner->pos) < (owner->maxSpeed*30 + 1 + SQUARE_SIZE*2) * (owner->maxSpeed*30 + 1 + SQUARE_SIZE*2)){ SetGoal(goal,curPos); } } } else { FinishCommand(); } return; }