float3 CMap::Pos2BuildPos(float3 pos, const UnitDef* ud){ NLOG("CMap::Pos2BuildPos"); if(ud->xsize&2) pos.x=floor((pos.x)/(SQUARE_SIZE*2))*SQUARE_SIZE*2+8; else pos.x=floor((pos.x+8)/(SQUARE_SIZE*2))*SQUARE_SIZE*2; if(ud->ysize&2) pos.z=floor((pos.z)/(SQUARE_SIZE*2))*SQUARE_SIZE*2+8; else pos.z=floor((pos.z+8)/(SQUARE_SIZE*2))*SQUARE_SIZE*2; pos.y=GetBuildHeight(pos,ud); if(ud->floater && pos.y<0) pos.y = -ud->waterline; return pos; }
CGameHelper::BuildSquareStatus CGameHelper::TestUnitBuildSquare( const BuildInfo& buildInfo, CFeature*& feature, int allyteam, bool synced, std::vector<float3>* canbuildpos, std::vector<float3>* featurepos, std::vector<float3>* nobuildpos, const std::vector<Command>* commands) { feature = NULL; const int xsize = buildInfo.GetXSize(); const int zsize = buildInfo.GetZSize(); const float3 pos = buildInfo.pos; const int x1 = (pos.x - (xsize * 0.5f * SQUARE_SIZE)); const int z1 = (pos.z - (zsize * 0.5f * SQUARE_SIZE)); const int z2 = z1 + zsize * SQUARE_SIZE; const int x2 = x1 + xsize * SQUARE_SIZE; const float bh = GetBuildHeight(pos, buildInfo.def, synced); const MoveDef* moveDef = (buildInfo.def->pathType != -1U) ? moveDefHandler->GetMoveDefByPathType(buildInfo.def->pathType) : NULL; const S3DModel* model = buildInfo.def->LoadModel(); const float buildHeight = (model != NULL) ? math::fabs(model->height) : 10.0f; BuildSquareStatus canBuild = BUILDSQUARE_OPEN; if (buildInfo.def->needGeo) { canBuild = BUILDSQUARE_BLOCKED; const std::vector<CFeature*>& features = quadField->GetFeaturesExact(pos, std::max(xsize, zsize) * 6); // look for a nearby geothermal feature if we need one for (std::vector<CFeature*>::const_iterator fi = features.begin(); fi != features.end(); ++fi) { if ((*fi)->def->geoThermal && math::fabs((*fi)->pos.x - pos.x) < (xsize * 4 - 4) && math::fabs((*fi)->pos.z - pos.z) < (zsize * 4 - 4)) { canBuild = BUILDSQUARE_OPEN; break; } } } if (commands != NULL) { // this is only called in unsynced context (ShowUnitBuildSquare) assert(!synced); for (int x = x1; x < x2; x += SQUARE_SIZE) { for (int z = z1; z < z2; z += SQUARE_SIZE) { BuildSquareStatus tbs = TestBuildSquare(float3(x, bh, z), buildHeight, buildInfo.def, moveDef, feature, gu->myAllyTeam, synced); if (tbs != BUILDSQUARE_BLOCKED) { //??? what does this do? for (std::vector<Command>::const_iterator ci = commands->begin(); ci != commands->end(); ++ci) { BuildInfo bc(*ci); if (std::max(bc.pos.x - x - SQUARE_SIZE, x - bc.pos.x) * 2 < bc.GetXSize() * SQUARE_SIZE && std::max(bc.pos.z - z - SQUARE_SIZE, z - bc.pos.z) * 2 < bc.GetZSize() * SQUARE_SIZE) { tbs = BUILDSQUARE_BLOCKED; break; } } } switch (tbs) { case BUILDSQUARE_OPEN: canbuildpos->push_back(float3(x, bh, z)); break; case BUILDSQUARE_RECLAIMABLE: case BUILDSQUARE_OCCUPIED: featurepos->push_back(float3(x, bh, z)); break; case BUILDSQUARE_BLOCKED: nobuildpos->push_back(float3(x, bh, z)); break; } canBuild = std::min(canBuild, tbs); } } } else { // this can be called in either context for (int x = x1; x < x2; x += SQUARE_SIZE) { for (int z = z1; z < z2; z += SQUARE_SIZE) { canBuild = std::min(canBuild, TestBuildSquare(float3(x, bh, z), buildHeight, buildInfo.def, moveDef, feature, allyteam, synced)); if (canBuild == BUILDSQUARE_BLOCKED) { return BUILDSQUARE_BLOCKED; } } } } return canBuild; }