new world: Flooded Veins as replacement for Ruby Cave

issue1247
Maikel de Vries 2014-08-27 16:18:10 +02:00
parent d071ee3f7f
commit 5274bf9d3e
18 changed files with 701 additions and 241 deletions

View File

@ -0,0 +1,31 @@
{\rtf1\ansi\deff3\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq0\fcharset1 Times New Roman;}{\f5\froman\fprq0\fcharset1 Liberation Serif{\*\falt Times New Roman};}{\f6\fswiss\fprq0\fcharset1 Liberation Sans{\*\falt Arial};}{\f7\fnil\fprq2\fcharset0 Droid Sans Fallback;}{\f8\fnil\fprq2\fcharset0 Arial;}{\f9\fswiss\fprq0\fcharset1 FreeSans;}{\f10\fnil\fprq0\fcharset1 FreeSans;}}
{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
{\stylesheet{\s0\snext0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033 Normal;}
{\s15\sbasedon0\snext16\ql\nowidctlpar\sb240\sa120\keepn\ltrpar\cf1\kerning1\dbch\af7\langfe2052\dbch\af10\afs28\alang1081\loch\f6\fs28\lang1033 Heading;}
{\s16\sbasedon0\snext16\sl288\slmult1\ql\nowidctlpar\sb0\sa140\ltrpar\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033 Text Body;}
{\s17\sbasedon16\snext17\sl288\slmult1\ql\nowidctlpar\sb0\sa140\ltrpar\cf1\kerning1\dbch\af8\langfe2052\dbch\af9\afs24\alang1081\loch\f5\fs24\lang1033 List;}
{\s18\sbasedon0\snext18\ql\nowidctlpar\sb120\sa120\noline\ltrpar\cf1\i\kerning1\dbch\af8\langfe2052\dbch\af9\afs24\alang1081\ai\loch\f5\fs24\lang1033 Caption;}
{\s19\sbasedon0\snext19\ql\nowidctlpar\noline\ltrpar\cf1\kerning1\dbch\af8\langfe2052\dbch\af9\afs24\alang1081\loch\f5\fs24\lang1033 Index;}
}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67240962}}\deftab720
\viewscale100
{\*\pgdsctbl
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
\pgndec\pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b\rtlch \ltrch\loch\fs20\lang1031\loch\f4
Geflutete G\u228\'e4nge}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang4105\loch\f4
You stumble upon an abandoned settlement beneath the Forest of Orgos in your quest for more gold. Legends tell a story of even more valuable materials named gems which may be found here. Might this abandoned settlement be a failed attempt to find these gems? Set up an expedition to explore the flooded caves around and to discover possible gem veins. }
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033\rtlch \ltrch\loch
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
Ziel: Verkaufe Edelsteine}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033\rtlch \ltrch\loch
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
- The flooded caves may be drained using pumps, you can get rid off the excess water where you entered the cave.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
- The large mushrooms can be chopped down for wood. }
\par }

View File

