bool CActions::DGunNearby(int uid){ NLOG("CActions::DGunNearby"); CUnitTypeData* utd = G->UnitDefLoader->GetUnitTypeDataByUnitId(uid); if(utd == 0 ){ G->L.print("Dgunning failed, utd == 0"); return false; } if(!utd->CanDGun()){ return false; } float3 compos = G->GetUnitPos(uid); if(G->Map->CheckFloat3(compos)==false){ return false; } int* en = new int[10000]; int e = G->GetEnemyUnits(en, compos, G->cb->GetUnitMaxRange(uid)*1.3f); // get all enemy units within weapons range atm if(e>0){ for(int i = 0; i < e; i++){ if(ValidUnitID(en[i])==false){ continue; } CUnitTypeData* edt = G->UnitDefLoader->GetUnitTypeDataByUnitId(en[i]); //if(endi->isCommander == true) continue; // no dgunning enemy commanders! // no dgunning enemy commanders is commented out because now if the enemy is a commander the CMD_DGUN is // changed to CMD_RECLAIM, allowing the enemy commander to be eliminated without causing a wild goose chase of // building dgunned building dgunned, commander in the way of building dgunned, BANG, both commanders bye bye // that and the line needs fiddling anyway due to the CUnitTypeData refactor if(edt->IsAirCraft()&&(edt->GetUnitDef()->speed<3)){ continue;// attempting to dgun an aircraft without predictive dgunning leads to a goose chase } int k = en[i]; delete [] en; if(edt->GetUnitDef()->canDGun){ int r = (int)G->Pl->ReclaimTime(utd->GetUnitDef(), edt->GetUnitDef(), G->chcb->GetUnitHealth(k)); int c = (int)G->Pl->CaptureTime(utd->GetUnitDef(), edt->GetUnitDef(), G->chcb->GetUnitHealth(k)); if (r<(4 SECONDS) && r < c){ return Reclaim(uid, k); } else { if (c<(4 SECONDS)){ return Capture(uid, k); } else { NLOG("CActions::IfNobodyNearMoveToNearest :: WipePlansForBuilder"); return MoveToStrike(uid, G->Map->nbasepos(compos), false); } } } else { if (utd->GetDGunCost()<G->cb->GetEnergy()){ return DGun(uid, k); } else { int r = (int)G->Pl->ReclaimTime(utd->GetUnitDef(), edt->GetUnitDef(), G->chcb->GetUnitHealth(k)); int c = (int)G->Pl->CaptureTime(utd->GetUnitDef(), edt->GetUnitDef(), G->chcb->GetUnitHealth(k)); if(r<(4 SECONDS) && r < c){ return Reclaim(uid, k); } else { if (c<(4 SECONDS)){ return Capture(uid, k); } else { return MoveToStrike(uid, G->Map->nbasepos(compos), false); } } } } } }else{ // we aint got enemies within immediate range, however this doesnt mean we're safe. // check fi there are nearby enemy groups // check the surrounding units and repair them if necessary. // if none need repairing then retreat, this may be an enemy base or an incoming army e = G->GetEnemyUnits(en, compos, G->cb->GetUnitMaxRange(uid)*2.5f); // get all enemy units within weapons range atm if(e > 0){ float total_enemy_power = 0; float total_allied_power = 0; for(int i = 0; i < e; i++){ if(!ValidUnitID(en[i])){ continue; } const UnitDef* endi = G->GetUnitDef(en[i]); if(endi){ total_enemy_power += endi->power; } } e = G->cb->GetFriendlyUnits(en, compos, G->cb->GetUnitMaxRange(uid)*2.5f); for(int i = 0; i < e; i++){ if(!ValidUnitID(en[i])){ continue; // filter out bad unit id's } const UnitDef* endi = G->GetUnitDef(en[i]); if(endi){ total_allied_power += endi->power; } } float ratio = total_allied_power/total_enemy_power; if((ratio<0.9f)&&(ratio > 0.4f)){ // repair nearby units int r_uid = -1; float best_r = 0; e = G->cb->GetFriendlyUnits(en, compos, G->cb->GetUnitMaxRange(uid)*2.5f); for(int i = 0; i < e; i++){ if(!ValidUnitID(en[i])){ continue; // filter out bad unit id's } if(en[i] == uid){ continue; // we cant repair ourself!! } const UnitDef* endi = G->GetUnitDef(en[i]); if(endi){ float ratio = G->cb->GetUnitHealth(en[i])/G->cb->GetUnitMaxHealth(en[i]); ratio = endi->power*ratio; if( ratio > best_r){ best_r = ratio; r_uid = en[i]; } } } delete[] en; if(ValidUnitID(r_uid)){ return Repair(uid, r_uid); } }else{ delete[] en; // runaway!!!!!!!!!!!!!!!!!! return MoveToStrike(uid, G->Map->nbasepos(compos), true); } } } delete [] en; return false; }