/** Cave Creates a nice cave. */ /* Randomly places a cave without a border unless specified otherwise. Custom properties are: width, height: size of the cave's bounding box borderwidth, borderheight: thickness of the border bordersize: implicit borderwidth and borderheight bordermat: material of the border, f.e. "Rock" bordertex: texture of the border, f.e. "rock_cracked" */ public func Place(int amount, proplist area, proplist settings) { /* var caves = Landscape_Cave->Place(1, nil, {width = 100, height = 50, borderheight = 5, bordermat = "Earth", bordertex = "earth_topSoil" } ); if (GetLength(caves) == 0) FatalError("No cave placed!"); */ var caves = []; amount = amount ?? ((LandscapeHeight() * LandscapeWidth()) / 1000); var width = settings.width ?? 100; var height = settings.height ?? 100; var realwidth = 50, realheight = 50; if(width < height) { var aspect = (100 * width) / height; realwidth = (aspect * realheight) / 100; } else { var aspect = (100 * height) / width; realheight = (aspect * realwidth) / 100; } var x = (100 - realwidth) / 2; var y = (100 - realheight) / 2; var borderstring = ""; if (settings.bordersize || settings.borderwidth || settings.borderheight) { var bordermat = settings.bordermat ?? "Rock"; var bordertex = settings.bordertex ?? "rock"; var borderwidth = settings.borderwidth ?? settings.bordersize ?? 0; var borderheight = settings.borderheight ?? settings.bordersize ?? 0; borderstring = Format("overlay { mat = %s; tex = %s; algo = border; a = %d; b = %d; loosebounds = 1; };", bordermat, bordertex, borderwidth, borderheight); } var map = Format("overlay { x = %d; y = %d; wdt = %d; hgt = %d; mat = Tunnel; loosebounds = 1; turbulence = 500; %s };", x, y, realwidth, realheight, borderstring); var failsafe = 100; while((--failsafe > 0) && amount > 0) { var spot = FindLocation(Loc_Solid(), Loc_Func(Landscape_Cave.IsGoodCaveSpot), Loc_InArea(area)); if (!spot) continue; DrawMap(spot.x - width, spot.y - height, 2 * width, 2 * height, Format("map Cave { %s };", map)); var cave = CreateObjectAbove(Landscape_Cave, spot.x, spot.y, NO_OWNER); PushBack(caves, cave); // project free objects down to the ground for (var obj in FindObjects(Find_InRect(spot.x - width, spot.y - height, 2 * width, 2 * height), Find_Category(C4D_Object))) { var originaly = obj->GetY(); var max = height; while ((!obj->GetContact(-1, CNAT_Bottom)) && !obj->Stuck() && (--max > 0)) { obj->SetPosition(obj->GetX(), obj->GetY() + 1); } if (max <= 0) obj->SetPosition(obj->GetX(), originaly); } --amount; } return caves; } func IsGoodCaveSpot(int x, int y) { // cave must be "far" underground! var no_sky_distance = 200; for (var yd = 0; yd <= no_sky_distance; yd += 10) if (GBackSky(x, y - yd)) return false; var cave = FindObjects(Find_ID(Landscape_Cave), Sort_Distance(x, y)); if (GetLength(cave) == 0) return true; cave = cave[0]; return Distance(x, y, cave->GetX(), cave->GetY()) > 100; }