@ -0,0 +1,34 @@
{\rtf1\ansi\deff3\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq0\fcharset1 Times New Roman;}{\f5\froman\fprq0\fcharset1 Liberation Serif{\*\falt Times New Roman};}{\f6\fswiss\fprq0\fcharset1 Liberation Sans{\*\falt Arial};}{\f7\fnil\fprq2\fcharset0 Droid Sans Fallback;}{\f8\fnil\fprq2\fcharset0 Arial;}{\f9\fswiss\fprq0\fcharset1 FreeSans;}{\f10\fnil\fprq0\fcharset1 FreeSans;}}
{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
{\stylesheet{\s0\snext0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033 Normal;}
{\s15\sbasedon0\snext16\ql\nowidctlpar\sb240\sa120\keepn\ltrpar\cf1\kerning1\dbch\af7\langfe2052\dbch\af10\afs28\alang1081\loch\f6\fs28\lang1033 Heading;}
{\s16\sbasedon0\snext16\sl288\slmult1\ql\nowidctlpar\sb0\sa140\ltrpar\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033 Text Body;}
{\s17\sbasedon16\snext17\sl288\slmult1\ql\nowidctlpar\sb0\sa140\ltrpar\cf1\kerning1\dbch\af8\langfe2052\dbch\af9\afs24\alang1081\loch\f5\fs24\lang1033 List;}
{\s18\sbasedon0\snext18\ql\nowidctlpar\sb120\sa120\noline\ltrpar\cf1\i\kerning1\dbch\af8\langfe2052\dbch\af9\afs24\alang1081\ai\loch\f5\fs24\lang1033 Caption;}
{\s19\sbasedon0\snext19\ql\nowidctlpar\noline\ltrpar\cf1\kerning1\dbch\af8\langfe2052\dbch\af9\afs24\alang1081\loch\f5\fs24\lang1033 Index;}
}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67240962}}\deftab720
\viewscale100
{\*\pgdsctbl
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
\pgndec\pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b\rtlch \ltrch\loch\fs20\lang1031\loch\f4
Flooded Veins}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang4105\loch\f4
You stumble upon an abandoned settlement beneath the }{\b0\rtlch \ltrch\loch\fs16\lang4105\loch\f4
Forest of Orgos }{\b0\rtlch \ltrch\loch\fs16\lang4105\loch\f4
in your quest for more gold. Legends tell a story of even more valuable materials named gems which may be found here. Might this abandoned settlement be a failed attempt to find these gems? Set up an expedition to explore the flooded caves around and to discover possible gem veins. }
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033\rtlch \ltrch\loch
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
Goal: Sell gems}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033\rtlch \ltrch\loch
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
- }{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
The flooded caves may be drained using pumps, you can get rid off the excess water where you entered the cave.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf1\kerning1\dbch\af8\langfe2052\dbch\af10\afs24\alang1081\loch\f5\fs24\lang1033{\b0\rtlch \ltrch\loch\fs16\lang1031\loch\f4
- The large mushrooms can be chopped down for wood. }
\par }

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,313 @@
/**
Flooded Veins
Dynamic map with a cave leading to gems filled with water deep down.
@author Sven2, Maikel
*/
#include Library_Map
// Scenario properties which can be set later by the lobby options.
static const SCENOPT_MapSize = 1;
// 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;
if (SCENOPT_MapSize == 1)
map_size = [100, 150];
if (SCENOPT_MapSize == 2)
map_size = [100, 175];
if (SCENOPT_MapSize == 3)
map_size = [100, 200];
// Set the map size.
map->Resize(map_size[0], map_size[1]);
// The map is completely covered in earth.
map->Draw("Earth");
// Draw a cavern somewhere at the top where the settlement is located.
// This takes up the top 25 landscape pixels.
DrawCavern(map);
// Draw the middle section of the map with useful resources.
// This takes 50, 55 or 60 landscape pixels.
DrawMiddle(map, 45 + 5 * SCENOPT_MapSize);
// Draw the gem veins including it being flooded at the bottom of the map.
// This takes up the remaining landscape pixels, which depends on the map size.
DrawGemVeins(map, 55 + 20 * SCENOPT_MapSize);
// Return true to tell the engine a map has been successfully created.
return true;
}
// Draws the top cavern where the player starts it settlement.
public func DrawCavern(proplist map)
{
var wdt = map.Wdt;
var hgt = map.Hgt;
var cavern_hgt = 20;
// Create a mask for the cavern part.
var map_top = {Algo = MAPALGO_Rect, X = 0, Y = 0, Wdt = wdt, Hgt = cavern_hgt};
// The top part is mainly granite and rock.
map->DrawMaterial("Earth-earth_rough", map_top, 2, 16);
map->DrawMaterial("Earth-earth_dry", map_top, 2, 16);
map->DrawMaterial("Earth-earth_midsoil", map_top, 4, 12);
map->DrawMaterial("Granite", map_top, 3, 60);
map->DrawMaterial("Tunnel", map_top, 2, 16);
map->DrawMaterial("Rock-rock_cracked", map_top, 3, 20);
map->DrawMaterial("Rock", map_top, 3, 20);
// The cavern is located a bit to the left and can be entered from the left side of the map.
var cavern = {Algo = MAPALGO_Ellipsis, X = wdt / 2 - 10, Y = cavern_hgt - 7, Wdt = 20, Hgt = 7};
cavern = {Algo = MAPALGO_Or, Op = [cavern, {Algo = MAPALGO_Turbulence, Iterations = 4, Seed = Random(65536), Op = cavern}]};
cavern = {Algo = MAPALGO_Or, Op = [cavern, {Algo = MAPALGO_Rect, X = wdt / 2 - 30, Y = cavern_hgt - 7, Wdt = 40, Hgt = 7}]};
cavern = {Algo = MAPALGO_And, Op = [cavern, map_top]};
map->Draw("Tunnel", cavern);
map->DrawMaterial("Tunnel-brickback", cavern, 5, 32);
map->DrawMaterial("Sky", cavern, 5, 16);
map->DrawMaterial("Sky", cavern, 4, 16);
map->DrawMaterial("Sky", cavern, 3, 16);
var cavern_ground = {Algo = MAPALGO_Border, Bottom = -2, Op = cavern};
map->DrawMaterial("Brick", cavern_ground, 3, 80);
// Draw the left tunnel.
var tunnel_left = {Algo = MAPALGO_Polygon, X = [0, wdt / 2 - 30], Y = [cavern_hgt, cavern_hgt], Wdt = -5, Open = 1, Empty = 1};
tunnel_left = {Algo = MAPALGO_Or, Op = [tunnel_left, {Algo = MAPALGO_Turbulence, Amplitude = 6, Scale = 8, Iterations = 4, Seed = Random(65536), Op = tunnel_left}]};
tunnel_left = {Algo = MAPALGO_And, Op = [tunnel_left, map_top]};
map->Draw("Tunnel", tunnel_left);
map->DrawMaterial("Tunnel-brickback", tunnel_left, 3, 32);
map->DrawMaterial("Sky", tunnel_left, 5, 16);
map->DrawMaterial("Sky", tunnel_left, 3, 24);
var tunnel_entrance = {Algo = MAPALGO_And, Op = [tunnel_left, {Algo = MAPALGO_Rect, X = 0, Y = 0, Wdt = 2, Hgt = cavern_hgt}]};
map->Draw("Sky", tunnel_entrance);
var tunnel_left_ground = {Algo = MAPALGO_Border, Bottom = -2, Op = tunnel_left};
tunnel_left_ground = {Algo = MAPALGO_Or, Op = [tunnel_left, {Algo = MAPALGO_Turbulence, Amplitude = 6, Scale = 6, Iterations = 2, Seed = Random(65536), Op = tunnel_left_ground}]};
tunnel_left_ground = {Algo = MAPALGO_And, Op = [tunnel_left_ground, {Algo = MAPALGO_Not, Op = map_top}]};
map->DrawMaterial("Brick", tunnel_left_ground, 3, 24);
// Draw the right tunnel.
var tunnel_right = {Algo = MAPALGO_Polygon, X = [wdt / 2 + 10, wdt / 2 + 30, wdt / 2 + 36], Y = [cavern_hgt - 4, cavern_hgt - 8, cavern_hgt + 6], Wdt = -4, Open = 1, Empty = 1};
tunnel_right = {Algo = MAPALGO_Or, Op = [tunnel_right, {Algo = MAPALGO_Turbulence, Amplitude = 8, Scale = 6, Iterations = 4, Seed = Random(65536), Op = tunnel_right}]};
//tunnel_right = {Algo = MAPALGO_And, Op = [tunnel_right, map_top]};
map->Draw("Tunnel", tunnel_right);
map->DrawMaterial("Tunnel-brickback", tunnel_right, 3, 24);
return;
}
// Draws the middle section of the map with useful resources.
public func DrawMiddle(proplist map, int size)
{
var wdt = map.Wdt;
var hgt = map.Hgt;
// Create a mask for the middle part.
var map_middle = {Algo = MAPALGO_Rect, X = 0, Y = 25, Wdt = wdt, Hgt = size};
// Fill the middle part with resources.
map->DrawMaterial("Earth-earth_rough", map_middle, 2, 16);
map->DrawMaterial("Earth-earth_dry", map_middle, 2, 16);
map->DrawMaterial("Earth-earth_midsoil", map_middle, 4, 12);
map->DrawMaterial("Granite", map_middle, 3, 10);
map->DrawMaterial("Tunnel", map_middle, 2, 8);
map->DrawMaterial("Rock-rock_cracked", map_middle, 3, 8);
map->DrawMaterial("Rock", map_middle, 3, 8);
map->DrawMaterial("Ore", map_middle, 6, 16);
map->DrawMaterial("Firestone", map_middle, 5, 12);
map->DrawMaterial("Coal", map_middle, 6, 16);
// Create a tunnel system which covers the middle part.
var tunnel = {Algo = MAPALGO_Rect, X = 0, Y = 0, Wdt = 0, Hgt = 0};
for (var i = 0; i < 5; i++)
{
var x1 = RandomX(8, wdt - 8);
var y1 = RandomX(30, 10 + size);
var dir = RandomX(-15, 15) + Random(2) * 180;
var dist = RandomX(20, 28);
var x2 = BoundBy(x1 + Cos(dir, dist), 4, wdt - 4);
var y2 = BoundBy(y1 + Sin(dir, dist), 30, 15 + size);
var add_tunnel = {Algo = MAPALGO_Polygon, X = [x1, x2], Y = [y1, y2], Wdt = -RandomX(3, 4), Open = 1, Empty = 1};
var tunnel = {Algo = MAPALGO_Or, Op = [tunnel, add_tunnel]};
}
tunnel = {Algo = MAPALGO_Turbulence, Amplitude = 6, Scale = 8, Iterations = 4, Seed = Random(65536), Op = tunnel};
map->Draw("Tunnel", tunnel);
var tunnel_ground = {Algo = MAPALGO_Border, Bottom = -2, Op = tunnel};
map->Draw("Earth", tunnel_ground);
map->DrawMaterial("Earth-earth_rough", tunnel_ground, 2, 16);
map->DrawMaterial("Earth-earth_dry", tunnel_ground, 2, 16);
map->DrawMaterial("Earth-earth_midsoil", tunnel_ground, 4, 12);
return;
}
// Draws the gem veins including it being flooded at the bottom of the map.
public func DrawGemVeins(proplist map, int size)
{
var wdt = map.Wdt;
var hgt = map.Hgt;
// Create a mask for the bottom part.
var map_bottom = {Algo = MAPALGO_Rect, X = 0, Y = hgt - size, Wdt = wdt, Hgt = size};
// Fill the bottom with mostly granite materials.
map->Draw("Granite", map_bottom);
map->DrawMaterial("Firestone", map_bottom, 2, 6);
map->DrawMaterial("Rock-rock_cracked", map_bottom, 3, 12);
map->DrawMaterial("Rock", map_bottom, 3, 12);
map->DrawMaterial("Earth-earth_rough", map_bottom, 2, 8);
map->DrawMaterial("Earth-earth_dry", map_bottom, 2, 8);
map->DrawMaterial("Earth-earth_midsoil", map_bottom, 4, 6);
// Draw a labyrinth using nodes and connections and make it out of tunnel.
var nodes = FindVeinNodes(map, size + 12, size / 2);
var connections = FindNodeConnections(nodes, 24);
for (var con in connections)
{
con = {Algo = MAPALGO_Turbulence, Amplitude = 5, Scale = 3, Op = con};
map->Draw("Tunnel", con);
}
// Make three out of the five gems nodes contain gems and protect with granite.
for (var i = 0; i < 3; i++)
{
var gem = {Algo = MAPALGO_Ellipsis, X = nodes[i].X, Y = nodes[i].Y, Wdt = 5, Hgt = 4};
gem = {Algo = MAPALGO_Turbulence, Amplitude = 3, Scale = 3, Iterations = 2, Seed = Random(65536), Op = gem};
var gem_border = {Algo = MAPALGO_Border, Wdt = 2, Op = gem};
gem = {Algo = MAPALGO_And, Op = [gem, {Algo = MAPALGO_Not, Op = gem_border}]};
map->Draw(["Ruby", "Amethyst"][Random(2)], gem);
map->Draw("Granite", gem_border);
}
// Replace the tunnels with water up to a certain level.
var water_level = 5 * size / 6;
var tunnels = Duplicate("Tunnel");
var tunnels_algo = {Algo = MAPALGO_Layer, Layer = tunnels};
tunnels_algo = {Algo = MAPALGO_And, Op = [tunnels_algo, {Algo = MAPALGO_Rect, X = 0, Y = hgt - water_level, Wdt = wdt, Hgt = water_level}]};
map->Draw("Water", tunnels_algo);
return;
}
/*-- Nodes and Connections --*/
public func FindVeinNodes(proplist map, int size, nr_nodes)
{
var wdt = map.Wdt;
var hgt = map.Hgt;
// Prepare a mask out of the map to search for nodes.
var mask = map->CreateLayer();
mask->Draw("Rock");
// Array for the nodes and definition for a minimum distance.
var nodes = [];
var node_dist = 8;
// The first five nodes are at the bottom of the map and are not to be connected.
for (var i = 0; i < 5; i++)
{
var node = {};
if (!mask->FindPosition(node, "Rock", [4, hgt - 10, wdt - 8, 6]))
continue;
mask->Draw("Tunnel", {Algo = MAPALGO_Ellipsis, X = node.X, Y = node.Y, Wdt = node_dist, Hgt = node_dist});
node.is_gem = true;
PushBack(nodes, node);
}
// The other nodes are scattered randomly in the lower areas
for (var i = 5; i < nr_nodes; i++)
{
var node = {};
if (!mask->FindPosition(node, "Rock", [4, hgt - size + 4, wdt - 8, size - 18]))
continue;
mask->Draw("Tunnel", {Algo = MAPALGO_Ellipsis, X = node.X, Y = node.Y, Wdt = node_dist, Hgt = node_dist});
PushBack(nodes, node);
}
return nodes;
}
public func FindNodeConnections(array nodes, int max_length)
{
var connections = [];
for (var node in nodes)
node.conn_count = 0;
for (var i = 0; i < GetLength(nodes) - 1; i++)
{
var from_node = nodes[i];
for (var j = i + 1; j < GetLength(nodes); j++)
{
var to_node = nodes[j];
// Check for the maximum connections per cave.
if (from_node.conn_count >= 4 || to_node.conn_count >= 4)
continue;
// Check for two gem nodes which may not connect.
if (from_node.is_gem && to_node.is_gem)
continue;
// Cave line parameters.
var fx = from_node.X;
var fy = from_node.Y;
var tx = to_node.X;
var ty = to_node.Y;
// Check for the maximum line distance.
if (Distance(fx, fy, tx, ty) > max_length)
continue;
// Check for overlap in existing connections.
var has_overlap = false;
for (var line in connections)
if (IsLineOverlap(fx, fy, tx, ty, line.X[0], line.Y[0], line.X[1], line.Y[1]))
{
//Log("(%d,%d) to (%d,%d) overlap with (%d,%d) to (%d,%d)", fx, fy, tx, ty, line.X[0], line.Y[0], line.X[1], line.Y[1]);
has_overlap = true;
break;
}
if (has_overlap)
continue;
var tunnel_width = 2;
if (!Random(4))
tunnel_width = 3;
var tunnel = {Algo = MAPALGO_Polygon, X = [fx, tx], Y = [fy, ty], Wdt = tunnel_width, Open = 1, Empty = 1};
PushBack(connections, tunnel);
nodes[i].conn_count++;
nodes[j].conn_count++;
}
}
return connections;
}
/*-- Helper Functions --*/
public func IsLineOverlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
{
// Same starting point is not overlapping.
if ((x1 == x3 && y1 == y3) || (x1 == x4 && y1 == y4) || (x2 == x3 && y2 == y3) || (x2 == x4 && y2 == y4))
return false;
// Check if line from x1,y1 to x2,y2 crosses the line from x3,y3 to x4,y4
var d1x = x2 - x1, d1y = y2 - y1, d2x = x4 - x3, d2y = y4 - y3, d3x = x3 - x1, d3y = y3 - y1;
var a = d1y * d3x - d1x * d3y;
var b = d2y * d3x - d2x * d3y;
var c = d2y * d1x - d2x * d1y;
if (!c)
return !a && Inside(x3, x1, x2) && Inside(y3, y1, y2); // lines are parallel
return a * c >= 0 && !(a * a / (c * c + 1)) && b * c >= 0 && !(b * b/(c * c + 1));
}
// Draws some material inside an island.
public func DrawMaterial(string mat, proplist onto_mask, int speck_size, int ratio)
{
if (!speck_size)
speck_size = 4;
if (!ratio)
ratio = 15;
// 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 algo = {Algo = MAPALGO_And, Op = [onto_mask, rnd_checker]};
return Draw(mat, algo);
}

