Tweaks random map appearance and resource placement.

Cleans up rmgen library.
Fixes bug in bound checking for circular maps.

This was SVN commit r9388.
This commit is contained in:
historic_bruno 2011-05-01 22:29:58 +00:00
parent e297dac1a5
commit c02818ceea
12 changed files with 858 additions and 361 deletions

View File

@ -4,10 +4,11 @@ RMS.LoadLibrary("rmgen");
const tGrass = ["medit_grass_field_a", "medit_grass_field_b"];
const tGrassForest = "medit_grass_wild";
const tCliff = ["medit_cliff_italia", "medit_cliff_italia_grass"];
const tGrassDirt75 = "medit_dirt";
const tGrassDirt50 = "medit_dirt_b";
const tGrassDirt25 = "medit_dirt_c";
const tGrassDirt75 = "medit_rocks_shrubs";
const tGrassDirt50 = "medit_rocks_grass_shrubs";
const tGrassDirt25 = "medit_rocks_grass";
const tDirt = "medit_dirt_b";
const tCity = "medit_city_tile";
const tGrassPatch = "medit_grass_wild";
const tShoreBlend = "medit_grass_field_brown";
const tShore = "medit_riparian_mud";
@ -20,8 +21,10 @@ const oApple = "gaia/flora_tree_apple";
const oPine = "gaia/flora_tree_pine";
const oAleppoPine = "gaia/flora_tree_aleppo_pine";
const oBerryBush = "gaia/flora_bush_berry";
const oSheep = "gaia/fauna_sheep";
const oChicken = "gaia/fauna_chicken";
const oDeer = "gaia/fauna_deer";
const oFish = "gaia/fauna_fish";
const oSheep = "gaia/fauna_sheep";
const oStone = "gaia/geology_stone_mediterranean";
const oMetal = "gaia/geology_metal_mediterranean_slabs";
@ -36,8 +39,8 @@ const aBushMedium = "actor|props/flora/bush_medit_me.xml";
const aBushSmall = "actor|props/flora/bush_medit_sm.xml";
// terrain + entity (for painting)
const pForestD = [tGrassForest + TERRAIN_SEPARATOR + oOak, tGrassForest + TERRAIN_SEPARATOR + oOakLarge];
const pForestP = [tGrassForest + TERRAIN_SEPARATOR + oPine, tGrassForest + TERRAIN_SEPARATOR + oAleppoPine];
const pForestD = [tGrassForest + TERRAIN_SEPARATOR + oOak, tGrassForest + TERRAIN_SEPARATOR + oOakLarge, tGrassForest];
const pForestP = [tGrassForest + TERRAIN_SEPARATOR + oPine, tGrassForest + TERRAIN_SEPARATOR + oAleppoPine, tGrassForest];
// initialize map
@ -64,28 +67,28 @@ var clSettlement = createTileClass();
// place players
var playerX = new Array(numPlayers+1);
var playerZ = new Array(numPlayers+1);
var playerAngle = new Array(numPlayers+1);
var playerX = new Array(numPlayers);
var playerZ = new Array(numPlayers);
var playerAngle = new Array(numPlayers);
var startAngle = randFloat() * 2 * PI;
for (var i = 1; i <= numPlayers; i++)
var startAngle = randFloat(0, TWO_PI);
for (var i = 0; i < numPlayers; i++)
{
playerAngle[i] = startAngle + i*2*PI/numPlayers;
playerAngle[i] = startAngle + i*TWO_PI/numPlayers;
playerX[i] = 0.5 + 0.35*cos(playerAngle[i]);
playerZ[i] = 0.5 + 0.35*sin(playerAngle[i]);
}
for (var i = 1; i <= numPlayers; i++)
for (var i = 0; i < numPlayers; i++)
{
log("Creating base for player " + i + "...");
log("Creating base for player " + (i + 1) + "...");
// some constants
var radius = 17;
var radius = scaleByMapSize(15,25);
var cliffRadius = 2;
var elevation = 20;
// get the x and y in tiles
// get the x and z in tiles
var fx = fractionToTiles(playerX[i]);
var fz = fractionToTiles(playerZ[i]);
var ix = round(fx);
@ -95,7 +98,7 @@ for (var i = 1; i <= numPlayers; i++)
var size = PI * radius * radius;
// create the hill
var placer = new ClumpPlacer(size, 0.95, 0.6, 0, ix, iz);
var placer = new ClumpPlacer(size, 0.95, 0.6, 10, ix, iz);
var terrainPainter = new LayeredPainter(
[tCliff, tGrass], // terrains
[cliffRadius] // widths
@ -108,40 +111,72 @@ for (var i = 1; i <= numPlayers; i++)
createArea(placer, [terrainPainter, elevationPainter, paintClass(clPlayer)], null);
// create the ramp
var rampAngle = playerAngle[i] + PI + (2*randFloat()-1)*PI/8;
var rampAngle = playerAngle[i] + PI + randFloat(-PI/8, PI/8);
var rampDist = radius;
var rampX = round(fx + rampDist * cos(rampAngle));
var rampZ = round(fz + rampDist * sin(rampAngle));
placer = new ClumpPlacer(100, 0.9, 0.5, 0, rampX, rampZ);
placer = new ClumpPlacer(100, 0.9, 0.5, 1, rampX, rampZ);
var painter = new SmoothElevationPainter(ELEVATION_SET, elevation-6, 5);
createArea(placer, painter, null);
placer = new ClumpPlacer(75, 0.9, 0.5, 0, rampX, rampZ);
placer = new ClumpPlacer(75, 0.9, 0.5, 1, rampX, rampZ);
painter = new TerrainPainter(tGrass);
createArea(placer, painter, null);
// create the central dirt patch
placer = new ClumpPlacer(PI*3.5*3.5, 0.3, 0.1, 0, ix, iz);
painter = new LayeredPainter(
[tGrassDirt75, tGrassDirt50, tGrassDirt25, tDirt], // terrains
[1,1,1] // widths
);
// create the city patch
var cityRadius = 5;
placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
painter = new TerrainPainter(tCity);
createArea(placer, painter, null);
// create the TC and citizens
var civ = getCivCode(i - 1);
// create the TC
var civ = getCivCode(i);
var group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0), new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
[new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0)],
true, null, ix, iz
);
createObjectGroup(group, i);
createObjectGroup(group, i+1);
// create starting units
var uDist = 7;
var uAngle = playerAngle[i] + PI + randFloat(-PI/8, PI/8);
var ux = round(fx + uDist * cos(uAngle));
var uz = round(fz + uDist * sin(uAngle));
group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("units/"+civ+"_support_female_citizen", 4,4, 1,2)],
true, null, ux, uz
);
createObjectGroup(group, i+1);
uAngle += PI/4;
ux = round(fx + uDist * cos(uAngle));
uz = round(fz + uDist * sin(uAngle));
group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("units/"+civ+"_infantry_javelinist_a", 4,4, 1,2)],
true, null, ux, uz
);
createObjectGroup(group, i+1);
// create animals
for (var j = 0; j < 2; ++j)
{
var aAngle = randFloat(0, TWO_PI);
var aDist = 7;
var aX = round(fx + aDist * cos(aAngle));
var aZ = round(fz + aDist * sin(aAngle));
group = new SimpleGroup(
[new SimpleObject(oChicken, 5,5, 0,3)],
true, clBaseResource, aX, aZ
);
createObjectGroup(group, 0);
}
// create berry bushes
var bbAngle = randFloat()*2*PI;
var bbDist = 9;
var bbAngle = randFloat(0, TWO_PI);
var bbDist = 12;
var bbX = round(fx + bbDist * cos(bbAngle));
var bbZ = round(fz + bbDist * sin(bbAngle));
group = new SimpleGroup(
[new SimpleObject(oBerryBush, 5,5, 0,2)],
[new SimpleObject(oBerryBush, 5,5, 0,3)],
true, clBaseResource, bbX, bbZ
);
createObjectGroup(group, 0);
@ -150,9 +185,9 @@ for (var i = 1; i <= numPlayers; i++)
var mAngle = bbAngle;
while(abs(mAngle - bbAngle) < PI/3)
{
mAngle = randFloat()*2*PI;
mAngle = randFloat(0, TWO_PI);
}
var mDist = 11;
var mDist = radius - 4;
var mX = round(fx + mDist * cos(mAngle));
var mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
@ -166,7 +201,7 @@ for (var i = 1; i <= numPlayers; i++)
mX = round(fx + mDist * cos(mAngle));
mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oStone, 2,2, 0,1)],
[new SimpleObject(oStone, 5,5, 0,3)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
@ -181,15 +216,15 @@ for (var i = 1; i <= numPlayers; i++)
// create grass tufts
for (var j = 0; j < 10; j++)
{
var gAngle = randFloat()*2*PI;
var gDist = 6 + randInt(9);
var gAngle = randFloat(0, TWO_PI);
var gDist = radius - (5 + randInt(7));
var gX = round(fx + gDist * cos(gAngle));
var gZ = round(fz + gDist * sin(gAngle));
group = new SimpleGroup(
[new SimpleObject(aGrassShort, 2,5, 0,1, -PI/8,PI/8)],
false, clBaseResource, gX, gZ
);
createObjectGroup(group, undefined);
createObjectGroup(group, 0);
}
}
@ -197,7 +232,8 @@ RMS.SetProgress(5);
// create lakes
log("Creating lakes...");
placer = new ClumpPlacer(mapArea * 0.003, 0.8, 0.1, 0);
var numLakes = round(scaleByMapSize(1,4) * numPlayers);
placer = new ClumpPlacer(scaleByMapSize(100,250), 0.8, 0.1, 10);
terrainPainter = new LayeredPainter(
[tShoreBlend, tShore, tWater], // terrains
[1,1] // widths
@ -207,17 +243,29 @@ var waterAreas = createAreas(
placer,
[terrainPainter, elevationPainter, paintClass(clWater)],
avoidClasses(clPlayer, 2, clWater, 20),
round(1.3 * numPlayers)
numLakes
);
// create reeds
log("Creating reeds...");
group = new SimpleGroup(
[new SimpleObject(aReeds, 5,10, 0,4), new SimpleObject(aLillies, 1,1, 0,4)], true
[new SimpleObject(aReeds, 5,10, 0,4), new SimpleObject(aLillies, 0,1, 0,4)], true
);
createObjectGroupsByAreas(group, undefined,
[new BorderTileClassConstraint(clWater, 3, 0), stayClasses(clWater, 1)],
10 * numPlayers, 100,
createObjectGroupsByAreas(group, 0,
[borderClasses(clWater, 3, 0), stayClasses(clWater, 1)],
numLakes, 100,
waterAreas
);
// create fish
log("Creating fish...");
group = new SimpleGroup(
[new SimpleObject(oFish, 1,1, 0,1)],
true, clFood
);
createObjectGroupsByAreas(group, 0,
borderClasses(clWater, 2, 0), avoidClasses(clFood, 8),
numLakes, 50,
waterAreas
);
waterAreas = [];
@ -226,20 +274,20 @@ RMS.SetProgress(22);
// create bumps
log("Creating bumps...");
placer = new ClumpPlacer(mapArea * 0.000229 + 10, 0.3, 0.06, 0);
placer = new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1);
painter = new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2);
createAreas(
placer,
painter,
avoidClasses(clWater, 2, clPlayer, 0),
44
scaleByMapSize(100, 200)
);
RMS.SetProgress(25);
// create hills
log("Creating hills...");
placer = new ClumpPlacer(mapArea * 0.000688 + 20, 0.2, 0.1, 0);
placer = new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1);
terrainPainter = new LayeredPainter(
[tCliff, [tGrass,tGrass,tGrassDirt75]], // terrains
[2] // widths
@ -249,28 +297,28 @@ var hillAreas = createAreas(
placer,
[terrainPainter, elevationPainter, paintClass(clHill)],
avoidClasses(clPlayer, 2, clWater, 5, clHill, 15),
3 * numPlayers
scaleByMapSize(1, 4) * numPlayers
);
RMS.SetProgress(30);
// calculate desired number of trees for map (based on size)
const MIN_TREES = 300;
const MAX_TREES = 1500;
const MIN_TREES = 500;
const MAX_TREES = 2500;
const P_FOREST = 0.7;
var totalTrees = MIN_TREES + (MAX_TREES - MIN_TREES) / 384 * (mapSize - 128);
var totalTrees = scaleByMapSize(MIN_TREES, MAX_TREES);
var numForest = totalTrees * P_FOREST;
var numStragglers = totalTrees * (1.0 - P_FOREST);
// create forests
log("Creating forests...");
var types = [pForestD, pForestP]; // some variation
var size = numForest / (2 * numPlayers);
var size = numForest / (scaleByMapSize(2,8) * numPlayers);
var num = floor(size / types.length);
for (var i = 0; i < types.length; ++i)
{
placer = new ClumpPlacer(numForest / num, 0.1, 0.1, 0);
placer = new ClumpPlacer(numForest / num, 0.1, 0.1, 1);
painter = new LayeredPainter(
[[tGrassForest, tGrass, types[i]], [tGrassForest, types[i]]], // terrains
[2] // widths
@ -285,23 +333,23 @@ for (var i = 0; i < types.length; ++i)
RMS.SetProgress(53);
log("Placing stone mines...");
log("Creating stone mines...");
// create stone
group = new SimpleGroup([new SimpleObject(oStone, 2,2, 0,8)], true, clRock);
group = new SimpleGroup([new SimpleObject(oStone, 3,5, 0,8)], true, clRock);
createObjectGroupsByAreas(group, 0,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clRock, 15),
new BorderTileClassConstraint(clHill, 0, 4)],
4 * numPlayers, 100,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clRock, 10),
borderClasses(clHill, 1, 4)],
8 * numPlayers, 100,
hillAreas
);
log("Placing metal mines...");
log("Creating metal mines...");
// create metal
group = new SimpleGroup([new SimpleObject(oMetal, 1,1, 0,8)], true, clMetal);
createObjectGroupsByAreas(group, 0,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clMetal, 15, clRock, 5),
new BorderTileClassConstraint(clHill, 0, 4)],
4 * numPlayers, 100,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clMetal, 10, clRock, 5),
borderClasses(clHill, 1, 4)],
scaleByMapSize(8,32) * numPlayers, 100,
hillAreas
);
hillAreas = [];
@ -311,7 +359,7 @@ log("Creating dirt patches...");
var sizes = [0.000183, 0.000321, 0.000458];
for (var i = 0; i < sizes.length; i++)
{
placer = new ClumpPlacer(mapArea * sizes[i], 0.3, 0.06, 0);
placer = new ClumpPlacer(mapArea * sizes[i], 0.3, 0.06, 0.5);
painter = new LayeredPainter(
[[tGrass,tGrassDirt75],[tGrassDirt75,tGrassDirt50], [tGrassDirt50,tGrassDirt25]], // terrains
[1,1] // widths
@ -320,7 +368,7 @@ for (var i = 0; i < sizes.length; i++)
placer,
[painter, paintClass(clDirt)],
avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0),
11
scaleByMapSize(15, 45)
);
}
@ -329,24 +377,16 @@ log("Creating grass patches...");
var sizes = [0.000115, 0.000206, 0.000298];
for (var i = 0; i < sizes.length; i++)
{
placer = new ClumpPlacer(mapArea * sizes[i], 0.3, 0.06, 0);
placer = new ClumpPlacer(mapArea * sizes[i], 0.3, 0.06, 0.5);
painter = new TerrainPainter(tGrassPatch);
createAreas(
placer,
painter,
avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0),
11
scaleByMapSize(15, 45)
);
}
// create settlements
// log("Creating settlements...");
// group = new SimpleGroup([new SimpleObject("gaia/special_settlement", 1,1, 0,0)], true, clSettlement);
// createObjectGroups(group, 0,
// avoidClasses(clWater, 0, clForest, 0, clPlayer, 15, clHill, 0, clRock, 5, clSettlement, 35),
// 2 * numPlayers, 50
// );
RMS.SetProgress(60);
// create small decorative rocks
@ -356,7 +396,7 @@ group = new SimpleGroup(
true
);
createObjectGroups(
group, undefined,
group, 0,
avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0),
mapArea/1000, 50
);
@ -368,7 +408,7 @@ group = new SimpleGroup(
true
);
createObjectGroups(
group, undefined,
group, 0,
avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0),
mapArea/2000, 50
);
@ -416,7 +456,7 @@ log("Creating small grass tufts...");
group = new SimpleGroup(
[new SimpleObject(aGrassShort, 1,2, 0,1, -PI/8,PI/8)]
);
createObjectGroups(group, undefined,
createObjectGroups(group, 0,
avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0),
mapArea * 0.000763
);
@ -428,7 +468,7 @@ log("Creating large grass tufts...");
group = new SimpleGroup(
[new SimpleObject(aGrass, 2,4, 0,1.8, -PI/8,PI/8), new SimpleObject(aGrassShort, 3,6, 1.2,2.5, -PI/8,PI/8)]
);
createObjectGroups(group, undefined,
createObjectGroups(group, 0,
avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0),
mapArea * 0.000763
);
@ -440,7 +480,7 @@ log("Creating bushes...");
group = new SimpleGroup(
[new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)]
);
createObjectGroups(group, undefined,
createObjectGroups(group, 0,
avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1),
mapArea * 0.000763, 50
);

