Simplifies random map output, see #782.
Changes random maps to XZ coordinates, matching the engine. More documentation for rmgen library. This was SVN commit r9271.
This commit is contained in:
parent
3adba8721a
commit
b4503bb61e
@ -2,7 +2,7 @@
|
||||
// Constants
|
||||
// TODO: Move some of these into common location (other scripts may need)
|
||||
const MAP_SIZES_TEXT = ["Tiny (2 player)", "Small (3 player)", "Medium (4 player)", "Normal (6 player)", "Large (8 player)", "Very Large", "Giant"];
|
||||
const MAP_SIZES_DATA = [8, 12, 16, 20, 24, 28, 32];
|
||||
const MAP_SIZES_DATA = [128, 192, 256, 320, 384, 448, 512];
|
||||
|
||||
// Max number of players for any map
|
||||
const MAX_PLAYERS = 8;
|
||||
@ -28,7 +28,7 @@ var g_GameAttributes = {
|
||||
map: "",
|
||||
mapPath: "",
|
||||
settings: {
|
||||
Size: 12,
|
||||
Size: 192,
|
||||
Seed: 0,
|
||||
BaseTerrain: "grass1_spring",
|
||||
BaseHeight: 0,
|
||||
|
@ -60,7 +60,7 @@ var clSettlement = createTileClass();
|
||||
// place players
|
||||
|
||||
var playerX = new Array(numPlayers+1);
|
||||
var playerY = new Array(numPlayers+1);
|
||||
var playerZ = new Array(numPlayers+1);
|
||||
var playerAngle = new Array(numPlayers+1);
|
||||
|
||||
var startAngle = randFloat() * 2 * PI;
|
||||
@ -68,7 +68,7 @@ for (var i=1; i<=numPlayers; i++)
|
||||
{
|
||||
playerAngle[i] = startAngle + i*2*PI/numPlayers;
|
||||
playerX[i] = 0.5 + 0.35*cos(playerAngle[i]);
|
||||
playerY[i] = 0.5 + 0.35*sin(playerAngle[i]);
|
||||
playerZ[i] = 0.5 + 0.35*sin(playerAngle[i]);
|
||||
}
|
||||
|
||||
for (var i=1; i<=numPlayers; i++)
|
||||
@ -82,15 +82,15 @@ for (var i=1; i<=numPlayers; i++)
|
||||
|
||||
// get the x and y in tiles
|
||||
var fx = fractionToTiles(playerX[i]);
|
||||
var fy = fractionToTiles(playerY[i]);
|
||||
var fz = fractionToTiles(playerZ[i]);
|
||||
var ix = round(fx);
|
||||
var iy = round(fy);
|
||||
var iz = round(fz);
|
||||
|
||||
// calculate size based on the radius
|
||||
var size = PI * radius * radius;
|
||||
|
||||
// create the hill
|
||||
var placer = new ClumpPlacer(size, 0.95, 0.6, 0, ix, iy);
|
||||
var placer = new ClumpPlacer(size, 0.95, 0.6, 0, ix, iz);
|
||||
var terrainPainter = new LayeredPainter(
|
||||
[tCliff, tGrass], // terrains
|
||||
[cliffRadius] // widths
|
||||
@ -106,16 +106,16 @@ for (var i=1; i<=numPlayers; i++)
|
||||
var rampAngle = playerAngle[i] + PI + (2*randFloat()-1)*PI/8;
|
||||
var rampDist = radius;
|
||||
var rampX = round(fx + rampDist * cos(rampAngle));
|
||||
var rampY = round(fy + rampDist * sin(rampAngle));
|
||||
placer = new ClumpPlacer(100, 0.9, 0.5, 0, rampX, rampY);
|
||||
var rampZ = round(fz + rampDist * sin(rampAngle));
|
||||
placer = new ClumpPlacer(100, 0.9, 0.5, 0, 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, rampY);
|
||||
placer = new ClumpPlacer(75, 0.9, 0.5, 0, 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, iy);
|
||||
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
|
||||
@ -126,7 +126,7 @@ for (var i=1; i<=numPlayers; i++)
|
||||
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), new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
|
||||
true, null, ix, iy
|
||||
true, null, ix, iz
|
||||
);
|
||||
createObjectGroup(group, i);
|
||||
|
||||
@ -134,10 +134,10 @@ for (var i=1; i<=numPlayers; i++)
|
||||
var bbAngle = randFloat()*2*PI;
|
||||
var bbDist = 9;
|
||||
var bbX = round(fx + bbDist * cos(bbAngle));
|
||||
var bbY = round(fy + bbDist * sin(bbAngle));
|
||||
var bbZ = round(fz + bbDist * sin(bbAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oBerryBush, 5,5, 0,2)],
|
||||
true, clBaseResource, bbX, bbY
|
||||
true, clBaseResource, bbX, bbZ
|
||||
);
|
||||
createObjectGroup(group, 0);
|
||||
|
||||
@ -149,18 +149,18 @@ for (var i=1; i<=numPlayers; i++)
|
||||
}
|
||||
var mDist = 9;
|
||||
var mX = round(fx + mDist * cos(mAngle));
|
||||
var mY = round(fy + mDist * sin(mAngle));
|
||||
var mZ = round(fz + mDist * sin(mAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oStone, 2,2, 0,3),
|
||||
new SimpleObject(oMetal, 2,2, 0,3)],
|
||||
true, clBaseResource, mX, mY
|
||||
true, clBaseResource, mX, mZ
|
||||
);
|
||||
createObjectGroup(group, 0);
|
||||
|
||||
// create starting straggler trees
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oTree, 3,3, 8,12)],
|
||||
true, clBaseResource, ix, iy
|
||||
true, clBaseResource, ix, iz
|
||||
);
|
||||
createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
|
||||
|
||||
@ -170,10 +170,10 @@ for (var i=1; i<=numPlayers; i++)
|
||||
var gAngle = randFloat()*2*PI;
|
||||
var gDist = 6 + randInt(9);
|
||||
var gX = round(fx + gDist * cos(gAngle));
|
||||
var gY = round(fy + gDist * sin(gAngle));
|
||||
var gZ = round(fz + gDist * sin(gAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aGrassShort, 3,6, 0,1, -PI/8,PI/8)],
|
||||
false, clBaseResource, gX, gY
|
||||
false, clBaseResource, gX, gZ
|
||||
);
|
||||
createObjectGroup(group, undefined);
|
||||
}
|
||||
|
@ -90,18 +90,18 @@ var clSettlement = createTileClass();
|
||||
log("Placing players...");
|
||||
|
||||
var playerX = new Array(numPlayers+1);
|
||||
var playerY = new Array(numPlayers+1);
|
||||
var playerZ = new Array(numPlayers+1);
|
||||
|
||||
var numLeftPlayers = ceil(numPlayers/2);
|
||||
for (var i=1; i <= numLeftPlayers; i++)
|
||||
{
|
||||
playerX[i] = 0.28 + (2*randFloat()-1)*0.01;
|
||||
playerY[i] = (0.5+i-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
|
||||
playerZ[i] = (0.5+i-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
|
||||
}
|
||||
for (var i=numLeftPlayers+1; i <= numPlayers; i++)
|
||||
{
|
||||
playerX[i] = 0.72 + (2*randFloat()-1)*0.01;
|
||||
playerY[i] = (0.5+i-numLeftPlayers-1)/numLeftPlayers + (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++)
|
||||
@ -110,16 +110,16 @@ for (var i=1; i <= numPlayers; i++)
|
||||
|
||||
// get fractional locations in tiles
|
||||
var ix = round(fractionToTiles(playerX[i]));
|
||||
var iy = round(fractionToTiles(playerY[i]));
|
||||
addToClass(ix, iy, clPlayer);
|
||||
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, iy, "structures/"+civ + "_civil_centre", i, PI*3/4);
|
||||
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, iy
|
||||
true, null, ix, iz
|
||||
);
|
||||
createObjectGroup(group, i);
|
||||
|
||||
@ -127,10 +127,10 @@ for (var i=1; i <= numPlayers; i++)
|
||||
var bbAngle = randFloat()*2*PI;
|
||||
var bbDist = 9;
|
||||
var bbX = round(ix + bbDist * cos(bbAngle));
|
||||
var bbY = round(iy + bbDist * sin(bbAngle));
|
||||
var bbZ = round(iz + bbDist * sin(bbAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oBerryBush, 5,5, 0,2)],
|
||||
true, clBaseResource, bbX, bbY
|
||||
true, clBaseResource, bbX, bbZ
|
||||
);
|
||||
createObjectGroup(group, 0);
|
||||
|
||||
@ -141,44 +141,50 @@ for (var i=1; i <= numPlayers; i++)
|
||||
}
|
||||
var mDist = 9;
|
||||
var mX = round(ix + mDist * cos(mAngle));
|
||||
var mY = round(iy + mDist * sin(mAngle));
|
||||
var mZ = round(iz + mDist * sin(mAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oStone, 2,2, 0,3),
|
||||
new SimpleObject(oMetal, 2,2, 0,3)],
|
||||
true, clBaseResource, mX, mY
|
||||
true, clBaseResource, mX, mZ
|
||||
);
|
||||
createObjectGroup(group, 0);
|
||||
|
||||
// create starting straggler trees
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oPalm, 3,3, 7,10)],
|
||||
true, clBaseResource, ix, iy
|
||||
true, clBaseResource, ix, iz
|
||||
);
|
||||
createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
|
||||
}
|
||||
|
||||
function distanceToPlayers(x, y)
|
||||
function distanceToPlayers(x, z)
|
||||
{
|
||||
var r = 10000;
|
||||
for (var i=1; i <= numPlayers; i++)
|
||||
{
|
||||
var dx = x - playerX[i];
|
||||
var dy = y - playerY[i];
|
||||
r = min(r, dx*dx + dy*dy);
|
||||
var dz = z - playerZ[i];
|
||||
r = min(r, dx*dx + dz*dz);
|
||||
}
|
||||
return sqrt(r);
|
||||
}
|
||||
|
||||
function playerNearness(x, y)
|
||||
function playerNearness(x, z)
|
||||
{
|
||||
var d = fractionToTiles(distanceToPlayers(x,y));
|
||||
var d = fractionToTiles(distanceToPlayers(x,z));
|
||||
|
||||
if (d < 13)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (d < 19)
|
||||
{
|
||||
return (d-13)/(19-13);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Paint elevation
|
||||
@ -198,11 +204,11 @@ var noise5 = new Noise2D(11 * mapSize/128);
|
||||
|
||||
for (var ix=0; ix<=mapSize; ix++)
|
||||
{
|
||||
for (var iy=0; iy<=mapSize; iy++)
|
||||
for (var iz=0; iz<=mapSize; iz++)
|
||||
{
|
||||
var x = ix / (mapSize + 1.0);
|
||||
var y = iy / (mapSize + 1.0);
|
||||
var pn = playerNearness(x, y);
|
||||
var z = iz / (mapSize + 1.0);
|
||||
var pn = playerNearness(x, z);
|
||||
|
||||
var h = 0;
|
||||
var distToWater = 0;
|
||||
@ -226,7 +232,7 @@ for (var ix=0; ix<=mapSize; ix++)
|
||||
}
|
||||
|
||||
// add some base noise
|
||||
var baseNoise = 16*noise0.get(x,y) + 8*noise1.get(x,y) + 4*noise2.get(x,y) - (16+8+4)/2;
|
||||
var baseNoise = 16*noise0.get(x,z) + 8*noise1.get(x,z) + 4*noise2.get(x,z) - (16+8+4)/2;
|
||||
if ( baseNoise < 0 )
|
||||
{
|
||||
baseNoise *= pn;
|
||||
@ -238,13 +244,13 @@ for (var ix=0; ix<=mapSize; ix++)
|
||||
// add some higher-frequency noise on land
|
||||
if ( oldH > 0 )
|
||||
{
|
||||
h += (0.4*noise2a.get(x,y) + 0.2*noise2b.get(x,y)) * min(oldH/10.0, 1.0);
|
||||
h += (0.4*noise2a.get(x,z) + 0.2*noise2b.get(x,z)) * min(oldH/10.0, 1.0);
|
||||
}
|
||||
|
||||
// create cliff noise
|
||||
if ( h > -10 )
|
||||
{
|
||||
var cliffNoise = (noise3.get(x,y) + 0.5*noise4.get(x,y)) / 1.5;
|
||||
var cliffNoise = (noise3.get(x,z) + 0.5*noise4.get(x,z)) / 1.5;
|
||||
if (h < 1)
|
||||
{
|
||||
var u = 1 - 0.3*((h-1)/-10);
|
||||
@ -254,7 +260,7 @@ for (var ix=0; ix<=mapSize; ix++)
|
||||
if (cliffNoise > 0.6)
|
||||
{
|
||||
var u = 0.8 * (cliffNoise - 0.6);
|
||||
cliffNoise += u * noise5.get(x,y);
|
||||
cliffNoise += u * noise5.get(x,z);
|
||||
cliffNoise /= (1 + u);
|
||||
}
|
||||
cliffNoise -= 0.59;
|
||||
@ -266,7 +272,7 @@ for (var ix=0; ix<=mapSize; ix++)
|
||||
}
|
||||
|
||||
// set the height
|
||||
setHeight(ix, iy, h);
|
||||
setHeight(ix, iz, h);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,17 +290,17 @@ var noise10 = new Noise2D(50 * mapSize/128);
|
||||
|
||||
for (var ix=0; ix<mapSize; ix++)
|
||||
{
|
||||
for (var iy=0; iy<mapSize; iy++)
|
||||
for (var iz=0; iz<mapSize; iz++)
|
||||
{
|
||||
var x = ix / (mapSize + 1.0);
|
||||
var y = iy / (mapSize + 1.0);
|
||||
var pn = playerNearness(x, y);
|
||||
var z = iz / (mapSize + 1.0);
|
||||
var pn = playerNearness(x, z);
|
||||
|
||||
// get heights of surrounding vertices
|
||||
var h00 = getHeight(ix, iy);
|
||||
var h01 = getHeight(ix, iy+1);
|
||||
var h10 = getHeight(ix+1, iy);
|
||||
var h11 = getHeight(ix+1, iy+1);
|
||||
var h00 = getHeight(ix, iz);
|
||||
var h01 = getHeight(ix, iz+1);
|
||||
var h10 = getHeight(ix+1, iz);
|
||||
var h11 = getHeight(ix+1, iz+1);
|
||||
|
||||
// find min and max height
|
||||
var maxH = Math.max(h00, h01, h10, h11);
|
||||
@ -305,12 +311,12 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
if (maxH > 15)
|
||||
{
|
||||
var maxNx = min(ix+2, mapSize);
|
||||
var maxNy = min(iy+2, mapSize);
|
||||
var maxNz = min(iz+2, mapSize);
|
||||
for (var nx=max(ix-1, 0); nx <= maxNx; nx++)
|
||||
{
|
||||
for (var ny=max(iy-1, 0); ny <= maxNy; ny++)
|
||||
for (var nz=max(iz-1, 0); nz <= maxNz; nz++)
|
||||
{
|
||||
minAdjHeight = min(minAdjHeight, getHeight(nx, ny));
|
||||
minAdjHeight = min(minAdjHeight, getHeight(nx, nz));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -350,14 +356,14 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
|
||||
if (minH < 0)
|
||||
{
|
||||
addToClass(ix, iy, clWater);
|
||||
addToClass(ix, iz, clWater);
|
||||
}
|
||||
|
||||
// cliffs
|
||||
if (maxH - minH > 2.9 && minH > -7)
|
||||
{
|
||||
t = tCliff;
|
||||
addToClass(ix, iy, clCliff);
|
||||
addToClass(ix, iz, clCliff);
|
||||
}
|
||||
else if ((maxH - minH > 2.5 && minH > -5) || (maxH-minAdjHeight > 2.9 && minH > 0) )
|
||||
{
|
||||
@ -368,20 +374,20 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
else
|
||||
t = [tDirtCliff, tGrassCliff, tGrassCliff, tGrassRock, tCliff];
|
||||
|
||||
addToClass(ix, iy, clCliff);
|
||||
addToClass(ix, iz, clCliff);
|
||||
}
|
||||
|
||||
// forests
|
||||
if (maxH - minH < 1 && minH > 1)
|
||||
{
|
||||
var forestNoise = (noise6.get(x,y) + 0.5*noise7.get(x,y)) / 1.5 * pn;
|
||||
var forestNoise = (noise6.get(x,z) + 0.5*noise7.get(x,z)) / 1.5 * pn;
|
||||
forestNoise -= 0.59;
|
||||
|
||||
if (forestNoise > 0)
|
||||
{
|
||||
if (minH > 5)
|
||||
{
|
||||
var typeNoise = noise10.get(x,y);
|
||||
var typeNoise = noise10.get(x,z);
|
||||
|
||||
if (typeNoise < 0.43 && forestNoise < 0.05)
|
||||
t = tPoplarForest;
|
||||
@ -390,12 +396,12 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
else
|
||||
t = tPineForest;
|
||||
|
||||
addToClass(ix, iy, clForest);
|
||||
addToClass(ix, iz, clForest);
|
||||
}
|
||||
else if (minH < 3)
|
||||
{
|
||||
t = tPalmForest;
|
||||
addToClass(ix, iy, clForest);
|
||||
addToClass(ix, iz, clForest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -403,7 +409,7 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
// grass variations
|
||||
if (t == tGrass)
|
||||
{
|
||||
var grassNoise = (noise8.get(x,y) + 0.6*noise9.get(x,y)) / 1.6;
|
||||
var grassNoise = (noise8.get(x,z) + 0.6*noise9.get(x,z)) / 1.6;
|
||||
if (grassNoise < 0.3)
|
||||
{
|
||||
t = (maxH - minH > 1.2) ? tDirtCliff : tDirt;
|
||||
@ -413,7 +419,7 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
t = (maxH - minH > 1.2) ? tGrassCliff : tGrassDry;
|
||||
if (maxH - minH < 0.5 && randFloat() < 0.03)
|
||||
{
|
||||
placeObject(ix+randFloat(), iy+randFloat(), aGrassDry, 0, randFloat()*2*PI);
|
||||
placeObject(ix+randFloat(), iz+randFloat(), aGrassDry, 0, randFloat()*2*PI);
|
||||
}
|
||||
}
|
||||
else if (grassNoise > 0.61)
|
||||
@ -424,12 +430,12 @@ for (var ix=0; ix<mapSize; ix++)
|
||||
{
|
||||
if ((maxH - minH) < 0.5 && randFloat() < 0.05)
|
||||
{
|
||||
placeObject(ix+randFloat(), iy+randFloat(), aGrass, 0, randFloat()*2*PI);
|
||||
placeObject(ix+randFloat(), iz+randFloat(), aGrass, 0, randFloat()*2*PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
placeTerrain(ix, iy, t);
|
||||
placeTerrain(ix, iz, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,19 +76,19 @@ for (var i=0; i < numPlayers; i++)
|
||||
|
||||
// get the x and y in tiles
|
||||
var fx = fractionToTiles(playerX[i]);
|
||||
var fy = fractionToTiles(playerY[i]);
|
||||
var fz = fractionToTiles(playerY[i]);
|
||||
var ix = round(fx);
|
||||
var iy = round(fy);
|
||||
var iz = round(fz);
|
||||
|
||||
// calculate size based on the radius
|
||||
var size = PI * radius * radius;
|
||||
|
||||
// create the player area
|
||||
var placer = new ClumpPlacer(size, 0.9, 0.5, 0, ix, iy);
|
||||
var placer = new ClumpPlacer(size, 0.9, 0.5, 0, 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, iy);
|
||||
placer = new ClumpPlacer(PI*2*2, 0.6, 0.3, 0.5, ix, iz);
|
||||
var painter = new TerrainPainter(tDirt);
|
||||
createArea(placer, painter, null);
|
||||
|
||||
@ -99,7 +99,7 @@ for (var i=0; i < numPlayers; i++)
|
||||
new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0),
|
||||
new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)
|
||||
],
|
||||
true, null, ix, iy
|
||||
true, null, ix, iz
|
||||
);
|
||||
createObjectGroup(group, i+1);
|
||||
|
||||
@ -107,7 +107,7 @@ for (var i=0; i < numPlayers; i++)
|
||||
var bbAngle = randFloat()*2*PI;
|
||||
var bbDist = 10;
|
||||
var bbX = round(fx + bbDist * cos(bbAngle));
|
||||
var bbY = round(fy + bbDist * sin(bbAngle));
|
||||
var bbY = round(fz + bbDist * sin(bbAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oSheep, 5,5, 0,2)],
|
||||
true, clBaseResource, bbX, bbY
|
||||
@ -121,18 +121,18 @@ for (var i=0; i < numPlayers; i++)
|
||||
}
|
||||
var mDist = 12;
|
||||
var mX = round(fx + mDist * cos(mAngle));
|
||||
var mY = round(fy + mDist * sin(mAngle));
|
||||
var mZ = round(fz + mDist * sin(mAngle));
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oStone, 2,2, 0,3),
|
||||
new SimpleObject(oMetal, 2,2, 0,3)],
|
||||
true, clBaseResource, mX, mY
|
||||
true, clBaseResource, mX, mZ
|
||||
);
|
||||
createObjectGroup(group, 0);
|
||||
|
||||
// create starting straggler trees
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oTree, 2,2, 6,12)],
|
||||
true, null, ix, iy
|
||||
true, null, ix, iz
|
||||
);
|
||||
createObjectGroup(group, 0, avoidClasses(clBaseResource,1));
|
||||
}
|
||||
|
@ -1,4 +1,19 @@
|
||||
function Area(points)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Area
|
||||
//
|
||||
// Object representing a group of points/tiles
|
||||
//
|
||||
// points: Array of Point objects
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Area(points, id)
|
||||
{
|
||||
this.points = (points !== undefined ? points : []);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
Area.prototype.getID = function()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
@ -1,27 +1,37 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// NullConstraints: No constraint - always return true
|
||||
// NullConstraint
|
||||
//
|
||||
// Class representing null constraint - always valid
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function NullConstraint() {}
|
||||
|
||||
NullConstraint.prototype.allows = function(x, y)
|
||||
NullConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AndConstraints: Check multiple constraints
|
||||
// AndConstraint
|
||||
//
|
||||
// Class representing a logical AND constraint
|
||||
//
|
||||
// constraints: Array of contraint objects, all of which must be satisfied
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AndConstraint(constraints)
|
||||
{
|
||||
this.constraints = constraints;
|
||||
}
|
||||
|
||||
AndConstraint.prototype.allows = function(x, y)
|
||||
AndConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
for (var i=0; i < this.constraints.length; ++i)
|
||||
{
|
||||
if (!this.constraints[i].allows(x, y))
|
||||
if (!this.constraints[i].allows(x, z))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -30,32 +40,48 @@ AndConstraint.prototype.allows = function(x, y)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AvoidAreaConstraint
|
||||
//
|
||||
// Class representing avoid area constraint
|
||||
//
|
||||
// area: Area object, containing points to be avoided
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
function AvoidAreaConstraint(area)
|
||||
{
|
||||
this.area = area;
|
||||
}
|
||||
|
||||
AvoidAreaConstraint.prototype.allows = function(x, y)
|
||||
AvoidAreaConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
return g_Map.area[x][y] != this.area;
|
||||
return g_Map.area[x][z] != this.area.getID();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AvoidTextureConstraint
|
||||
//
|
||||
// Class representing avoid texture constraint
|
||||
//
|
||||
// textureID: ID of the texture to be avoided
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
function AvoidTextureConstraint(textureID)
|
||||
{
|
||||
this.textureID = textureID;
|
||||
}
|
||||
|
||||
AvoidTextureConstraint.prototype.allows = function(x, y)
|
||||
AvoidTextureConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
return g_Map.texture[x][y] != this.textureID;
|
||||
return g_Map.texture[x][z] != this.textureID;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AvoidTileClassConstraint
|
||||
//
|
||||
// Class representing avoid TileClass constraint
|
||||
//
|
||||
// tileClassID: ID of the TileClass to avoid
|
||||
// distance: distance by which it must be avoided
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
function AvoidTileClassConstraint(tileClassID, distance)
|
||||
{
|
||||
@ -63,13 +89,19 @@ function AvoidTileClassConstraint(tileClassID, distance)
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
AvoidTileClassConstraint.prototype.allows = function(x, y)
|
||||
AvoidTileClassConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
return this.tileClass.countMembersInRadius(x, y, this.distance) == 0;
|
||||
return this.tileClass.countMembersInRadius(x, z, this.distance) == 0;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// StayInTileClassConstraint
|
||||
//
|
||||
// Class representing stay in TileClass constraint
|
||||
//
|
||||
// tileClassID: ID of TileClass to stay within
|
||||
// distance: distance from test point to find matching TileClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
function StayInTileClassConstraint(tileClassID, distance)
|
||||
{
|
||||
@ -77,13 +109,20 @@ function StayInTileClassConstraint(tileClassID, distance)
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
StayInTileClassConstraint.prototype.allows = function(x, y)
|
||||
StayInTileClassConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
return this.tileClass.countNonMembersInRadius(x, y, this.distance) == 0;
|
||||
return this.tileClass.countNonMembersInRadius(x, z, this.distance) == 0;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BorderTileClassConstraint
|
||||
//
|
||||
// Class representing border TileClass constraint
|
||||
//
|
||||
// tileClassID: ID of TileClass to border
|
||||
// distanceInside: Distance from test point to find matching TileClass
|
||||
// distanceOutside: Distance from test point to find other TileClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
function BorderTileClassConstraint(tileClassID, distanceInside, distanceOutside)
|
||||
{
|
||||
@ -92,8 +131,8 @@ function BorderTileClassConstraint(tileClassID, distanceInside, distanceOutside)
|
||||
this.distanceOutside = distanceOutside;
|
||||
}
|
||||
|
||||
BorderTileClassConstraint.prototype.allows = function(x, y)
|
||||
BorderTileClassConstraint.prototype.allows = function(x, z)
|
||||
{
|
||||
return (this.tileClass.countMembersInRadius(x, y, this.distanceOutside) > 0
|
||||
&& this.tileClass.countNonMembersInRadius(x, y, this.distanceInside) > 0);
|
||||
return (this.tileClass.countMembersInRadius(x, z, this.distanceOutside) > 0
|
||||
&& this.tileClass.countNonMembersInRadius(x, z, this.distanceInside) > 0);
|
||||
};
|
||||
|
@ -1,22 +1,26 @@
|
||||
function Entity(name, player, x, y, angle)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Entity
|
||||
//
|
||||
// Object for holding entity data
|
||||
// TODO: support y position or offset (height) and full 3D rotation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Entity(name, player, x, z, orientation)
|
||||
{
|
||||
// Get unique ID
|
||||
this.id = g_Map.getEntityID();
|
||||
this.name = name;
|
||||
|
||||
// Convert from tile coords to map coords
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
// Tile units
|
||||
this.tileX = x;
|
||||
this.tileZ = z;
|
||||
|
||||
if (player !== undefined)
|
||||
{
|
||||
this.player = player;
|
||||
this.isActor = false;
|
||||
}
|
||||
else
|
||||
{ // Actors have no player ID
|
||||
this.isActor = true;
|
||||
}
|
||||
// Map units (4.0 map units per 1.0 tile)
|
||||
this.x = x * 4.0;
|
||||
this.y = 0;
|
||||
this.z = z * 4.0;
|
||||
|
||||
this.orientation = (angle !== undefined ? angle : 0);
|
||||
this.player = (player !== undefined ? player : 0);
|
||||
this.orientation = (orientation !== undefined ? orientation : 0);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Some functions to manipulate environment properties
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Sky + lighting
|
||||
// Sky + lighting
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Set skyset
|
||||
function setSkySet(set)
|
||||
@ -40,7 +40,8 @@ function setUnitsAmbientColour(r, g, b)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Water
|
||||
// Water
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Set water colour RGB (0,1)
|
||||
function setWaterColour(r, g, b)
|
||||
|
@ -9,8 +9,6 @@ const SEA_LEVEL = 20.0;
|
||||
|
||||
const TERRAIN_SEPARATOR = "|";
|
||||
|
||||
const TILES_PER_PATCH = 16;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utility functions
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -79,14 +77,14 @@ function floor(x)
|
||||
return Math.floor(x);
|
||||
}
|
||||
|
||||
function max(x, y)
|
||||
function max(a, b)
|
||||
{
|
||||
return x > y ? x : y;
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
function min(x, y)
|
||||
function min(a, b)
|
||||
{
|
||||
return x < y ? x : y;
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
function println(x)
|
||||
@ -143,14 +141,14 @@ function createAreas(centeredPlacer, painter, constraint, num, retryFactor)
|
||||
var r = halfSize * Math.sqrt(randFloat()); // uniform distribution
|
||||
var theta = randFloat(0, 2 * PI);
|
||||
centeredPlacer.x = Math.floor(r * Math.cos(theta)) + halfSize;
|
||||
centeredPlacer.y = Math.floor(r * Math.sin(theta)) + halfSize;
|
||||
centeredPlacer.z = Math.floor(r * Math.sin(theta)) + halfSize;
|
||||
}
|
||||
else
|
||||
{ // Rectangular coordinates
|
||||
centeredPlacer.x = randInt(getMapSize());
|
||||
centeredPlacer.y = randInt(getMapSize());
|
||||
centeredPlacer.z = randInt(getMapSize());
|
||||
}
|
||||
|
||||
|
||||
var area = g_Map.createArea(centeredPlacer, painter, constraint);
|
||||
if (area !== undefined)
|
||||
{
|
||||
@ -183,12 +181,12 @@ function createObjectGroups(placer, player, constraint, num, retryFactor)
|
||||
var r = halfSize * Math.sqrt(randFloat()); // uniform distribution
|
||||
var theta = randFloat(0, 2 * PI);
|
||||
placer.x = Math.floor(r * Math.cos(theta)) + halfSize;
|
||||
placer.y = Math.floor(r * Math.sin(theta)) + halfSize;
|
||||
placer.z = Math.floor(r * Math.sin(theta)) + halfSize;
|
||||
}
|
||||
else
|
||||
{ // Rectangular coordinates
|
||||
placer.x = randInt(getMapSize());
|
||||
placer.y = randInt(getMapSize());
|
||||
placer.z = randInt(getMapSize());
|
||||
}
|
||||
|
||||
var result = createObjectGroup(placer, player, constraint);
|
||||
@ -245,15 +243,15 @@ function createSimpleTerrain(terrain)
|
||||
}
|
||||
}
|
||||
|
||||
function placeObject(x, y, type, player, angle)
|
||||
function placeObject(x, z, type, player, angle)
|
||||
{
|
||||
g_Map.addObjects(new Entity(type, player, x, y, angle));
|
||||
g_Map.addObjects(new Entity(type, player, x, z, angle));
|
||||
}
|
||||
|
||||
function placeTerrain(x, y, terrain)
|
||||
function placeTerrain(x, z, terrain)
|
||||
{
|
||||
// convert terrain param into terrain object
|
||||
g_Map.placeTerrain(x, y, createTerrain(terrain));
|
||||
g_Map.placeTerrain(x, z, createTerrain(terrain));
|
||||
|
||||
}
|
||||
|
||||
@ -312,14 +310,14 @@ function getCivCode(player)
|
||||
return g_MapSettings.PlayerData[player].Civ;
|
||||
}
|
||||
|
||||
function getHeight(x, y)
|
||||
function getHeight(x, z)
|
||||
{
|
||||
return g_Map.getHeight(x, y);
|
||||
return g_Map.getHeight(x, z);
|
||||
}
|
||||
|
||||
function setHeight(x, y, height)
|
||||
function setHeight(x, z, height)
|
||||
{
|
||||
g_Map.setHeight(x, y, height);
|
||||
g_Map.setHeight(x, z, height);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -328,13 +326,13 @@ function setHeight(x, y, height)
|
||||
|
||||
|
||||
// Add point to given class by id
|
||||
function addToClass(x, y, id)
|
||||
function addToClass(x, z, id)
|
||||
{
|
||||
var tileClass = getTileClass(id);
|
||||
|
||||
if (tileClass !== null)
|
||||
{
|
||||
tileClass.add(x, y);
|
||||
tileClass.add(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,38 +1,43 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Map
|
||||
//
|
||||
// Class for holding map data and providing basic API to change it
|
||||
//
|
||||
// size: Size of the map in tiles
|
||||
// baseHeight: Starting height of the map
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Map(size, baseHeight)
|
||||
{
|
||||
// Size must be 0 to 1024, divisible by 16
|
||||
// Size must be 0 to 1024, divisible by patches
|
||||
this.size = size;
|
||||
|
||||
// Create 2D arrays for texture, object, and area maps
|
||||
// Create 2D arrays for textures, object, and areas
|
||||
this.texture = new Array(size);
|
||||
this.terrainObjects = new Array(size);
|
||||
this.area = new Array(size);
|
||||
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
this.texture[i] = new Uint16Array(size); // uint16
|
||||
this.terrainObjects[i] = new Array(size); // entity
|
||||
this.area[i] = new Array(size); // area
|
||||
this.texture[i] = new Uint16Array(size); // uint16 - texture IDs
|
||||
this.terrainObjects[i] = new Array(size); // array of entities
|
||||
this.area[i] = new Uint16Array(size); // uint16 - area IDs
|
||||
|
||||
for (var j = 0; j < size; j++)
|
||||
{
|
||||
this.area[i][j] = {}; // undefined would cause a warning in strict mode
|
||||
this.terrainObjects[i][j] = [];
|
||||
}
|
||||
}
|
||||
|
||||
var mapSize = size+1;
|
||||
|
||||
// Create 2D array for heightmap
|
||||
var mapSize = size+1;
|
||||
this.height = new Array(mapSize);
|
||||
for (var i=0; i < mapSize; i++)
|
||||
for (var i = 0; i < mapSize; i++)
|
||||
{
|
||||
this.height[i] = new Float32Array(mapSize);
|
||||
for (var j=0; j < mapSize; j++)
|
||||
this.height[i] = new Float32Array(mapSize); // float32
|
||||
|
||||
for (var j = 0; j < mapSize; j++)
|
||||
{ // Initialize height map to baseHeight
|
||||
this.height[i][j] = baseHeight;
|
||||
}
|
||||
@ -44,9 +49,10 @@ function Map(size, baseHeight)
|
||||
|
||||
// Other arrays
|
||||
this.objects = []; //object
|
||||
this.areas = []; //area
|
||||
this.tileClasses = []; //int
|
||||
|
||||
this.areaID = 0;
|
||||
|
||||
// Starting entity ID
|
||||
this.entityCount = 150;
|
||||
}
|
||||
@ -55,9 +61,9 @@ Map.prototype.initTerrain = function(baseTerrain)
|
||||
{
|
||||
// Initialize base terrain
|
||||
var size = this.size;
|
||||
for (var i=0; i < size; i++)
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
for (var j=0; j < size; j++)
|
||||
for (var j = 0; j < size; j++)
|
||||
{
|
||||
baseTerrain.place(i, j);
|
||||
}
|
||||
@ -65,7 +71,7 @@ Map.prototype.initTerrain = function(baseTerrain)
|
||||
};
|
||||
|
||||
// Return ID of texture (by name)
|
||||
Map.prototype.getID = function(texture)
|
||||
Map.prototype.getTextureID = function(texture)
|
||||
{
|
||||
if (texture in (this.nameToID))
|
||||
{
|
||||
@ -86,16 +92,16 @@ Map.prototype.getEntityID = function()
|
||||
return this.entityCount++;
|
||||
}
|
||||
|
||||
// Check bounds
|
||||
Map.prototype.validT = function(x, y)
|
||||
// Check bounds on tile map
|
||||
Map.prototype.validT = function(x, z)
|
||||
{
|
||||
return x >= 0 && y >= 0 && x < this.size && y < this.size;
|
||||
return x >= 0 && z >= 0 && x < this.size && z < this.size;
|
||||
};
|
||||
|
||||
// Check bounds on height map (size + 1 by size + 1)
|
||||
Map.prototype.validH = function(x, y)
|
||||
Map.prototype.validH = function(x, z)
|
||||
{
|
||||
return x >= 0 && y >= 0 && x <= this.size && y <= this.size;
|
||||
return x >= 0 && z >= 0 && x <= this.size && z <= this.size;
|
||||
};
|
||||
|
||||
// Check bounds on tile class
|
||||
@ -104,57 +110,69 @@ Map.prototype.validClass = function(c)
|
||||
return c >= 0 && c < this.tileClasses.length;
|
||||
};
|
||||
|
||||
Map.prototype.getTexture = function(x, y)
|
||||
Map.prototype.getTexture = function(x, z)
|
||||
{
|
||||
if (!this.validT(x, y))
|
||||
error("getTexture: invalid tile position ("+x+", "+y+")");
|
||||
if (!this.validT(x, z))
|
||||
{
|
||||
error("getTexture: invalid tile position ("+x+", "+z+")");
|
||||
}
|
||||
|
||||
return this.IDToName[this.texture[x][y]];
|
||||
return this.IDToName[this.texture[x][z]];
|
||||
};
|
||||
|
||||
Map.prototype.setTexture = function(x, y, texture)
|
||||
Map.prototype.setTexture = function(x, z, texture)
|
||||
{
|
||||
if (!this.validT(x, y))
|
||||
error("setTexture: invalid tile position ("+x+", "+y+")");
|
||||
if (!this.validT(x, z))
|
||||
{
|
||||
error("setTexture: invalid tile position ("+x+", "+z+")");
|
||||
}
|
||||
|
||||
this.texture[x][y] = this.getID(texture);
|
||||
this.texture[x][z] = this.getTextureID(texture);
|
||||
};
|
||||
|
||||
Map.prototype.getHeight = function(x, y)
|
||||
Map.prototype.getHeight = function(x, z)
|
||||
{
|
||||
if (!this.validH(x, y))
|
||||
error("getHeight: invalid vertex position ("+x+", "+y+")");
|
||||
if (!this.validH(x, z))
|
||||
{
|
||||
error("getHeight: invalid vertex position ("+x+", "+z+")");
|
||||
}
|
||||
|
||||
return this.height[x][y];
|
||||
return this.height[x][z];
|
||||
};
|
||||
|
||||
Map.prototype.setHeight = function(x, y, height)
|
||||
Map.prototype.setHeight = function(x, z, height)
|
||||
{
|
||||
if (!this.validH(x, y))
|
||||
error("setHeight: invalid vertex position ("+x+", "+y+")");
|
||||
if (!this.validH(x, z))
|
||||
{
|
||||
error("setHeight: invalid vertex position ("+x+", "+z+")");
|
||||
}
|
||||
|
||||
this.height[x][y] = height;
|
||||
this.height[x][z] = height;
|
||||
};
|
||||
|
||||
Map.prototype.getTerrainObjects = function(x, y)
|
||||
Map.prototype.getTerrainObjects = function(x, z)
|
||||
{
|
||||
if (!this.validT(x, y))
|
||||
error("getTerrainObjects: invalid tile position ("+x+", "+y+")");
|
||||
if (!this.validT(x, z))
|
||||
{
|
||||
error("getTerrainObjects: invalid tile position ("+x+", "+z+")");
|
||||
}
|
||||
|
||||
return this.terrainObjects[x][y];
|
||||
return this.terrainObjects[x][z];
|
||||
};
|
||||
|
||||
Map.prototype.setTerrainObjects = function(x, y, objects)
|
||||
Map.prototype.setTerrainObject = function(x, z, object)
|
||||
{
|
||||
if (!this.validT(x, y))
|
||||
error("setTerrainObjects: invalid tile position ("+x+", "+y+")");
|
||||
if (!this.validT(x, z))
|
||||
{
|
||||
error("setTerrainObject: invalid tile position ("+x+", "+z+")");
|
||||
}
|
||||
|
||||
this.terrainObjects[x][y] = objects;
|
||||
this.terrainObjects[x][z] = object;
|
||||
};
|
||||
|
||||
Map.prototype.placeTerrain = function(x, y, terrain)
|
||||
Map.prototype.placeTerrain = function(x, z, terrain)
|
||||
{
|
||||
terrain.place(x, y);
|
||||
terrain.place(x, z);
|
||||
};
|
||||
|
||||
Map.prototype.addObjects = function(obj)
|
||||
@ -186,16 +204,16 @@ Map.prototype.createArea = function(placer, painter, constraint)
|
||||
if (!points)
|
||||
return undefined;
|
||||
|
||||
var a = new Area(points);
|
||||
var newID = ++this.areaID;
|
||||
var area = new Area(points, newID);
|
||||
for (var i=0; i < points.length; i++)
|
||||
{
|
||||
this.area[points[i].x][points[i].y] = a;
|
||||
this.area[points[i].x][points[i].z] = newID;
|
||||
}
|
||||
|
||||
painter.paint(a);
|
||||
this.areas.push(a);
|
||||
painter.paint(area);
|
||||
|
||||
return a;
|
||||
return area;
|
||||
};
|
||||
|
||||
Map.prototype.createObjectGroup = function(placer, player, constraint)
|
||||
@ -223,19 +241,19 @@ Map.prototype.createTileClass = function()
|
||||
};
|
||||
|
||||
// Get height taking into account terrain curvature
|
||||
Map.prototype.getExactHeight = function(x, y)
|
||||
Map.prototype.getExactHeight = function(x, z)
|
||||
{
|
||||
var xi = min(Math.floor(x), this.size);
|
||||
var yi = min(Math.floor(y), this.size);
|
||||
var zi = min(Math.floor(z), this.size);
|
||||
var xf = x - xi;
|
||||
var yf = y - yi;
|
||||
var zf = z - zi;
|
||||
|
||||
var h00 = this.height[xi][yi];
|
||||
var h01 = this.height[xi][yi+1];
|
||||
var h10 = this.height[xi+1][yi];
|
||||
var h11 = this.height[xi+1][yi+1];
|
||||
var h00 = this.height[xi][zi];
|
||||
var h01 = this.height[xi][zi+1];
|
||||
var h10 = this.height[xi+1][zi];
|
||||
var h11 = this.height[xi+1][zi+1];
|
||||
|
||||
return ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ;
|
||||
return ( 1 - zf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + zf * ( ( 1 - xf ) * h01 + xf * h11 ) ;
|
||||
};
|
||||
|
||||
Map.prototype.getMapData = function()
|
||||
@ -247,26 +265,20 @@ Map.prototype.getMapData = function()
|
||||
|
||||
// Terrain objects first (trees)
|
||||
var size = this.size;
|
||||
for (var x=0; x < size; ++x)
|
||||
for (var x = 0; x < size; ++x)
|
||||
{
|
||||
for (var y=0; y < size; ++y)
|
||||
for (var z = 0; z < size; ++z)
|
||||
{
|
||||
if (this.terrainObjects[x][y].length)
|
||||
entities = entities.concat(this.terrainObjects[x][y]);
|
||||
if (this.terrainObjects[x][z] !== undefined)
|
||||
{
|
||||
entities.push(this.terrainObjects[x][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now other entities
|
||||
entities = entities.concat(this.objects);
|
||||
|
||||
// Convert from tiles to map coordinates
|
||||
for (var n in entities)
|
||||
for (var i = 0; i < this.objects.length; ++i)
|
||||
{
|
||||
var e = entities[n];
|
||||
e.x *= 4;
|
||||
e.y *= 4;
|
||||
|
||||
entities[n] = e;
|
||||
entities.push(this.objects[i]);
|
||||
}
|
||||
data["entities"] = entities;
|
||||
|
||||
@ -277,18 +289,23 @@ Map.prototype.getMapData = function()
|
||||
// Flat because it's easier to handle by the engine
|
||||
var mapSize = size+1;
|
||||
var height16 = new Array(mapSize*mapSize); // uint16
|
||||
for (var x=0; x < mapSize; x++)
|
||||
for (var x = 0; x < mapSize; x++)
|
||||
{
|
||||
for (var y=0; y < mapSize; y++)
|
||||
for (var z = 0; z < mapSize; z++)
|
||||
{
|
||||
var intHeight = Math.floor((this.height[x][y] + SEA_LEVEL) * 256.0 / 0.35);
|
||||
var intHeight = Math.floor((this.height[x][z] + SEA_LEVEL) * 256.0 / 0.35);
|
||||
|
||||
if (intHeight > 65000)
|
||||
intHeight = 65000;
|
||||
// Prevent under/overflow in terrain data
|
||||
if (intHeight > 0xFFFF)
|
||||
{
|
||||
intHeight = 0xFFFF;
|
||||
}
|
||||
else if (intHeight < 0)
|
||||
{
|
||||
intHeight = 0;
|
||||
}
|
||||
|
||||
height16[y*mapSize + x] = intHeight;
|
||||
height16[z*mapSize + x] = intHeight;
|
||||
}
|
||||
}
|
||||
data["height"] = height16;
|
||||
@ -297,26 +314,19 @@ Map.prototype.getMapData = function()
|
||||
// Get array of textures used in this map
|
||||
var textureNames = [];
|
||||
for (var name in this.nameToID)
|
||||
{
|
||||
textureNames.push(name);
|
||||
|
||||
}
|
||||
data["textureNames"] = textureNames;
|
||||
|
||||
// Convert 2D tile data to flat array, reodering into patches as expected by MapReader
|
||||
// Convert 2D tile data to flat array
|
||||
var tiles = new Array(size*size);
|
||||
var patches = size/16;
|
||||
for (var x=0; x < size; x++)
|
||||
for (var x = 0; x < size; x++)
|
||||
{
|
||||
var patchX = Math.floor(x/16);
|
||||
var offX = x%16;
|
||||
for (var y=0; y < size; y++)
|
||||
for (var z = 0; z < size; z++)
|
||||
{
|
||||
var patchY = Math.floor(y/16);
|
||||
var offY = y%16;
|
||||
tiles[(patchY*patches + patchX)*256 + (offY*16 + offX)] =
|
||||
{ "texIdx1" : this.texture[x][y],
|
||||
"texIdx2" : 0xFFFF,
|
||||
"priority" : 0
|
||||
};
|
||||
// TODO: For now just use the texture's index as priority, might want to do this another way
|
||||
tiles[z*size + x] = { "idx": this.texture[x][z], "priority": this.texture[x][z] };
|
||||
}
|
||||
}
|
||||
data["tileData"] = tiles;
|
||||
|
@ -46,7 +46,7 @@ function InitMap()
|
||||
// until SpiderMonkey gets upgraded
|
||||
g_MapSettings.Size = Math.floor(g_MapSettings.Size);
|
||||
|
||||
g_Map = new Map(g_MapSettings.Size * TILES_PER_PATCH, g_MapSettings.BaseHeight);
|
||||
g_Map = new Map(g_MapSettings.Size, g_MapSettings.BaseHeight);
|
||||
g_Map.initTerrain(terrain);
|
||||
}
|
||||
|
||||
@ -60,6 +60,9 @@ function ExportMap()
|
||||
// Add environment and camera settings
|
||||
g_Environment.Water.WaterBody.Height = SEA_LEVEL - 0.1;
|
||||
data.Environment = g_Environment;
|
||||
|
||||
// Adjust default cam to roughly center of the map - useful for Atlas
|
||||
g_Camera.Position = {x: g_MapSettings.Size*2, y: g_MapSettings.Size*2, z: -g_MapSettings.Size*2};
|
||||
data.Camera = g_Camera;
|
||||
|
||||
RMS.ExportMap(data);
|
||||
|
@ -16,6 +16,9 @@ function modPos(num, m)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Noise2D
|
||||
//
|
||||
// Class representing 2D noise with a given base frequency
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Noise2D(freq)
|
||||
@ -31,7 +34,7 @@ function Noise2D(freq)
|
||||
{
|
||||
var a = randFloat() * 2 * PI;
|
||||
|
||||
this.grads[i][j] = new Vector2D(cos(a), sin(a));
|
||||
this.grads[i][j] = new Vector2D(Math.cos(a), Math.sin(a));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,6 +67,9 @@ Noise2D.prototype.get = function(x, y)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Noise3D
|
||||
//
|
||||
// Class representing 3D noise with given base frequencies
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Noise3D(freq, vfreq)
|
||||
|
@ -1,15 +1,21 @@
|
||||
// Constants for using SmoothElevationPainter
|
||||
const ELEVATION_SET = 0;
|
||||
const ELEVATION_MODIFY = 1;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ElevationPainter
|
||||
//
|
||||
// Class for painting elevation over an area
|
||||
//
|
||||
// elevation: Target elevation/height to be painted
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ElevationPainter(elevation)
|
||||
{
|
||||
this.elevation = elevation;
|
||||
this.DX = [0, 1, 1, 0];
|
||||
this.DY = [0, 0, 1, 1];
|
||||
this.DZ = [0, 0, 1, 1];
|
||||
}
|
||||
|
||||
ElevationPainter.prototype.paint = function(area)
|
||||
@ -23,13 +29,19 @@ ElevationPainter.prototype.paint = function(area)
|
||||
|
||||
for (var j=0; j < 4; j++)
|
||||
{
|
||||
g_Map.height[pt.x+this.DX[j]][pt.y+this.DY[j]] = elevation;
|
||||
g_Map.height[pt.x + this.DX[j]][pt.z + this.DZ[j]] = elevation;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// LayeredPainter
|
||||
//
|
||||
// Class for painting multiple layered terrains over an area
|
||||
//
|
||||
// terrainArray: Array of terrain painter objects
|
||||
// widths: Array of widths for each layer
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function LayeredPainter(terrainArray, widths)
|
||||
@ -39,7 +51,9 @@ function LayeredPainter(terrainArray, widths)
|
||||
|
||||
this.terrains = [];
|
||||
for (var i = 0; i < terrainArray.length; ++i)
|
||||
{
|
||||
this.terrains.push(createTerrain(terrainArray[i]));
|
||||
}
|
||||
|
||||
this.widths = widths;
|
||||
}
|
||||
@ -63,24 +77,25 @@ LayeredPainter.prototype.paint = function(area)
|
||||
// push edge points
|
||||
var pts = area.points;
|
||||
var length = pts.length;
|
||||
var areaID = area.getID();
|
||||
|
||||
for (var i=0; i < length; i++)
|
||||
{
|
||||
var x = pts[i].x;
|
||||
var y = pts[i].y;
|
||||
var z = pts[i].z;
|
||||
|
||||
for (var dx=-1; dx <= 1; dx++)
|
||||
{
|
||||
var nx = x+dx;
|
||||
for (var dy=-1; dy <= 1; dy++)
|
||||
for (var dz=-1; dz <= 1; dz++)
|
||||
{
|
||||
var ny = y+dy;
|
||||
var nz = z+dz;
|
||||
|
||||
if (g_Map.validT(nx, ny) && g_Map.area[nx][ny] != area && !saw[nx][ny])
|
||||
if (g_Map.validT(nx, nz) && g_Map.area[nx][nz] != areaID && !saw[nx][nz])
|
||||
{
|
||||
saw[nx][ny] = 1;
|
||||
dist[nx][ny] = 0;
|
||||
pointQ.push(new Point(nx, ny));
|
||||
saw[nx][nz] = 1;
|
||||
dist[nx][nz] = 0;
|
||||
pointQ.push(new PointXZ(nx, nz));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,11 +106,11 @@ LayeredPainter.prototype.paint = function(area)
|
||||
{
|
||||
var pt = pointQ.shift(); // Pop queue
|
||||
var px = pt.x;
|
||||
var py = pt.y;
|
||||
var d = dist[px][py];
|
||||
var pz = pt.z;
|
||||
var d = dist[px][pz];
|
||||
|
||||
// paint if in area
|
||||
if (g_Map.area[px][py] == area)
|
||||
if (g_Map.area[px][pz] == areaID)
|
||||
{
|
||||
var w=0;
|
||||
var i=0;
|
||||
@ -108,22 +123,22 @@ LayeredPainter.prototype.paint = function(area)
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.terrains[i].place(px, py);
|
||||
this.terrains[i].place(px, pz);
|
||||
}
|
||||
|
||||
// enqueue neighbours
|
||||
for (var dx=-1; dx<=1; dx++)
|
||||
{
|
||||
var nx = px+dx;
|
||||
for (var dy=-1; dy<=1; dy++)
|
||||
for (var dz=-1; dz<=1; dz++)
|
||||
{
|
||||
var ny = py+dy;
|
||||
var nz = pz+dz;
|
||||
|
||||
if (g_Map.validT(nx, ny) && g_Map.area[nx][ny] == area && !saw[nx][ny])
|
||||
if (g_Map.validT(nx, nz) && g_Map.area[nx][nz] == areaID && !saw[nx][nz])
|
||||
{
|
||||
saw[nx][ny] = 1;
|
||||
dist[nx][ny] = d+1;
|
||||
pointQ.push(new Point(nx, ny));
|
||||
saw[nx][nz] = 1;
|
||||
dist[nx][nz] = d+1;
|
||||
pointQ.push(new PointXZ(nx, nz));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,6 +147,11 @@ LayeredPainter.prototype.paint = function(area)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MultiPainter
|
||||
//
|
||||
// Class for applying multiple painters over an area
|
||||
//
|
||||
// painters: Array of painter objects
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function MultiPainter(painters)
|
||||
@ -149,6 +169,15 @@ MultiPainter.prototype.paint = function(area)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// SmoothElevationPainter
|
||||
//
|
||||
// Class for painting elevation smoothly over an area
|
||||
//
|
||||
// type: Type of elevation modification
|
||||
// ELEVATION_MODIFY = relative
|
||||
// ELEVATION_SET = absolute
|
||||
// elevation: Target elevation/height of area
|
||||
// blendRadius: How steep the elevation change is
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function SmoothElevationPainter(type, elevation, blendRadius)
|
||||
@ -161,16 +190,9 @@ function SmoothElevationPainter(type, elevation, blendRadius)
|
||||
error("SmoothElevationPainter: invalid type '"+type+"'");
|
||||
}
|
||||
|
||||
SmoothElevationPainter.prototype.checkInArea = function(area, x, y)
|
||||
SmoothElevationPainter.prototype.checkInArea = function(areaID, x, z)
|
||||
{
|
||||
if (g_Map.validT(x, y))
|
||||
{
|
||||
return (g_Map.area[x][y] == area);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (g_Map.validT(x, z) && g_Map.area[x][z] == areaID);
|
||||
};
|
||||
|
||||
SmoothElevationPainter.prototype.paint = function(area)
|
||||
@ -196,25 +218,26 @@ SmoothElevationPainter.prototype.paint = function(area)
|
||||
}
|
||||
|
||||
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 y = pts[i].y;
|
||||
var z = pts[i].z;
|
||||
|
||||
for (var dx=-1; dx <= 2; dx++)
|
||||
{
|
||||
var nx = x+dx;
|
||||
for (var dy=-1; dy <= 2; dy++)
|
||||
for (var dz=-1; dz <= 2; dz++)
|
||||
{
|
||||
var ny = y+dy;
|
||||
var nz = z+dz;
|
||||
|
||||
if (g_Map.validH(nx, ny) && !gotHeightPt[nx][ny])
|
||||
if (g_Map.validH(nx, nz) && !gotHeightPt[nx][nz])
|
||||
{
|
||||
gotHeightPt[nx][ny] = 1;
|
||||
heightPts.push(new Point(nx, ny));
|
||||
newHeight[nx][ny] = g_Map.height[nx][ny];
|
||||
gotHeightPt[nx][nz] = 1;
|
||||
heightPts.push(new PointXZ(nx, nz));
|
||||
newHeight[nx][nz] = g_Map.height[nx][nz];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -223,24 +246,25 @@ SmoothElevationPainter.prototype.paint = function(area)
|
||||
// push edge points
|
||||
for (var i=0; i < length; i++)
|
||||
{
|
||||
var x = pts[i].x, y = pts[i].y;
|
||||
var x = pts[i].x;
|
||||
var z = pts[i].z;
|
||||
for (var dx=-1; dx <= 2; dx++)
|
||||
{
|
||||
var nx = x+dx;
|
||||
for (var dy=-1; dy <= 2; dy++)
|
||||
for (var dz=-1; dz <= 2; dz++)
|
||||
{
|
||||
var ny = y+dy;
|
||||
var nz = z+dz;
|
||||
|
||||
if (g_Map.validH(nx, ny)
|
||||
&& !this.checkInArea(area, nx, ny)
|
||||
&& !this.checkInArea(area, nx-1, ny)
|
||||
&& !this.checkInArea(area, nx, ny-1)
|
||||
&& !this.checkInArea(area, nx-1, ny-1)
|
||||
&& !saw[nx][ny])
|
||||
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])
|
||||
{
|
||||
saw[nx][ny]= 1;
|
||||
dist[nx][ny] = 0;
|
||||
pointQ.push(new Point(nx, ny));
|
||||
saw[nx][nz]= 1;
|
||||
dist[nx][nz] = 0;
|
||||
pointQ.push(new PointXZ(nx, nz));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -251,35 +275,35 @@ SmoothElevationPainter.prototype.paint = function(area)
|
||||
{
|
||||
var pt = pointQ.shift();
|
||||
var px = pt.x;
|
||||
var py = pt.y;
|
||||
var d = dist[px][py];
|
||||
var pz = pt.z;
|
||||
var d = dist[px][pz];
|
||||
|
||||
// paint if in area
|
||||
if (g_Map.validH(px, py)
|
||||
&& (this.checkInArea(area, px, py) || this.checkInArea(area, px-1, py)
|
||||
|| this.checkInArea(area, px, py-1) || this.checkInArea(area, px-1, py-1)))
|
||||
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 (d <= this.blendRadius)
|
||||
{
|
||||
var a = (d-1) / this.blendRadius;
|
||||
if (this.type == ELEVATION_SET)
|
||||
{
|
||||
newHeight[px][py] = a*this.elevation + (1-a)*g_Map.height[px][py];
|
||||
newHeight[px][pz] = a*this.elevation + (1-a)*g_Map.height[px][pz];
|
||||
}
|
||||
else
|
||||
{ // type == MODIFY
|
||||
newHeight[px][py] += a*this.elevation;
|
||||
newHeight[px][pz] += a*this.elevation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // also happens when blendRadius == 0
|
||||
if (this.type == ELEVATION_SET)
|
||||
{
|
||||
newHeight[px][py] = this.elevation;
|
||||
newHeight[px][pz] = this.elevation;
|
||||
}
|
||||
else
|
||||
{ // type == MODIFY
|
||||
newHeight[px][py] += this.elevation;
|
||||
newHeight[px][pz] += this.elevation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,18 +312,18 @@ SmoothElevationPainter.prototype.paint = function(area)
|
||||
for (var dx=-1; dx <= 1; dx++)
|
||||
{
|
||||
var nx = px+dx;
|
||||
for (var dy=-1; dy <= 1; dy++)
|
||||
for (var dz=-1; dz <= 1; dz++)
|
||||
{
|
||||
var ny = py+dy;
|
||||
var nz = pz+dz;
|
||||
|
||||
if (g_Map.validH(nx, ny)
|
||||
&& (this.checkInArea(area, nx, ny) || this.checkInArea(area, nx-1, ny)
|
||||
|| this.checkInArea(area, nx, ny-1) || this.checkInArea(area, nx-1, ny-1))
|
||||
&& !saw[nx][ny])
|
||||
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])
|
||||
{
|
||||
saw[nx][ny] = 1;
|
||||
dist[nx][ny] = d+1;
|
||||
pointQ.push(new Point(nx, ny));
|
||||
saw[nx][nz] = 1;
|
||||
dist[nx][nz] = d+1;
|
||||
pointQ.push(new PointXZ(nx, nz));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -312,36 +336,41 @@ SmoothElevationPainter.prototype.paint = function(area)
|
||||
{
|
||||
var pt = heightPts[i];
|
||||
var px = pt.x;
|
||||
var py = pt.y;
|
||||
var pz = pt.z;
|
||||
|
||||
if ((this.checkInArea(area, px, py) || this.checkInArea(area, px-1, py)
|
||||
|| this.checkInArea(area, px, py-1) || this.checkInArea(area, px-1, py-1)))
|
||||
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)))
|
||||
{
|
||||
var sum = 8 * newHeight[px][py];
|
||||
var sum = 8 * newHeight[px][pz];
|
||||
var count = 8;
|
||||
|
||||
for (var dx=-1; dx <= 1; dx++)
|
||||
{
|
||||
var nx = px+dx;
|
||||
for (var dy=-1; dy <= 1; dy++)
|
||||
for (var dz=-1; dz <= 1; dz++)
|
||||
{
|
||||
var ny = py+dy;
|
||||
var nz = pz+dz;
|
||||
|
||||
if (g_Map.validH(nx, ny))
|
||||
if (g_Map.validH(nx, nz))
|
||||
{
|
||||
sum += newHeight[nx][ny];
|
||||
sum += newHeight[nx][nz];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_Map.height[px][py] = sum/count;
|
||||
g_Map.height[px][pz] = sum/count;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TerrainPainter
|
||||
//
|
||||
// Class for painting a terrain over an area
|
||||
//
|
||||
// terrain: Terrain placer object
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function TerrainPainter(terrain)
|
||||
@ -355,12 +384,17 @@ TerrainPainter.prototype.paint = function(area)
|
||||
for (var i=0; i < length; i++)
|
||||
{
|
||||
var pt = area.points[i];
|
||||
this.terrain.place(pt.x, pt.y);
|
||||
this.terrain.place(pt.x, pt.z);
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TileClassPainter
|
||||
//
|
||||
// Class for painting tileClasses over an area
|
||||
//
|
||||
// tileClass: TileClass object
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function TileClassPainter(tileClass)
|
||||
@ -374,6 +408,6 @@ TileClassPainter.prototype.paint = function(area)
|
||||
for (var i=0; i < length; i++)
|
||||
{
|
||||
var pt = area.points[i];
|
||||
this.tileClass.add(pt.x, pt.y);
|
||||
this.tileClass.add(pt.x, pt.z);
|
||||
}
|
||||
};
|
||||
|
@ -1,22 +1,30 @@
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ClumpPlacer
|
||||
//
|
||||
// Class for generating a roughly circular clump of points
|
||||
//
|
||||
// size: The average number of points in the clump
|
||||
// coherence: How much the radius of the clump varies (1.0 = circle, 0.0 = very random)
|
||||
// smoothness: How smooth the border of the clump is (1.0 = few "peaks", 0.0 = very jagged)
|
||||
// failfraction: Percentage of place attempts allowed to fail (optional)
|
||||
// x, z: Tile coordinates of placer center (optional)
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ClumpPlacer(size, coherence, smoothness, failFraction, x, y)
|
||||
function ClumpPlacer(size, coherence, smoothness, failFraction, x, z)
|
||||
{
|
||||
this.size = size;
|
||||
this.coherence = coherence;
|
||||
this.smoothness = smoothness;
|
||||
this.failFraction = (failFraction !== undefined ? failFraction : 0);
|
||||
this.x = (x !== undefined ? x : -1);
|
||||
this.y = (y !== undefined ? y : -1);
|
||||
this.z = (z !== undefined ? z : -1);
|
||||
}
|
||||
|
||||
ClumpPlacer.prototype.place = function(constraint)
|
||||
{
|
||||
// Preliminary bounds check
|
||||
if (!g_Map.validT(this.x, this.y) || !constraint.allows(this.x, this.y))
|
||||
if (!g_Map.validT(this.x, this.z) || !constraint.allows(this.x, this.z))
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
@ -37,7 +45,9 @@ ClumpPlacer.prototype.place = function(constraint)
|
||||
var ctrlPts = 1 + Math.floor(1.0/Math.max(this.smoothness,1.0/intPerim));
|
||||
|
||||
if (ctrlPts > radius * 2 * PI)
|
||||
ctrlPts = Math.floor(radius * 2 * PI) + 1;
|
||||
{
|
||||
ctrlPts = Math.floor(radius * 2 * PI) + 1;
|
||||
}
|
||||
|
||||
var noise = new Float32Array(intPerim); //float32
|
||||
var ctrlCoords = new Float32Array(ctrlPts+1); //float32
|
||||
@ -83,7 +93,7 @@ ClumpPlacer.prototype.place = function(constraint)
|
||||
var s = sin(th);
|
||||
var c = cos(th);
|
||||
var xx=this.x;
|
||||
var yy=this.y;
|
||||
var yy=this.z;
|
||||
|
||||
for (var k=0; k < ceil(r); k++)
|
||||
{
|
||||
@ -94,7 +104,7 @@ ClumpPlacer.prototype.place = function(constraint)
|
||||
if (!gotRet[i][j])
|
||||
{ // Only include each point once
|
||||
gotRet[i][j] = 1;
|
||||
retVec.push(new Point(i, j));
|
||||
retVec.push(new PointXZ(i, j));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -111,24 +121,30 @@ ClumpPlacer.prototype.place = function(constraint)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RectPlacer
|
||||
//
|
||||
// Class for generating a rectangular block of points
|
||||
//
|
||||
// x1,z1: Top left corner of block
|
||||
// x2,z2: Bottom right corner of block
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function RectPlacer(x1, y1, x2, y2)
|
||||
function RectPlacer(x1, z1, x2, z2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.z1 = z1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.z2 = z2;
|
||||
|
||||
if (x1 > x2 || y1 > y2)
|
||||
if (x1 > x2 || z1 > z2)
|
||||
error("RectPlacer: incorrect bounds on rect");
|
||||
}
|
||||
|
||||
RectPlacer.prototype.place = function(constraint)
|
||||
{
|
||||
// Preliminary bounds check
|
||||
if (!g_Map.validT(this.x1, this.y1) || !constraint.allows(this.x1, this.y1) ||
|
||||
!g_Map.validT(this.x2, this.y2) || !constraint.allows(this.x2, this.y2))
|
||||
if (!g_Map.validT(this.x1, this.z1) || !constraint.allows(this.x1, this.z1) ||
|
||||
!g_Map.validT(this.x2, this.z2) || !constraint.allows(this.x2, this.z2))
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
@ -136,15 +152,15 @@ RectPlacer.prototype.place = function(constraint)
|
||||
var ret = [];
|
||||
|
||||
var x2 = this.x2;
|
||||
var y2 = this.y2;
|
||||
var z2 = this.z2;
|
||||
|
||||
for (var x=this.x1; x < x2; x++)
|
||||
{
|
||||
for (var y=this.y1; y < y2; y++)
|
||||
for (var z=this.z1; z < z2; z++)
|
||||
{
|
||||
if (g_Map.validT(x, y) && constraint.allows(x, y))
|
||||
if (g_Map.validT(x, z) && constraint.allows(x, z))
|
||||
{
|
||||
ret.push(new Point(x, y));
|
||||
ret.push(new PointXZ(x, z));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -163,7 +179,15 @@ RectPlacer.prototype.place = function(constraint)
|
||||
function ObjectGroupPlacer() {}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SimpleGroup
|
||||
// SimpleObject
|
||||
//
|
||||
// Class specifying a type of entity that can be placed on the map
|
||||
//
|
||||
// type: The entity's template name
|
||||
// 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 SimpleObject(type, minCount, maxCount, minDistance, maxDistance, minAngle, maxAngle)
|
||||
@ -186,7 +210,7 @@ function SimpleObject(type, minCount, maxCount, minDistance, maxDistance, minAng
|
||||
error("SimpleObject: minAngle must be less than or equal to maxAngle");
|
||||
}
|
||||
|
||||
SimpleObject.prototype.place = function(cx, cy, player, avoidSelf, constraint)
|
||||
SimpleObject.prototype.place = function(cx, cz, player, avoidSelf, constraint)
|
||||
{
|
||||
var failCount = 0;
|
||||
var count = randInt(this.minCount, this.maxCount);
|
||||
@ -200,10 +224,10 @@ SimpleObject.prototype.place = function(cx, cy, player, avoidSelf, constraint)
|
||||
var direction = randFloat(0, 2*PI);
|
||||
|
||||
var x = cx + 0.5 + distance*cos(direction);
|
||||
var y = cy + 0.5 + distance*sin(direction);
|
||||
var z = cz + 0.5 + distance*sin(direction);
|
||||
var fail = false; // reset place failure flag
|
||||
|
||||
if (x < 0 || y < 0 || x > g_Map.size || y > g_Map.size)
|
||||
if (!g_Map.validT(x, z))
|
||||
{
|
||||
fail = true;
|
||||
}
|
||||
@ -215,7 +239,7 @@ SimpleObject.prototype.place = function(cx, cy, player, avoidSelf, constraint)
|
||||
for (var i = 0; (i < length) && !fail; i++)
|
||||
{
|
||||
var dx = x - resultObjs[i].x;
|
||||
var dy = y - resultObjs[i].y;
|
||||
var dy = z - resultObjs[i].z;
|
||||
|
||||
if ((dx*dx + dy*dy) < 1)
|
||||
{
|
||||
@ -226,14 +250,14 @@ SimpleObject.prototype.place = function(cx, cy, player, avoidSelf, constraint)
|
||||
|
||||
if (!fail)
|
||||
{
|
||||
if (!constraint.allows(Math.floor(x), Math.floor(y)))
|
||||
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);
|
||||
resultObjs.push(new Entity(this.type, player, x, y, angle));
|
||||
resultObjs.push(new Entity(this.type, player, x, z, angle));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -253,13 +277,25 @@ SimpleObject.prototype.place = function(cx, cy, player, avoidSelf, constraint)
|
||||
return resultObjs;
|
||||
};
|
||||
|
||||
function SimpleGroup(elements, avoidSelf, tileClass, x, y)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SimpleGroup
|
||||
//
|
||||
// Class for placing groups of different objects
|
||||
//
|
||||
// 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 SimpleGroup(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.y = (y !== undefined ? y : -1);
|
||||
this.z = (z !== undefined ? z : -1);
|
||||
}
|
||||
|
||||
SimpleGroup.prototype.place = function(player, constraint)
|
||||
@ -270,7 +306,7 @@ SimpleGroup.prototype.place = function(player, constraint)
|
||||
var length = this.elements.length;
|
||||
for (var i=0; i < length; i++)
|
||||
{
|
||||
var objs = this.elements[i].place(this.x, this.y, player, this.avoidSelf, constraint);
|
||||
var objs = this.elements[i].place(this.x, this.z, player, this.avoidSelf, constraint);
|
||||
if (objs === undefined)
|
||||
{ // Failure
|
||||
return false;
|
||||
@ -289,7 +325,7 @@ SimpleGroup.prototype.place = function(player, constraint)
|
||||
|
||||
if (this.tileClass !== undefined)
|
||||
{ // Round object position to integer
|
||||
this.tileClass.add(Math.floor(resultObjs[i].x), Math.floor(resultObjs[i].y));
|
||||
this.tileClass.add(Math.floor(resultObjs[i].tileX), Math.floor(resultObjs[i].tileZ));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,26 @@
|
||||
function Point(x, y)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// PointXZ
|
||||
//
|
||||
// Class for representing 2D point in tile coordinates (X,Z)
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
function PointXZ(x, z)
|
||||
{
|
||||
this.x = (x !== undefined ? x : 0);
|
||||
this.z = (z !== undefined ? z : 0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Point3D
|
||||
//
|
||||
// Class for representing generic 3D point
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Point3D(x, y, z)
|
||||
{
|
||||
this.x = (x !== undefined ? x : 0);
|
||||
this.y = (y !== undefined ? y : 0);
|
||||
this.z = (z !== undefined ? z : 0);
|
||||
}
|
||||
|
@ -1,27 +1,39 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Terrain
|
||||
//
|
||||
// Abstract class for terrain placers
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Terrain() {}
|
||||
|
||||
Terrain.prototype.place = function(x, y)
|
||||
Terrain.prototype.place = function(x, z)
|
||||
{
|
||||
// Clear old array
|
||||
g_Map.terrainObjects[x][y] = [];
|
||||
g_Map.terrainObjects[x][z] = undefined;
|
||||
|
||||
this.placeNew(x, y);
|
||||
this.placeNew(x, z);
|
||||
};
|
||||
|
||||
Terrain.prototype.placeNew = function() {};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SimpleTerrain
|
||||
//
|
||||
// Class for placing simple terrains
|
||||
// (one texture and one tree per tile)
|
||||
//
|
||||
// texture: Terrain texture name
|
||||
// treeType: Optional template of the tree entity for this terrain
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function SimpleTerrain(texture, treeType)
|
||||
{
|
||||
if (texture === undefined)
|
||||
{
|
||||
error("SimpleTerrain: texture not defined");
|
||||
}
|
||||
|
||||
this.texture = texture;
|
||||
this.treeType = treeType;
|
||||
@ -29,29 +41,38 @@ function SimpleTerrain(texture, treeType)
|
||||
|
||||
SimpleTerrain.prototype = new Terrain();
|
||||
SimpleTerrain.prototype.constructor = SimpleTerrain;
|
||||
SimpleTerrain.prototype.placeNew = function(x, y)
|
||||
SimpleTerrain.prototype.placeNew = function(x, z)
|
||||
{
|
||||
if (this.treeType !== undefined)
|
||||
g_Map.terrainObjects[x][y].push(new Entity(this.treeType, 0, x+0.5, y+0.5, randFloat()*PI));
|
||||
{
|
||||
g_Map.terrainObjects[x][z] = new Entity(this.treeType, 0, x+0.5, z+0.5, randFloat()*PI);
|
||||
}
|
||||
|
||||
g_Map.texture[x][y] = g_Map.getID(this.texture);
|
||||
g_Map.texture[x][z] = g_Map.getTextureID(this.texture);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// RandomTerrain
|
||||
//
|
||||
// Class for placing random SimpleTerrains
|
||||
//
|
||||
// terrains: Array of SimpleTerrain objects
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function RandomTerrain(terrains)
|
||||
{
|
||||
if (!(terrains instanceof Array) || !terrains.length)
|
||||
{
|
||||
error("Invalid terrains array");
|
||||
}
|
||||
|
||||
this.terrains = terrains;
|
||||
}
|
||||
|
||||
RandomTerrain.prototype = new Terrain();
|
||||
RandomTerrain.prototype.constructor = RandomTerrain;
|
||||
RandomTerrain.prototype.placeNew = function(x, y)
|
||||
RandomTerrain.prototype.placeNew = function(x, z)
|
||||
{
|
||||
this.terrains[randInt(this.terrains.length)].placeNew(x, y);
|
||||
this.terrains[randInt(this.terrains.length)].placeNew(x, z);
|
||||
};
|
||||
|
@ -1,5 +1,8 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// RangeOp
|
||||
//
|
||||
// Class for efficiently finding number of points within a range
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function RangeOp(size)
|
||||
@ -60,6 +63,10 @@ RangeOp.prototype.get = function(start, end)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// TileClass
|
||||
//
|
||||
// Class for representing terrain types and containing all the tiles
|
||||
// within that type
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function TileClass(size, id)
|
||||
@ -76,22 +83,22 @@ function TileClass(size, id)
|
||||
}
|
||||
}
|
||||
|
||||
TileClass.prototype.add = function(x, y)
|
||||
TileClass.prototype.add = function(x, z)
|
||||
{
|
||||
if (!this.inclusionCount[x][y])
|
||||
if (!this.inclusionCount[x][z])
|
||||
{
|
||||
this.rangeCount[y].add(x, 1);
|
||||
this.rangeCount[z].add(x, 1);
|
||||
}
|
||||
|
||||
this.inclusionCount[x][y]++;
|
||||
this.inclusionCount[x][z]++;
|
||||
};
|
||||
|
||||
TileClass.prototype.remove = function(x, y)
|
||||
TileClass.prototype.remove = function(x, z)
|
||||
{
|
||||
this.inclusionCount[x][y]--;
|
||||
if(!this.inclusionCount[x][y])
|
||||
this.inclusionCount[x][z]--;
|
||||
if(!this.inclusionCount[x][z])
|
||||
{
|
||||
this.rangeCount[y].add(x, -1);
|
||||
this.rangeCount[z].add(x, -1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Vector2D
|
||||
//
|
||||
// Class for representing and manipulating 2D vectors
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: Type errors if v not instanceof Vector classes
|
||||
// TODO: Possible implement in C++
|
||||
// TODO: Possibly implement in C++
|
||||
|
||||
function Vector2D(x, y)
|
||||
{
|
||||
@ -68,13 +71,16 @@ Vector2D.prototype.normalize = function()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Vector3D
|
||||
//
|
||||
// Class for representing and manipulating 3D vectors
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
function Vector3D(x, y, z)
|
||||
{
|
||||
if (arguments.length == 3)
|
||||
{
|
||||
this.set(x, y, z);
|
||||
this.set(x, y, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -57,13 +57,13 @@
|
||||
</playercolours>
|
||||
|
||||
<mapsizes>
|
||||
<size name="Tiny" patches="8"/>
|
||||
<size name="Small" patches="12"/>
|
||||
<size name="Medium" patches="16"/>
|
||||
<size name="Normal" patches="20"/>
|
||||
<size name="Large" patches="24"/>
|
||||
<size name="Very Large" patches="28"/>
|
||||
<size name="Giant" patches="32"/>
|
||||
<size name="Tiny" tiles="128"/>
|
||||
<size name="Small" tiles="192"/>
|
||||
<size name="Medium" tiles="256"/>
|
||||
<size name="Normal" tiles="320"/>
|
||||
<size name="Large" tiles="384"/>
|
||||
<size name="Very Large" tiles="448"/>
|
||||
<size name="Giant" tiles="512"/>
|
||||
</mapsizes>
|
||||
|
||||
</lists>
|
||||
|
@ -395,10 +395,10 @@ function init(window)
|
||||
boxSizer.add(10, 0);
|
||||
// TODO: Get this data from single location (currently specified here, Atlas\lists.xml, and game setup)
|
||||
var sizeNames = ["Tiny", "Small", "Medium", "Normal", "Large", "Very Large", "Giant"];
|
||||
var sizePatches = [8, 12, 16, 20, 24, 28, 32];
|
||||
var sizeTiles = [128, 192, 256, 320, 384, 448, 512];
|
||||
var sizeChoice = new wxChoice(rmsPanel, -1, wxDefaultPosition, wxDefaultSize, sizeNames);
|
||||
var numChoices = sizeNames.length;
|
||||
sizeChoice.toolTip = 'Select the desired map size\n'+sizeNames[0]+' = '+sizePatches[0]+' patches, '+sizeNames[numChoices-1]+' = '+sizePatches[numChoices-1]+' patches';
|
||||
sizeChoice.toolTip = 'Select the desired map size\n'+sizeNames[0]+' = '+sizeTiles[0]+' patches, '+sizeNames[numChoices-1]+' = '+sizeTiles[numChoices-1]+' patches';
|
||||
sizeChoice.selection = 0;
|
||||
boxSizer.add(sizeChoice, 1);
|
||||
rmsSizer.add(boxSizer, 0, wxStretch.EXPAND | wxDirection.ALL, 2);
|
||||
@ -430,18 +430,14 @@ function init(window)
|
||||
terrainArray.push(RMSData.BaseTerrain);
|
||||
}
|
||||
|
||||
// Stringify player data
|
||||
var pDataStr = JSON.stringify(Atlas.State.mapSettings.settings.PlayerData);
|
||||
// Complete map settings
|
||||
Atlas.State.mapSettings.settings.Seed = Atlas.State.Seed ? Atlas.State.Seed : 0;
|
||||
Atlas.State.mapSettings.settings.Size = sizeTiles[sizeChoice.selection];
|
||||
Atlas.State.mapSettings.settings.BaseTerrain = terrainArray;
|
||||
Atlas.State.mapSettings.settings.BaseHeight = RMSData.BaseHeight;
|
||||
|
||||
// Generate map
|
||||
var ret = Atlas.Message.GenerateMap(
|
||||
RMSData.Script,
|
||||
sizePatches[sizeChoice.selection],
|
||||
Atlas.State.Seed ? Atlas.State.Seed : 0,
|
||||
terrainArray,
|
||||
RMSData.BaseHeight,
|
||||
pDataStr
|
||||
);
|
||||
var ret = Atlas.Message.GenerateMap(RMSData.Script, JSON.stringify(Atlas.State.mapSettings.settings));
|
||||
|
||||
// Check for error
|
||||
if (ret.status < 0)
|
||||
|
@ -27,7 +27,6 @@ struct Entity
|
||||
float positionX;
|
||||
float positionZ;
|
||||
float orientationY;
|
||||
bool isActor;
|
||||
};
|
||||
|
||||
|
||||
|
@ -252,9 +252,8 @@ int CMapReader::ApplyData()
|
||||
{
|
||||
if (m_PatchesPerSide == 0)
|
||||
{
|
||||
debug_warn(L"Map has no terrain data");
|
||||
return -1;
|
||||
// we'll probably crash when trying to use this map later
|
||||
throw PSERROR_Game_World_MapLoadFailed("Error loading map: no terrain data.\nCheck application log for details.");
|
||||
}
|
||||
|
||||
if (!only_xml)
|
||||
@ -1128,7 +1127,7 @@ int CMapReader::ParseTerrain()
|
||||
{ LOGERROR(L"CMapReader::ParseTerrain() failed to get '%hs' property", #prop);\
|
||||
throw PSERROR_Game_World_MapLoadFailed("Error parsing terrain data.\nCheck application log for details"); }
|
||||
|
||||
int size;
|
||||
size_t size;
|
||||
GET_TERRAIN_PROPERTY(size, size)
|
||||
|
||||
m_PatchesPerSide = size / PATCH_SIZE;
|
||||
@ -1153,12 +1152,24 @@ int CMapReader::ParseTerrain()
|
||||
// build tile data
|
||||
m_Tiles.resize(SQR(size));
|
||||
|
||||
// flat array of tile descriptors
|
||||
std::vector<CMapIO::STileDesc> tileData;
|
||||
GET_TERRAIN_PROPERTY(tileData, tileData)
|
||||
|
||||
for (size_t i = 0; i < tileData.size(); ++i)
|
||||
debug_assert(SQR(size) == tileData.size());
|
||||
|
||||
// reorder by patches and store
|
||||
for (size_t x = 0; x < size; ++x)
|
||||
{
|
||||
m_Tiles[i] = tileData[i];
|
||||
size_t patchX = x / PATCH_SIZE;
|
||||
size_t offX = x % PATCH_SIZE;
|
||||
for (size_t y = 0; y < size; ++y)
|
||||
{
|
||||
size_t patchY = y / PATCH_SIZE;
|
||||
size_t offY = y % PATCH_SIZE;
|
||||
|
||||
m_Tiles[(patchY * m_PatchesPerSide + patchX) * SQR(PATCH_SIZE) + (offY * PATCH_SIZE + offX)] = tileData[y*size + x];
|
||||
}
|
||||
}
|
||||
|
||||
// reset generator state
|
||||
|
@ -970,7 +970,7 @@ bool Autostart(const CmdLineArgs& args)
|
||||
* -autostart-client -- multiplayer client mode
|
||||
* -autostart-ip=127.0.0.1 -- multiplayer connect to 127.0.0.1
|
||||
* -autostart-random=104 -- random map, optional seed value = 104 (default is 0, random is -1)
|
||||
* -autostart-size=12 -- random map size in patches = 12 (default is 12)
|
||||
* -autostart-size=192 -- random map size in tiles = 192 (default is 192)
|
||||
*
|
||||
* Examples:
|
||||
* -autostart=Acropolis -autostart-host -autostart-players=2 -- Host game on Acropolis map, 2 players
|
||||
@ -1030,8 +1030,8 @@ bool Autostart(const CmdLineArgs& args)
|
||||
throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details.");
|
||||
}
|
||||
|
||||
// Get optional map size argument (default 12)
|
||||
uint mapSize = 12;
|
||||
// Get optional map size argument (default 192)
|
||||
uint mapSize = 192;
|
||||
if (args.Has("autostart-size"))
|
||||
{
|
||||
CStr size = args.Get("autostart-size");
|
||||
|
@ -149,23 +149,18 @@ template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, jsval v, Entit
|
||||
if (!JS_ValueToObject(cx, v, &obj) || obj == NULL)
|
||||
FAIL("Argument must be an object");
|
||||
|
||||
jsval name, id, player, x, z, orient, actor;
|
||||
jsval name, id, player, x, z, orient;
|
||||
|
||||
if(!JS_GetProperty(cx, obj, "isActor", &actor) || !FromJSVal(cx, actor, out.isActor))
|
||||
FAIL("Failed to read Entity.isActor property");
|
||||
|
||||
if (!out.isActor)
|
||||
if(!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID))
|
||||
FAIL("Failed to read Entity.player property");
|
||||
|
||||
if(!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID))
|
||||
FAIL("Failed to read Entity.player property");
|
||||
if (!JS_GetProperty(cx, obj, "name", &name) || !FromJSVal(cx, name, out.templateName))
|
||||
FAIL("Failed to read Entity.name property");
|
||||
if (!JS_GetProperty(cx, obj, "id", &id) || !FromJSVal(cx, id, out.entityID))
|
||||
FAIL("Failed to read Entity.id property");
|
||||
if (!JS_GetProperty(cx, obj, "x", &x) || !FromJSVal(cx, x, out.positionX))
|
||||
FAIL("Failed to read Entity.x property");
|
||||
if (!JS_GetProperty(cx, obj, "y", &z) || !FromJSVal(cx, z, out.positionZ))
|
||||
FAIL("Failed to read Entity.y property");
|
||||
if (!JS_GetProperty(cx, obj, "z", &z) || !FromJSVal(cx, z, out.positionZ))
|
||||
FAIL("Failed to read Entity.z property");
|
||||
if (!JS_GetProperty(cx, obj, "orientation", &orient) || !FromJSVal(cx, orient, out.orientationY))
|
||||
FAIL("Failed to read Entity.orientation property");
|
||||
|
||||
@ -178,11 +173,9 @@ template<> bool ScriptInterface::FromJSVal<CMapIO::STileDesc>(JSContext* cx, jsv
|
||||
if (!JS_ValueToObject(cx, v, &obj) || obj == NULL)
|
||||
FAIL("Argument must be an object");
|
||||
|
||||
jsval texIdx1, texIdx2, priority;
|
||||
if (!JS_GetProperty(cx, obj, "texIdx1", &texIdx1) || !FromJSVal(cx, texIdx1, out.m_Tex1Index))
|
||||
jsval texIdx, priority;
|
||||
if (!JS_GetProperty(cx, obj, "idx", &texIdx) || !FromJSVal(cx, texIdx, out.m_Tex1Index))
|
||||
FAIL("Failed to read CMapIO::STileDesc.m_Tex1Index property");
|
||||
if (!JS_GetProperty(cx, obj, "texIdx2", &texIdx2) || !FromJSVal(cx, texIdx2, out.m_Tex2Index))
|
||||
FAIL("Failed to read CMapIO::STileDesc.m_Tex2Index property");
|
||||
if (!JS_GetProperty(cx, obj, "priority", &priority) || !FromJSVal(cx, priority, out.m_Priority))
|
||||
FAIL("Failed to read CMapIO::STileDesc.m_Priority property");
|
||||
|
||||
|
@ -492,6 +492,8 @@ template jsval ScriptInterface::ToJSVal<wxMouseEvent>(JSContext*, wxMouseEvent c
|
||||
template jsval ScriptInterface::ToJSVal<int>(JSContext*, int const&);
|
||||
template jsval ScriptInterface::ToJSVal<float>(JSContext*, float const&);
|
||||
template jsval ScriptInterface::ToJSVal<std::vector<int> >(JSContext*, std::vector<int> const&);
|
||||
template jsval ScriptInterface::ToJSVal<size_t>(JSContext*, size_t const&);
|
||||
template jsval ScriptInterface::ToJSVal<std::vector<wxString> >(JSContext*, std::vector<wxString> const&);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -53,16 +53,16 @@ NewDialog::NewDialog(wxWindow* parent, const wxString& title, const wxSize& size
|
||||
AtObj sizes(Datafile::ReadList("mapsizes"));
|
||||
for (AtIter s = sizes["size"]; s.defined(); ++s)
|
||||
{
|
||||
if (s["@name"].defined() && s["@patches"].defined())
|
||||
if (s["@name"].defined() && s["@tiles"].defined())
|
||||
{
|
||||
m_SizeArray.Add(wxString(s["@name"]));
|
||||
|
||||
size_t patch;
|
||||
size_t size;
|
||||
std::wstringstream stream;
|
||||
stream << (std::wstring)s["@patches"];
|
||||
stream >> patch;
|
||||
stream << (std::wstring)s["@tiles"];
|
||||
stream >> size;
|
||||
|
||||
m_PatchesArray.push_back(patch);
|
||||
m_TilesArray.push_back(size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ void NewDialog::OnHeightChange(wxSpinEvent& event)
|
||||
|
||||
size_t NewDialog::GetSelectedSize()
|
||||
{
|
||||
return m_PatchesArray[m_SelectedSize];
|
||||
return m_TilesArray[m_SelectedSize];
|
||||
}
|
||||
|
||||
size_t NewDialog::GetBaseHeight()
|
||||
|
@ -45,7 +45,7 @@ private:
|
||||
size_t m_BaseHeight;
|
||||
|
||||
wxArrayString m_SizeArray;
|
||||
std::vector<size_t> m_PatchesArray;
|
||||
std::vector<size_t> m_TilesArray;
|
||||
|
||||
};
|
||||
|
||||
|
@ -691,22 +691,26 @@ void ScenarioEditor::OnNew(wxCommandEvent& WXUNUSED(event))
|
||||
wxBusyInfo busy(_("Creating blank map"));
|
||||
|
||||
// Generate new blank map
|
||||
size_t patches = dlg.GetSelectedSize();
|
||||
size_t tiles = dlg.GetSelectedSize();
|
||||
size_t height = dlg.GetBaseHeight();
|
||||
|
||||
// Get terrain texture
|
||||
// TODO: Support choosing multiple textures
|
||||
std::vector<std::wstring> textures;
|
||||
std::wstring baseTexture(g_SelectedTexture.wc_str());
|
||||
textures.push_back(baseTexture);
|
||||
std::vector<wxString> textures;
|
||||
textures.push_back(g_SelectedTexture);
|
||||
|
||||
// Get player data
|
||||
std::string pData;
|
||||
m_ScriptInterface.Eval(_T("JSON.stringify(Atlas.State.mapSettings.settings.PlayerData)"), pData);
|
||||
// TODO: This seems like a nasty way to do this
|
||||
std::string settings;
|
||||
m_ScriptInterface.SetValue(_T("Atlas.State.mapSettings.settings.Size"), tiles);
|
||||
m_ScriptInterface.SetValue(_T("Atlas.State.mapSettings.settings.Seed"), 0);
|
||||
m_ScriptInterface.SetValue(_T("Atlas.State.mapSettings.settings.BaseTerrain"), textures);
|
||||
m_ScriptInterface.SetValue(_T("Atlas.State.mapSettings.settings.BaseHeight"), height);
|
||||
m_ScriptInterface.Eval(_T("JSON.stringify(Atlas.State.mapSettings.settings)"), settings);
|
||||
|
||||
// Generate map
|
||||
// Script name, size (patches), seed, base terrain(s), base height, player data
|
||||
qGenerateMap qry(L"blank.js", patches, 0, textures, height, pData);
|
||||
qGenerateMap qry(L"blank.js", settings);
|
||||
|
||||
|
||||
|
||||
// Wait for map generation to finish
|
||||
qry.Post();
|
||||
|
@ -79,22 +79,12 @@ QUERYHANDLER(GenerateMap)
|
||||
// Random map
|
||||
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
|
||||
|
||||
CScriptValRooted settings = scriptInterface.ParseJSON(*msg->settings);
|
||||
|
||||
CScriptValRooted attrs;
|
||||
scriptInterface.Eval("({})", attrs);
|
||||
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("random"));
|
||||
scriptInterface.SetProperty(attrs.get(), "script", std::wstring(*msg->script));
|
||||
|
||||
CScriptValRooted settings;
|
||||
scriptInterface.Eval("({})", settings);
|
||||
scriptInterface.SetProperty(settings.get(), "Size", (int)msg->size);
|
||||
scriptInterface.SetProperty(settings.get(), "Seed", (int)msg->seed);
|
||||
scriptInterface.SetProperty(settings.get(), "BaseTerrain", std::vector<std::wstring>(*msg->terrain));
|
||||
scriptInterface.SetProperty(settings.get(), "BaseHeight", (int)msg->height);
|
||||
scriptInterface.SetProperty(settings.get(), "CircularMap", true); // now default to circular map
|
||||
|
||||
CScriptValRooted pData = scriptInterface.ParseJSON(*msg->playerData);
|
||||
scriptInterface.SetProperty(settings.get(), "PlayerData", pData);
|
||||
|
||||
scriptInterface.SetProperty(attrs.get(), "script", std::wstring(*msg->filename));
|
||||
scriptInterface.SetProperty(attrs.get(), "settings", settings, false);
|
||||
|
||||
try
|
||||
|
@ -133,14 +133,10 @@ MESSAGE(ResizeScreen,
|
||||
// Messages for map panel
|
||||
|
||||
QUERY(GenerateMap,
|
||||
((std::wstring, script)) // name of script
|
||||
((int, size)) // size in number of patches
|
||||
((int, seed)) // seed for rng
|
||||
((std::vector<std::wstring>, terrain)) // base terrain(s)
|
||||
((int, height)) // base height
|
||||
((std::string, playerData)) // JSON player data
|
||||
((std::wstring, filename)) // random map script filename
|
||||
((std::string, settings)) // map settings as JSON string
|
||||
,
|
||||
((int, status)) // Status code, 0 for success, or < 0 for failure
|
||||
((int, status))
|
||||
);
|
||||
|
||||
MESSAGE(LoadMap,
|
||||
|
Loading…
Reference in New Issue
Block a user