View File

@ -1,5 +1,5 @@
[Head]
Title=RubyCave
Title=FloodedVeins
Icon=24
Version=5,4,0,0
Difficulty=30
@ -23,13 +23,14 @@ Crew=Clonk=2
Sky=Clouds1
TopOpen=0
BottomOpen=0
AutoScanSideOpen=0
LeftOpen=160
MapWidth=150
MapHeight=150
MapZoom=8
[Weather]
Climate=00,0,0,00
StartSeason=0,0,0,00
YearSpeed=0,0,0,000
Climate=0,0,0,0
StartSeason=0,0,0,0
YearSpeed=0,0,0,0
Wind=100,0,100,100

View File

@ -0,0 +1,215 @@
/**
Flooded Veins
A cave landscape where the player starts at the top and needs to retrieve some gems from
caves filled with water.
@author Sven2, Maikel
*/
// Scenario properties which can be set later by the lobby options.
static const SCENOPT_Material = 3; // Amount of material available from start.
static const SCENOPT_MapSize = 1; // Size of the map.
static const SCENOPT_Difficulty = 1; // Difficulty settings.
// Whether the intro has been initialized.
static intro_init;
// Whether the first players has been initialized.
static first_plr_init;
protected func Initialize()
{
// Rules: team account and buying at flagpole.
CreateObject(Rule_TeamAccount);
CreateObject(Rule_BuyAtFlagpole);
// Goal: Sell a certain amount of gems dependent on difficulty.
var goal = CreateObject(Goal_SellGems);
goal->SetTargetAmount(8 * SCENOPT_Difficulty);
// Initialize different parts of the scenario.
InitEnvironment(SCENOPT_Difficulty);
InitVegetation(SCENOPT_MapSize);
InitAnimals(SCENOPT_MapSize, SCENOPT_Difficulty);
return;
}
/*-- Player Initialization --*/
protected func InitializePlayer(int plr)
{
// Harsh zoom range.
SetPlayerZoomByViewRange(plr, 300, nil, PLRZOOM_Direct | PLRZOOM_LimitMax);
SetPlayerViewLock(plr, true);
// First player init base
if (!first_plr_init)
{
InitBase(plr, SCENOPT_Material);
first_plr_init = true;
}
// Position and materials
var crew;
for (var i = 0; crew = GetCrew(plr, i); ++i)
{
crew->SetPosition(20 + Random(32), 160 - 10);
crew->CreateContents(Shovel);
if (i == 0)
crew->CreateContents(Hammer);
else
crew->CreateContents(Axe);
}
// Give the player basic and pumping knowledge.
GivePlayerBasicKnowledge(plr);
GivePlayerPumpingKnowledge(plr);
GivePlayerSpecificKnowledge(plr, [WallKit, WindBag, TeleGlove]);
// Give the player the elementary base materials.
GivePlayerElementaryBaseMaterial(plr);
// Initialize the intro sequence if not yet started.
if (!intro_init)
{
StartSequence("Intro", 0);
intro_init = true;
}
return;
}
private func InitBase(int owner, int amount)
{
var y = 160;
// The basic settlement consists of a flagpole and a wind generator.
var x = 232;
while ((!GBackSky(x, y - 62) || !GBackSky(x, y - 66)) && x < 400)
x++;
CreateObject(WindGenerator, x + 4, y, owner);
CreateObject(Flagpole, x - 24, y, owner);
// Additional material includes a foundry and tools workshop.
if (amount >= 2)
{
var foundry = CreateObject(Foundry, x + 38, y, owner);
foundry->CreateContents(Coal, 4);
foundry->CreateContents(Metal, 2);
var workshop = CreateObject(ToolsWorkshop, x - 56, y, owner);
workshop->CreateContents(Wood, 4);
workshop->CreateContents(Metal, 2);
var lorry = CreateObject(Lorry, x - 56, 160);
// And even more material includes explosives and food.
if (amount >= 3)
{
var chemicallab = CreateObject(ChemicalLab, x + 84, y, owner);
chemicallab->CreateContents(Dynamite, 4);
chemicallab->CreateContents(DynamiteBox, 4);
workshop->CreateContents(Wood, 4);
workshop->CreateContents(Metal, 2);
workshop->CreateContents(Pickaxe, 1);
lorry->CreateContents(Bread, 4);
}
}
return;
}
/*-- Scenario Initialization --*/
private func InitEnvironment(int difficulty)
{
// Sky has some parallax.
SetSkyParallax(1, 20, 20);
// Some earthquakes if difficulty prescribes it.
if (difficulty >= 3)
Earthquake->SetChance(6);
return;
}
private func InitVegetation(int map_size)
{
var wdt = LandscapeWidth();
var hgt = LandscapeHeight();
// Cave mushrooms scattered around the top and middle sections.
LargeCaveMushroom->Place(10, Rectangle(0, 0, wdt, hgt / 8), { terraform = false });
LargeCaveMushroom->Place(15, Rectangle(0, hgt / 8, wdt, hgt / 8), { terraform = false });
LargeCaveMushroom->Place(15, Rectangle(0, 2 * hgt / 8, wdt, hgt / 8), { terraform = false });
// Cave entrance covered with mushrooms and bushes.
SproutBerryBush->Place(4, Rectangle(0, 120, 100, 40));
Fern->Place(4, Rectangle(0, 120, 100, 40));
Mushroom->Place(8, Rectangle(0, 120, 100, 40));
// The cavern has some grass wherever possible.
PlaceGrass(100);
// Entrance also location for a small cemetary.
CreateObject(Column, 64, 160)->SetObjDrawTransform(400, 0, 0, 0, 400, 0);
for (var x = 72; x < 104; x += RandomX(6, 14))
CreateObject(Clonk_Grave, x, 160)->SetInscriptionMessage("R.I.P.");
CreateObject(Column, 112, 160)->SetObjDrawTransform(400, 0, 0, 0, 400, 0);
// Some ferns and mushrooms scattered around the top and middle sections.
Fern->Place(12, Rectangle(0, 0, wdt, 3 * hgt / 8));
Mushroom->Place(20, Rectangle(0, 0, wdt, 3 * hgt / 8));
// Create earth materials in big clusters so the whole object arrangement looks a bit less uniform and more interesting.
PlaceBatches([Firestone], 3, 100, 5);
PlaceBatches([Rock, Loam, Loam], 10, 200, 10);
// Place some underwater vegetation in the flooded caves.
var place_rect = Rectangle(50, hgt / 2, wdt - 100, hgt / 2);
Seaweed->Place(16 + 4 * map_size, place_rect);
Coral->Place(16 + 8 * map_size, place_rect);
return;
}
private func InitAnimals(int map_size, int difficulty)
{
var wdt = LandscapeWidth();
var hgt = LandscapeHeight();
// Place some fishes and piranhas if difficulty prescribes it.
var place_rect = Rectangle(50, hgt / 2, wdt - 100, hgt / 2);
Fish->Place(10 + 8 * map_size, place_rect);
if (difficulty >= 3)
Piranha->Place(4 + 2 * map_size, place_rect);
return;
}
/*-- Some helper functions --*/
private func PlaceBatches(array item_ids, int n_per_batch, int batch_radius, int n_batches)
{
// place a number (n_batches) of batches of objects of types item_ids. Each batch has n_per_batch objects.
// fewer batches and/or objects may be placed if no space is found
var loc, loc2, n_item_ids = GetLength(item_ids), n_created = 0, obj;
for (var i = 0; i < n_batches; ++i)
if (loc = FindLocation(Loc_Material("Earth")))
for (var j = 0; j < n_per_batch; ++j)
if (loc2 = FindLocation(Loc_InRect(loc.x - batch_radius,loc.y - batch_radius, batch_radius * 2, batch_radius * 2), Loc_Material("Earth")))
if (obj = CreateObject(item_ids[Random(n_item_ids)], loc2.x, loc2.y))
{
obj->SetPosition(loc2.x, loc2.y);
++n_created;
}
return n_created;
}
global func TestGemCount()
{
var pos;
while (pos = FindLocation(Loc_Or(Loc_Material("Ruby"), Loc_Material("Amethyst"))))
{
var pos = CreateObject(Rock, pos.x, pos.y)->Explode(100);
}
var gem_count = ObjectCount(Find_Or(Find_ID(Ruby), Find_ID(Amethyst)));
return gem_count;
}

