forked from Mirrors/openclonk
200 lines
8.3 KiB
C
200 lines
8.3 KiB
C
/**
|
|
Gem Grabbers
|
|
Dynamic map with sky islands and hard to reach gems. There is a main island, with at the bottom gem stalactites
|
|
and some smaller islands which also have gem stalactites hanging from the bottom. Each of the smaller islands
|
|
have different materials.
|
|
|
|
@author Maikel
|
|
*/
|
|
|
|
#include Library_Map
|
|
|
|
|
|
// Called be the engine: draw the complete map here.
|
|
protected func InitializeMap(proplist map)
|
|
{
|
|
// Retrieve the settings according to the MapSize setting.
|
|
var map_size, main_size, nr_islands;
|
|
if (SCENPAR_MapSize == 1)
|
|
{
|
|
map_size = [240, 200]; main_size = 80; nr_islands = RandomX(6, 7);
|
|
}
|
|
if (SCENPAR_MapSize == 2)
|
|
{
|
|
map_size = [280, 220]; main_size = 90; nr_islands = RandomX(7, 8);
|
|
}
|
|
if (SCENPAR_MapSize == 3)
|
|
{
|
|
map_size = [320, 240]; main_size = 100; nr_islands = RandomX(8, 9);
|
|
}
|
|
|
|
// Set the map size.
|
|
map->Resize(map_size[0], map_size[1]);
|
|
|
|
// Draw the main island.
|
|
map->DrawMainIsland(map, main_size);
|
|
|
|
// Draw a number of sky islands at random positions, each with different resources.
|
|
var resources = [["Coal", "Ore"], ["Coal", "Gold"], ["Firestone", "Coal"], ["Rock", "Ore"], ["Rock", "Coal", "Firestone"], ["Gold", "Ore", "Coal"]];
|
|
while (nr_islands > 0)
|
|
{
|
|
var x = 12 + Random(map.Wdt - 24);
|
|
var y = 26 + Random(map.Hgt - 52);
|
|
var wdt = RandomX(35, 45);
|
|
var hgt = wdt - RandomX(16, 22);
|
|
// DrawIsland itself makes sure there is no other island nearby.
|
|
if (DrawIsland(map, x, y, wdt, hgt, resources[Random(6)]))
|
|
nr_islands--;
|
|
}
|
|
|
|
// Fix the liquid borders with a library function.
|
|
FixLiquidBorders("Earth");
|
|
|
|
// Return true to tell the engine a map has been successfully created.
|
|
return true;
|
|
}
|
|
|
|
// Draws the main island with all basic resources
|
|
public func DrawMainIsland(proplist map, int size)
|
|
{
|
|
// Shape of the main island.
|
|
var island = {Algo = MAPALGO_Polygon};
|
|
var x = map.Wdt / 2;
|
|
var y = map.Hgt / 2;
|
|
island.X = [x-size/3, x-size/2, x-size/3, x-size/6, x+size/6, x+size/3, x+size/2, x+size/3];
|
|
island.Y = [y-size/6, y, y+size/3, y+size/6, y+size/6, y+size/3, y, y-size/6];
|
|
|
|
// Draw the earth patch of the island.
|
|
island = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = [10, 6], Seed = Random(65536), Op = island};
|
|
Draw("Earth", island);
|
|
|
|
// Overlay a set of materials inside the island.
|
|
DrawIslandMat("Earth-earth_root", island, 4, 30);
|
|
DrawIslandMat("Earth-earth", island, 3, 30);
|
|
DrawIslandMat("Tunnel", island, 3, 10);
|
|
DrawIslandMat("Water", island, 4, 8);
|
|
DrawIslandMat("Gold", island, 3, 6);
|
|
DrawIslandMat("Ore", island, 6, 12);
|
|
DrawIslandMat("Firestone", island, 6, 12);
|
|
DrawIslandMat("Coal", island, 6, 12);
|
|
|
|
// Draw a top border out of sand and top soil.
|
|
var sand_border = {Algo = MAPALGO_And, Op = [{Algo = MAPALGO_Border, Op = island, Top = [-1, 2]}, {Algo = MAPALGO_RndChecker, Ratio = 50, Wdt = 4, Hgt = 3}]};
|
|
var topsoil_border = {Algo = MAPALGO_And, Op = [{Algo = MAPALGO_Border, Op = island, Top = [-1, 3]}, {Algo = MAPALGO_RndChecker, Ratio = 40, Wdt = 4, Hgt = 2}]};
|
|
Draw("Sand", sand_border);
|
|
Draw("Earth-earth_root", topsoil_border);
|
|
|
|
// Draw a bottom border out of granite and rock (or everrock on insane).
|
|
var granite_border = {Algo = MAPALGO_Border, Op = island, Bottom = [-4, 3]};
|
|
Draw(["Rock", "Granite", "Everrock"][SCENPAR_Difficulty - 1], granite_border);
|
|
var rock_border = {Algo = MAPALGO_RndChecker, Ratio = 25, Wdt = 2, Hgt = 2};
|
|
Draw(["Granite", "Rock", "Rock"][SCENPAR_Difficulty - 1], {Algo = MAPALGO_And, Op = [granite_border, rock_border]});
|
|
Draw(["Granite", "Rock", "Granite"][SCENPAR_Difficulty - 1], {Algo = MAPALGO_And, Op = [granite_border, rock_border]});
|
|
|
|
// Draw some gems attached at the bottom of the island.
|
|
var full_island = {Algo = MAPALGO_Or, Op = [island, granite_border]};
|
|
var rect = [x - size / 2, y - size / 3, size / 2, 3 * size / 4];
|
|
DrawGems("Ruby", rect, 3, map, full_island);
|
|
rect = [x, y - size / 3, size / 2, 3 * size / 4];
|
|
DrawGems("Amethyst", rect, 3, map, full_island);
|
|
return;
|
|
}
|
|
|
|
// Draws a smaller island at the specified location if the location rectangle is free, returns whether succeeded.
|
|
public func DrawIsland(proplist map, int x, int y, int wdt, int hgt, array mats)
|
|
{
|
|
// Don't draw an island if there is already something nearby.
|
|
var rect = [x - wdt, y - 3 * hgt / 2, 2 * wdt, 3 * hgt];
|
|
if (GetPixelCount("Solid", rect) > 0)
|
|
return false;
|
|
|
|
// An island is just an ellipse with turbulence.
|
|
var island = {Algo = MAPALGO_Ellipsis, X = x, Y = y, Wdt = wdt / 2, Hgt = hgt / 2};
|
|
island = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = [6, 12], Seed = Random(65536), Op = island};
|
|
Draw("Earth", island);
|
|
|
|
// Overlay a set of materials inside the island.
|
|
DrawIslandMat("Earth-earth_root", island, 4, 30);
|
|
DrawIslandMat("Earth-earth", island, 3, 30);
|
|
DrawIslandMat("Tunnel", island, 3, 10);
|
|
for (var mat in mats)
|
|
{
|
|
DrawIslandMat(mat, island, 4, 18);
|
|
DrawIslandMat(mat, island, 6, 12);
|
|
}
|
|
|
|
// Draw a top border out of sand and top soil.
|
|
var sand_border = {Algo = MAPALGO_And, Op = [{Algo = MAPALGO_Border, Op = island, Top = [-1,2]}, {Algo = MAPALGO_RndChecker, Ratio = 50, Wdt = 4, Hgt = 3}]};
|
|
var topsoil_border = {Algo = MAPALGO_And, Op = [{Algo = MAPALGO_Border, Op = island, Top = [-1,3]}, {Algo = MAPALGO_RndChecker, Ratio = 40, Wdt = 4, Hgt = 2}]};
|
|
Draw("Sand", sand_border);
|
|
Draw("Earth-earth", topsoil_border);
|
|
|
|
// Draw a bottom border out of granite and rock (or everrock on insane).
|
|
var granite_border = {Algo = MAPALGO_Border, Op = island, Bottom = [-2,3]};
|
|
Draw(["Rock", "Granite", "Everrock"][SCENPAR_Difficulty - 1], granite_border);
|
|
var rock_border = {Algo = MAPALGO_RndChecker, Ratio = 20, Wdt = 2, Hgt = 2};
|
|
Draw(["Granite", "Rock", "Granite"][SCENPAR_Difficulty - 1], {Algo = MAPALGO_And, Op = [granite_border, rock_border]});
|
|
Draw(["Granite", "Rock", "Granite"][SCENPAR_Difficulty - 1], {Algo = MAPALGO_And, Op = [granite_border, rock_border]});
|
|
|
|
// Draw some gems attached at the bottom of the island.
|
|
var gem = ["Ruby", "Amethyst"][Random(2)];
|
|
var full_island = {Algo = MAPALGO_Or, Op = [island, granite_border]};
|
|
DrawGems(gem, rect, 3, map, full_island);
|
|
return true;
|
|
}
|
|
|
|
// Looks for a location at the bottom of a sky islands and places some gems.
|
|
public func DrawGems(string gem_mat, array rect, int size, proplist map, proplist island)
|
|
{
|
|
// Adapt rect to find at least a spot 8 * MapZoom pixel distance from the map borders.
|
|
rect[2] -= Max(0, 8 - rect[0]); rect[0] = Max(8, rect[0]); // Left boundary.
|
|
rect[2] = Min(rect[2], map.Wdt - rect[0] - 8); // Right boundary.
|
|
|
|
var low_spot = {X = rect[0], Y = rect[1]};
|
|
for (var i = 0; i < 250; i++)
|
|
{
|
|
var spot = {};
|
|
this->FindPosition(spot, "Solid", rect);
|
|
if (spot.Y > low_spot.Y)
|
|
{
|
|
low_spot = spot;
|
|
}
|
|
}
|
|
|
|
// Sometimes draw a large patch of tunnel behind the gems.
|
|
if (!Random(3))
|
|
{
|
|
var gem_tunnel = {Algo = MAPALGO_Ellipsis, X = low_spot.X, Y = low_spot.Y + 2, Wdt = size * 3, Hgt = 2 * size};
|
|
gem_tunnel = {Algo = MAPALGO_And, Op = [gem_tunnel, {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Lines, X = 1, Y = 0, OffX = Random(6), Distance = RandomX(4, 6)}}]};
|
|
gem_tunnel = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 14, Scale = 8, Seed = Random(65536), Op = gem_tunnel};
|
|
gem_tunnel = {Algo = MAPALGO_And, Op = [gem_tunnel, {Algo = MAPALGO_Not, Op = island}]};
|
|
Draw("Tunnel", gem_tunnel);
|
|
}
|
|
|
|
// Draw the gems.
|
|
var gems = {Algo = MAPALGO_Ellipsis, X = low_spot.X, Y = low_spot.Y + 1, Wdt = size - 1, Hgt = size};
|
|
gems = {Algo = MAPALGO_Turbulence, Amplitude = 5, Scale = 5, Iterations = 2, Op = gems};
|
|
Draw(gem_mat, gems);
|
|
|
|
// Some rock/granite/everrock border above the gems to make it harder to reach.
|
|
var gem_border = {Algo = MAPALGO_Border, Top = -4, Op = gems};
|
|
Draw(["Rock", "Granite", "Everrock"][SCENPAR_Difficulty - 1], gem_border);
|
|
return;
|
|
}
|
|
|
|
// Draws some material inside an island.
|
|
public func DrawIslandMat(string mat, proplist onto_mask, int speck_size, int ratio)
|
|
{
|
|
if (!speck_size)
|
|
speck_size = 3;
|
|
if (!ratio)
|
|
ratio = 20;
|
|
// Use random checker algorithm to draw patches of the material.
|
|
var rnd_checker = {Algo = MAPALGO_RndChecker, Ratio = ratio, Wdt = speck_size, Hgt = speck_size};
|
|
rnd_checker = {Algo = MAPALGO_Turbulence, Iterations = 4, Op = rnd_checker};
|
|
var mask_border = {Algo = MAPALGO_Border, Op = onto_mask, Wdt = 3};
|
|
var algo = {Algo = MAPALGO_And, Op = [{Algo = MAPALGO_Xor, Op = [onto_mask, mask_border]}, rnd_checker]};
|
|
Draw(mat, algo);
|
|
return;
|
|
}
|