openclonk/planet/Worlds.ocf/AcidRift.ocs/Map.c

188 lines
6.5 KiB
C

/**
Acid Rift
Mine the rubies before it's too late
@author Sven2
*/
#include Library_Map
//static const SCENPAR_MapSize = 2;
//static const SCENPAR_Difficulty = 2;
local top_off = 20; // top open area of basin
local bottom_off = 20; // bottom granite area of basin
local border_width = 10; // left and right border width
local bottom_indent = 5; // diagonal indent at bottom left and bottom right corners
local top_off_earth = 50;// top offset from which earth and materials can start
local bottom_off_earth = 50;// bottom offset from which earth and materials can start
static g_start_map_x, g_start_map_y;
// Called be the engine: draw the complete map here.
func InitializeMap(proplist map)
{
var s = SCENPAR_MapSize - 1;
var d = SCENPAR_Difficulty - 1;
// Map size
var map_size = [[100, 200],[120, 250],[130, 400]][s];
Resize(map_size[0], map_size[1]);
// Parameters by map size and difficulty
var acid_level = [10, 30, 40][d]; // filling (in %) of basin with acid
var num_earth = [15, 20, 30][s];
var num_coal = [12, 15, 20][s];
var num_ore = [4, 5, 8][s];
var num_firestone = [15, 20, 30][s];
var num_water = [4, 5, 8][s];
var num_granite = [80, 100, 120][s];
var num_granite_top = [15, 20, 25][s];
var num_rock = [35,40,60][s];
var num_gold = [15, 18, 25][s];
var num_gems = 100;
var num_acidsurround = [20, 25, 40][s];
var size_earth = [[16,12,8][d], 8];
var size_coal = [6, 3];
var size_ore = [4, 4];
var size_water = [4, 4];
var size_firestone = [3, 3];
var size_granite = [2, 1];
var size_granite_top = [[8,4,1][d], 2];
var size_rock = [3,3];
var size_gold = [5,4,3][d];
var size_gems = [5,3,2][d];
var size_gem_cave = 10;
var size_acidsurround = [[5,4], [6,5], [7,5]][s];
// Draw starting acid filling
var acid_area = [0, top_off + (100-acid_level) * (this.Hgt-top_off-bottom_off) / 100, this.Wdt, this.Hgt];
Draw("^Acid", nil, acid_area);
// Basin surrounded by granite
var surround_poly = [
[-50, top_off],
[border_width, top_off],
[border_width+bottom_indent, this.Hgt*3/4],
[this.Wdt/2, this.Hgt-bottom_off],
[this.Wdt-border_width-bottom_indent, this.Hgt*3/4],
[this.Wdt-border_width, top_off],
[this.Wdt+50, top_off],
[this.Wdt+50, this.Hgt+50],
[-50, this.Hgt+50]
];
surround_poly = TransposeArray(surround_poly);
var algo = {Algo=MAPALGO_Polygon,
X = surround_poly[0],
Y = surround_poly[1]};
algo = { Algo=MAPALGO_Turbulence, Op=algo, Amplitude=10, Scale=30 };
algo = { Algo=MAPALGO_Turbulence, Op=algo, Amplitude=20, Scale=5 };
var basin = CreateLayer();
basin->Draw("Granite", algo);
basin->DrawMaterial("Rock", basin, [10,4], 30);
// Bottom acid cave containing gems
algo = { Algo=MAPALGO_Ellipsis, X=this.Wdt/2, Y=this.Hgt-bottom_off, Wdt=size_gem_cave, Hgt=size_gem_cave };
algo = { Algo=MAPALGO_Turbulence, Op=algo, Amplitude=20, Scale=20 };
basin->Draw("Transparent", algo);
// Materials areas are in surrounding basin
var basin_materials = CreateLayer();
basin_materials->Draw("Snow", {Algo=MAPALGO_Border, Wdt=-5, Op=basin});
// Acid caves in lower area
acid_area[1] += 20;
basin->DrawPatches(num_acidsurround, "Acid", "Granite", size_acidsurround, false, 20, acid_area);
// Gold in upper area
var gold_area = [0, top_off_earth, this.Wdt, this.Hgt-bottom_off-top_off_earth-size_gem_cave];
basin->DrawPatches(num_gold, "Gold", basin_materials, size_gold, false, 10, gold_area);
// Gems in lower area
var gem_area = [0, this.Hgt-bottom_off-size_gem_cave, this.Wdt, this.Hgt];
var i=0;
while (basin->GetPixelCount("Ruby")+basin->GetPixelCount("Amethyst") < num_gems)
{
basin->DrawPatch(["Ruby", "Amethyst"][++i%2], basin_materials, size_gems, false, 6, gem_area);
}
// Initial basin blit to ensure earth is not drawn there
Blit(basin);
// Small patches of rock and granite
DrawPatches(num_granite, "Granite", "^*", size_granite, false, 3);
DrawPatches(num_rock, "Rock", "^*", size_rock, false, 3);
// Alternate rock textures
var rock_area = Duplicate("Rock");
DrawMaterial("Rock", rock_area, [3, 3], 50);
// Patches of earth
DrawPatches(num_earth, "Earth", "^*", size_earth, true, 20, [0, top_off_earth, this.Wdt, this.Hgt - top_off_earth - bottom_off_earth]);
// Large patches of granite in top map area
DrawPatches(num_granite_top, "Granite", "^*", size_granite_top, false, 3, [0, top_off/2, this.Wdt, this.Hgt/4]);
// Empty starting area
var start_x = this.Wdt/4 + Random(this.Wdt/2);
var start_y = this.Hgt/3;
var start_algo = {Algo = MAPALGO_Ellipsis, X=start_x, Y=start_y, Wdt=10, Hgt=10};
Draw("Sky", start_algo);
g_start_map_x = start_x; g_start_map_y = start_y;
// Materials
DrawPatches(num_water, "Water", "Earth", size_water, false, 10);
Draw("Earth-earth", {Algo=MAPALGO_Border, Op=Duplicate("Water")});
DrawPatches(num_firestone, "Firestone", "Earth", size_firestone, false, 10);
DrawPatches(num_coal, "Coal", "Earth", size_coal, false, 7);
DrawPatches(num_ore, "Ore", "Earth", size_ore, true, 6);
// Re-draw basin to ensure it wasn't overdrawn by earth turbulence
Blit(basin);
// Draw starting area
var algo = {Algo = MAPALGO_Ellipsis, X=start_x, Y=start_y+5, Wdt=6, Hgt=5};
algo = {Algo = MAPALGO_Turbulence, Iterations = 1, Amplitude=5, Scale=5, Op = algo};
Draw("Earth", algo);
Draw("Sky", nil, [start_x-4, start_y-6, 8, 8]);
algo = {Algo=MAPALGO_Polygon, X=[start_x-4, start_x+4], Y=[start_y+2, start_y+2]};
// Alternations in earth texture
var earth_area = Duplicate("Earth");
DrawMaterial("Earth-earth_root", earth_area, [10, 4], 30);
DrawMaterial("Earth-earth", earth_area, [10, 4], 30);
// Start area is always dark
Draw("Earth-earth", algo);
// Return true to tell the engine a map has been successfully created.
return true;
}
/*-- Helper Functions --*/
// Find places matching mask and draw spots of material on it
private func DrawPatches(int num, ...)
{
for (var i=0; i<num; ++i) DrawPatch(...);
}
private func DrawPatch(string mat, mask, size, bool allow_rotation, int turbulence, array area)
{
var pos = {};
if (!area) area = [0, top_off, this.Wdt, this.Hgt];
if (GetType(size) != C4V_Array) size = [size, size];
var mask_layer = this;
if (GetType(mask) != C4V_String)
{
mask_layer = mask;
mask = "Snow";
}
if (!mask_layer->FindPosition(pos, mask, area)) return false;
var algo = {Algo = MAPALGO_Ellipsis, X=pos.X, Y=pos.Y, Wdt=size[0], Hgt=size[1]};
algo = {Algo = MAPALGO_Turbulence, Iterations = 3, Amplitude=turbulence, Scale=5, Op = algo};
if (allow_rotation) algo = {Algo= MAPALGO_Rotate, R=Random(360), OffX=pos.X, OffY=pos.Y, Op=algo};
return Draw(mat, algo);
}