View File

@ -0,0 +1,73 @@
// Intro sequence for Gold Rush: crew runs to middle of screen talking about settlement.
#appendto Sequence
public func Intro_Start()
{
SetPlayerZoomByViewRange(NO_OWNER, 200, nil, PLRZOOM_Set | PLRZOOM_LimitMax);
return ScheduleNext(4);
}
public func Intro_1()
{
for (var i = 0; i < GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
MessageBox(Format("$MsgAbandonedSettlement$", GetCrew(plr, 1)->GetName()), GetCrew(plr, 0), GetCrew(plr, 0), plr, true);
GetCrew(plr, 0)->SetCommand("MoveTo", nil, 200 + Random(12), 160);
}
return ScheduleNext(4 * 36);
}
public func Intro_2()
{
for (var i = 0; i < GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
MessageBox("$MsgLegendGems$", GetCrew(plr, 0), GetCrew(plr, 1), plr, true);
GetCrew(plr, 0)->SetDir(DIR_Left);
GetCrew(plr, 1)->SetCommand("MoveTo", nil, 180 + Random(12), 160);
}
return ScheduleNext(4 * 36);
}
public func Intro_3()
{
for (var i = 0; i < GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
MessageBox(Format("$MsgExplore$", GetCrew(plr, 1)->GetName()), GetCrew(plr, 0), GetCrew(plr, 0), plr, true);
GetCrew(plr, 0)->SetCommand("MoveTo", nil, 320 + Random(12), 160);
}
return ScheduleNext(4 * 36);
}
public func Intro_4()
{
for (var i = 0; i < GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
MessageBox("$MsgAgree$", GetCrew(plr, 0), GetCrew(plr, 1), plr, true);
GetCrew(plr, 0)->SetDir(DIR_Left);
GetCrew(plr, 1)->SetCommand("MoveTo", nil, 300 + Random(12), 160);
}
return ScheduleNext(4 * 36);
}
public func Intro_5()
{
for (var i = 0; i < GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
GetCrew(plr, 0)->SetCommand("None");
GetCrew(plr, 1)->SetCommand("None");
}
return Stop();
}
public func Intro_Stop()
{
// Reset player zoom.
SetPlayerZoomByViewRange(NO_OWNER, 300, nil, PLRZOOM_Set | PLRZOOM_LimitMax);
return true;
}