View File

@ -11,6 +11,7 @@ const tBeachWet = "medit_sand_wet";
const tBeachDry = "medit_sand";
const tBeachGrass = "medit_rocks_grass";
const tBeachCliff = "medit_dirt";
const tCity = "medit_city_tile";
const tGrassDry = ["medit_grass_field_brown", "medit_grass_field_dry", "medit_grass_field_b"];
const tGrass = ["medit_grass_field_dry", "medit_grass_field_brown", "medit_grass_field_b"];
const tGrassLush = ["grass_temperate_dry_tufts", "medit_grass_flowers"];
@ -34,6 +35,9 @@ const oOak = "gaia/flora_tree_oak";
const oPalm = "gaia/flora_tree_medit_fan_palm";
const oPine = "gaia/flora_tree_aleppo_pine";
const oPoplar = "gaia/flora_tree_poplar";
const oChicken = "gaia/fauna_chicken";
const oDeer = "gaia/fauna_deer";
const oFish = "gaia/fauna_fish";
const oSheep = "gaia/fauna_sheep";
const oStone = "gaia/geology_stone_mediterranean";
const oMetal = "gaia/geology_metal_mediterranean_slabs";
@ -45,23 +49,18 @@ const aBushMedDry = "actor|props/flora/bush_medit_me_dry.xml";
const aBushMed = "actor|props/flora/bush_medit_me.xml";
const aBushSmall = "actor|props/flora/bush_medit_sm.xml";
const aBushSmallDry = "actor|props/flora/bush_medit_sm_dry.xml";
const aGrass = "actor|props/flora/grass_medit_field.xml";
const aGrassDry = "actor|props/flora/grass_soft_dry_small.xml";
const aRockLarge = "actor|geology/stone_granite_greek_large.xml";
const aRockMed = "actor|geology/stone_granite_greek_med.xml";
const aRockSmall = "actor|geology/stone_granite_greek_small.xml";
const aGrass = "actor|props/flora/grass_soft_large_tall.xml";
const aGrassDry = "actor|props/flora/grass_soft_dry_large_tall.xml";
const aRockLarge = "actor|geology/stone_granite_large.xml";
const aRockMed = "actor|geology/stone_granite_med.xml";
const aRockSmall = "actor|geology/stone_granite_small.xml";
const aWaterLog = "actor|props/flora/water_log.xml";
// terrain + entity (for painting)
var pPalmForest = tForestFloor+TERRAIN_SEPARATOR+oPalm;
var pPineForest = tForestFloor+TERRAIN_SEPARATOR+oPine;
var pCarobForest = tForestFloor+TERRAIN_SEPARATOR+oCarob;
var pBeechForest = tForestFloor+TERRAIN_SEPARATOR+oBeech;
var pPoplarForest = tForestFloor+TERRAIN_SEPARATOR+oLombardyPoplar;
var tPalmForest = [pPalmForest, tGrass];
var tPineForest = [pPineForest, tGrass];
var tMainForest = [pCarobForest, pBeechForest, tGrass, tGrass];
var tPoplarForest = [pPoplarForest, tGrass];
var pPalmForest = [tForestFloor+TERRAIN_SEPARATOR+oPalm, tGrass];
var pPineForest = [tForestFloor+TERRAIN_SEPARATOR+oPine, tGrass];
var pPoplarForest = [tForestFloor+TERRAIN_SEPARATOR+oLombardyPoplar, tGrass];
var pMainForest = [tForestFloor+TERRAIN_SEPARATOR+oCarob, tForestFloor+TERRAIN_SEPARATOR+oBeech, tGrass, tGrass];
// initialize map
@ -87,80 +86,27 @@ var clSettlement = createTileClass();
// Place players
log("Placing players...");
log("Creating players...");
var playerX = new Array(numPlayers+1);
var playerZ = new Array(numPlayers+1);
var numLeftPlayers = ceil(numPlayers/2);
for (var i=1; i <= numLeftPlayers; i++)
for (var i = 1; i <= numLeftPlayers; i++)
{
playerX[i] = 0.28 + (2*randFloat()-1)*0.01;
playerZ[i] = (0.5+i-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
playerX[i] = 0.28 + randFloat(-0.01, 0.01);
playerZ[i] = (0.5+i-1)/numLeftPlayers + randFloat(-0.01, 0.01);
}
for (var i=numLeftPlayers+1; i <= numPlayers; i++)
for (var i = numLeftPlayers+1; i <= numPlayers; i++)
{
playerX[i] = 0.72 + (2*randFloat()-1)*0.01;
playerZ[i] = (0.5+i-numLeftPlayers-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
}
for (var i=1; i <= numPlayers; i++)
{
log("Creating base for player " + i + "...");
// get fractional locations in tiles
var ix = round(fractionToTiles(playerX[i]));
var iz = round(fractionToTiles(playerZ[i]));
addToClass(ix, iz, clPlayer);
// create TC and starting units
// TODO: Get civ specific starting units
var civ = getCivCode(i - 1);
placeObject(ix, iz, "structures/"+civ + "_civil_centre", i, PI*3/4);
var group = new SimpleGroup(
[new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
true, null, ix, iz
);
createObjectGroup(group, i);
// create starting berry bushes
var bbAngle = randFloat()*2*PI;
var bbDist = 9;
var bbX = round(ix + bbDist * cos(bbAngle));
var bbZ = round(iz + bbDist * sin(bbAngle));
group = new SimpleGroup(
[new SimpleObject(oBerryBush, 5,5, 0,2)],
true, clBaseResource, bbX, bbZ
);
createObjectGroup(group, 0);
// create starting mines
var mAngle = bbAngle;
while(abs(mAngle - bbAngle) < PI/3) {
mAngle = randFloat()*2*PI;
}
var mDist = 9;
var mX = round(ix + mDist * cos(mAngle));
var mZ = round(iz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oStone, 2,2, 0,3),
new SimpleObject(oMetal, 1,1, 0,3)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
// create starting straggler trees
group = new SimpleGroup(
[new SimpleObject(oPalm, 3,3, 7,10)],
true, clBaseResource, ix, iz
);
createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
playerX[i] = 0.72 + randFloat(-0.01, 0.01);
playerZ[i] = (0.5+i-numLeftPlayers-1)/numLeftPlayers + randFloat(-0.01, 0.01);
}
function distanceToPlayers(x, z)
{
var r = 10000;
for (var i=1; i <= numPlayers; i++)
for (var i = 1; i <= numPlayers; i++)
{
var dx = x - playerX[i];
var dz = z - playerZ[i];
@ -202,9 +148,9 @@ var noise3 = new Noise2D(4 * mapSize/128);
var noise4 = new Noise2D(6 * mapSize/128);
var noise5 = new Noise2D(11 * mapSize/128);
for (var ix=0; ix<=mapSize; ix++)
for (var ix = 0; ix <= mapSize; ix++)
{
for (var iz=0; iz<=mapSize; iz++)
for (var iz = 0; iz <= mapSize; iz++)
{
var x = ix / (mapSize + 1.0);
var z = iz / (mapSize + 1.0);
@ -288,9 +234,9 @@ var noise9 = new Noise2D(26 * mapSize/128);
var noise10 = new Noise2D(50 * mapSize/128);
for (var ix=0; ix<mapSize; ix++)
for (var ix = 0; ix < mapSize; ix++)
{
for (var iz=0; iz<mapSize; iz++)
for (var iz = 0; iz < mapSize; iz++)
{
var x = ix / (mapSize + 1.0);
var z = iz / (mapSize + 1.0);
@ -312,9 +258,9 @@ for (var ix=0; ix<mapSize; ix++)
{
var maxNx = min(ix+2, mapSize);
var maxNz = min(iz+2, mapSize);
for (var nx=max(ix-1, 0); nx <= maxNx; nx++)
for (var nx = max(ix-1, 0); nx <= maxNx; nx++)
{
for (var nz=max(iz-1, 0); nz <= maxNz; nz++)
for (var nz = max(iz-1, 0); nz <= maxNz; nz++)
{
minAdjHeight = min(minAdjHeight, getHeight(nx, nz));
}
@ -380,8 +326,7 @@ for (var ix=0; ix<mapSize; ix++)
// forests
if (maxH - minH < 1 && minH > 1)
{
var forestNoise = (noise6.get(x,z) + 0.5*noise7.get(x,z)) / 1.5 * pn;
forestNoise -= 0.59;
var forestNoise = (noise6.get(x,z) + 0.5*noise7.get(x,z)) / 1.5 * pn - 0.59;
if (forestNoise > 0)
{
@ -390,17 +335,17 @@ for (var ix=0; ix<mapSize; ix++)
var typeNoise = noise10.get(x,z);
if (typeNoise < 0.43 && forestNoise < 0.05)
t = tPoplarForest;
t = pPoplarForest;
else if (typeNoise < 0.63)
t = tMainForest;
t = pMainForest;
else
t = tPineForest;
t = pPineForest;
addToClass(ix, iz, clForest);
}
else if (minH < 3)
{
t = tPalmForest;
t = pPalmForest;
addToClass(ix, iz, clForest);
}
}
@ -417,9 +362,9 @@ for (var ix=0; ix<mapSize; ix++)
else if (grassNoise < 0.34)
{
t = (maxH - minH > 1.2) ? tGrassCliff : tGrassDry;
if (maxH - minH < 0.5 && randFloat() < 0.03)
if (maxH - minH < 0.5 && randFloat() < 0.02)
{
placeObject(ix+randFloat(), iz+randFloat(), aGrassDry, 0, randFloat()*2*PI);
placeObject(ix+randFloat(), iz+randFloat(), aGrassDry, 0, randFloat(0, TWO_PI));
}
}
else if (grassNoise > 0.61)
@ -428,9 +373,9 @@ for (var ix=0; ix<mapSize; ix++)
}
else
{
if ((maxH - minH) < 0.5 && randFloat() < 0.05)
if ((maxH - minH) < 0.5 && randFloat() < 0.02)
{
placeObject(ix+randFloat(), iz+randFloat(), aGrass, 0, randFloat()*2*PI);
placeObject(ix+randFloat(), iz+randFloat(), aGrass, 0, randFloat(0, TWO_PI));
}
}
}
@ -439,15 +384,112 @@ for (var ix=0; ix<mapSize; ix++)
}
}
log("Placing settlements...");
// create settlements
// group = new SimpleGroup([new SimpleObject("gaia/special_settlement", 1,1, 0,0)], true, clSettlement);
// createObjectGroups(group, 0,
// avoidClasses(clWater, 5, clForest, 4, clPlayer, 25, clCliff, 4, clSettlement, 35),
// 2*numPlayers, 50
// );
for (var i = 1; i <= numPlayers; i++)
{
log("Creating base for player " + i + "...");
// get fractional locations in tiles
var fx = fractionToTiles(playerX[i]);
var fz = fractionToTiles(playerZ[i]);
var ix = round(fx);
var iz = round(fz);
addToClass(ix, iz, clPlayer);
// create the city patch
var cityRadius = 8;
var placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
var painter = new LayeredPainter([tGrass, tCity], [1]);
createArea(placer, painter, null);
// create TC and starting units
// TODO: Get civ specific starting units
// create the TC
var civ = getCivCode(i-1);
var group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0)],
true, null, ix, iz
);
createObjectGroup(group, i);
// create starting units
var uDist = 7;
var uAngle = randFloat(0, TWO_PI);
var ux = round(fx + uDist * cos(uAngle));
var uz = round(fz + uDist * sin(uAngle));
group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("units/"+civ+"_support_female_citizen", 4,4, 1,2)],
true, null, ux, uz
);
createObjectGroup(group, i);
uAngle += PI/4;
ux = round(fx + uDist * cos(uAngle));
uz = round(fz + uDist * sin(uAngle));
group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("units/"+civ+"_infantry_javelinist_a", 4,4, 1,2)],
true, null, ux, uz
);
createObjectGroup(group, i);
// create animals
for (var j = 0; j < 2; ++j)
{
var aAngle = randFloat(0, TWO_PI);
var aDist = 7;
var aX = round(fx + aDist * cos(aAngle));
var aZ = round(fz + aDist * sin(aAngle));
group = new SimpleGroup(
[new SimpleObject(oChicken, 5,5, 0,3)],
true, clBaseResource, aX, aZ
);
createObjectGroup(group, 0);
}
// create starting berry bushes
var bbAngle = randFloat(0, TWO_PI);
var bbDist = 9;
var bbX = round(fx + bbDist * cos(bbAngle));
var bbZ = round(fz + bbDist * sin(bbAngle));
group = new SimpleGroup(
[new SimpleObject(oBerryBush, 5,5, 0,2)],
true, clBaseResource, bbX, bbZ
);
createObjectGroup(group, 0);
// create metal mine
var mAngle = bbAngle;
while(abs(mAngle - bbAngle) < PI/3)
{
mAngle = randFloat(0, TWO_PI);
}
var mDist = 15;
var mX = round(fx + mDist * cos(mAngle));
var mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oMetal, 1,1, 0,0)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
// create stone mines
mAngle += randFloat(PI/8, PI/4);
mX = round(fx + mDist * cos(mAngle));
mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oStone, 5,5, 0,3)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
// create starting straggler trees
group = new SimpleGroup(
[new SimpleObject(oPalm, 3,3, 7,10)],
true, clBaseResource, ix, iz
);
createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
}
log("Placing straggler trees...");
log("Creating straggler trees...");
// create straggler trees
var trees = [oCarob, oBeech, oLombardyPoplar, oLombardyPoplar, oPine];
for (var t in trees)
@ -459,7 +501,7 @@ for (var t in trees)
);
}
log("Placing cypress trees...");
log("Creating cypress trees...");
// create cypresses
group = new SimpleGroup(
[new SimpleObject(oCypress2, 1,3, 0,3),
@ -470,7 +512,7 @@ createObjectGroups(group, 0,
mapArea/3500, 50
);
log("Placing bushes...");
log("Creating bushes...");
// create bushes
group = new SimpleGroup(
[new SimpleObject(aBushSmall, 0,2, 0,2), new SimpleObject(aBushSmallDry, 0,2, 0,2),
@ -481,7 +523,7 @@ createObjectGroups(group, 0,
mapArea/1800, 50
);
log("Placing rocks...");
log("Creating rocks...");
// create rocks
group = new SimpleGroup(
[new SimpleObject(aRockSmall, 0,3, 0,2), new SimpleObject(aRockMed, 0,2, 0,2),
@ -492,33 +534,52 @@ createObjectGroups(group, 0,
mapArea/1800, 50
);
log("Placing stone mines...");
log("Creating stone mines...");
// create stone
group = new SimpleGroup([new SimpleObject(oStone, 2,3, 0,2)], true, clStone);
group = new SimpleGroup([new SimpleObject(oStone, 3,5, 0,2)], true, clStone);
createObjectGroups(group, 0,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clStone, 15),
new BorderTileClassConstraint(clCliff, 0, 5)],
3 * numPlayers, 100
borderClasses(clCliff, 0, 5)],
8 * numPlayers, 100
);
log("Placing metal mines...");
log("Creating metal mines...");
// create metal
group = new SimpleGroup([new SimpleObject(oMetal, 1,1, 0,2)], true, clMetal);
createObjectGroups(group, 0,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clMetal, 15, clStone, 5),
new BorderTileClassConstraint(clCliff, 0, 5)],
3 * numPlayers, 100
borderClasses(clCliff, 0, 5)],
scaleByMapSize(8,32) * numPlayers, 100
);
log("Placing sheep...");
log("Creating sheep...");
// create sheep
group = new SimpleGroup([new SimpleObject(oSheep, 2,4, 0,2)], true, clFood);
createObjectGroups(group, 0,
avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20, clMetal, 2, clStone, 2, clFood, 8),
3 * numPlayers, 100
3 * numPlayers, 50
);
log("Placing berry bushes...");
log("Creating fish...");
// create fish
group = new SimpleGroup([new SimpleObject(oFish, 1,1, 0,1)], true, clFood);
createObjectGroups(group, 0,
[borderClasses(clWater, 0, 7), avoidClasses(clFood, 8, clCliff, 0)],
3 * numPlayers, 50
);
// create deer
log("Creating deer...");
group = new SimpleGroup(
[new SimpleObject(oDeer, 5,7, 0,4)],
true, clFood
);
createObjectGroups(group, 0,
avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20, clMetal, 2, clStone, 2, clFood, 8),
3 * numPlayers, 50
);
log("Creating berry bushes...");
// create berry bushes
group = new SimpleGroup([new SimpleObject(oBerryBush, 5,7, 0,3)], true, clFood);
createObjectGroups(group, 0,

View File

@ -1,35 +1,46 @@
RMS.LoadLibrary("rmgen");
// terrain textures
const tCity = "desert_city_tile";
const tCityPlaza = "desert_city_tile_plaza";
const tSand = "desert_dirt_rough";
const tDunes = "desert_sand_dunes_100";
const tFineSand = "desert_sand_smooth";
const tCliff = "desert_cliff_badlands";
const tGrassSand75 = "desert_grass_a";
const tCliff = ["desert_cliff_badlands", "desert_cliff_badlands_2"];
const tForestFloor = "desert_forestfloor_palms";
const tGrass = "desert_grass_a";
const tGrassSand50 = "desert_grass_a_sand";
const tGrassSand25 = "desert_grass_a_stones";
const tDirt = "desert_dirt_rough";
const tDirtCracks = "desert_dirt_cracks";
const tShore = "desert_sand_wet";
const tWater = "desert_shore_stones";
const tShore = "desert_shore_stones";
const tWaterDeep = "desert_shore_stones_wet";
// gaia entities
const oBerryBush = "gaia/flora_bush_berry";
const oGoat = "gaia/fauna_goat";
const oChicken = "gaia/fauna_chicken";
const oCamel = "gaia/fauna_camel";
const oFish = "gaia/fauna_fish";
const oGazelle = "gaia/fauna_gazelle";
const oGiraffe = "gaia/fauna_giraffe";
const oGoat = "gaia/fauna_goat";
const oWildebeest = "gaia/fauna_wildebeest";
const oStone = "gaia/geology_stone_desert_small";
const oMetal = "gaia/geology_metal_desert_slabs";
const oDatePalm = "gaia/flora_tree_date_palm";
const oSDatePalm = "gaia/flora_tree_senegal_date_palm";
// decorative props
const aBush = "actor|props/flora/bush_dry_a.xml";
const aDecorativeRock = "actor|geology/gray1.xml";
const aBush1 = "actor|props/flora/bush_desert_a.xml";
const aBush2 = "actor|props/flora/bush_desert_dry_a.xml";
const aBush3 = "actor|props/flora/bush_dry_a.xml";
const aBush4 = "actor|props/flora/plant_desert_a.xml";
const aBushes = [aBush1, aBush2, aBush3, aBush4];
const aDecorativeRock = "actor|geology/stone_desert_med.xml";
// terrain + entity (for painting)
var pForest = [tGrassSand75 + TERRAIN_SEPARATOR + oDatePalm, tGrassSand75 + TERRAIN_SEPARATOR + oSDatePalm];
var pForest = [tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor];
var pForestOasis = [tGrass + TERRAIN_SEPARATOR + oDatePalm, tGrass + TERRAIN_SEPARATOR + oSDatePalm, tGrass];
// initialize map
@ -58,27 +69,27 @@ var clBaseResource = createTileClass();
// place players
var playerX = new Array(numPlayers);
var playerY = new Array(numPlayers);
var playerZ = new Array(numPlayers);
var playerAngle = new Array(numPlayers);
var startAngle = randFloat() * 2 * PI;
for (var i=0; i < numPlayers; i++)
var startAngle = randFloat(0, TWO_PI);
for (var i = 0; i < numPlayers; i++)
{
playerAngle[i] = startAngle + i*2*PI/numPlayers;
playerX[i] = 0.5 + 0.39*cos(playerAngle[i]);
playerY[i] = 0.5 + 0.39*sin(playerAngle[i]);
playerAngle[i] = startAngle + i*TWO_PI/numPlayers;
playerX[i] = 0.5 + 0.35*cos(playerAngle[i]);
playerZ[i] = 0.5 + 0.35*sin(playerAngle[i]);
}
for (var i=0; i < numPlayers; i++)
for (var i = 0; i < numPlayers; i++)
{
log("Creating base for player " + (i + 1) + "...");
// scale radius of player area by map size
var radius = mapSize * 0.026 + 7;
var radius = scaleByMapSize(15,25);
// get the x and y in tiles
// get the x and z in tiles
var fx = fractionToTiles(playerX[i]);
var fz = fractionToTiles(playerY[i]);
var fz = fractionToTiles(playerZ[i]);
var ix = round(fx);
var iz = round(fz);
@ -86,48 +97,90 @@ for (var i=0; i < numPlayers; i++)
var size = PI * radius * radius;
// create the player area
var placer = new ClumpPlacer(size, 0.9, 0.5, 0, ix, iz);
var placer = new ClumpPlacer(size, 0.9, 0.5, 10, ix, iz);
createArea(placer, paintClass(clPlayer), null);
// create the central road patch
placer = new ClumpPlacer(PI*2*2, 0.6, 0.3, 0.5, ix, iz);
var painter = new TerrainPainter(tDirt);
// create the city patch
var cityRadius = 10;
placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
var painter = new LayeredPainter([tCity, tCityPlaza], [3]);
createArea(placer, painter, null);
// create the TC and citizens
var civ = getCivCode(i);
var group = new SimpleGroup(
[ // elements (type, count, distance)
new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0),
new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)
],
var group = new SimpleGroup( // elements (type, count, distance)
[new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0)],
true, null, ix, iz
);
createObjectGroup(group, i+1);
// create starting units
var uDist = 7;
var uAngle = playerAngle[i] + PI + randFloat(-PI/8, PI/8);
var ux = round(fx + uDist * cos(uAngle));
var uz = round(fz + uDist * sin(uAngle));
group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("units/"+civ+"_support_female_citizen", 4,4, 1,2)],
true, null, ux, uz
);
createObjectGroup(group, i+1);
uAngle += PI/4;
ux = round(fx + uDist * cos(uAngle));
uz = round(fz + uDist * sin(uAngle));
group = new SimpleGroup( // elements (type, min/max count, min/max distance)
[new SimpleObject("units/"+civ+"_infantry_javelinist_a", 4,4, 1,2)],
true, null, ux, uz
);
createObjectGroup(group, i+1);
// create animals
for (var j = 0; j < 2; ++j)
{
var aAngle = randFloat(0, TWO_PI);
var aDist = 7;
var aX = round(fx + aDist * cos(aAngle));
var aZ = round(fz + aDist * sin(aAngle));
group = new SimpleGroup(
[new SimpleObject(oChicken, 5,5, 0,3)],
true, clBaseResource, aX, aZ
);
createObjectGroup(group, 0);
}
// create berry bushes
var bbAngle = randFloat()*2*PI;
var bbDist = 10;
var bbAngle = randFloat(0, TWO_PI);
var bbDist = 12;
var bbX = round(fx + bbDist * cos(bbAngle));
var bbY = round(fz + bbDist * sin(bbAngle));
var bbZ = round(fz + bbDist * sin(bbAngle));
group = new SimpleGroup(
[new SimpleObject(oGoat, 5,5, 0,2)],
true, clBaseResource, bbX, bbY
[new SimpleObject(oBerryBush, 5,5, 0,3)],
true, clBaseResource, bbX, bbZ
);
createObjectGroup(group, 0);
// create mines
// create metal mine
var mAngle = bbAngle;
while(abs(mAngle - bbAngle) < PI/3) {
mAngle = randFloat()*2*PI;
while(abs(mAngle - bbAngle) < PI/3)
{
mAngle = randFloat(0, TWO_PI);
}
var mDist = 12;
var mDist = 11;
var mX = round(fx + mDist * cos(mAngle));
var mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oStone, 2,2, 0,3),
new SimpleObject(oMetal, 1,1, 0,3)],
true, clBaseResource, mX, mZ
[new SimpleObject(oMetal, 1,1, 0,0), new RandomObject(aBushes, 2,4, 0,2)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
// create stone mines
mAngle += randFloat(PI/8, PI/4);
mX = round(fx + mDist * cos(mAngle));
mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oStone, 5,5, 0,3), new RandomObject(aBushes, 2,4, 0,2)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
@ -142,164 +195,264 @@ for (var i=0; i < numPlayers; i++)
RMS.SetProgress(5);
// create patches
log("Creating sand patches...");
var placer = new ClumpPlacer(mapArea * 0.000688 + 20, 0.2, 0.1, 0);
var painter = new LayeredPainter([[tSand, tFineSand], tFineSand], [1]);
log("Creating dune patches...");
placer = new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, 0);
painter = new TerrainPainter(tDunes);
createAreas(placer, [painter, paintClass(clPatch)],
avoidClasses(clPatch, 5),
73
avoidClasses(clPatch, 2, clPlayer, 0),
scaleByMapSize(5, 20)
);
log("Creating sand patches...");
var placer = new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0);
var painter = new TerrainPainter([tSand, tFineSand]);
createAreas(placer, [painter, paintClass(clPatch)],
avoidClasses(clPatch, 2, clPlayer, 0),
scaleByMapSize(15, 50)
);
RMS.SetProgress(24);
log("Creating dirt patches...");
placer = new ClumpPlacer(mapArea * 0.000229, 0.2, 0.1, 0);
painter = new TerrainPainter([tSand, tDirt]);
placer = new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0);
painter = new TerrainPainter([tDirt]);
createAreas(placer, [painter, paintClass(clPatch)],
avoidClasses(clPatch, 5),
73
avoidClasses(clPatch, 2, clPlayer, 0),
scaleByMapSize(15, 50)
);
RMS.SetProgress(32);
// create the oasis (roughly 4% of map area)
// create the oasis
log("Creating oasis...");
placer = new ClumpPlacer(mapArea * 0.04, 0.6, 0.1, 0, mapSize/2, mapSize/2);
painter = new LayeredPainter([[tSand, pForest], tShore, tWaterDeep], [6,1]);
elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, -11, 5);
var oRadius = scaleByMapSize(14, 40);
placer = new ClumpPlacer(PI*oRadius*oRadius, 0.6, 0.15, 0, mapSize/2, mapSize/2);
painter = new LayeredPainter([[tSand, pForest], [tGrassSand25, pForestOasis], tGrassSand25, tShore, tWaterDeep], [2, 3, 1, 1]);
elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, -12, 7);
createArea(placer, [painter, elevationPainter, paintClass(clForest)], null);
// create oasis wildlife
var num = round(PI * oRadius / 8);
var constraint = new AndConstraint([borderClasses(clForest, 0, 3), avoidClasses(clForest, 0)]);
var halfSize = mapSize/2;
for (var i = 0; i < num; ++i)
{
var r = 0;
var angle = TWO_PI / num * i;
do {
// Work outward until we find
var gx = round(halfSize + r * cos(angle));
var gz = round(halfSize + r * sin(angle));
++r;
} while (!constraint.allows(gx,gz) && r < halfSize);
group = new RandomGroup(
[ new SimpleObject(oGiraffe, 2,4, 0,3), // select from these groups randomly
new SimpleObject(oWildebeest, 3,5, 0,3),
new SimpleObject(oGazelle, 5,7, 0,3)
], true, clFood, gx, gz
);
createObjectGroup(group, 0);
}
constraint = new AndConstraint([borderClasses(clForest, 15, 0), avoidClasses(clFood, 5)]);
num = round(PI * oRadius / 16);
for (var i = 0; i < num; ++i)
{
var r = 0;
var angle = TWO_PI / num * i;
do {
// Work outward until we find
var gx = round(halfSize + r * cos(angle));
var gz = round(halfSize + r * sin(angle));
++r;
} while (!constraint.allows(gx,gz) && r < halfSize);
group = new SimpleGroup(
[new SimpleObject(oFish, 1,1, 0,1)],
true, clFood, gx, gz
);
createObjectGroup(group, 0);
}
RMS.SetProgress(51);
// create hills
log("Creating level 1 hills...");
placer = new ClumpPlacer(mapArea * 0.00344, 0.25, 0.1, 0.3);
placer = new ClumpPlacer(scaleByMapSize(50,300), 0.25, 0.1, 0.5);
var terrainPainter = new LayeredPainter(
[tCliff, tSand], // terrains
[1] // widths
);
var elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
avoidClasses(clForest, 2, clPlayer, 0, clHill1, 16),
12, 100
var hillAreas = createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
avoidClasses(clForest, 3, clPlayer, 0, clHill1, 10),
scaleByMapSize(10,20), 100
);
RMS.SetProgress(70);
log("Creating small level 1 hills...");
placer = new ClumpPlacer(mapArea * 0.00138, 0.25, 0.1, 0.3);
placer = new ClumpPlacer(scaleByMapSize(25,150), 0.25, 0.1, 0.5);
terrainPainter = new LayeredPainter(
[tCliff, tSand], // terrains
[1] // widths
);
elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
avoidClasses(clForest, 2, clPlayer, 0, clHill1, 3),
16, 100
var tempAreas = createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
avoidClasses(clForest, 3, clPlayer, 0, clHill1, 3),
scaleByMapSize(15,25), 100
);
for (var i = 0; i < tempAreas.length; ++i)
{
hillAreas.push(tempAreas[i]);
}
RMS.SetProgress(70);
log("Creating stone mines...");
// create stone
group = new SimpleGroup([new SimpleObject(oStone, 3,5, 0,8), new RandomObject(aBushes, 2,4, 0,2)], true, clRock);
createObjectGroupsByAreas(group, 0,
[avoidClasses(clForest, 2, clPlayer, 0, clRock, 10),
borderClasses(clHill1, 0, 4)],
8 * numPlayers, 100,
hillAreas
);
log("Creating metal mines...");
// create metal
group = new SimpleGroup([new SimpleObject(oMetal, 1,1, 0,8), new RandomObject(aBushes, 2,4, 0,2)], true, clMetal);
createObjectGroupsByAreas(group, 0,
[avoidClasses(clForest, 2, clPlayer, 0, clMetal, 10, clRock, 5),
borderClasses(clHill1, 0, 4)],
scaleByMapSize(8,32) * numPlayers, 100,
hillAreas
);
// create decorative rocks for hills
log("Creating decorative rocks...");
group = new SimpleGroup(
[new RandomObject([aDecorativeRock, aBush2, aBush3], 3,8, 0,2)],
true
);
createObjectGroupsByAreas(group, 0,
borderClasses(clHill1, 0, 3),
scaleByMapSize(40,100), 100,
hillAreas
);
RMS.SetProgress(81);
log("Creating level 2 hills...");
placer = new ClumpPlacer(mapArea * 0.00138, 0.2, 0.1, 0.9);
placer = new ClumpPlacer(scaleByMapSize(25,150), 0.25, 0.1, 0);
terrainPainter = new LayeredPainter(
[tCliff, tSand], // terrains
[1] // widths
);
elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill2)],
[avoidClasses(clHill2, 1), stayClasses(clHill1, 0)],
16, 200
createAreasInAreas(placer, [terrainPainter, elevationPainter],
[stayClasses(clHill1, 0)],
scaleByMapSize(15,25), 50,
hillAreas
);
RMS.SetProgress(91);
log("Creating level 3 hills...");
placer = new ClumpPlacer(mapArea * 0.000573, 0.2, 0.1, 0.9);
placer = new ClumpPlacer(scaleByMapSize(12, 75), 0.25, 0.1, 0);
terrainPainter = new LayeredPainter(
[tCliff, tSand], // terrains
[1] // widths
);
elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill3)],
[avoidClasses(clHill3, 1), stayClasses(clHill2, 0)],
5, 300
createAreas(placer, [terrainPainter, elevationPainter],
[stayClasses(clHill1, 0)],
scaleByMapSize(15,25), 50,
hillAreas
);
hillAreas = [];
// create bumps
log("Creating bumps...");
placer = new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 0);
elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2);
createAreas(
placer,
elevationPainter,
avoidClasses(clForest, 0, clPlayer, 0, clHill1, 2),
scaleByMapSize(100, 200)
);
// calculate desired number of trees for map (based on size)
const MIN_TREES = 500;
const MAX_TREES = 2500;
const P_FOREST = 0.5;
var totalTrees = scaleByMapSize(MIN_TREES, MAX_TREES);
var numForest = totalTrees * P_FOREST;
var numStragglers = totalTrees * (1.0 - P_FOREST);
// create forests
log("Creating forests...");
placer = new ClumpPlacer(mapArea * 0.000573, 0.15, 0.1, 0.3);
var num = scaleByMapSize(10,30);
placer = new ClumpPlacer(numForest / num, 0.15, 0.1, 0.5);
painter = new TerrainPainter([tSand, pForest]);
createAreas(placer, [painter, paintClass(clForest)],
avoidClasses(clWater, 0, clPlayer, 1, clForest, 20, clHill1, 0),
11, 50
);
log("Placing stone mines...");
// create stone
group = new SimpleGroup([new SimpleObject(oStone, 1,2, 0,2)], true, clRock);
createObjectGroups(group, 0,
[avoidClasses(clWater, 2, clForest, 2, clPlayer, 0, clRock, 13),
new BorderTileClassConstraint(clHill1, 0, 4)],
5 * numPlayers, 100
);
log("Placing metal mines...");
// create metal
group = new SimpleGroup([new SimpleObject(oMetal, 1,1, 0,0)], true, clMetal);
createObjectGroups(group, 0,
[avoidClasses(clWater, 2, clForest, 2, clPlayer, 0, clMetal, 13, clRock, 5),
new BorderTileClassConstraint(clHill1, 0, 4)],
5 * numPlayers, 100
avoidClasses(clPlayer, 1, clForest, 10, clHill1, 1),
num, 50
);
RMS.SetProgress(97);
// create decorative rocks for hills
log("Creating decorative rocks...");
group = new SimpleGroup([new SimpleObject(aDecorativeRock, 1,1, 0,0)], true);
createObjectGroups(group, undefined,
new BorderTileClassConstraint(clHill1, 0, 3),
mapArea/2000, 100
);
// create deer
log("Creating deer...");
// create gazelles
log("Creating gazelles...");
group = new SimpleGroup([new SimpleObject(oGazelle, 5,7, 0,4)], true, clFood);
createObjectGroups(group, 0,
avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill1, 0, clFood, 25),
mapArea/5000, 50
avoidClasses(clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10),
scaleByMapSize(5,20), 50
);
// create sheep
log("Creating sheep...");
group = new SimpleGroup([new SimpleObject(oGoat, 1,3, 0,2)], true, clFood);
// create goats
log("Creating goats...");
group = new SimpleGroup([new SimpleObject(oGoat, 2,4, 0,3)], true, clFood);
createObjectGroups(group, 0,
avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill1, 0, clFood, 15),
mapArea/5000, 50
avoidClasses(clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10),
scaleByMapSize(5,20), 50
);
// create camels
log("Creating camels...");
group = new SimpleGroup([new SimpleObject(oCamel, 2,4, 0,2)], true, clFood);
createObjectGroups(group, 0,
avoidClasses(clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10),
scaleByMapSize(5,20), 50
);
// create straggler trees
log("Creating straggler trees...");
group = new SimpleGroup([new SimpleObject(oDatePalm, 1,1, 0,0)], true);
createObjectGroups(group, 0,
avoidClasses(clWater, 0, clForest, 0, clHill1, 0, clPlayer, 0),
mapArea/1500
);
var types = [oDatePalm, oSDatePalm]; // some variation
var num = floor(numStragglers / types.length);
for (var i = 0; i < types.length; ++i)
{
group = new SimpleGroup([new SimpleObject(types[i], 1,1, 0,0)], true);
createObjectGroups(group, 0,
avoidClasses(clForest, 0, clHill1, 1, clPlayer, 0),
num
);
}
// create bushes
log("Creating bushes...");
group = new SimpleGroup([new SimpleObject(aBush, 2,3, 0,2)]);
createObjectGroups(group, undefined,
avoidClasses(clWater, 3, clHill1, 0, clPlayer, 0, clForest, 0),
group = new SimpleGroup([new RandomObject(aBushes, 2,3, 0,2)]);
createObjectGroups(group, 0,
avoidClasses(clHill1, 1, clPlayer, 0, clForest, 0),
mapArea/1000
);
// create bushes
// create rocks
log("Creating more decorative rocks...");
group = new SimpleGroup([new SimpleObject(aDecorativeRock, 1,2, 0,2)]);
createObjectGroups(group, undefined,
avoidClasses(clWater, 3, clHill1, 0, clPlayer, 0, clForest, 0),
createObjectGroups(group, 0,
avoidClasses(clHill1, 1, clPlayer, 0, clForest, 0),
mapArea/1000
);

View File

@ -3,7 +3,7 @@
"Name" : "Neareastern Badlands",
"Script" : "neareastern_badlands.js",
"Description" : "A jumbled maze of cliffs, canyons, and rugged terrain with an oasis in the center",
"BaseTerrain" : "desert_rough",
"BaseTerrain" : ["desert_sand_smooth", "desert_sand_smooth_b"],
"BaseHeight" : 10,
"CircularMap" : true,
"XXXXXX" : "Optionally define other things here, like we would for a scenario"

View File

@ -133,7 +133,6 @@ function BorderTileClassConstraint(tileClassID, distanceInside, distanceOutside)
BorderTileClassConstraint.prototype.allows = function(x, z)
{
//error("BTCC.allows("+x+", "+z+"): class="+this.tileClass.id+", in="+this.tileClass.countMembersInRadius(x, z, this.distanceOutside)+", out="+this.tileClass.countNonMembersInRadius(x, z, this.distanceInside));
return (this.tileClass.countMembersInRadius(x, z, this.distanceOutside) > 0
&& this.tileClass.countNonMembersInRadius(x, z, this.distanceInside) > 0);
};

View File

@ -4,14 +4,13 @@
/////////////////////////////////////////////////////////////////////////////////////////////
const PI = Math.PI;
const SEA_LEVEL = 20.0;
const TWO_PI = 2 * Math.PI;
const TERRAIN_SEPARATOR = "|";
const SEA_LEVEL = 20.0;
const CELL_SIZE = 4;
const HEIGHT_UNITS_PER_METRE = 732;
const MIN_MAP_SIZE = 128;
const MAX_MAP_SIZE = 512;
/////////////////////////////////////////////////////////////////////////////////////////////
// Utility functions
@ -37,6 +36,11 @@ function sizeToFraction(s)
return s / getMapArea();
}
function scaleByMapSize(min, max)
{
return min + ((max-min) * (getMapSize()-MIN_MAP_SIZE) / (MAX_MAP_SIZE-MIN_MAP_SIZE));
}
function cos(x)
{
return Math.cos(x);
@ -119,7 +123,7 @@ function chooseRand()
{
if (arguments.length==0)
{
error("chooseRand: requires at least 1 argument");
throw("chooseRand: requires at least 1 argument");
}
var ar = argsToArray(arguments);
return ar[randInt(ar.length)];
@ -167,6 +171,42 @@ function createAreas(centeredPlacer, painter, constraint, num, retryFactor)
return result;
}
function createAreasInAreas(centeredPlacer, painter, constraint, num, retryFactor, areas)
{
if (retryFactor === undefined)
{
retryFactor = 10;
}
var maxFail = num * retryFactor;
var good = 0;
var bad = 0;
var result = [];
var numAreas = areas.length;
while(good < num && bad <= maxFail && numAreas)
{
// Choose random point from area
var i = randInt(numAreas);
var size = areas[i].points.length;
var pt = areas[i].points[randInt(size)];
centeredPlacer.x = pt.x;
centeredPlacer.z = pt.z;
var area = g_Map.createArea(centeredPlacer, painter, constraint);
if (area !== undefined)
{
good++;
result.push(area);
}
else
{
bad++;
}
}
return result;
}
function createObjectGroups(placer, player, constraint, num, retryFactor)
{
if (retryFactor === undefined)
@ -218,7 +258,7 @@ function createObjectGroupsByAreas(placer, player, constraint, num, retryFactor,
var bad = 0;
var numAreas = areas.length;
while(good < num && bad <= maxFail)
while(good < num && bad <= maxFail && numAreas)
{
// Choose random point from area
var i = randInt(numAreas);
@ -276,8 +316,7 @@ function createSimpleTerrain(terrain)
}
else
{
error("createSimpleTerrain expects string as input, received "+terrain);
return undefined;
throw("createSimpleTerrain expects string as input, received "+terrain);
}
}
@ -384,22 +423,58 @@ function paintClass(id)
function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
{
var ar = new Array(arguments.length/2);
for (var i=0; i < arguments.length/2; i++)
for (var i = 0; i < arguments.length/2; i++)
{
ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
}
// Return single constraint
return new AndConstraint(ar);
if (ar.length == 1)
{
return ar[0];
}
else
{
return new AndConstraint(ar);
}
}
// Create a stay constraint for the given classes by the given distances
function stayClasses(/*class1, dist1, class2, dist2, etc*/)
{
var ar = new Array(arguments.length/2);
for (var i=0; i < arguments.length/2; i++)
for (var i = 0; i < arguments.length/2; i++)
{
ar[i] = new StayInTileClassConstraint(arguments[2*i], arguments[2*i+1]);
}
// Return single constraint
return new AndConstraint(ar);
if (ar.length == 1)
{
return ar[0];
}
else
{
return new AndConstraint(ar);
}
}
// Create a border constraint for the given classes by the given distances
function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/)
{
var ar = new Array(arguments.length/3);
for (var i = 0; i < arguments.length/3; i++)
{
ar[i] = new BorderTileClassConstraint(arguments[3*i], arguments[3*i+1], arguments[3*i+2]);
}
// Return single constraint
if (ar.length == 1)
{
return ar[0];
}
else
{
return new AndConstraint(ar);
}
}

View File

@ -95,7 +95,17 @@ Map.prototype.getEntityID = function()
// Check bounds on tile map
Map.prototype.validT = function(x, z)
{
return x >= 0 && z >= 0 && x < this.size && z < this.size;
if (g_MapSettings.CircularMap)
{ // Within map circle
var halfSize = 0.5*this.size;
var dx = (x - halfSize);
var dz = (z - halfSize);
return Math.sqrt(dx*dx + dz*dz) < (halfSize - 1.5);
}
else
{ // Within map square
return x >= 0 && z >= 0 && x < this.size && z < this.size;
}
};
// Check bounds on height map (size + 1 by size + 1)
@ -114,7 +124,7 @@ Map.prototype.getTexture = function(x, z)
{
if (!this.validT(x, z))
{
error("getTexture: invalid tile position ("+x+", "+z+")");
throw("getTexture: invalid tile position ("+x+", "+z+")");
}
return this.IDToName[this.texture[x][z]];
@ -124,7 +134,7 @@ Map.prototype.setTexture = function(x, z, texture)
{
if (!this.validT(x, z))
{
error("setTexture: invalid tile position ("+x+", "+z+")");
throw("setTexture: invalid tile position ("+x+", "+z+")");
}
this.texture[x][z] = this.getTextureID(texture);
@ -134,7 +144,7 @@ Map.prototype.getHeight = function(x, z)
{
if (!this.validH(x, z))
{
error("getHeight: invalid vertex position ("+x+", "+z+")");
throw("getHeight: invalid vertex position ("+x+", "+z+")");
}
return this.height[x][z];
@ -144,7 +154,7 @@ Map.prototype.setHeight = function(x, z, height)
{
if (!this.validH(x, z))
{
error("setHeight: invalid vertex position ("+x+", "+z+")");
throw("setHeight: invalid vertex position ("+x+", "+z+")");
}
this.height[x][z] = height;
@ -154,7 +164,7 @@ Map.prototype.getTerrainObjects = function(x, z)
{
if (!this.validT(x, z))
{
error("getTerrainObjects: invalid tile position ("+x+", "+z+")");
throw("getTerrainObjects: invalid tile position ("+x+", "+z+")");
}
return this.terrainObjects[x][z];
@ -164,7 +174,7 @@ Map.prototype.setTerrainObject = function(x, z, object)
{
if (!this.validT(x, z))
{
error("setTerrainObject: invalid tile position ("+x+", "+z+")");
throw("setTerrainObject: invalid tile position ("+x+", "+z+")");
}
this.terrainObjects[x][z] = object;

View File

@ -35,7 +35,7 @@ function InitMap()
if (g_MapSettings === undefined)
{
// Should never get this far, failed settings would abort prior to loading scripts
error("InitMapGen: settings missing");
throw("InitMapGen: settings missing");
}
// Create new map

View File

@ -47,7 +47,9 @@ ElevationPainter.prototype.paint = function(area)
function LayeredPainter(terrainArray, widths)
{
if (!(terrainArray instanceof Array))
error("terrains must be an array!");
{
throw("LayeredPainter: terrains must be an array!");
}
this.terrains = [];
for (var i = 0; i < terrainArray.length; ++i)
@ -187,12 +189,20 @@ function SmoothElevationPainter(type, elevation, blendRadius)
this.blendRadius = blendRadius;
if (type != ELEVATION_SET && type != ELEVATION_MODIFY)
error("SmoothElevationPainter: invalid type '"+type+"'");
{
throw("SmoothElevationPainter: invalid type '"+type+"'");
}
}
SmoothElevationPainter.prototype.checkInArea = function(areaID, x, z)
{
return (g_Map.validT(x, z) && g_Map.area[x][z] == areaID);
// Check given tile and its neighbors
return (
(g_Map.validT(x, z) && g_Map.area[x][z] == areaID)
|| (g_Map.validT(x-1, z) && g_Map.area[x-1][z] == areaID)
|| (g_Map.validT(x, z-1) && g_Map.area[x][z-1] == areaID)
|| (g_Map.validT(x-1, z-1) && g_Map.area[x-1][z-1] == areaID)
);
};
SmoothElevationPainter.prototype.paint = function(area)
@ -255,12 +265,7 @@ SmoothElevationPainter.prototype.paint = function(area)
{
var nz = z+dz;
if (g_Map.validH(nx, nz)
&& !this.checkInArea(areaID, nx, nz)
&& !this.checkInArea(areaID, nx-1, nz)
&& !this.checkInArea(areaID, nx, nz-1)
&& !this.checkInArea(areaID, nx-1, nz-1)
&& !saw[nx][nz])
if (g_Map.validH(nx, nz) && !this.checkInArea(areaID, nx, nz) && !saw[nx][nz])
{
saw[nx][nz]= 1;
dist[nx][nz] = 0;
@ -279,9 +284,7 @@ SmoothElevationPainter.prototype.paint = function(area)
var d = dist[px][pz];
// paint if in area
if (g_Map.validH(px, pz)
&& (this.checkInArea(areaID, px, pz) || this.checkInArea(areaID, px-1, pz)
|| this.checkInArea(areaID, px, pz-1) || this.checkInArea(areaID, px-1, pz-1)))
if (g_Map.validH(px, pz) && this.checkInArea(areaID, px, pz))
{
if (d <= this.blendRadius)
{
@ -316,10 +319,7 @@ SmoothElevationPainter.prototype.paint = function(area)
{
var nz = pz+dz;
if (g_Map.validH(nx, nz)
&& (this.checkInArea(areaID, nx, nz) || this.checkInArea(areaID, nx-1, nz)
|| this.checkInArea(areaID, nx, nz-1) || this.checkInArea(areaID, nx-1, nz-1))
&& !saw[nx][nz])
if (g_Map.validH(nx, nz) && this.checkInArea(areaID, nx, nz) && !saw[nx][nz])
{
saw[nx][nz] = 1;
dist[nx][nz] = d+1;
@ -338,8 +338,7 @@ SmoothElevationPainter.prototype.paint = function(area)
var px = pt.x;
var pz = pt.z;
if ((this.checkInArea(areaID, px, pz) || this.checkInArea(areaID, px-1, pz)
|| this.checkInArea(areaID, px, pz-1) || this.checkInArea(areaID, px-1, pz-1)))
if (this.checkInArea(areaID, px, pz))
{
var sum = 8 * newHeight[px][pz];
var count = 8;

View File

@ -137,7 +137,9 @@ function RectPlacer(x1, z1, x2, z2)
this.z2 = z2;
if (x1 > x2 || z1 > z2)
error("RectPlacer: incorrect bounds on rect");
{
throw("RectPlacer: incorrect bounds on rect");
}
}
RectPlacer.prototype.place = function(constraint)
@ -201,13 +203,13 @@ function SimpleObject(type, minCount, maxCount, minDistance, maxDistance, minAng
this.maxAngle = (maxAngle !== undefined ? maxAngle : 2*PI);
if (minCount > maxCount)
error("SimpleObject: minCount must be less than or equal to maxCount");
warn("SimpleObject: minCount should be less than or equal to maxCount");
if (minDistance > maxDistance)
error("SimpleObject: minDistance must be less than or equal to maxDistance");
warn("SimpleObject: minDistance should be less than or equal to maxDistance");
if (minAngle > maxAngle)
error("SimpleObject: minAngle must be less than or equal to maxAngle");
warn("SimpleObject: minAngle should be less than or equal to maxAngle");
}
SimpleObject.prototype.place = function(cx, cz, player, avoidSelf, constraint)
@ -277,6 +279,108 @@ SimpleObject.prototype.place = function(cx, cz, player, avoidSelf, constraint)
return resultObjs;
};
/////////////////////////////////////////////////////////////////////////////////////////
// RandomObject
//
// Class specifying entities that can be placed on the map, selected randomly
//
// types: Array of entity template names
// minCount,maxCount: The number of objects to place
// minDistance,maxDistance: The distance between placed objects
// minAngle,maxAngle: The variation in angle of placed objects (optional)
//
/////////////////////////////////////////////////////////////////////////////////////////
function RandomObject(types, minCount, maxCount, minDistance, maxDistance, minAngle, maxAngle)
{
this.types = types;
this.minCount = minCount;
this.maxCount = maxCount;
this.minDistance = minDistance;
this.maxDistance = maxDistance;
this.minAngle = (minAngle !== undefined ? minAngle : 0);
this.maxAngle = (maxAngle !== undefined ? maxAngle : 2*PI);
if (minCount > maxCount)
warn("RandomObject: minCount should be less than or equal to maxCount");
if (minDistance > maxDistance)
warn("RandomObject: minDistance should be less than or equal to maxDistance");
if (minAngle > maxAngle)
warn("RandomObject: minAngle should be less than or equal to maxAngle");
}
RandomObject.prototype.place = function(cx, cz, player, avoidSelf, constraint)
{
var failCount = 0;
var count = randInt(this.minCount, this.maxCount);
var resultObjs = [];
for (var i=0; i < count; i++)
{
while(true)
{
var distance = randFloat(this.minDistance, this.maxDistance);
var direction = randFloat(0, 2*PI);
var x = cx + 0.5 + distance*cos(direction);
var z = cz + 0.5 + distance*sin(direction);
var fail = false; // reset place failure flag
if (!g_Map.validT(x, z))
{
fail = true;
}
else
{
if (avoidSelf)
{
var length = resultObjs.length;
for (var i = 0; (i < length) && !fail; i++)
{
var dx = x - resultObjs[i].x;
var dy = z - resultObjs[i].z;
if ((dx*dx + dy*dy) < 1)
{
fail = true;
}
}
}
if (!fail)
{
if (!constraint.allows(Math.floor(x), Math.floor(z)))
{
fail = true;
}
else
{ // if we got here, we're good
var angle = randFloat(this.minAngle, this.maxAngle);
//Randomly select entity
var type = this.types[randInt(this.types.length)];
resultObjs.push(new Entity(type, player, x, z, angle));
break;
}
}
}
if (fail)
{
failCount++;
if (failCount > 20) // TODO: Make this adjustable
{
return undefined;
}
}
}
}
return resultObjs;
};
/////////////////////////////////////////////////////////////////////////////////////////
// SimpleGroup
//
@ -335,3 +439,58 @@ SimpleGroup.prototype.place = function(player, constraint)
return true;
};
/////////////////////////////////////////////////////////////////////////////////////////
// RandomGroup
//
// Class for placing group of a random simple object
//
// elements: Array of SimpleObjects
// avoidSelf: Objects will not overlap
// tileClass: Optional tile class to add with these objects
// x,z: Tile coordinates of center of placer
//
/////////////////////////////////////////////////////////////////////////////////////////
function RandomGroup(elements, avoidSelf, tileClass, x, z)
{
this.elements = elements;
this.tileClass = (tileClass !== undefined ? getTileClass(tileClass) : undefined);
this.avoidSelf = (avoidSelf !== undefined ? avoidSelf : false);
this.x = (x !== undefined ? x : -1);
this.z = (z !== undefined ? z : -1);
}
RandomGroup.prototype.place = function(player, constraint)
{
var resultObjs = [];
// Pick one of the object placers at random
var placer = this.elements[randInt(this.elements.length)];
var objs = placer.place(this.x, this.z, player, this.avoidSelf, constraint);
if (objs === undefined)
{ // Failure
return false;
}
else
{
for (var j = 0; j < objs.length; ++j)
{
resultObjs.push(objs[j]);
}
}
// Add placed objects to map
var length = resultObjs.length;
for (var i=0; i < length; i++)
{
g_Map.addObject(resultObjs[i]);
if (this.tileClass !== undefined)
{ // Round object position to integer
this.tileClass.add(Math.floor(resultObjs[i].tileX), Math.floor(resultObjs[i].tileZ));
}
}
return true;
};

View File

@ -1,3 +1,4 @@
// TODO: rename/change these functions, so the bounds are more clear
/*
* Return a random floating point number using Math.random library
@ -20,7 +21,7 @@ function randFloat()
}
else
{
error("randFloat() received invalid number of arguments: "+arguments.length);
error("randFloat: invalid number of arguments: "+arguments.length);
return undefined;
}
}
@ -47,7 +48,7 @@ function randInt()
}
else
{
error("randInt() received invalid number of arguments: "+arguments.length);
error("randInt: invalid number of arguments: "+arguments.length);
return undefined;
}
}

View File

@ -32,7 +32,7 @@ function SimpleTerrain(texture, treeType)
{
if (texture === undefined)
{
error("SimpleTerrain: texture not defined");
throw("SimpleTerrain: texture not defined");
}
this.texture = texture;
@ -64,7 +64,7 @@ function RandomTerrain(terrains)
{
if (!(terrains instanceof Array) || !terrains.length)
{
error("Invalid terrains array");
throw("RandomTerrain: Invalid terrains array");
}
this.terrains = terrains;