std::string AttenuationShaderTemplate::AttenuationFragmentShaderSource( Object *selected_object, const std::set<Object *> &objects, const std::set<Object *> &areas) { std::ostringstream result; result.precision(std::numeric_limits<double>::max_digits10); result << kAttenuationFragmentShaderSourcePrefix << MinimumAttenuationTemplate() << std::endl; for (auto object : objects) { if (selected_object != object) { result << ObjectTemplate(object, true) << std::endl; } } for (auto area : areas) { if (selected_object != area) { result << ObjectTemplate(area, false) << std::endl; } } result << SuffixTemplate() << kAttenuationFragmentShaderSourceSuffix; return result.str(); }
void CMapGenerator::createConnections2() { for (auto & connection : connectionsLeft) { auto zoneA = connection.getZoneA(); auto zoneB = connection.getZoneB(); int3 guardPos(-1, -1, -1); int3 posA = zoneA->getPos(); int3 posB = zoneB->getPos(); auto strength = connection.getGuardStrength(); if (posA.z != posB.z) //try to place subterranean gates { auto sgt = VLC->objtypeh->getHandlerFor(Obj::SUBTERRANEAN_GATE, 0)->getTemplates().front(); auto tilesBlockedByObject = sgt.getBlockedOffsets(); auto factory = VLC->objtypeh->getHandlerFor(Obj::SUBTERRANEAN_GATE, 0); auto gate1 = factory->create(ObjectTemplate()); auto gate2 = factory->create(ObjectTemplate()); while (!guardPos.valid()) { bool continueOuterLoop = false; //find common tiles for both zones auto tileSetA = zoneA->getPossibleTiles(), tileSetB = zoneB->getPossibleTiles(); std::vector<int3> tilesA(tileSetA.begin(), tileSetA.end()), tilesB(tileSetB.begin(), tileSetB.end()); std::vector<int3> commonTiles; //required for set_intersection boost::sort(tilesA); boost::sort(tilesB); boost::set_intersection(tilesA, tilesB, std::back_inserter(commonTiles), [](const int3 &lhs, const int3 &rhs) -> bool { //ignore z coordinate if (lhs.x < rhs.x) return true; else return lhs.y < rhs.y; }); vstd::erase_if(commonTiles, [](const int3 &tile) -> bool { return (!tile.x) || (!tile.y); //gates shouldn't go outside map (x = 0) and look bad at the very top (y = 0) }); if (commonTiles.empty()) break; //nothing more to do boost::sort(commonTiles, [posA, posB](const int3 &lhs, const int3 &rhs) -> bool { //choose tiles which are equidistant to zone centers return (std::abs<double>(posA.dist2dSQ(lhs) - posB.dist2dSQ(lhs)) < std::abs<double>((posA.dist2dSQ(rhs) - posB.dist2dSQ(rhs)))); }); for (auto tile : commonTiles) { tile.z = posA.z; int3 otherTile = tile; otherTile.z = posB.z; float distanceFromA = posA.dist2d(tile); float distanceFromB = posB.dist2d(otherTile); if (distanceFromA > 5 && distanceFromB > 5) { if (zoneA->areAllTilesAvailable(this, gate1, tile, tilesBlockedByObject) && zoneB->areAllTilesAvailable(this, gate2, otherTile, tilesBlockedByObject)) { if (zoneA->getAccessibleOffset(this, sgt, tile).valid() && zoneB->getAccessibleOffset(this, sgt, otherTile).valid()) { EObjectPlacingResult::EObjectPlacingResult result1 = zoneA->tryToPlaceObjectAndConnectToPath(this, gate1, tile); EObjectPlacingResult::EObjectPlacingResult result2 = zoneB->tryToPlaceObjectAndConnectToPath(this, gate2, otherTile); if ((result1 == EObjectPlacingResult::SUCCESS) && (result2 == EObjectPlacingResult::SUCCESS)) { zoneA->placeObject(this, gate1, tile); zoneA->guardObject(this, gate1, strength, true, true); zoneB->placeObject(this, gate2, otherTile); zoneB->guardObject(this, gate2, strength, true, true); guardPos = tile; //set to break the loop break; } else if ((result1 == EObjectPlacingResult::SEALED_OFF) || (result2 == EObjectPlacingResult::SEALED_OFF)) { //sealed-off tiles were blocked, exit inner loop and get another tile set continueOuterLoop = true; break; } else continue; //try with another position } } } } if (!continueOuterLoop) //we didn't find ANY tile - break outer loop break; } if (!guardPos.valid()) //cleanup? is this safe / enough? { delete gate1; delete gate2; } } if (!guardPos.valid()) { auto factory = VLC->objtypeh->getHandlerFor(Obj::MONOLITH_TWO_WAY, getNextMonlithIndex()); auto teleport1 = factory->create(ObjectTemplate()); auto teleport2 = factory->create(ObjectTemplate()); zoneA->addRequiredObject(teleport1, strength); zoneB->addRequiredObject(teleport2, strength); } } }