View File

@ -0,0 +1,5 @@
# Intro sequence messages
MsgAbandonedSettlement=%s do you see that abandoned settlement as well?
MsgLegendGems=Yes, I do. Do you know that legends describe large amounts of gems near this location?!
MsgExplore=Yes %s, I have heard those tales. Let's explore the caves below!
MsgAgree=I am dying to find out if this legend is true, I'll join.

View File

@ -0,0 +1,5 @@
# Intro sequence messages
MsgAbandonedSettlement=%s do you see that abandoned settlement as well?
MsgLegendGems=Yes, I do. Do you know that legends describe large amounts of gems near this location?!
MsgExplore=Yes %s, I have heard those tales. Let's explore the caves below!
MsgAgree=I am dying to find out if this legend is true, I'll join.

View File

@ -0,0 +1,2 @@
DE:Geflutete Gänge
US:Flooded Veins

View File

@ -127,8 +127,6 @@ private func InitAnimals()
private func InitMaterial(int amount)
{
var lorry;
// No extra materials for little materials.
if (amount <= 1)
return;
@ -137,23 +135,22 @@ private func InitMaterial(int amount)
if (amount >= 2)
{
var x = 160 + Random(40);
lorry = CreateObject(Lorry, x, FindHeight(x) - 20);
var lorry = CreateObject(Lorry, x, FindHeight(x) - 20);
lorry->CreateContents(Wood, 6);
lorry->CreateContents(Metal, 4);
lorry->CreateContents(Rock, 4);
lorry->CreateContents(Dynamite, 4);
lorry->CreateContents(Pickaxe);
}
// For large amount of materials add more explosives into the lorry
if (amount >= 3)
{
lorry->CreateContents(Wood, 6);
lorry->CreateContents(Metal, 4);
lorry->CreateContents(Rock, 4);
lorry->CreateContents(DynamiteBox, 2);
// For large amount of materials add more explosives into the lorry
if (amount >= 3)
{
lorry->CreateContents(Wood, 6);
lorry->CreateContents(Metal, 4);
lorry->CreateContents(Rock, 4);
lorry->CreateContents(DynamiteBox, 2);
}
}
return;
}

