void BaseInfo::RemoveBuilding(int building) { if (buildingCount==0) { return; } Unit *buildingU = Unit::GetInstance(ai->callback, building); UnitDef *def = quadTree->GetUnitDef(building); //remove unit from quadtree, using pos if(def != NULL) { buildingCount--; if(def->IsBuilder()) { productionBuildings--; } else { resourceBuildings--; } ai->knowledge->mapInfo->pathfindingMap->RemoveBuilding( buildingU ); } else ai->utility->Log(ALL,KNOWLEDGE,"RemoveBuilding: We are trying to remove a seen building with no unitdef"); quadTree->RemoveUnit( building ); delete buildingU; buildingU = NULL; delete def; def = NULL; }
int CUnitDefHandler::PushNewUnitDef(const std::string& unitName, const LuaTable& udTable) { if (std::find_if(unitName.begin(), unitName.end(), isblank) != unitName.end()) { logOutput.Print( "WARNING: UnitDef name \"%s\" contains white-spaces, " "which will likely cause problems. Please contact the " "Game/Mod developers.", unitName.c_str() ); } UnitDef* newDef = NULL; int defid = unitDefs.size(); try { newDef = new UnitDef(udTable, unitName, defid); UnitDefLoadSounds(newDef, udTable); if (!newDef->decoyName.empty()) { decoyNameMap[unitName] = StringToLower(newDef->decoyName); } // force-initialize the real* members newDef->SetNoCost(true); newDef->SetNoCost(noCost); } catch (content_error) { delete newDef; return 0; } unitDefIDsByName[unitName] = defid; unitDefs.push_back(newDef); return defid; }
void BaseInfo::AddBuilding(Unit* building) { UnitDef* d = building->GetDef(); //check for builder units if(d->GetSpeed() > 0) { delete d; d = NULL; return; } delete d; d = NULL; //ai->utility->Log(ALL, MISC, "Adding base unit..."); map<int, UnitInformationContainer> units = quadTree->GetUnits(); if ( units.find(building->GetUnitId()) == units.end()) { quadTree->InsertUnit(building->GetUnitId(), building->GetPos()); buildingCount++; if(building->GetDef()->IsBuilder()) { productionBuildings++; } else { resourceBuildings++; } ai->knowledge->mapInfo->pathfindingMap->AddBuilding( building ); } }
void CAllyTeam::UpdateFriendlyUnits(CCircuitAI* circuit) { if (lastUpdate >= circuit->GetLastFrame()) { return; } for (auto& kv : friendlyUnits) { delete kv.second; } friendlyUnits.clear(); const std::vector<Unit*>& units = circuit->GetCallback()->GetFriendlyUnits(); for (auto u : units) { // FIXME: Why engine returns vector with some nullptrs? // TODO: Check every GetEnemy/FriendlyUnits for nullptr if (u == nullptr) { continue; } int unitId = u->GetUnitId(); UnitDef* unitDef = u->GetDef(); CCircuitUnit* unit = new CCircuitUnit(u, circuit->GetCircuitDef(unitDef->GetUnitDefId())); delete unitDef; friendlyUnits[unitId] = unit; } lastUpdate = circuit->GetLastFrame(); }
void ArmyInfo::RemoveUnit(int unit) { //if (unitCount==0) //{ // return; //} bool removed = quadTree->RemoveUnit( unit); if (removed) { Unit* u = Unit::GetInstance(ai->callback, unit); unitCount--; UnitDef *unitDef = u->GetDef(); if(unitDef != NULL) { if(unitDef->GetSpeed() > 0) { aggressive--; aggressiveDps -= ai->utility->GetDpsFromUnitDef(unitDef); } else { defensive--; defensiveDps -= ai->utility->GetDpsFromUnitDef(unitDef); } } delete unitDef; unitDef = NULL; delete u; u = NULL; } }
//Return unitType, and populates `result` int BattleFileReader::CountGroupUnits(vector<Unit*> units_old, vector<int> &result, bool airGroup) { int unitType = ( airGroup ) ? 1 : 0; result.clear(); for( unsigned int i = 0 ; i < units_all.size() ; i++ ) { result.push_back(0); } //fill vectors for( unsigned int i=0 ; i < units_old.size() ; i++ ) { UnitDef* ud = units_old[i]->GetDef(); for( unsigned int j = 0 ; j < units_all[unitType].size() ; j++ ) { if( ud->GetUnitDefId() == units_all[unitType][j] ) { //ai->utility->ChatMsg("Added unit: (%d) %s", j, ud->GetName()); result[j]++; break; } } delete ud; } return unitType; }
void BattleFileReader::RemoveCommander(vector<Unit*> &units) { for ( unsigned int i = 0 ; i < units.size() ; i++ ) { UnitDef *d = units[i]->GetDef(); if(d->IsCommander()) { delete units[i]; units.erase(units.begin() + i); delete d; break; } delete d; } }
SAIFloat3 ConstructionUnitGroup::FindGoodBuildSite(SAIFloat3 builderPos, UnitDef* building, float radius) { SAIFloat3 bestBuildSpot=builderPos; float bestDistance = radius*radius+1; bool foundBuildSite = false; Map *map = ai->callback->GetMap(); vector<Unit*> nearByBuildings = ai->knowledge->selfInfo->baseInfo->GetUnitsInRange(builderPos, radius); vector<Unit*>::iterator it; for(it = nearByBuildings.begin(); it != nearByBuildings.end(); it++) { UnitDef* ud = (*it)->GetDef(); if(!ud->IsBuilder()) { SAIFloat3 unitPos = (*it)->GetPos(); float muls[][2] = {{-1,0},{1,0},{0,-1},{0,1}};//left, right, up, down for(int i=0; i<4;i++) { SAIFloat3 newPos = unitPos; newPos.x += muls[i][0]*((ud->GetXSize()*8/2)+(building->GetXSize()*8/2)); newPos.z += muls[i][1]*((ud->GetZSize()*8/2)+(building->GetZSize()*8/2)); float newDist = ai->utility->EuclideanDistance(builderPos,newPos); if(newDist < bestDistance && map->IsPossibleToBuildAt(*building, newPos, 0) && !IsMetalExtracitonSite(building, newPos) && !BuildBlocksSelf(building, newPos, 0) ) { //TODO: test if it is blocking a contruction yard bestBuildSpot = newPos; bestDistance = newDist; foundBuildSite = true; } } } delete (*it); delete ud; } delete map; if (!foundBuildSite) { //We didn't find a good BuildSite (e.g. no non-builder buildings) bestBuildSpot = FindClosestNonConflictingBuildSite(building, builderPos, radius, 0, 0); } return bestBuildSpot; }
bool GroupController::UnitIdle( Unit* unit ) { bool allIdle = false; ai->utility->Log(ALL, MISC, "GroupController::UnitIdle()"); UnitDef *def = unit->GetDef(); if ( def->IsBuilder() ) { ConstructionGroupMgr->UnitIdle( unit ); return false;//TODO: CORRECT THIS } else { allIdle = MilitaryGroupMgr->UnitIdle(unit); } delete def; return allIdle; }
bool ConstructionUnitGroup::InersectsWithMex(UnitDef *unitDef, SAIFloat3 pos, SAIFloat3 mexPos) { if (ai->utility->IsMetalMap()) { return false;//Since metal can be extracted from all spots, there are no limited metal extraction sites } UnitDef *mexDef = ai->utility->GetMexDef(); bool retVal = ai->math->BoxIntersect( pos, unitDef->GetXSize()*8, unitDef->GetZSize()*8, mexPos, mexDef->GetXSize()*8, mexDef->GetZSize()*8); ai->utility->Log(ALL, MISC, "Mex intersect box 1 at (%f,%f,%f): %ix%i", pos.x, pos.y, pos.z, unitDef->GetXSize()*8, unitDef->GetZSize()*8); ai->utility->Log(ALL, MISC, "Mex intersect box 2 at (%f,%f,%f): %ix%i", mexPos.x, mexPos.y, mexPos.z, mexDef->GetXSize()*8, mexDef->GetZSize()*8); ai->utility->Log(ALL, MISC, "Checking InersectsWithMex: %i", retVal); return retVal; }
void GroupController::AddUnit(Unit *unit) { UnitDef* d = unit->GetDef(); if ( d->IsBuilder() ) { ConstructionGroupMgr->AddUnit( unit ); } else if ( d->IsAbleToAttack() ) { if ( d->IsCommander() ) { delete d; return; } MilitaryGroupMgr->AddUnit( unit ); } delete d; }
//updates the position of the unit in the QuadTree. void ArmyInfo::UpdateUnit(Unit* unit) { UnitDef* unitDef = unit->GetDef(); vector<WeaponMount*> wpmt = unitDef->GetWeaponMounts(); if ( wpmt.size() == 0 ) { delete unitDef; unitDef = NULL; return; } wpmt.clear(); SAIFloat3 new_pos = unit->GetPos(); int i = quadTree->UpdateUnit( unit->GetUnitId(), unit->GetPos() ); unitCount += i; if (unitDef == NULL) { return;//we dont know this unit?! } knownUnitDefs[unit->GetUnitId()] = unitDef; if(i != 0) { if(unitDef->GetSpeed() > 0) { aggressive += i; aggressiveDps += ai->utility->GetDpsFromUnitDef(unitDef); } else { defensive += i; defensiveDps += ai->utility->GetDpsFromUnitDef(unitDef); } } delete unitDef; unitDef = NULL; }
/** @param ETA the build time in frames @return an id, to be used for removal */ int ResourceInfo::AddChangeToCome(Unit *unit, int ETA) { UnitDef* ud = unit->GetDef(); Change temp; temp.ETA = ai->frame + ETA; temp.id = unit->GetUnitId(); temp.metalProduction = - ud->GetUpkeep(*metal) + ud->GetResourceMake(*metal) + ud->GetExtractsResource(*metal); temp.energyProduction = - ud->GetUpkeep(*energy) + ud->GetResourceMake(*energy) + ud->GetExtractsResource(*energy); list<Change>::iterator it; for(it = changes.begin(); it != changes.end(); it++) { if(((Change)*it).ETA > temp.ETA) { changes.insert(it,temp); break; } } return temp.id; }
float CAICallback::GetUnitDefHeight(int def) { UnitDef *ud = &unitDefHandler->unitDefs[def]; S3DOModel* mdl = ud->LoadModel(0); return mdl->height; }
float CAICallback::GetUnitDefRadius(int def) { UnitDef *ud = &unitDefHandler->unitDefs[def]; S3DOModel* mdl = ud->LoadModel(0); return mdl->radius; }
///@returns whether a new building would block a lab bool ConstructionUnitGroup::BuildBlocksSelf(UnitDef *toBuildUnitDef, SAIFloat3 pos, int facing) { ai->utility->Log(ALL, MISC, "BuildBlocksSelf check position (%f,%f)...", pos.x, pos.z); if(pos.y > 200) pos.y = 200; if(figureId == 0) figureId = ai->utility->DrawCircle(pos, 50); else ai->utility->DrawCircle(pos, 50, figureId); vector<Unit*> units = ai->callback->GetFriendlyUnits(); SAIFloat3 fromPos; UnitDef *unitDef; UnitDef *commanderdef = ai->commander->GetDef(); bool blocks = false; //Check if the new building at the selected location would block any exsisting labs for (int i = 0; i < (int)units.size(); i++) { unitDef = units[i]->GetDef(); if ( strcmp(unitDef->GetName(), "armlab")==0 || strcmp(unitDef->GetName(), "armvp")==0 ) { if(CheckAbilityToExitFromBuilding(unitDef, units[i]->GetPos(), toBuildUnitDef, pos)) blocks = true; } delete unitDef; } for(int i = 0; i < (int)units.size(); i++) delete units[i]; if(blocks) return true; ai->utility->Log(ALL, MISC, "BuildBlocksSelf check 1 done"); //If what we want to build is a lab, check that this position allows its units a path out of the base //without using the locaion of the new building if ( strcmp(toBuildUnitDef->GetName(), "armlab")==0 || strcmp(toBuildUnitDef->GetName(), "armvp")==0 ) { if(CheckAbilityToExitFromBuilding(toBuildUnitDef, pos, toBuildUnitDef, pos)) { ai->utility->Log(ALL, MISC, "No path from exit of new lab or plant"); delete commanderdef; return true; } } ai->utility->Log(ALL, MISC, "BuildBlocksSelf check 2 done"); //If we build this new building, does the commander have a path out of the base? fromPos = ai->commander->GetPos(); ///TODO: Maybe ensure that the commander does not walk into a building-block "trap" :) if (!ai->knowledge->mapInfo->pathfindingMap->IsPossibleToEscapeFrom(commanderdef, toBuildUnitDef, pos, fromPos, ai->utility->GetSafePosition())) { ai->utility->Log(ALL, MISC, "BuildBlocksSelf blocked build by reason 3 (No path for commander)"); delete commanderdef; return true; } ai->utility->Log(ALL, MISC, "BuildBlocksSelf check 3 done"); //ai->utility->Log(ALL, MISC, "Commander: %s", commander->GetDef()->GetName()); if ( !ai->knowledge->mapInfo->pathfindingMap->PathExists(commanderdef, fromPos, pos) ) { ai->utility->Log( ALL, MISC, "BuildBlocksSelf blocked build by reason 4 (No path to buildsite)"); delete commanderdef; return true; } ai->utility->Log(ALL, MISC, "BuildBlocksSelf check 4 done"); fromPos = ai->utility->GoTo(ai->commander->GetUnitId(), pos, true); if(fromPos.y != -1) { if ( !ai->knowledge->mapInfo->pathfindingMap->IsPossibleToEscapeFrom(commanderdef, toBuildUnitDef, pos, fromPos, ai->utility->GetSafePosition()) ) { ai->utility->Log( ALL, MISC, "BuildBlocksSelf blocked build by reason 5 (No path from builder position to safe position)"); delete commanderdef; return true; } } else { ai->utility->Log( ALL, MISC, "BuildBlocksSelf blocked build by reason 6 (No path from builder to build position)"); return true; } ai->utility->Log(ALL, MISC, "BuildBlocksSelf check 5+6 done, we can build %s at %f,%f", toBuildUnitDef->GetName(), pos.x, pos.z); delete commanderdef; return false; }