1
0
forked from 0ad/0ad
This was SVN commit r12248.
This commit is contained in:
wraitii 2012-07-31 15:59:36 +00:00
parent 8074f18d6d
commit a796800bb1
4 changed files with 924 additions and 1 deletions

Binary file not shown.

View File

@ -2,7 +2,7 @@
"settings" : {
"Name" : "Corsica vs Sardinia",
"Script" : "corsica.js",
"Description" : "The players start on two opposing islands, both with a very jagged relief that will make landing difficult.\n\nThe small and very mountainous island of Corsica has made it a disputed and undisputedly hard to conquer island. Originally occupied by the Torreans, it was later settled by Etruscans, Phocaeans and Syracusans who mainly established ports. Conquered by Carthage, it was taken from them during the first punic war and united in 238 BC with Sardinia to form the \"Corsica et Sardinia\" province. The Corsicans regularly revolted and over the course of a century, the island lost two thirds of its Corsican population.",
"Description" : "The players start on two opposing islands, both with a very jagged relief that will make landing difficult.\n\n\nCorsica is an island in the Mediterranean Sea. It is located west of Italy, southeast of the French mainland, and north of the island of Sardinia. Mountains comprise two-thirds of the island, forming a single chain. Sardinia is the second-largest island in the Mediterranean Sea (after Sicily and before Cyprus). Originally occupied by the Torreans, then marginally settled by Etruscans, Phocaeans and Syracusans. Rome conquered these two islands from Carthage during the first punic war and in 238 BC created the \"Corsica et Sardinia\" province. The Corsicans regularly revolted and over the course of a century, the island lost two thirds of its Corsican population.",
"BaseTerrain" : ["medit_dirt", "medit_dirt_b", "medit_dirt_c"],
"BaseHeight" : -8,
"Keywords": ["naval"],

View File

@ -0,0 +1,908 @@
RMS.LoadLibrary("rmgen");
// Some functions
// This is the basic SmoothElevationPainter with a random component thrown in.
function SemiRandomElevationPainter(elevation, blendRadius,roughness)
{
this.elevation = elevation;
this.blendRadius = blendRadius;
if (!roughness)
this.roughness = 5;
else
this.roughness = roughness;
}
SemiRandomElevationPainter.prototype.checkInArea = function(areaID, x, z)
{
// 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)
);
};
SemiRandomElevationPainter.prototype.paint = function(area)
{
var pointQ = [];
var pts = area.points;
var heightPts = [];
var mapSize = getMapSize()+1;
var saw = new Array(mapSize);
var dist = new Array(mapSize);
var gotHeightPt = new Array(mapSize);
var newHeight = new Array(mapSize);
// init typed arrays
for (var i = 0; i < mapSize; ++i)
{
saw[i] = new Uint8Array(mapSize); // bool / uint8
dist[i] = new Uint16Array(mapSize); // uint16
gotHeightPt[i] = new Uint8Array(mapSize); // bool / uint8
newHeight[i] = new Float32Array(mapSize); // float32
}
var length = pts.length;
var areaID = area.getID();
// get a list of all points
for (var i=0; i < length; i++)
{
var x = pts[i].x;
var z = pts[i].z;
for (var dx=-1; dx <= 2; dx++)
{
var nx = x+dx;
for (var dz=-1; dz <= 2; dz++)
{
var nz = z+dz;
if (g_Map.validH(nx, nz) && !gotHeightPt[nx][nz])
{
gotHeightPt[nx][nz] = 1;
heightPts.push(new PointXZ(nx, nz));
newHeight[nx][nz] = g_Map.height[nx][nz];
}
}
}
}
// push edge points
for (var i=0; i < length; i++)
{
var x = pts[i].x;
var z = pts[i].z;
for (var dx=-1; dx <= 2; dx++)
{
var nx = x+dx;
for (var dz=-1; dz <= 2; dz++)
{
var nz = z+dz;
if (g_Map.validH(nx, nz) && !this.checkInArea(areaID, nx, nz) && !saw[nx][nz])
{
saw[nx][nz]= 1;
dist[nx][nz] = 0;
pointQ.push(new PointXZ(nx, nz));
}
}
}
}
// do BFS inwards to find distances to edge
while(pointQ.length)
{
var pt = pointQ.shift();
var px = pt.x;
var pz = pt.z;
var d = dist[px][pz];
// paint if in area
if (g_Map.validH(px, pz) && this.checkInArea(areaID, px, pz))
{
if (d <= this.blendRadius)
{
var a = (d-1) / this.blendRadius;
newHeight[px][pz] += a*this.elevation + randFloat(-this.roughness,this.roughness);
}
else
{ // also happens when blendRadius == 0
newHeight[px][pz] += this.elevation + randFloat(-this.roughness,this.roughness);
}
}
// enqueue neighbours
for (var dx=-1; dx <= 1; dx++)
{
var nx = px+dx;
for (var dz=-1; dz <= 1; dz++)
{
var nz = pz+dz;
if (g_Map.validH(nx, nz) && this.checkInArea(areaID, nx, nz) && !saw[nx][nz])
{
saw[nx][nz] = 1;
dist[nx][nz] = d+1;
pointQ.push(new PointXZ(nx, nz));
}
}
}
}
length = heightPts.length;
// smooth everything out
for (var i = 0; i < length; ++i)
{
var pt = heightPts[i];
var px = pt.x;
var pz = pt.z;
if (this.checkInArea(areaID, px, pz))
{
var sum = 8 * newHeight[px][pz];
var count = 8;
for (var dx=-1; dx <= 1; dx++)
{
var nx = px+dx;
for (var dz=-1; dz <= 1; dz++)
{
var nz = pz+dz;
if (g_Map.validH(nx, nz))
{
sum += newHeight[nx][nz];
count++;
}
}
}
g_Map.height[px][pz] = sum/count;
}
}
};
TILE_CENTERED_HEIGHT_MAP = true;
var tGrassSpecific = ["new_alpine_grass_d","new_alpine_grass_d", "new_alpine_grass_e"];
var tGrass = ["new_alpine_grass_d", "new_alpine_grass_b", "new_alpine_grass_e"];
var tGrassMidRange = ["new_alpine_grass_b", "alpine_grass_a"];
var tGrassHighRange = ["new_alpine_grass_a", "alpine_grass_a", "alpine_grass_rocky"];
var tHighRocks = ["alpine_cliff_b", "alpine_cliff_c","alpine_cliff_c", "alpine_grass_rocky"];
var tSnowedRocks = ["alpine_cliff_b", "alpine_cliff_snow"];
var tTopSnow = ["alpine_snow_rocky","alpine_snow_a"];
var tTopSnowOnly = ["alpine_snow_a"];
var tDirtyGrass = ["new_alpine_grass_d","alpine_grass_d","alpine_grass_c", "alpine_grass_b"];
var tLushGrass = ["new_alpine_grass_a","new_alpine_grass_d"];
var tMidRangeCliffs = ["alpine_cliff_b","alpine_cliff_c"];
var tHighRangeCliffs = ["alpine_mountainside","alpine_cliff_snow" ];
var tPass = ["alpine_cliff_b", "alpine_cliff_c", "alpine_grass_rocky", "alpine_grass_rocky", "alpine_grass_rocky"];
var tSand = ["beach_c", "beach_d"];
var tWetSand = ["sand_wet_a", "sand_wet_b"];
var tSandTransition = ["beach_scrub_50_"];
var tWater = ["sand_wet_a","sand_wet_b","sand_wet_b","sand_wet_b"];
var tGrassLandForest = "alpine_forrestfloor";
var tGrassLandForest2 = "alpine_grass_d";
var tForestTransition = ["new_alpine_grass_d", "new_alpine_grass_b","alpine_grass_d"];
var tGrassDForest = "alpine_forrestfloor_snow";
var tCliff = ["alpine_cliff_a", "alpine_cliff_b"];
var tGrassA = "alpine_grass_snow_50";
var tGrassB = ["alpine_grass_snow_50", "alpine_dirt_snow"];
var tGrassC = ["alpine_snow_rocky"];
var tDirt = ["alpine_dirt_snow", "alpine_snow_a"];
var tRoad = "new_alpine_citytile";
var tRoadWild = "new_alpine_citytile";
var tShore = "alpine_shore_rocks_icy";
// gaia entities
var oBeech = "gaia/flora_tree_euro_beech";
var oPine = "gaia/flora_tree_aleppo_pine";
var oBerryBush = "gaia/flora_bush_berry";
var oChicken = "gaia/fauna_chicken";
var oDeer = "gaia/fauna_deer";
var oGoat = "gaia/fauna_goat";
var oFish = "gaia/fauna_fish";
var oRabbit = "gaia/fauna_rabbit";
var oStoneLarge = "gaia/geology_stonemine_alpine_quarry";
var oStoneSmall = "gaia/geology_stone_alpine_a";
var oMetalLarge = "gaia/geology_metal_alpine_slabs";
// decorative props
var aRain = "actor|particle/rain_shower.xml";
var aGrass = "actor|props/flora/grass_soft_small_tall.xml";
var aGrassShort = "actor|props/flora/grass_soft_large.xml";
var aRockLarge = "actor|geology/stone_granite_med.xml";
var aRockMedium = "actor|geology/stone_granite_med.xml";
var aReeds = "actor|props/flora/reeds_pond_lush_a.xml";
var aLillies = "actor|props/flora/water_lillies.xml";
var aBushMedium = "actor|props/flora/bush_medit_me.xml";
var aBushSmall = "actor|props/flora/bush_medit_sm.xml";
var pForestLand = [tGrassLandForest + TERRAIN_SEPARATOR + oPine,tGrassLandForest + TERRAIN_SEPARATOR + oBeech,
tGrassLandForest2 + TERRAIN_SEPARATOR + oPine,tGrassLandForest2 + TERRAIN_SEPARATOR + oBeech,
tGrassLandForest,tGrassLandForest2,tGrassLandForest2,tGrassLandForest2];
var pForestLandLight = [tGrassLandForest + TERRAIN_SEPARATOR + oPine,tGrassLandForest + TERRAIN_SEPARATOR + oBeech,
tGrassLandForest2 + TERRAIN_SEPARATOR + oPine,tGrassLandForest2 + TERRAIN_SEPARATOR + oBeech,
tGrassLandForest,tGrassLandForest2,tForestTransition,tGrassLandForest2,
tGrassLandForest,tForestTransition,tGrassLandForest2,tForestTransition,
tGrassLandForest2,tGrassLandForest2,tGrassLandForest2,tGrassLandForest2];
var pForestLandVeryLight = [ tGrassLandForest2 + TERRAIN_SEPARATOR + oPine,tGrassLandForest2 + TERRAIN_SEPARATOR + oBeech,
tForestTransition,tGrassLandForest2,tForestTransition,tForestTransition,tForestTransition,
tGrassLandForest,tForestTransition,tGrassLandForest2,tForestTransition,
tGrassLandForest2,tGrassLandForest2,tGrassLandForest2,tGrassLandForest2];
const BUILDING_ANGlE = -PI/4;
// initialize map
log("Initializing map...");
InitMap();
var numPlayers = getNumPlayers();
var mapSize = getMapSize();
var mapArea = mapSize*mapSize;
// create tile classes
var clDirt = createTileClass();
var clLush = createTileClass();
var clRock = createTileClass();
var clMetal = createTileClass();
var clFood = createTileClass();
var clBaseResource = createTileClass();
var clSettlement = createTileClass();
var clPass = createTileClass();
var clPyrenneans = createTileClass();
var clPass = createTileClass();
var clPlayer = createTileClass();
var clHill = createTileClass();
var clForest = createTileClass();
var clWater = createTileClass();
// Initial Terrain Creation
// I'll use very basic noised sinusoidal functions to give the terrain a way aspect
// It looks like we can't go higher than ≈ 75. Given this I'll lower the ground
var baseHeight = -6;
setWaterHeight(8);
// let's choose the angle of the pyreneans
var MoutainAngle = randFloat(0,TWO_PI);
var lololo = randFloat(-PI/12,-PI/12); // used by oceans
var baseHeights = [];
for (var ix = 0; ix < mapSize; ix++)
{
baseHeights.push([]);
for (var iz = 0; iz < mapSize; iz++)
{
if (g_Map.validT(ix,iz) && !checkIfInClass(ix,iz,clWater)) {
placeTerrain(ix, iz, tGrass);
setHeight(ix,iz,baseHeight +randFloat(-1,1) + scaleByMapSize(1,3)*(cos(ix/scaleByMapSize(5,30))+sin(iz/scaleByMapSize(5,30))));
baseHeights[ix].push( baseHeight +randFloat(-1,1) + scaleByMapSize(1,3)*(cos(ix/scaleByMapSize(5,30))+sin(iz/scaleByMapSize(5,30))) );
} else
baseHeights[ix].push(-100);
}
}
// randomize player order
var playerIDs = [];
for (var i = 0; i < numPlayers; i++)
{
playerIDs.push(i+1);
}
playerIDs = primeSortPlayers(sortPlayers(playerIDs));
// place players
// TODO: sort players by team
var playerX = new Array(numPlayers);
var playerZ = new Array(numPlayers);
var playerAngle = new Array(numPlayers);
for (var i = 0; i < numPlayers; i++)
{
if ( i%2 == 1)
playerAngle[i] = MoutainAngle+lololo + PI/2 + i/numPlayers*(PI/3) + (1-i/numPlayers)*(-PI/3);
else
playerAngle[i] = MoutainAngle + lololo - PI/2 + (i+1)/numPlayers*(PI/3) + (1-(i+1)/numPlayers)*(-PI/3);
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++)
{
var id = playerIDs[i];
log("Creating base for player " + id + "...");
// some constants
var radius = scaleByMapSize(15,25);
var cliffRadius = 2;
var elevation = 20;
// get the x and z in tiles
var fx = fractionToTiles(playerX[i]);
var fz = fractionToTiles(playerZ[i]);
ix = round(fx);
iz = round(fz);
addToClass(ix, iz, clPlayer);
addToClass(ix+5, iz, clPlayer);
addToClass(ix, iz+5, clPlayer);
addToClass(ix-5, iz, clPlayer);
addToClass(ix, iz-5, clPlayer);
// create the city patch
var cityRadius = radius/3;
var placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
var painter = new LayeredPainter([tRoadWild, tRoad], [1]);
createArea(placer, painter, null);
// create starting units
placeCivDefaultEntities(fx, fz, id, BUILDING_ANGlE);
// 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));
var group = new SimpleGroup(
[new SimpleObject(oChicken, 5,5, 0,3)],
true, clBaseResource, aX, aZ
);
createObjectGroup(group, 0);
}
// create berry bushes
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,3)],
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 = 12;
var mX = round(fx + mDist * cos(mAngle));
var mZ = round(fz + mDist * sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oMetalLarge, 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(oStoneLarge, 1,1, 0,2)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
var hillSize = PI * radius * radius;
// create starting trees
var num = floor(hillSize / 100);
var tAngle = randFloat(-PI/3, 4*PI/3);
var tDist = randFloat(11, 13);
var tX = round(fx + tDist * cos(tAngle));
var tZ = round(fz + tDist * sin(tAngle));
group = new SimpleGroup(
[new SimpleObject(oPine, num, num, 0,5)],
false, clBaseResource, tX, tZ
);
createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
// create grass tufts
var num = hillSize / 250;
for (var j = 0; j < num; j++)
{
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, 0);
}
}
RMS.SetProgress(30);
log ("Creating the pyreneans...");
// This is the basic orientation of the pyreneans
var MountainStartX = fractionToTiles(0.5) + cos(MoutainAngle)*fractionToTiles(0.34);
var MountainStartZ = fractionToTiles(0.5) + sin(MoutainAngle)*fractionToTiles(0.34);
var MountainEndX = fractionToTiles(0.5) - cos(MoutainAngle)*fractionToTiles(0.34);
var MountainEndZ = fractionToTiles(0.5) - sin(MoutainAngle)*fractionToTiles(0.34);
var MountainHeight = scaleByMapSize(50,65);
// Number of peaks
var NumOfIterations = scaleByMapSize(100,1000);
var randomNess = randFloat(-scaleByMapSize(1,12),scaleByMapSize(1,12));
for (var i = 0; i < NumOfIterations; i++)
{
RMS.SetProgress(45 * i/NumOfIterations + 30 * (1-i/NumOfIterations));
var position = i/NumOfIterations;
var width = scaleByMapSize(15,55);
var randHeight2 = randFloat(0,10) + MountainHeight;
for (var dist = 0; dist < width*3; dist++)
{
var okDist = dist/3;
var S1x = round((MountainStartX * (1-position) + MountainEndX*position) + randomNess*cos(position*3.14*4) + cos(MoutainAngle+PI/2)*okDist);
var S1z = round((MountainStartZ * (1-position) + MountainEndZ*position) + randomNess*sin(position*3.14*4) + sin(MoutainAngle+PI/2)*okDist);
var S2x = round((MountainStartX * (1-position) + MountainEndX*position) + randomNess*cos(position*3.14*4) + cos(MoutainAngle-PI/2)*okDist);
var S2z = round((MountainStartZ * (1-position) + MountainEndZ*position) + randomNess*sin(position*3.14*4) + sin(MoutainAngle-PI/2)*okDist);
// complicated sigmoid
// Ranges is 0-1, FormX is 0-1 too.
var FormX = (-2*(1-okDist/width)+1.9) - 4*(2*(1-okDist/width)-randFloat(0.9,1.1))*(2*(1-okDist/width)-randFloat(0.9,1.1))*(2*(1-okDist/width)-randFloat(0.9,1.1));
var Formula = (1/(1 + Math.exp(FormX)));
// If we're too far from the border, we flatten
Formula *= (0.2 - Math.max(0,abs(0.5 - position) - 0.3)) * 5;
var randHeight = randFloat(-9,9) * Formula;
var height = baseHeights[S1x][S1z];
setHeight(S1x,S1z, height + randHeight2 * Formula + randHeight );
var height = baseHeights[S2x][S2z];
setHeight(S2x,S2z, height + randHeight2 * Formula + randHeight );
if (getHeight(S1x,S1z) > 15)
addToClass(S1x,S1z, clPyrenneans);
if (getHeight(S2x,S2z) > 15)
addToClass(S2x,S2z, clPyrenneans);
}
}
// Allright now slight smoothing (decreasing with height)
for (var ix = 1; ix < mapSize-1; ix++)
{
for (var iz = 1; iz < mapSize-1; iz++)
{
if (g_Map.validT(ix,iz) && checkIfInClass(ix,iz,clPyrenneans) ) {
var NB = getNeighborsHeight(ix,iz);
var index = 9/(1 + Math.max(0,getHeight(ix,iz)/7));
setHeight(ix,iz, (getHeight(ix,iz)*(9-index) + NB*index)/9 );
}
}
}
RMS.SetProgress(48);
// Okay so the mountains are pretty much here.
// Making the passes
var passWidth = scaleByMapSize(15,100) /1.8;
var S1x = round((MountainStartX * (0.35) + MountainEndX*0.65) + cos(MoutainAngle+PI/2)*passWidth);
var S1z = round((MountainStartZ * (0.35) + MountainEndZ*0.65) + sin(MoutainAngle+PI/2)*passWidth);
var S2x = round((MountainStartX * (0.35) + MountainEndX*0.65) + cos(MoutainAngle-PI/2)*passWidth);
var S2z = round((MountainStartZ * (0.35) + MountainEndZ*0.65) + sin(MoutainAngle-PI/2)*passWidth);
PassMaker(S1x, S1z, S2x, S2z, 4, 7, (getHeight(S1x,S1z) + getHeight(S2x,S2z))/2.0, MountainHeight-25, 2, clPass);
S1x = round((MountainStartX * (0.65) + MountainEndX*0.35) + cos(MoutainAngle+PI/2)*passWidth);
S1z = round((MountainStartZ * (0.65) + MountainEndZ*0.35) + sin(MoutainAngle+PI/2)*passWidth);
S2x = round((MountainStartX * (0.65) + MountainEndX*0.35) + cos(MoutainAngle-PI/2)*passWidth);
S2z = round((MountainStartZ * (0.65) + MountainEndZ*0.35) + sin(MoutainAngle-PI/2)*passWidth);
PassMaker(S1x, S1z, S2x, S2z, 4, 7, (getHeight(S1x,S1z) + getHeight(S2x,S2z))/2.0, MountainHeight-25, 2, clPass);
RMS.SetProgress(50);
// Smoothing the mountains
for (var ix = 1; ix < mapSize-1; ix++)
{
for (var iz = 1; iz < mapSize-1; iz++)
{
if ( g_Map.validT(ix,iz) && checkIfInClass(ix,iz,clPyrenneans) ) {
var NB = getNeighborsHeight(ix,iz);
var index = 9/(1 + Math.max(0,(getHeight(ix,iz)-10)/7));
setHeight(ix,iz, (getHeight(ix,iz)*(9-index) + NB*index)/9 );
baseHeights[ix][iz] = (getHeight(ix,iz)*(9-index) + NB*index)/9;
}
}
}
log ("creating Oceans");
// ALlright for hacky reasons I can't use a smooth Elevation Painter, that wouldn't work.
// I'll use a harsh one, and then smooth it out
var OceanX = fractionToTiles(0.5) + cos(MoutainAngle + lololo)*fractionToTiles(0.48);
var OceanZ = fractionToTiles(0.5) + sin(MoutainAngle + lololo)*fractionToTiles(0.48);
var radius = fractionToTiles(0.18);
var size = radius*radius*PI;
var placer = new ClumpPlacer(size, 0.9, 0.05, 10, OceanX, OceanZ);
var elevationPainter = new ElevationPainter(-22);
createArea(placer, [paintClass(clWater),elevationPainter], null);
OceanX = fractionToTiles(0.5) + cos(PI + MoutainAngle + lololo)*fractionToTiles(0.48);
OceanZ = fractionToTiles(0.5) + sin(PI + MoutainAngle + lololo)*fractionToTiles(0.48);
radius = fractionToTiles(0.18);
size = radius*radius*PI;
placer = new ClumpPlacer(size, 0.9, 0.05, 10, OceanX, OceanZ);
elevationPainter = new ElevationPainter(-22);
createArea(placer, [paintClass(clWater),elevationPainter], null);
// Smoothing around the water, then going a bit random
for (var ix = 1; ix < mapSize-1; ix++)
{
for (var iz = 1; iz < mapSize-1; iz++)
{
if ( g_Map.validT(ix,iz) && getTileClass(clWater).countInRadius(ix,iz,5,true) > 0 ) {
// Allright smoothing
// I'll have to hack again.
var averageHeight = 0;
var size = 5;
if (getTileClass(clPyrenneans).countInRadius(ix,iz,1,true) > 0)
size = 1;
else if (getTileClass(clPyrenneans).countInRadius(ix,iz,2,true) > 0)
size = 2;
else if (getTileClass(clPyrenneans).countInRadius(ix,iz,3,true) > 0)
size = 3;
else if (getTileClass(clPyrenneans).countInRadius(ix,iz,4,true) > 0)
size = 4;
var todivide = 0;
for (var xx = -size; xx <= size;xx++)
for (var yy = -size; yy <= size;yy++) {
if (g_Map.validT(ix + xx,iz + yy) && (xx != 0 || yy != 0)){
averageHeight += getHeight(ix + xx,iz + yy) / (abs(xx)+abs(yy));
todivide += 1/(abs(xx)+abs(yy));
}
}
averageHeight += getHeight(ix,iz)*2;
averageHeight /= (todivide+2);
setHeight(ix,iz, averageHeight );
//baseHeights[ix][iz] = averageHeight;
}
if ( g_Map.validT(ix,iz) && getTileClass(clWater).countInRadius(ix,iz,4,true) > 0 && getTileClass(clWater).countInRadius(ix,iz,4) > 0 )
setHeight(ix,iz, getHeight(ix,iz) + randFloat(-1,1));
}
}
RMS.SetProgress(55);
//create hills
log ("Creating hills...");
placer = new ClumpPlacer(scaleByMapSize(60, 120), 0.3, 0.06, 5);
painter = new SemiRandomElevationPainter(7, 4,1);
var terrainPainter = new TerrainPainter(tGrassSpecific);
createAreas( placer, [painter,terrainPainter, paintClass(clHill)], avoidClasses(clWater, 5, clPlayer, 10, clBaseResource, 6, clPyrenneans, 2), scaleByMapSize(5, 35) );
// create forests
log("Creating forests...");
var types = [ [tForestTransition,pForestLandVeryLight, pForestLandLight, pForestLand]];
var size = scaleByMapSize(40,115)*PI;
var num = floor(scaleByMapSize(8,40) / types.length);
for (var i = 0; i < types.length; ++i)
{
placer = new ClumpPlacer(size, 0.2, 0.1, 1);
painter = new LayeredPainter( types[i], [scaleByMapSize(1,2),scaleByMapSize(3,6),scaleByMapSize(3,6)] );
createAreas( placer, [painter, paintClass(clForest)], avoidClasses(clPlayer, 12, clPyrenneans,0, clForest, 7, clWater, 2), num);
}
RMS.SetProgress(60);
log("Creating lone trees...");
var num = scaleByMapSize(80,400);
var group = new SimpleGroup([new SimpleObject(oPine, 1,2, 1,3),new SimpleObject(oBeech, 1,2, 1,3)], true, clForest);
createObjectGroups(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 8,clPyrenneans, 1), num, 20 );
// Painting
log("Painting the map");
var terrainGrass = createTerrain(tGrass);
var terrainGrassMidRange = createTerrain(tGrassMidRange);
var terrainGrassHighRange = createTerrain(tGrassHighRange);
var terrainRocks = createTerrain(tHighRocks);
var terrainRocksSnow = createTerrain(tSnowedRocks);
var terrainTopSnow = createTerrain(tTopSnow);
var terrainTopSnowOnly = createTerrain(tTopSnowOnly);
var terrainMidRangeCliff = createTerrain(tMidRangeCliffs);
var terrainHighRangeCliff = createTerrain(tHighRangeCliffs);
var terrainPass = createTerrain(tPass);
var terrainSand = createTerrain(tSand);
var terrainWetSand = createTerrain(tWetSand);
var terrainSandTransition = createTerrain(tSandTransition);
var terrainWater = createTerrain(tWater);
/*
// first pass: who's water?
for (var sandx = 0; sandx < mapSize; sandx++)
for (var sandz = 0; sandz < mapSize; sandz++)
if (getHeight(sandx,sandz) < 0)
addToClass(sandx,sandz,clWater);
*/
// second pass: who's not water
for (var x = 0; x < mapSize; x++) {
for (var z = 0; z < mapSize; z++) {
var height = getHeight(x,z);
var heightDiff = getHeightDifference(x,z);
if (getTileClass(clPyrenneans).countInRadius(x,z,2,true) > 0) {
if (height < 6) {
if (heightDiff < 5)
terrainGrass.place(x,z);
else
terrainMidRangeCliff.place(x,z);
} else if (height >= 6 && height < 18) {
if (heightDiff < 8)
terrainGrassMidRange.place(x,z);
else
terrainMidRangeCliff.place(x,z);
} else if (height >= 18 && height < 30) {
if (heightDiff < 8)
terrainGrassHighRange.place(x,z);
else
terrainMidRangeCliff.place(x,z);
} else if (height >= 30 && height < MountainHeight-20) {
if (heightDiff < 8)
terrainRocks.place(x,z);
else
terrainHighRangeCliff.place(x,z);
} else if (height >= MountainHeight-20 && height < MountainHeight-10) {
if (heightDiff < 7)
terrainRocksSnow.place(x,z);
else
terrainHighRangeCliff.place(x,z);
} else if (height >= MountainHeight-10) {
if (heightDiff < 6)
terrainTopSnowOnly.place(x,z);
else
terrainTopSnow.place(x,z);
}
if (height >= 30 && getTileClass(clPass).countInRadius(x,z,2,true) > 0)
if (heightDiff < 5)
terrainPass.place(x,z);
}
if (height > -14 && height <= -2 && getTileClass(clWater).countInRadius(x,z,2,true) > 0) {
if (heightDiff < 2.5)
terrainSand.place(x,z);
else
terrainMidRangeCliff.place(x,z);
} else if (height > -14 && height <= 0 && getTileClass(clWater).countInRadius(x,z,3,true) > 0) {
if (heightDiff < 2.5)
terrainSandTransition.place(x,z);
else
terrainMidRangeCliff.place(x,z);
} else if (height <= -14) {
terrainWater.place(x,z);
}
}
}
// create dirt patches
log("Creating dirt patches...");
var sizes = [scaleByMapSize(3, 20), scaleByMapSize(5, 40), scaleByMapSize(8, 60)];
for (var i = 0; i < sizes.length; i++)
{
placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0.5);
painter = new TerrainPainter(tDirtyGrass);
createAreas( placer, [painter, paintClass(clDirt)], avoidClasses(clWater, 3, clForest, 0, clPyrenneans,5, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45) );
}
// create grass patches
log("Creating grass patches...");
var sizes = [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)];
for (var i = 0; i < sizes.length; i++)
{
placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0.5);
painter = new TerrainPainter(tLushGrass);
createAreas( placer, [painter,paintClass(clLush)], avoidClasses(clWater, 3, clForest, 0, clPyrenneans,5, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45) );
}
RMS.SetProgress(70);
// making more in dirt areas so as to appear different
log("Creating small grass tufts...");
var group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -PI/8,PI/8)] );
createObjectGroups(group, 0, avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0, clPyrenneans,2), scaleByMapSize(13, 200) );
createObjectGroups(group, 0, stayClasses(clDirt,1), scaleByMapSize(13, 200),10);
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, 0, avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0, clPyrenneans,2), scaleByMapSize(13, 200) );
createObjectGroups(group, 0, stayClasses(clDirt,1), scaleByMapSize(13, 200),10);
RMS.SetProgress(75);
// create bushes
log("Creating bushes...");
group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] );
createObjectGroups(group, 0, avoidClasses(clWater, 2, clPlayer, 1, clPyrenneans, 1), scaleByMapSize(13, 200), 50 );
RMS.SetProgress(80);
log("Creating stone mines...");
// create large stone quarries
group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock);
createObjectGroups(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 10, clRock, 8, clPyrenneans, 1), scaleByMapSize(4,16), 100 );
// create small stone quarries
group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock);
createObjectGroups(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 10, clRock, 8, clPyrenneans, 1), scaleByMapSize(4,16), 100 );
log("Creating metal mines...");
group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal);
createObjectGroups(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 10, clMetal, 8, clRock, 5, clPyrenneans, 1), scaleByMapSize(4,16), 100 );
RMS.SetProgress(85);
log("Creating small decorative rocks...");
group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true );
createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0), scaleByMapSize(16, 262), 50 );
log("Creating large decorative rocks...");
group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true );
createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0), scaleByMapSize(8, 131), 50 );
RMS.SetProgress(90);
log("Creating deer...");
group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood );
createObjectGroups(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 10, clPyrenneans, 1, clFood, 15), 3 * numPlayers, 50 );
log("Creating rabbit...");
group = new SimpleGroup( [new SimpleObject(oRabbit, 2,3, 0,2)], true, clFood );
createObjectGroups(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 10, clPyrenneans, 1, clFood,15), 3 * numPlayers, 50 );
log("Creating fish...");
group = new SimpleGroup( [new SimpleObject(oFish, 2,3, 0,2)], true, clFood );
createObjectGroups(group, 0, [avoidClasses(clFood, 15), stayClasses(clWater, 6)], 20 * numPlayers, 60 );
setSunElevation(randFloat(PI/5, PI / 3));
setSunRotation(randFloat(0, TWO_PI));
setWaterTint(0.1, 0.1, 0.3); // muddy brown
setWaterReflectionTint(0.2, 0.2, 0.5); // muddy brown
setWaterMurkiness(0.8);
setWaterReflectionTintStrength(0.3);
//var rt = randInt(1,6);
//if (rt==1){
// setSkySet("stormy");
// setSunColour(0.36,0.38,0.45);
// setTerrainAmbientColour(0.52,0.575,0.6);
// setUnitsAmbientColour(0.52,0.575,0.6);
// setSunElevation(PI/7);
// setWaterTint(0.1, 0.1, 0.2); // muddy brown
//} else {
setSkySet("cumulus");
setSunColour(0.73,0.73,0.65);
setTerrainAmbientColour(0.45,0.45,0.50);
setUnitsAmbientColour(0.4,0.4,0.4);
setWaterTint(0.15, 0.15, 0.3); // muddy brown
setWaterReflectionTintStrength(0.15);
//}
// Export map data
ExportMap();
function getNeighborsHeight(x1, z1)
{
var toCheck = [ [-1,-1], [-1,0], [-1,1], [0,1], [1,1], [1,0], [1,-1], [0,-1] ];
var height = 0;
for (i in toCheck) {
var xx = x1 + toCheck[i][0];
var zz = z1 + toCheck[i][1];
height += getHeight(round(xx),round(zz));
}
height /= 8;
return height;
}
// Taken from Corsica vs Sardinia with tweaks
function PassMaker(x1, z1, x2, z2, startWidth, centerWidth, startElevation, centerElevation, smooth, tileclass, terrain)
{
var mapSize = g_Map.size;
var stepNB = sqrt((x2-x1)*(x2-x1) + (z2-z1)*(z2-z1)) + 2;
var startHeight = startElevation;
var finishHeight = centerElevation;
for (var step = 0; step <= stepNB; step+=0.5)
{
var ix = ((stepNB-step)*x1 + x2*step) / stepNB;
var iz = ((stepNB-step)*z1 + z2*step) / stepNB;
var width = (abs(step - stepNB/2.0) *startWidth + (stepNB/2 - abs(step - stepNB/2.0)) * centerWidth ) / (stepNB/2);
var oldDirection = [x2-x1, z2-z1];
// let's get the perpendicular direction
var direction = [ -oldDirection[1],oldDirection[0] ];
if (abs(direction[0]) > abs(direction[1]))
{
direction[1] = direction[1] / abs(direction[0]);
if (direction[0] > 0)
direction[0] = 1;
else
direction[0] = -1;
} else {
direction[0] = direction[0] / abs(direction[1]);
if (direction[1] > 0)
direction[1] = 1;
else
direction[1] = -1;
}
for (var po = -Math.floor(width/2.0); po <= Math.floor(width/2.0); po+=0.5)
{
var rx = po*direction[0];
var rz = po*direction[1];
var relativeWidth = abs(po / Math.floor(width/2));
var targetHeight = (abs(step - stepNB/2.0) *startHeight + (stepNB/2 - abs(step - stepNB/2.0)) * finishHeight ) / (stepNB/2);
if (round(ix + rx) < mapSize && round(iz + rz) < mapSize && round(ix + rx) >= 0 && round(iz + rz) >= 0)
{
// smoothing the sides
if ( abs(abs(po) - abs(Math.floor(width/2.0))) < smooth)
{
var localHeight = getHeight(round(ix + rx), round(iz + rz));
var localPart = smooth - abs(abs(po) - abs(Math.floor(width/2.0)));
var targetHeight = (localHeight * localPart + targetHeight * (1/localPart) )/ (localPart + 1/localPart);
}
g_Map.setHeight(round(ix + rx), round(iz + rz), targetHeight);
if (tileclass != null)
addToClass(round(ix + rx), round(iz + rz), tileclass);
if (terrain != null)
placeTerrain(round(ix + rx), round(iz + rz), terrain);
}
}
}
}
// no need for preliminary rounding
function getHeightDifference(x1, z1)
{
x1 = round(x1);
z1 = round(z1);
var height = getHeight(x1,z1);
if (!g_Map.validT(x1,z1))
return 0;
// I wanna store the height difference with any neighbor
var toCheck = [ [-1,-1], [-1,0], [-1,1], [0,1], [1,1], [1,0], [1,-1], [0,-1] ];
var diff = 0;
var todiv = 0;
for (i in toCheck) {
var xx = round(x1 + toCheck[i][0]);
var zz = round(z1 + toCheck[i][1]);
if (g_Map.validT(xx,zz)) {
diff += abs(getHeight(xx,zz) - height);
todiv++;
}
}
if (todiv > 0)
diff /= todiv;
return diff;
}

View File

@ -0,0 +1,12 @@
{
"settings" : {
"Name" : "Pyrenean Sierra",
"Script" : "pyrenean_sierra.js",
"Description" : "High mountains separating the enemies.\n\n\nThe Pyreneans is a great mountain range located between modern France and Spain.",
"BaseTerrain" : ["alpine_dirt_grass_50"],
"BaseHeight" : -100,
"Preview" : "pyrenean_sierra.png",
"CircularMap" : true,
"XXXXXX" : "Optionally define other things here, like we would for a scenario"
}
}