View File

@ -38,7 +38,6 @@ public func Intro_3()
return Stop();
}
public func Intro_Stop()
{
// Reset player zoom.

View File

@ -15,5 +15,12 @@ implement these options with a static const set to the standard value, you'd pre
If you want your scenario in this folder please add it or contact the maintainer in IRC or the forum.
[Open Todos]
* Add additional decoration to all worlds.
* Translate Gold Rush into German.
* Translate Iron Peak into German.
* Implement rock fall and blizzards for Iron Peak.
* Implement rock fall and blizzards for Iron Peak.
* Translate Flooded Veins into German.
* Improve the gem distribution (make it look more vein-like).

View File

@ -1,101 +0,0 @@
/**
Ruby cave
@author Sven2
*/
overlay VaryTex { turbulence=10; algo=rndchecker; zoomX=-100; zoomY=-100; };
overlay GraniteBorders {turbulence=100; mat=Granite; loosebounds=1; VaryTex {mat=Rock; tex=rock_cracked; a=1;};};
map CrystalCaves {
// Base background is earth
mat=Earth; tex=earth_rough;
VaryTex { mat=Earth; tex=earth_dry; };
VaryTex { mat=Earth; tex=earth; };
// Resources
VaryTex { mat=Rock; y=50px; zoomX=30; a=3;};
VaryTex { mat=Granite; y=80px; zoomX=30; a=5;};
VaryTex { mat=Coal; a=10; };
VaryTex { mat=Ore; a=10; };
VaryTex { mat=Firestone; y=40px; a=8; hgt=50px;x=60px;};
VaryTex { mat=Gold; y=70px; a=20; };
// Top caves for mushyrooms
overlay { hgt=32px; mask=1;
overlay { algo=rndchecker; x=55px; hgt=32px; mat=Tunnel; a=3;zoomX=50;zoomY=-20; turbulence=100; loosebounds=1; };
};
// Water. Only in bottom area.
overlay { y=35px; mask=1;
overlay WaterVein { x=100px; turbulence=100; algo=rndchecker; zoomX=-100; zoomY=100; a=5; loosebounds=1; mat=Water; };
WaterVein { x=70px; rotate=-20; };
WaterVein { x=30px; rotate=20; };
};
// Rock/granite in mid area
overlay { y=30px; hgt=12px; turbulence=1000; loosebounds=1; mask=1;
VaryTex { mat=Rock; zoomX=-100; };
VaryTex { mat=Granite; zoomX=-100; };
};
// Granite borders
GraniteBorders { y=-20px; hgt=24px; };
GraniteBorders { x=146px; };
GraniteBorders { y=126px; rotate=-10; VaryTex {mat=Water; };};
GraniteBorders { x=-20px; wdt=24px; };
// Ruby cave water basin
overlay { algo=poly; mat=Water; turbulence=10;
point { x=100px; y=120px; };
point { x=110px; y=90px; };
point { x=130px; y=85px; };
point { x=145px; y=95px; };
point { x=140px; y=105px; };
point { x=145px; y=130px; };
point { x=125px; y=140px; };
point { x=115px; y=140px; };
};
// Ruby cave socket
overlay { algo=poly; mat=Granite; turbulence=10;
point { x=100px; y=150px; };
point { x=115px; y=145px; };
point { x=117px; y=120px; };
point { x=123px; y=120px; };
point { x=125px; y=145px; };
point { x=140px; y=150px; };
};
// Ruby cave rubies!
overlay { algo=poly; mat=Ruby; turbulence=10;
point { x=114px; y=125px; };
point { x=116px; y=119px; };
point { x=120px; y=115px; };
point { x=124px; y=119px; };
point { x=126px; y=125px; };
point { x=120px; y=128px; };
overlay {algo=border; a=2; b=0; turbulence=10; mat=Amethyst; };
overlay {algo=border; a=1; b=1; mat=Granite; };
};
// Starting cave
overlay { algo=poly; mat=Tunnel; turbulence=10;
hgt=25px;
point { x=-100px; y=10px; };
point { x=0px; y=10px; };
point { x=0px; y=10px; };
point { x=18px; y=5px; };
point { x=40px; y=15px; };
point { x=40px; y=20px; };
point { x=30px; y=35px; };
point { x=-100px; y=35px; };
// sky back
VaryTex { a=2; wdt=23px; };
// windmill positions
overlay { x=5px; wdt=22px; y=10px; turbulence=10; loosebounds=1;};
overlay { y=24px; mat=Brick; };
};
};

View File

@ -1,119 +0,0 @@
/**
Ruby Cave
@author Sven2
*/
protected func Initialize()
{
// Goal
var goal = CreateObject(Goal_SellGems);
goal->SetTargetAmount(10);
// Rules
CreateObject(Rule_TeamAccount);
CreateObject(Rule_BuyAtFlagpole);
// Mushrooms before any earth materials, because they create their own caves
LargeCaveMushroom->Place(15, Rectangle(400, 0, 800, 200));
// Create earth materials
// Create them in big clusters so the whole object arrangement looks a bit less uniform and more interesting
PlaceBatches([Firestone], 3, 100, 5);
PlaceBatches([Rock, Loam, Loam], 10, 200, 10);
// Misc vegetation
SproutBerryBush->Place(5, Rectangle(350, 0, 850, 250));
Mushroom->Place(5, Rectangle(350, 0, 850, 250));
// Sky
SetSkyParallax(1, 20, 20, 0, 0, nil, nil);
return true;
}
/*-- Player Initialization --*/
static g_was_player_init;
protected func InitializePlayer(int plr)
{
// Harsh zoom range.
SetPlayerZoomByViewRange(plr, 500, nil, PLRZOOM_Direct | PLRZOOM_LimitMax);
SetPlayerViewLock(plr, true);
// First player init base
if (!g_was_player_init)
{
InitBase(plr);
g_was_player_init = true;
}
// Position and materials
var crew;
for (var i = 0; crew = GetCrew(plr, i); ++i)
{
crew->SetPosition(100 + Random(80), 192 - 10);
crew->CreateContents(Shovel);
if (!i)
{
crew->CreateContents(Hammer);
}
else if (i == 1)
{
crew->CreateContents(Axe);
}
}
// Give the player basic and pumping knowledge.
GivePlayerBasicKnowledge(plr);
GivePlayerPumpingKnowledge(plr);
GivePlayerSpecificKnowledge(plr, [WallKit, WindBag, TeleGlove]);
// Give the player the elementary base materials.
GivePlayerElementaryBaseMaterial(plr);
return;
}
private func InitBase(int owner)
{
// Create standard base owned by player
var y=192;
var workshop = CreateObject(ToolsWorkshop, 70, y, owner);
if (workshop)
{
workshop->CreateContents(Wood, 3);
workshop->CreateContents(Metal, 1);
workshop->CreateContents(Pipe, 2);
}
var windgenerator = CreateObject(WindGenerator, 150, y, owner);
var flag = CreateObject(Flagpole, 180, y, owner);
var foundry = CreateObject(Foundry, 220, y, owner);
if (foundry)
{
foundry->CreateContents(Coal, 3);
foundry->CreateContents(Metal, 2);
}
var chest = CreateObject(Chest, 260, y, owner);
if (chest)
{
chest->CreateContents(DynamiteBox, 1);
chest->CreateContents(Dynamite, 2);
}
return;
}
/*-- Scenario Initialization --*/
private func PlaceBatches(array item_ids, int n_per_batch, int batch_radius, int n_batches)
{
// place a number (n_batches) of batches of objects of types item_ids. Each batch has n_per_batch objects.
// fewer batches and/or objects may be placed if no space is found
var loc,loc2,n_item_ids=GetLength(item_ids), n_created=0, obj;
for (var i=0; i<n_batches; ++i)
if (loc = FindLocation(Loc_Material("Earth")))
for (var j=0; j<n_per_batch; ++j)
if (loc2 = FindLocation(Loc_InRect(loc.x-batch_radius,loc.y-batch_radius,batch_radius*2,batch_radius*2), Loc_Material("Earth")))
if (obj=CreateObject(item_ids[Random(n_item_ids)],loc2.x,loc2.y))
{
obj->SetPosition(loc2.x,loc2.y);
++n_created;
}
return n_created;
}

View File

@ -1,2 +0,0 @@
DE:Rubinhöhle
US:Ruby Cave