Ejemplo n.º 1
0
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;
}