copy badosu maps into community mod, need to check feldmap compatibibility.
This commit is contained in:
parent
bcc27a8564
commit
ae94c04bac
403
community-mod/maps/random/bad_hyrcanian_shores.js
Normal file
403
community-mod/maps/random/bad_hyrcanian_shores.js
Normal file
@ -0,0 +1,403 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
const tPrimary = "temp_grass_long";
|
||||
const tGrass = ["temp_grass_clovers"];
|
||||
const tGrassPForest = "temp_plants_bog";
|
||||
const tGrassDForest = "alpine_dirt_grass_50";
|
||||
const tCliff = ["temp_cliff_a", "temp_cliff_b"];
|
||||
const tGrassA = "temp_grass_d";
|
||||
const tGrassB = "temp_grass_c";
|
||||
const tGrassC = "temp_grass_clovers_2";
|
||||
const tHill = ["temp_highlands", "temp_grass_long_b"];
|
||||
const tRoad = "temp_road";
|
||||
const tRoadWild = "temp_road_overgrown";
|
||||
const tGrassPatch = "temp_grass_plants";
|
||||
const tShore = "medit_sand_wet";
|
||||
const tWater = "medit_sand_wet";
|
||||
|
||||
const oPoplar = "gaia/tree/poplar";
|
||||
const oPalm = "gaia/tree/cretan_date_palm_short";
|
||||
const oApple = "gaia/fruit/apple";
|
||||
const oOak = "gaia/tree/oak";
|
||||
const oBerryBush = "gaia/fruit/berry_01";
|
||||
const oDeer = "gaia/fauna_deer";
|
||||
const oFish = "gaia/fish/generic";
|
||||
const oGoat = "gaia/fauna_goat";
|
||||
const oBoar = "gaia/fauna_boar";
|
||||
const oStoneLarge = "gaia/rock/temperate_large";
|
||||
const oStoneSmall = "gaia/rock/temperate_small";
|
||||
const oMetalLarge = "gaia/ore/temperate_large";
|
||||
|
||||
const oFruitBush = oBerryBush;
|
||||
const oMainHuntableAnimal = oDeer;
|
||||
const oSecondaryHuntableAnimal = oGoat;
|
||||
|
||||
const aGrass = "actor|props/flora/grass_soft_large_tall.xml";
|
||||
const aGrassShort = "actor|props/flora/grass_soft_large.xml";
|
||||
const aRockLarge = "actor|geology/stone_granite_large.xml";
|
||||
const aRockMedium = "actor|geology/stone_granite_med.xml";
|
||||
const aBushMedium = "actor|props/flora/bush_medit_me_lush.xml";
|
||||
const aBushSmall = "actor|props/flora/bush_medit_sm_lush.xml";
|
||||
|
||||
const pForestD = [tGrassDForest + TERRAIN_SEPARATOR + oPoplar, tGrassDForest];
|
||||
const pForestP = [tGrassPForest + TERRAIN_SEPARATOR + oOak, tGrassPForest];
|
||||
|
||||
const heightSeaGround1 = -3;
|
||||
const heightShore1 = -1.5;
|
||||
const heightShore2 = 0;
|
||||
const heightLand = 1;
|
||||
const heightOffsetBump = 4;
|
||||
const heightHill = 15;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tPrimary);
|
||||
|
||||
const mapCenter = g_Map.getCenter();
|
||||
const mapBounds = g_Map.getBounds();
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clWater = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
const clHighlands = g_Map.createTileClass();
|
||||
|
||||
const waterPosition = fractionToTiles(0.25)
|
||||
const highlandsPosition = fractionToTiles(0.75);
|
||||
|
||||
const startAngle = randomAngle();
|
||||
const playerPlacements = placeOpposingTeams(fractionToTiles(0.25), -startAngle, mapCenter)
|
||||
const [playerIDs, playerPositions] = playerPlacements;
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oBerryBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oOak,
|
||||
"count": 2
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
Engine.SetProgress(10);
|
||||
|
||||
paintRiver({
|
||||
"parallel": true,
|
||||
"start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(startAngle, mapCenter),
|
||||
"end": new Vector2D(mapBounds.right, mapBounds.top).rotateAround(startAngle, mapCenter),
|
||||
"width": (numPlayers === 2 ? 2.5 : 2) * waterPosition,
|
||||
"fadeDist": scaleByMapSize(6, 25),
|
||||
"deviation": 0,
|
||||
"heightRiverbed": heightSeaGround1,
|
||||
"heightLand": heightLand,
|
||||
"meanderShort": 20,
|
||||
"meanderLong": 0,
|
||||
"waterFunc": (position, height, riverFraction) => {
|
||||
if (height < heightShore2)
|
||||
clWater.add(position);
|
||||
|
||||
createTerrain(height < heightShore1 ? tWater : tShore).place(position);
|
||||
}
|
||||
});
|
||||
Engine.SetProgress(20);
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i)
|
||||
{
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oFish, 3, 3, 0, 4)], true, clFood),
|
||||
0,
|
||||
stayClasses(clWater, 3),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(3, Vector2D.add(playerPositions[i], new Vector2D(scaleByMapSize(46, 90)).rotate(startAngle - Math.PI / 2))).place(new NullConstraint()))]
|
||||
);
|
||||
Engine.SetProgress(20 + i);
|
||||
}
|
||||
|
||||
const mineralConstraints = avoidClasses(clWater, 3);
|
||||
placeBalancedMinerals(playerPositions, mineralConstraints);
|
||||
|
||||
Engine.SetProgress(30);
|
||||
|
||||
placeBalancedFood(playerPlacements, avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10));
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
g_Map.log("Marking highlands area");
|
||||
createArea(
|
||||
new ConvexPolygonPlacer(
|
||||
[
|
||||
new Vector2D(mapBounds.left, mapBounds.top - highlandsPosition),
|
||||
new Vector2D(mapBounds.right, mapBounds.top - highlandsPosition),
|
||||
new Vector2D(mapBounds.left, mapBounds.bottom),
|
||||
new Vector2D(mapBounds.right, mapBounds.bottom)
|
||||
].map(pos => pos.rotateAround(startAngle, mapCenter)),
|
||||
Infinity),
|
||||
new TileClassPainter(clHighlands));
|
||||
|
||||
Engine.SetProgress(43);
|
||||
|
||||
g_Map.log("Creating fish");
|
||||
for (let i = 0; i < scaleByMapSize(50, 80); ++i)
|
||||
createObjectGroupsDeprecated(
|
||||
new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood),
|
||||
0,
|
||||
[stayClasses(clWater, 8), avoidClasses(clFood, 10)],
|
||||
numPlayers,
|
||||
50);
|
||||
Engine.SetProgress(46);
|
||||
|
||||
g_Map.log("Creating bumps");
|
||||
createAreas(
|
||||
new ClumpPlacer(scaleByMapSize(10, 60), 0.3, 0.06, Infinity),
|
||||
new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3),
|
||||
stayClasses(clHighlands, 1),
|
||||
scaleByMapSize(300, 600));
|
||||
|
||||
Engine.SetProgress(49);
|
||||
|
||||
g_Map.log("Creating hills");
|
||||
createAreas(
|
||||
new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity),
|
||||
[
|
||||
new LayeredPainter([tCliff, tHill], [2]),
|
||||
new SmoothElevationPainter(ELEVATION_SET, heightHill, 2),
|
||||
new TileClassPainter(clHill)
|
||||
],
|
||||
avoidClasses(clPlayer, 20, clWater, 5, clHill, 15, clHighlands, 5, clRock, 6, clMetal, 6, clFood, 2),
|
||||
scaleByMapSize(1, 4) * numPlayers);
|
||||
|
||||
Engine.SetProgress(52);
|
||||
|
||||
g_Map.log("Creating mainland forests");
|
||||
var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.7);
|
||||
var types = [
|
||||
[[tGrassDForest, tGrass, pForestD], [tGrassDForest, pForestD]]
|
||||
];
|
||||
var size = forestTrees * 1.3 / (scaleByMapSize(2,8) * numPlayers);
|
||||
var num = Math.floor(0.7 * size / types.length);
|
||||
for (let type of types)
|
||||
createAreas(
|
||||
new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity),
|
||||
[
|
||||
new LayeredPainter(type, [2]),
|
||||
new TileClassPainter(clForest)
|
||||
],
|
||||
avoidClasses(clPlayer, 20, clWater, 3, clForest, 10, clHill, 0, clBaseResource, 3, clRock, 2, clMetal, 2),
|
||||
num);
|
||||
Engine.SetProgress(55);
|
||||
|
||||
g_Map.log("Creating highland forests");
|
||||
var types = [
|
||||
[[tGrassDForest, tGrass, pForestP], [tGrassDForest, pForestP]]
|
||||
];
|
||||
var size = forestTrees / (scaleByMapSize(2,8) * numPlayers);
|
||||
var num = Math.floor(size / types.length);
|
||||
for (let type of types)
|
||||
createAreas(
|
||||
new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity),
|
||||
[
|
||||
new LayeredPainter(type, [2]),
|
||||
new TileClassPainter(clForest)
|
||||
],
|
||||
avoidClasses(clPlayer, 20, clWater, 3, clForest, 2, clHill, 0, clMetal, 2, clRock, 2),
|
||||
num);
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)])
|
||||
createAreas(
|
||||
new ClumpPlacer(size, 0.3, 0.06, 0.5),
|
||||
[
|
||||
new LayeredPainter([[tGrass, tGrassA], [tGrassA, tGrassB], [tGrassB, tGrassC]], [1, 1]),
|
||||
new TileClassPainter(clDirt)
|
||||
],
|
||||
avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 4),
|
||||
scaleByMapSize(15, 45));
|
||||
Engine.SetProgress(63);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)])
|
||||
createAreas(
|
||||
new ClumpPlacer(size, 0.3, 0.06, 0.5),
|
||||
new LayeredPainter([tGrassC, tGrassPatch], [2]),
|
||||
avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6, clBaseResource, 6),
|
||||
scaleByMapSize(15, 45));
|
||||
|
||||
Engine.SetProgress(66);
|
||||
|
||||
var group;
|
||||
g_Map.log("Creating stone mines");
|
||||
var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
[avoidClasses(clWater, 0, clForest, 1, clPlayer, 60, clRock, 10, clHill, 2)],
|
||||
scaleByMapSize(4,16), 100
|
||||
);
|
||||
|
||||
Engine.SetProgress(69);
|
||||
|
||||
g_Map.log("Creating small stone quarries");
|
||||
group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
[avoidClasses(clWater, 0, clForest, 1, clPlayer, 60, clRock, 10, clHill, 2)],
|
||||
scaleByMapSize(4,16), 100
|
||||
);
|
||||
|
||||
Engine.SetProgress(73);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
[avoidClasses(clWater, 0, clForest, 1, clPlayer, 60, clMetal, 10, clRock, 5, clHill, 2)],
|
||||
scaleByMapSize(4,16), 100
|
||||
);
|
||||
|
||||
Engine.SetProgress(76);
|
||||
|
||||
g_Map.log("Creating small decorative rocks");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aRockMedium, 1,3, 0,1)],
|
||||
true
|
||||
);
|
||||
createObjectGroupsDeprecated(
|
||||
group, 0,
|
||||
avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0),
|
||||
scaleByMapSize(16, 262), 50
|
||||
);
|
||||
Engine.SetProgress(79);
|
||||
|
||||
g_Map.log("Creating large decorative rocks");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
|
||||
true
|
||||
);
|
||||
createObjectGroupsDeprecated(
|
||||
group, 0,
|
||||
avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0),
|
||||
scaleByMapSize(8, 131), 50
|
||||
);
|
||||
Engine.SetProgress(82);
|
||||
|
||||
g_Map.log("Creating deer");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oDeer, 5,7, 0,4)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 0, clForest, 0, clPlayer, 50, clHill, 0, clFood, 5),
|
||||
6 * numPlayers, 50
|
||||
);
|
||||
Engine.SetProgress(85);
|
||||
|
||||
g_Map.log("Creating sheep");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oGoat, 2,3, 0,2)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 0, clForest, 0, clPlayer, 50, clHill, 0, clFood, 20),
|
||||
3 * numPlayers, 50
|
||||
);
|
||||
Engine.SetProgress(88);
|
||||
|
||||
g_Map.log("Creating berry bush");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oBerryBush, 5,7, 0,4)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 6, clForest, 0, clPlayer, 45, clHill, 1, clFood, 10),
|
||||
randIntInclusive(1, 4) * numPlayers + 2, 50
|
||||
);
|
||||
Engine.SetProgress(92);
|
||||
|
||||
g_Map.log("Creating boar");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oBoar, 2,3, 0,2)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 0, clForest, 0, clPlayer, 50, clHill, 0, clFood, 20),
|
||||
2 * numPlayers, 50
|
||||
);
|
||||
|
||||
createStragglerTrees(
|
||||
[oPoplar, oPalm, oApple],
|
||||
avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 38, clMetal, 6, clRock, 6),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
for (let playerPosition of playerPositions) {
|
||||
const playerArea = new Area(new DiskPlacer(40, playerPosition).place(avoidClasses(clWater, 1, clForest, 1, clHill, 1, clMetal, 6, clRock, 6, clPlayer, 15, clFood, 4)));
|
||||
|
||||
for (let templateName of [oPoplar, oPalm]) {
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(templateName, 1, 1, 0, 3)], true, clForest),
|
||||
0,
|
||||
new NullConstraint(),
|
||||
25, 400,
|
||||
[playerArea]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
g_Map.log("Creating small grass tufts");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0),
|
||||
scaleByMapSize(13, 200)
|
||||
);
|
||||
|
||||
g_Map.log("Creating large grass tufts");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aGrass, 2,4, 0,1.8, -Math.PI / 8, Math.PI / 8), new SimpleObject(aGrassShort, 3,6, 1.2,2.5, -Math.PI / 8, Math.PI / 8)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0),
|
||||
scaleByMapSize(13, 200)
|
||||
);
|
||||
Engine.SetProgress(95);
|
||||
|
||||
g_Map.log("Creating bushes");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1),
|
||||
scaleByMapSize(13, 200), 50
|
||||
);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
|
||||
|
||||
setSkySet("cirrus");
|
||||
setWaterColor(0.114, 0.192, 0.463);
|
||||
setWaterTint(0.255, 0.361, 0.651);
|
||||
setWaterWaviness(2.0);
|
||||
setWaterType("ocean");
|
||||
setWaterMurkiness(0.83);
|
||||
|
||||
g_Map.ExportMap();
|
10
community-mod/maps/random/bad_hyrcanian_shores.json
Normal file
10
community-mod/maps/random/bad_hyrcanian_shores.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Balanced Hyrcanian Shores",
|
||||
"Script" : "bad_hyrcanian_shores.js",
|
||||
"Description" : "Each player starts in a coastal area between forested hills and the Caspian Sea. Resources are distributed evenly to players.",
|
||||
"Preview" : "badhyrcanian.png",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
285
community-mod/maps/random/badcontinent.js
Normal file
285
community-mod/maps/random/badcontinent.js
Normal file
@ -0,0 +1,285 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
const tShore = g_Terrains.shore;
|
||||
const tWater = g_Terrains.water;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oFish = g_Gaia.fish;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightSeaGround = -5;
|
||||
const heightLand = 3;
|
||||
|
||||
var g_Map = new RandomMap(heightSeaGround, tWater);
|
||||
|
||||
const numPlayers = getNumPlayers();
|
||||
const mapSize = g_Map.getSize();
|
||||
const mapCenter = g_Map.getCenter();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
const clLand = g_Map.createTileClass();
|
||||
|
||||
g_Map.log("Creating continent");
|
||||
createArea(
|
||||
new ChainPlacer(
|
||||
2,
|
||||
Math.floor(scaleByMapSize(5, 12)),
|
||||
Math.floor(scaleByMapSize(60, 700)),
|
||||
Infinity,
|
||||
mapCenter,
|
||||
0,
|
||||
[Math.floor(fractionToTiles(0.33))]),
|
||||
[
|
||||
new SmoothElevationPainter(ELEVATION_SET, heightLand, 4),
|
||||
new TileClassPainter(clLand)
|
||||
]);
|
||||
|
||||
const playerPlacements = playerPlacementCircle(fractionToTiles(0.25));
|
||||
const [playerIDs, playerPositions] = playerPlacements;
|
||||
|
||||
g_Map.log("Ensuring initial player land");
|
||||
for (let i = 0; i < numPlayers; ++i)
|
||||
createArea(
|
||||
new ChainPlacer(
|
||||
2,
|
||||
Math.floor(scaleByMapSize(5, 9)),
|
||||
Math.floor(scaleByMapSize(5, 20)),
|
||||
Infinity,
|
||||
playerPositions[i],
|
||||
0,
|
||||
[Math.floor(scaleByMapSize(23, 50))]),
|
||||
[
|
||||
new SmoothElevationPainter(ELEVATION_SET, heightLand, 4),
|
||||
new TileClassPainter(clLand)
|
||||
]);
|
||||
|
||||
Engine.SetProgress(20);
|
||||
|
||||
paintTerrainBasedOnHeight(3, 4, 3, tMainTerrain);
|
||||
paintTerrainBasedOnHeight(1, 3, 0, tShore);
|
||||
paintTerrainBasedOnHeight(-8, 1, 2, tWater);
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 2
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
Engine.SetProgress(30);
|
||||
|
||||
createBumps([avoidClasses(clPlayer, 10), stayClasses(clLand, 5)]);
|
||||
|
||||
Engine.SetProgress(35);
|
||||
|
||||
placeBalancedMinerals(playerPositions, stayClasses(clLand, 5));
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
placeBalancedFood(playerPlacements,
|
||||
new AndConstraint([avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10), stayClasses(clLand, 5)])
|
||||
);
|
||||
|
||||
Engine.SetProgress(45);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
new AndConstraint([avoidClasses(clForest, 18, clHill, 1, clMetal, 4, clRock, 4, clFood, 4), stayClasses(clLand, 5)]),
|
||||
clForest);
|
||||
}
|
||||
|
||||
Engine.SetProgress(50);
|
||||
|
||||
if (randBool())
|
||||
createHills([tMainTerrain, tCliff, tHill], [avoidClasses(clPlayer, 20, clHill, 15, clBaseResource, 3), stayClasses(clLand, 5)], clHill, scaleByMapSize(1, 4) * numPlayers);
|
||||
else
|
||||
createMountains(tCliff, [avoidClasses(clPlayer, 20, clHill, 15, clBaseResource, 3), stayClasses(clLand, 5)], clHill, scaleByMapSize(1, 4) * numPlayers);
|
||||
|
||||
Engine.SetProgress(55);
|
||||
|
||||
var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
|
||||
createForests(
|
||||
[tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
|
||||
[avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clBaseResource,2), stayClasses(clLand, 4)],
|
||||
clForest,
|
||||
forestTrees);
|
||||
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1,1],
|
||||
[avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)],
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
[avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)],
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
Engine.SetProgress(65);
|
||||
|
||||
g_Map.log("Creating stone mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)],
|
||||
[new SimpleObject(oStoneSmall, 2,5, 1,3)]
|
||||
],
|
||||
[avoidClasses(clForest, 1, clPlayer, 60, clRock, 10, clHill, 1), stayClasses(clLand, 6)],
|
||||
clRock);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oMetalLarge, 1,1, 0,4)]
|
||||
],
|
||||
[avoidClasses(clForest, 1, clPlayer, 60, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 6)],
|
||||
clMetal
|
||||
);
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
// create decoration
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
[avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)]);
|
||||
|
||||
Engine.SetProgress(75);
|
||||
|
||||
createBadFood(new AndConstraint([avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20), stayClasses(clLand, 5)]), 3);
|
||||
|
||||
createFood(
|
||||
[
|
||||
[new SimpleObject(oFruitBush, 5, 7, 0, 4)]
|
||||
],
|
||||
[
|
||||
3 * numPlayers
|
||||
],
|
||||
[avoidClasses(clForest, 0, clPlayer, 45, clHill, 1, clFood, 10, clMetal, 4, clRock, 4), stayClasses(clLand, 5)],
|
||||
clFood);
|
||||
|
||||
createFood(
|
||||
[
|
||||
[new SimpleObject(oFish, 2, 3, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(50, 500)
|
||||
],
|
||||
avoidClasses(clLand, 2, clFood, 10),
|
||||
clFood);
|
||||
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
[avoidClasses(
|
||||
clForest, 7, clHill, 1, clPlayer,
|
||||
(currentBiome() == "generic/savanna") ? 12 : 38,
|
||||
clMetal, 6, clRock, 6, clFood, 1, clBaseResource, 2
|
||||
), stayClasses(clLand, 7)],
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createBalancedPlayerStragglerTrees(
|
||||
playerPositions,
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
[avoidClasses(clForest, 8, clHill, 1, clMetal, 6, clRock, 6, clFood, 1, clBaseResource, 2), stayClasses(clLand, 7)],
|
||||
25,
|
||||
clForest
|
||||
)
|
||||
|
||||
placePlayersNomad(
|
||||
clPlayer,
|
||||
[stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]);
|
||||
|
||||
setWaterWaviness(1.0);
|
||||
setWaterType("ocean");
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/badcontinent.json
Normal file
11
community-mod/maps/random/badcontinent.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Balanced Continent",
|
||||
"Script" : "badcontinent.js",
|
||||
"Description" : "All players starts on a continent surrounded by water. Resources are distributed evenly between players.",
|
||||
"Preview" : "continent.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
252
community-mod/maps/random/badmainland.js
Normal file
252
community-mod/maps/random/badmainland.js
Normal file
@ -0,0 +1,252 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightLand = 3;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tMainTerrain);
|
||||
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
|
||||
let playerDistanceFraction;
|
||||
|
||||
switch(g_Map.getSize()) {
|
||||
case 128: // tiny
|
||||
playerDistanceFraction = 0.32;
|
||||
break;
|
||||
case 192: // small
|
||||
playerDistanceFraction = 0.31;
|
||||
break;
|
||||
case 256: // medium
|
||||
playerDistanceFraction = 0.28;
|
||||
break;
|
||||
case 320: // normal
|
||||
playerDistanceFraction = 0.27;
|
||||
break;
|
||||
default:
|
||||
playerDistanceFraction = 0.26;
|
||||
}
|
||||
|
||||
const playerPlacements = playerPlacementCircle(fractionToTiles(playerDistanceFraction + numPlayers * 0.007));
|
||||
const [playerIDs, playerPositions] = playerPlacements;
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 5
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
|
||||
Engine.SetProgress(20);
|
||||
|
||||
createBumps(avoidClasses(clPlayer, 20));
|
||||
|
||||
Engine.SetProgress(25);
|
||||
|
||||
placeBalancedMinerals(playerPositions);
|
||||
|
||||
Engine.SetProgress(30);
|
||||
|
||||
placeBalancedFood(playerPlacements,
|
||||
avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10)
|
||||
);
|
||||
|
||||
Engine.SetProgress(35);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
avoidClasses(clForest, 18, clHill, 1, clMetal, 4, clRock, 4, clFood, 4),
|
||||
clForest);
|
||||
}
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
if (randBool())
|
||||
createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 35, clHill, 15, clForest, 6, clMetal, 6, clRock, 6, clFood, 6), clHill, scaleByMapSize(2, 11));
|
||||
else
|
||||
createMountains(tCliff, avoidClasses(clPlayer, 35, clHill, 15, clForest, 6, clMetal, 6, clRock, 6, clFood, 6), clHill, scaleByMapSize(2, 11));
|
||||
|
||||
Engine.SetProgress(45);
|
||||
|
||||
var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
|
||||
createForests(
|
||||
[tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
|
||||
avoidClasses(clPlayer, 30, clForest, 18, clHill, 1, clMetal, 4, clRock, 4, clFood, 4),
|
||||
clForest,
|
||||
forestTrees);
|
||||
|
||||
Engine.SetProgress(50);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1, 1],
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(55);
|
||||
|
||||
g_Map.log("Creating stone mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, 60, clRock, 22, clHill, 1),
|
||||
clRock,
|
||||
scaleByMapSize(4, 16) - 1
|
||||
);
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oMetalLarge, 1, 1, 0, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, 60, clMetal, 22, clRock, 5, clHill, 1),
|
||||
clMetal,
|
||||
scaleByMapSize(4, 16) - 1
|
||||
);
|
||||
|
||||
Engine.SetProgress(65);
|
||||
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 0, clHill, 0));
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
createBadFood(avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20));
|
||||
|
||||
Engine.SetProgress(75);
|
||||
|
||||
createFood(
|
||||
[
|
||||
[new SimpleObject(oFruitBush, 5, 7, 0, 4)]
|
||||
],
|
||||
[
|
||||
2 * numPlayers
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 45, clHill, 1, clMetal, 4, clRock, 4, clFood, 10),
|
||||
clFood);
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(
|
||||
clForest, 8, clHill, 1, clPlayer,
|
||||
(currentBiome() == "generic/savanna") ? 12 : 38,
|
||||
clMetal, 6, clRock, 6, clFood, 1, clBaseResource, 2
|
||||
),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createBalancedPlayerStragglerTrees(
|
||||
playerPositions,
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(clForest, 8, clHill, 1, clMetal, 6, clRock, 6, clFood, 1, clBaseResource, 2),
|
||||
25,
|
||||
clForest
|
||||
)
|
||||
|
||||
Engine.SetProgress(90);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/badmainland.json
Normal file
11
community-mod/maps/random/badmainland.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Balanced Mainland",
|
||||
"Script" : "badmainland.js",
|
||||
"Description" : "A typical map without any water. Resources are distributed evenly between players.",
|
||||
"Preview" : "mainland.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
248
community-mod/maps/random/badmainland_fixed.js
Normal file
248
community-mod/maps/random/badmainland_fixed.js
Normal file
@ -0,0 +1,248 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightLand = 3;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tMainTerrain);
|
||||
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
|
||||
let playerDistanceFraction;
|
||||
|
||||
switch(g_Map.getSize()) {
|
||||
case 128: // tiny
|
||||
playerDistanceFraction = 0.32;
|
||||
break;
|
||||
case 192: // small
|
||||
playerDistanceFraction = 0.31;
|
||||
break;
|
||||
case 256: // medium
|
||||
playerDistanceFraction = 0.28;
|
||||
break;
|
||||
case 320: // normal
|
||||
playerDistanceFraction = 0.27;
|
||||
break;
|
||||
default:
|
||||
playerDistanceFraction = 0.26;
|
||||
}
|
||||
|
||||
const playerPlacements = playerPlacementCircle(fractionToTiles(playerDistanceFraction + numPlayers * 0.007));
|
||||
let [playersOrder, playerPositions, playerAngles] = playerPlacements;
|
||||
|
||||
let playerIDs = [];
|
||||
for (let i = 0; i < numPlayers; ++i)
|
||||
playerIDs.push(i+1);
|
||||
|
||||
playerPlacements[0] = playerIDs;
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 5
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
|
||||
Engine.SetProgress(20);
|
||||
|
||||
createBumps(avoidClasses(clPlayer, 20));
|
||||
|
||||
Engine.SetProgress(25);
|
||||
|
||||
if (randBool())
|
||||
createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 35, clHill, 15), clHill, scaleByMapSize(2, 11));
|
||||
else
|
||||
createMountains(tCliff, avoidClasses(clPlayer, 35, clHill, 15), clHill, scaleByMapSize(2, 11));
|
||||
|
||||
placeBalancedMinerals(playerPositions);
|
||||
placeBalancedFood(playerPlacements,
|
||||
avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10)
|
||||
);
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
avoidClasses(clForest, 18, clHill, 1, clMetal, 4, clRock, 4, clFood, 4),
|
||||
clForest);
|
||||
}
|
||||
|
||||
var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
|
||||
createForests(
|
||||
[tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
|
||||
avoidClasses(clPlayer, 30, clForest, 18, clHill, 1, clMetal, 4, clRock, 4, clFood, 4),
|
||||
clForest,
|
||||
forestTrees);
|
||||
|
||||
Engine.SetProgress(50);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1, 1],
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
Engine.SetProgress(55);
|
||||
|
||||
g_Map.log("Creating stone mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, 60, clRock, 22, clHill, 1),
|
||||
clRock,
|
||||
scaleByMapSize(4, 16) - 1
|
||||
);
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oMetalLarge, 1, 1, 0, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, 60, clMetal, 22, clRock, 5, clHill, 1),
|
||||
clMetal,
|
||||
scaleByMapSize(4, 16) - 1
|
||||
);
|
||||
|
||||
Engine.SetProgress(65);
|
||||
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 0, clHill, 0));
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
createBadFood(avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20));
|
||||
|
||||
Engine.SetProgress(75);
|
||||
|
||||
createFood(
|
||||
[
|
||||
[new SimpleObject(oFruitBush, 5, 7, 0, 4)]
|
||||
],
|
||||
[
|
||||
2 * numPlayers
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 45, clHill, 1, clMetal, 4, clRock, 4, clFood, 10),
|
||||
clFood);
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(
|
||||
clForest, 8, clHill, 1, clPlayer,
|
||||
(currentBiome() == "generic/savanna") ? 12 : 38,
|
||||
clMetal, 6, clRock, 6, clFood, 1
|
||||
),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createBalancedPlayerStragglerTrees(
|
||||
playerPositions,
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(clForest, 8, clHill, 1, clMetal, 6, clRock, 6, clFood, 1, clBaseResource, 2),
|
||||
25,
|
||||
clForest
|
||||
)
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/badmainland_fixed.json
Normal file
11
community-mod/maps/random/badmainland_fixed.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Balanced Mainland (fixed)",
|
||||
"Script" : "badmainland_fixed.js",
|
||||
"Description" : "A typical map without any water. Resources are distributed evenly between players. Positions defined by players",
|
||||
"Preview" : "mainland.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
432
community-mod/maps/random/balancedHelpers/food.js
Normal file
432
community-mod/maps/random/balancedHelpers/food.js
Normal file
@ -0,0 +1,432 @@
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
|
||||
const debugFood = true;
|
||||
|
||||
function dWarn(message) {
|
||||
if (debugFood) {
|
||||
warn(message);
|
||||
}
|
||||
}
|
||||
|
||||
const temperateInitialFood = () => randBool(0.05) ? randIntInclusive(23, 30) : randIntInclusive(0, 22);
|
||||
|
||||
const balancedFoodConfig = {
|
||||
'generic/alpine': {
|
||||
placer: placeFoodTemperate,
|
||||
initialFood: temperateInitialFood,
|
||||
},
|
||||
'generic/aegean': {
|
||||
placer: placeFoodTemperate,
|
||||
initialFood: temperateInitialFood,
|
||||
},
|
||||
'generic/temperate': {
|
||||
placer: placeFoodTemperate,
|
||||
initialFood: temperateInitialFood,
|
||||
},
|
||||
'generic/autumn': {
|
||||
placer: placeFoodAutumn,
|
||||
initialFood: temperateInitialFood,
|
||||
},
|
||||
'generic/india': {
|
||||
placer: placeFoodTropic,
|
||||
initialFood: () => randIntInclusive(0, 22), // disallow high-food due to poor fauna
|
||||
},
|
||||
'generic/sahara': {
|
||||
placer: placeFoodDesert,
|
||||
initialFood: () => randIntInclusive(4, 30),
|
||||
},
|
||||
'generic/nubia': {
|
||||
placer: placeFoodDesert,
|
||||
initialFood: () => randIntInclusive(4, 30),
|
||||
},
|
||||
'generic/arctic': {
|
||||
placer: placeFoodSnowy,
|
||||
initialFood: () => randIntInclusive(3, 30),
|
||||
evenInitialFood: true,
|
||||
},
|
||||
'generic/steppe': {
|
||||
placer: placeFoodSnowy,
|
||||
initialFood: () => randIntInclusive(3, 30),
|
||||
evenInitialFood: true,
|
||||
},
|
||||
'generic/savanna': {
|
||||
placer: function() {
|
||||
if (oMainHuntableAnimal == 'gaia/fauna_elephant_african_bush') {
|
||||
placeFoodEles.apply(null, arguments);
|
||||
} else if (oMainHuntableAnimal == 'gaia/fauna_giraffe') {
|
||||
placeFoodGiraffes.apply(null, arguments);
|
||||
} else {
|
||||
placeFoodSavanna.apply(null, arguments);
|
||||
}
|
||||
},
|
||||
initialFood: function() {
|
||||
if (oMainHuntableAnimal == 'gaia/fauna_elephant_african_bush') {
|
||||
return randIntInclusive(17, 50);
|
||||
} else if (oMainHuntableAnimal == 'gaia/fauna_giraffe') {
|
||||
return 7 * randIntInclusive(2, 6);
|
||||
} else {
|
||||
return randIntInclusive(10, 30);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function placeInitialFoodAmount(type, min, max, foodAmount, playerPosition, constraints, minTileBound = 23, maxTileBound = 29) {
|
||||
if (type != oFruitBush) {
|
||||
minTileBound += 11;
|
||||
maxTileBound += 12;
|
||||
constraints = new AndConstraint([constraints, avoidClasses(clPlayer, minTileBound - 6)]);
|
||||
}
|
||||
|
||||
return placeFoodAmount(type, min, limitQtyForAmount(foodAmount, type, max), playerPosition, constraints, minTileBound, maxTileBound) * getFoodValue(type);
|
||||
}
|
||||
|
||||
function placeFoodAmount(type, min, max, position, constraints, minTileBound = 17, maxTileBound = 25) {
|
||||
const amountPlaced = randIntInclusive(min, max);
|
||||
const group = new SimpleGroup(
|
||||
[new SimpleObject(type, amountPlaced, amountPlaced, 0, 4)],
|
||||
true,
|
||||
clFood
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(group, 0,
|
||||
constraints,
|
||||
1, 400, [getAnnulusArea(minTileBound, maxTileBound, position)]
|
||||
);
|
||||
|
||||
return amountPlaced;
|
||||
}
|
||||
|
||||
function placeStragglerFauna(type, foodAmount, playerId, playerPosition, constraints) {
|
||||
const foodQty = Math.floor(foodAmount / getFoodValue(type));
|
||||
const [minTile, maxTile] = getCivCode(playerId) == 'iber' ? [21, 23] : [8, 12];
|
||||
const placedAmount = placeInitialFoodAmount(type, foodQty, foodQty, foodAmount, playerPosition, constraints, minTile, maxTile);
|
||||
|
||||
dWarn("Player " + playerId + " - placed " + type + ": " + placedAmount);
|
||||
|
||||
return placedAmount;
|
||||
}
|
||||
|
||||
function placeInitialBerries(foodAmount, playerId, playerPosition, constraints) {
|
||||
if (getCivCode(playerId) == 'iber') {
|
||||
return placeInitialFoodAmount(oFruitBush, 5, 7, foodAmount, playerPosition, constraints, 27, 30);
|
||||
} else {
|
||||
return placeInitialFoodAmount(oFruitBush, 5, 7, foodAmount, playerPosition, constraints);
|
||||
}
|
||||
}
|
||||
|
||||
function placeBalancedFood(playerPlacements, constraints, multiplier = 1) {
|
||||
const biome = currentBiome() || 'generic/temperate';
|
||||
const biomeConfig = balancedFoodConfig[biome];
|
||||
|
||||
dWarn('Placing food for biome: ' + biome);
|
||||
|
||||
const [playerIDs, playerPositions] = playerPlacements;
|
||||
const foodPlacer = biomeConfig.placer;
|
||||
const foodAmount = getFoodAmount(multiplier, biomeConfig);
|
||||
|
||||
for (let i = 0; i < playerPositions.length; ++i)
|
||||
foodPlacer(foodAmount, playerIDs[i], playerPositions[i], constraints);
|
||||
}
|
||||
|
||||
function getFoodAmount(multiplier = 1, biomeConfig) {
|
||||
let initialFoodAmount = Math.floor(multiplier * biomeConfig.initialFood());
|
||||
if (biomeConfig['evenInitialFood']) {
|
||||
if (initialFoodAmount % 2 == 1) initialFoodAmount++;
|
||||
}
|
||||
|
||||
return initialFoodAmount * 100;
|
||||
}
|
||||
|
||||
function placeFoodTemperate(initialFoodAmount, playerId, playerPosition, constraints, maxBerries = 2, mainHunt = oMainHuntableAnimal) {
|
||||
// Goats now are 70 food which messes everything up
|
||||
if (currentBiome() == 'generic/alpine') {
|
||||
mainHunt = 'gaia/fauna_sheep';
|
||||
}
|
||||
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = maxBerries;
|
||||
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood <= 400) {
|
||||
remainingFood -= placeStragglerFauna(mainHunt, remainingFood, playerId, playerPosition, constraints);
|
||||
} else if (remainingFood <= 1000) {
|
||||
const placedAmount = placeInitialFoodAmount(mainHunt, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + mainHunt + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
} else {
|
||||
const placedAmount = placeInitialFoodAmount(oSecondaryHuntableAnimal, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oSecondaryHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodAutumn(initialFoodAmount, playerId, playerPosition, constraints, maxBerries = 2) {
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = maxBerries;
|
||||
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood <= 400) {
|
||||
remainingFood -= placeStragglerFauna(oSecondaryHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
} else if (remainingFood <= 1000) {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodDesert(initialFoodAmount, playerId, playerPosition, constraints, maxBerries = 2) {
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = maxBerries;
|
||||
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood <= 400) {
|
||||
remainingFood -= placeStragglerFauna(oSecondaryHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
}
|
||||
else if (remainingFood <= 1000) {
|
||||
const placedAmount = placeInitialFoodAmount(oSecondaryHuntableAnimal, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oSecondaryHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodTropic(initialFoodAmount, playerId, playerPosition, constraints, maxBerries = 2) {
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = maxBerries;
|
||||
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood <= 400) {
|
||||
remainingFood -= placeStragglerFauna(oMainHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
} else if (remainingFood <= 950) {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 10, 12, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool(0.7)) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
} else {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 10, 12, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodSnowy(initialFoodAmount, playerId, playerPosition, constraints, maxBerries = 2) {
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = maxBerries;
|
||||
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood <= 400) {
|
||||
remainingFood -= placeStragglerFauna(oMainHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
} else if (remainingFood <= 900) {
|
||||
const placedAmount = placeInitialFoodAmount(oSecondaryHuntableAnimal, 2, 3, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oSecondaryHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
} else {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 5, 7, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodSavanna(initialFoodAmount, playerId, playerPosition, constraints) {
|
||||
if (oMainHuntableAnimal == 'gaia/fauna_elephant_african_bush') {
|
||||
placeFoodEles(initialFoodAmount, playerId, playerPosition, constraints);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (oMainHuntableAnimal == 'gaia/fauna_giraffe') {
|
||||
placeFoodGiraffes(initialFoodAmount, playerId, playerPosition);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = 2;
|
||||
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood<=getFoodValue(oSecondaryHuntableAnimal)*2 && remainingFood % getFoodValue(oSecondaryHuntableAnimal) == 0) {
|
||||
dWarn("place_stragglers_fauna");
|
||||
remainingFood -= placeStragglerFauna(oSecondaryHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
const foodQty = randIntInclusive(3, 4) * 2;
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, foodQty, foodQty, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodEles(initialFoodAmount, playerId, playerPosition, constraints) {
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = 2;
|
||||
dWarn("PLACE FOOD ELES");
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood<=getFoodValue(oSecondaryHuntableAnimal)*2 && remainingFood % getFoodValue(oSecondaryHuntableAnimal) == 0) {
|
||||
dWarn("place_stragglers_fauna");
|
||||
remainingFood -= placeStragglerFauna(oSecondaryHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, 1, 2, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function placeFoodGiraffes(initialFoodAmount, playerId, playerPosition, constraints) {
|
||||
let remainingFood = initialFoodAmount;
|
||||
let remainingBerries = 2;
|
||||
dWarn("PLACE FOOD GIRAFFES")
|
||||
dWarn("Assigning " + remainingFood + " food for player " + playerId);
|
||||
while (remainingFood > 0) {
|
||||
if (remainingFood<=getFoodValue(oSecondaryHuntableAnimal)*2 && remainingFood % getFoodValue(oSecondaryHuntableAnimal) == 0) {
|
||||
dWarn("place_stragglers_fauna");
|
||||
remainingFood -= placeStragglerFauna(oSecondaryHuntableAnimal, remainingFood, playerId, playerPosition, constraints);
|
||||
}
|
||||
else {
|
||||
if (remainingBerries > 0 && randBool()) {
|
||||
const placedAmount = placeInitialBerries(remainingFood, playerId, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
remainingBerries -= 1;
|
||||
dWarn("Player " + playerId + " - placed " + oFruitBush + ": " + placedAmount);
|
||||
}
|
||||
else {
|
||||
const foodQty = 4; // must be fixed at the moment
|
||||
const placedAmount = placeInitialFoodAmount(oMainHuntableAnimal, foodQty, foodQty, remainingFood, playerPosition, constraints);
|
||||
remainingFood -= placedAmount;
|
||||
dWarn("Player " + playerId + " - placed " + oMainHuntableAnimal + ": " + placedAmount);
|
||||
}
|
||||
}
|
||||
dWarn("Remaining " + remainingFood);
|
||||
}
|
||||
|
||||
if (remainingFood < 0)
|
||||
warn('Player ' + playerId + ' ended up with additional ' + Math.abs(remainingFood) + ' food');
|
||||
}
|
||||
|
||||
function createBadFood(constraints, multiplier = 2) {
|
||||
// Separate for eles generation farther
|
||||
let huntGenDistance = oMainHuntableAnimal == 'gaia/fauna_elephant_african_bush' ? 80 : 50;
|
||||
|
||||
createFood(
|
||||
[ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)] ],
|
||||
[ multiplier * numPlayers ],
|
||||
new AndConstraint([avoidClasses(clPlayer, huntGenDistance), constraints]),
|
||||
clFood);
|
||||
|
||||
createFood(
|
||||
[ [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ],
|
||||
[ multiplier * numPlayers ],
|
||||
new AndConstraint([avoidClasses(clPlayer, huntGenDistance), constraints]),
|
||||
clFood);
|
||||
}
|
||||
|
||||
function limitQtyForAmount(foodAmount, type, max) {
|
||||
return Math.min(max, Math.floor(foodAmount / getFoodValue(type)));
|
||||
}
|
34
community-mod/maps/random/balancedHelpers/foodValues.js
Normal file
34
community-mod/maps/random/balancedHelpers/foodValues.js
Normal file
@ -0,0 +1,34 @@
|
||||
const foodValues = {
|
||||
'gaia/fauna_wildebeest': 150, // m random savanna
|
||||
'gaia/fauna_zebra': 150, // m random savanna
|
||||
'gaia/fauna_giraffe': 350, // m random savanna
|
||||
'gaia/fauna_elephant_african_bush': 800, // m random savanna
|
||||
'gaia/fauna_gazelle': 100, // s savanna, s desert
|
||||
'gaia/fauna_camel': 200, // m desert
|
||||
'gaia/fauna_peacock': 50, // m tropical
|
||||
'gaia/fauna_goat': 70, // m alpine
|
||||
'gaia/fauna_deer': 100, // m alpine, m autumn, m mediterranean, m temperate
|
||||
'gaia/fauna_sheep': 100, // s alpine, s mediterranean, s temperate
|
||||
'gaia/fauna_rabbit': 50, // s autumn
|
||||
'gaia/fauna_horse': 200, // s steppe
|
||||
'gaia/fauna_muskox': 200, // m snowy
|
||||
'gaia/fauna_walrus': 300, // s snowy
|
||||
'gaia/fauna_tiger': 0, // s tropic
|
||||
'gaia/fruit/berry_': 200, // all regular biomes
|
||||
};
|
||||
|
||||
function getFoodValue(template) {
|
||||
let foodValue = foodValues[template];
|
||||
dWarn('get: ' + template);
|
||||
|
||||
if (foodValue)
|
||||
return foodValue;
|
||||
|
||||
for (let foodtemp in foodValues)
|
||||
if (template.startsWith(foodtemp))
|
||||
return foodValues[foodtemp];
|
||||
|
||||
dWarn('miss: ' + template);
|
||||
|
||||
return null;
|
||||
}
|
15
community-mod/maps/random/balancedHelpers/getAnnulusArea.js
Normal file
15
community-mod/maps/random/balancedHelpers/getAnnulusArea.js
Normal file
@ -0,0 +1,15 @@
|
||||
let annulusAreas = {};
|
||||
|
||||
// Memoize areas
|
||||
function getAnnulusArea(minTileBound, maxTileBound, position) {
|
||||
const key = [minTileBound, maxTileBound, position.x, position.y];
|
||||
|
||||
if (key in annulusAreas) {
|
||||
return annulusAreas[key];
|
||||
} else {
|
||||
const area = new Area(new AnnulusPlacer(minTileBound, maxTileBound, position).place());
|
||||
annulusAreas[key] = area;
|
||||
return area;
|
||||
}
|
||||
}
|
||||
|
33
community-mod/maps/random/balancedHelpers/minerals.js
Normal file
33
community-mod/maps/random/balancedHelpers/minerals.js
Normal file
@ -0,0 +1,33 @@
|
||||
function placeBalancedMinerals(playerPositions, constraints = new NullConstraint()) {
|
||||
for (let i = 0; i < playerPositions.length; ++i)
|
||||
{
|
||||
const playerPosition = playerPositions[i];
|
||||
|
||||
let placer = new AnnulusPlacer(40, 44, playerPosition).place(
|
||||
new AndConstraint([avoidClasses(clForest, 10, clHill, 2, clFood, 4, clPlayer, 34), constraints])
|
||||
);
|
||||
let surroundingArea = new Area(placer);
|
||||
|
||||
let stone = new SimpleGroup(
|
||||
[new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)],
|
||||
true,
|
||||
clRock
|
||||
);
|
||||
|
||||
let metal = new SimpleGroup(
|
||||
[new SimpleObject(oMetalLarge, 1, 1, 0, 4)],
|
||||
true,
|
||||
clRock
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(stone, 0,
|
||||
new NullConstraint(),
|
||||
1, 400, [surroundingArea]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(metal, 0,
|
||||
avoidClasses(clRock, 6),
|
||||
1, 400, [surroundingArea]
|
||||
);
|
||||
}
|
||||
}
|
63
community-mod/maps/random/balancedHelpers/player.js
Normal file
63
community-mod/maps/random/balancedHelpers/player.js
Normal file
@ -0,0 +1,63 @@
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
|
||||
function getTeams() {
|
||||
const playerIDs = [];
|
||||
for (let i = 0; i < getNumPlayers(); ++i)
|
||||
playerIDs.push(i + 1);
|
||||
|
||||
return playerIDs.reduce((obj, playerID) => {
|
||||
const teamID = g_MapSettings.PlayerData[playerID].Team;
|
||||
|
||||
if (!obj.hasOwnProperty(teamID))
|
||||
obj[teamID] = [];
|
||||
|
||||
obj[teamID].push(playerID);
|
||||
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function placeOpposingTeams(radius, startingAngle = undefined, center = undefined) {
|
||||
let startAngle = startingAngle !== undefined ? startingAngle : randomAngle();
|
||||
center = center || g_Map.getCenter();
|
||||
|
||||
const teams = getTeams();
|
||||
const teamIDs = shuffleArray(Object.keys(teams));
|
||||
const teamCount = teamIDs.length;
|
||||
|
||||
if (teamCount === 1)
|
||||
warn('This map is optimized for at least 2 teams');
|
||||
|
||||
const [teamPositions, teamAngles] = distributePointsOnCircle(teamIDs.length, startAngle, radius, center)
|
||||
|
||||
let playerPositions = [];
|
||||
let ids = [];
|
||||
for (let i = 0; i < teamCount; i++) {
|
||||
const team = teams[teamIDs[i]];
|
||||
ids = ids.concat(team);
|
||||
playerPositions = playerPositions.concat(placeTeam(
|
||||
team,
|
||||
teamCount === 1 ? center : teamPositions[i],
|
||||
teamAngles[i]
|
||||
));
|
||||
}
|
||||
|
||||
return [ids, playerPositions];
|
||||
}
|
||||
|
||||
// Places a team in a circle formation at a certain position
|
||||
function placeTeam(team, pos, startAngle = 0) {
|
||||
const teamSize = team.length;
|
||||
if (teamSize === 1)
|
||||
return [pos];
|
||||
|
||||
// Make uneven sizes point to center, and even to face center
|
||||
const orientationAngle = Math.min(teamSize - 2, 1) * Math.PI / Math.pow(2, teamSize - 2);
|
||||
|
||||
return distributePointsOnCircle(
|
||||
teamSize,
|
||||
orientationAngle + startAngle + Math.PI/2,
|
||||
22 + teamSize * 6,
|
||||
pos
|
||||
)[0];
|
||||
}
|
91
community-mod/maps/random/balancedHelpers/wood.js
Normal file
91
community-mod/maps/random/balancedHelpers/wood.js
Normal file
@ -0,0 +1,91 @@
|
||||
function pickRandomCollection(collection, amount) {
|
||||
let newCollection = [];
|
||||
let dup = collection.slice();
|
||||
|
||||
for (let i = 0; i < amount; ++i) {
|
||||
const index = Math.floor(dup.length * Math.random());
|
||||
const item = dup.splice(index, 1)[0];
|
||||
newCollection.push(item);
|
||||
}
|
||||
|
||||
return newCollection;
|
||||
}
|
||||
|
||||
function createBalancedPlayerStragglerTrees(playerPositions, templateNames, constraint, treeCount, tileClass) {
|
||||
templateNames = templateNames.filter((templateName) => !templateName.startsWith('gaia/fruit/'));
|
||||
|
||||
for (let playerPosition of playerPositions) {
|
||||
const playerArea = new Area(new DiskPlacer(38, playerPosition).place(avoidClasses(clPlayer, 12)));
|
||||
|
||||
for (let templateName of templateNames) {
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(templateName, 1, 1, 0, 3)], true, tileClass),
|
||||
0,
|
||||
constraint,
|
||||
Math.floor(treeCount / templateNames.length), 400,
|
||||
[playerArea]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createBalancedPlayerForests(playerPositions, constraint, tileClass, forestAmount, treeCount)
|
||||
{
|
||||
treeCount = treeCount !== undefined ? treeCount : randIntInclusive(25, 35);
|
||||
forestAmount = forestAmount !== undefined ? forestAmount : randIntInclusive(3, 4);
|
||||
for (let i = 0; i < playerPositions.length; ++i)
|
||||
{
|
||||
const playerPosition = playerPositions[i];
|
||||
|
||||
let forestArea = new Area(new AnnulusPlacer(28, 40, playerPosition).place(new NullConstraint()));
|
||||
|
||||
createForestsInArea(forestArea, constraint, tileClass, treeCount, 3, Math.floor(scaleByMapSize(3, 4)), 1, forestAmount, 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Places uniformly sized forests at random locations.
|
||||
* Generates two variants of forests from the given terrain textures and tree templates.
|
||||
* The forest border has less trees than the inside.
|
||||
*/
|
||||
function createForestsInArea(area, constraint, tileClass, treeCount,
|
||||
minRadius = 1,
|
||||
maxRadius = Math.floor(scaleByMapSize(3, 5)),
|
||||
forestVariantNumber = 2,
|
||||
numberOfForests = Math.floor(treeCount / (scaleByMapSize(3, 6) * getNumPlayers() * forestVariantNumber)),
|
||||
failurePercentage = 0.5,
|
||||
retryFactor = 400)
|
||||
{
|
||||
if (!treeCount)
|
||||
return;
|
||||
|
||||
const terrainSet = [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2];
|
||||
|
||||
// Construct different forest types from the terrain textures and template names.
|
||||
const [mainTerrain, terrainForestFloor1, terrainForestFloor2, terrainForestTree1, terrainForestTree2] = terrainSet;
|
||||
|
||||
// The painter will pick a random Terrain for each part of the forest.
|
||||
let forestVariants = pickRandomCollection([
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor2, mainTerrain, terrainForestTree1],
|
||||
"interiorTerrains": [terrainForestFloor2, terrainForestTree1]
|
||||
},
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor1, mainTerrain, terrainForestTree2],
|
||||
"interiorTerrains": [terrainForestFloor1, terrainForestTree2]
|
||||
}
|
||||
], forestVariantNumber);
|
||||
|
||||
g_Map.log("Creating forests");
|
||||
for (let forestVariant of forestVariants) {
|
||||
createAreasInAreas(
|
||||
new ChainPlacer(minRadius, maxRadius, treeCount / numberOfForests, failurePercentage),
|
||||
[
|
||||
new LayeredPainter([forestVariant.borderTerrains, forestVariant.interiorTerrains], [2]),
|
||||
new TileClassPainter(tileClass)
|
||||
],
|
||||
constraint,
|
||||
numberOfForests,
|
||||
retryFactor,
|
||||
[area]);
|
||||
}
|
||||
}
|
596
community-mod/maps/random/britannic_road.js
Normal file
596
community-mod/maps/random/britannic_road.js
Normal file
@ -0,0 +1,596 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
|
||||
const tPrimary = "alpine_grass_a";
|
||||
const tGrass = ["temp_forestfloor_aut", "temp_forestfloor_aut", "temp_forestfloor_aut"];
|
||||
const tGrassPForest = "temp_forestfloor_aut";
|
||||
const tGrassDForest = "temp_forestfloor_aut";
|
||||
const tGrassA = "temp_forestfloor_aut";
|
||||
const tGrassB = "temp_forestfloor_aut";
|
||||
const tGrassC = "temp_mud_a";
|
||||
const tRoad = "temp_road";
|
||||
const tRoadCenter = "temp_road_broken";
|
||||
const tRoadWild = "temp_road_overgrown_aut";
|
||||
const tGrassPatchBlend = "temp_forestfloor_aut";
|
||||
const tGrassPatchA = ["alpine_grass_c", "alpine_grass_c"];
|
||||
const tGrassPatchB = ["alpine_grass_d", "alpine_grass_d"];
|
||||
const tGrassPatchTypes = [tGrassPatchA, tGrassPatchB];
|
||||
const tShore = "temp_forestfloor_aut";
|
||||
const tWater = "temp_mud_a";
|
||||
|
||||
const oBeech = "gaia/tree/euro_beech_aut";
|
||||
const oOak = "gaia/tree/oak_aut";
|
||||
const oOakBig = "gaia/tree/oak_aut_new"
|
||||
const oBerryBush = "gaia/fruit/berry_01";
|
||||
const oDeer = "gaia/fauna_deer";
|
||||
const oRabbit = "gaia/fauna_rabbit";
|
||||
const oSheep = "gaia/fauna_sheep";
|
||||
const oStoneLarge = "gaia/rock/temperate_large_02";
|
||||
const oStoneSmall = "gaia/rock/temperate_small";
|
||||
const oMetalLarge = "gaia/ore/temperate_large";
|
||||
|
||||
const aDryGrass = "actor|props/flora/grass_field_dry_tall.xml";
|
||||
const aGrassFlower = "actor|props/flora/grass_field_flowering_tall.xml";
|
||||
const aGrassSoft = "actor|props/flora/grass_soft_large";
|
||||
const aGrassSoftTall = "actor|props/flora/grass_soft_large_tall";
|
||||
const aRockLarge = "actor|geology/stone_granite_med.xml";
|
||||
const aRockMedium = "actor|geology/stone_granite_med.xml";
|
||||
const aBushMedium = "actor|props/flora/bush_desert_dry_a.xml";
|
||||
const aBushSmall = "actor|props/flora/bush_desert_dry_a.xml";
|
||||
|
||||
const pForestB = [tGrassDForest + TERRAIN_SEPARATOR + oBeech, tGrassDForest];
|
||||
const pForestO = [tGrassPForest + TERRAIN_SEPARATOR + oOak, tGrassPForest];
|
||||
const pForestN = [tGrassPForest + TERRAIN_SEPARATOR + oOakBig, tGrassPForest];
|
||||
const pForestR = [tGrassDForest + TERRAIN_SEPARATOR + oBeech, tGrassDForest, tGrassDForest + TERRAIN_SEPARATOR + oOak, tGrassDForest, tGrassDForest, tGrassDForest];
|
||||
|
||||
const heightSeaGround = -4;
|
||||
const heightShallows = -2;
|
||||
const heightLand = 3;
|
||||
const heightOffsetBump = 2;
|
||||
|
||||
const surroundingPlayerAreaMin = 20;
|
||||
const surroundingPlayerAreaMax = 50;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tPrimary);
|
||||
|
||||
const numPlayers = getNumPlayers();
|
||||
const mapSize = g_Map.getSize();
|
||||
const mapCenter = g_Map.getCenter();
|
||||
const mapBounds = g_Map.getBounds();
|
||||
|
||||
const neighbouringPlayerTiles = 50;
|
||||
|
||||
var clPlayers = [];
|
||||
var clPlayer = g_Map.createTileClass();
|
||||
var clHill = g_Map.createTileClass();
|
||||
var clForest = g_Map.createTileClass();
|
||||
var clDirt = g_Map.createTileClass();
|
||||
var clDryGrass = g_Map.createTileClass();
|
||||
var clRock = g_Map.createTileClass();
|
||||
var clMetal = g_Map.createTileClass();
|
||||
var clFood = g_Map.createTileClass();
|
||||
var clBaseResource = g_Map.createTileClass();
|
||||
var clRoad = g_Map.createTileClass();
|
||||
var clBorder = g_Map.createTileClass();
|
||||
|
||||
var surroundingPlayersAreas = [];
|
||||
|
||||
var startAngle = randomAngle();
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i) {
|
||||
clPlayers[i] = g_Map.createTileClass();
|
||||
}
|
||||
|
||||
var playerPositions = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.5));
|
||||
placePlayerBasesCustom({
|
||||
"PlayerPlacement": playerPositions,
|
||||
// PlayerTileClass marked below
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad//,
|
||||
//"painters": [
|
||||
// new TileClassPainter(clPlayer)
|
||||
//]
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oBerryBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oOak,
|
||||
"count": 3
|
||||
},
|
||||
});
|
||||
Engine.SetProgress(20);
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i) {
|
||||
let playerClass = clPlayers[i];
|
||||
surroundingPlayersAreas[i] = createArea(new DiskPlacer(surroundingPlayerAreaMax, playerPositions[1][i]), null, avoidClasses(playerClass, surroundingPlayerAreaMin));
|
||||
}
|
||||
Engine.SetProgress(30);
|
||||
|
||||
var roadPositions = [
|
||||
new Vector2D(mapBounds.left + 1, mapCenter.y),
|
||||
new Vector2D(mapBounds.right - 1, mapCenter.y)
|
||||
].map(v => v.rotateAround(startAngle, mapCenter));
|
||||
|
||||
g_Map.log("Creating the central road");
|
||||
createArea(
|
||||
new PathPlacer(roadPositions[0], roadPositions[1], scaleByMapSize(2, 4), 0.2, 3 * scaleByMapSize(1, 4), 0.1, 0.01),
|
||||
[new TerrainPainter(tRoadCenter), new TileClassPainter(clRoad)],
|
||||
avoidClasses(clPlayer, 4));
|
||||
Engine.SetProgress(35);
|
||||
|
||||
g_Map.log("Creating bumps");
|
||||
createAreas(
|
||||
new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity),
|
||||
new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2),
|
||||
avoidClasses(clRoad, 2, clPlayer, 15),
|
||||
scaleByMapSize(100, 200)
|
||||
);
|
||||
Engine.SetProgress(55);
|
||||
|
||||
g_Map.log("Creating primary grass patches");
|
||||
for (let size of [scaleByMapSize(8, 20), scaleByMapSize(13, 35), scaleByMapSize(25, 70)])
|
||||
createAreas(
|
||||
new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5),
|
||||
[new LayeredPainter([tGrassPatchA, tGrassPatchA], [1]), new TileClassPainter(clDryGrass)],
|
||||
avoidClasses(clRoad, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6),
|
||||
scaleByMapSize(15, 45)
|
||||
);
|
||||
Engine.SetProgress(58);
|
||||
|
||||
g_Map.log("Creating secondary grass patches");
|
||||
//for (let size of [scaleByMapSize(3, 8), scaleByMapSize(5, 15), scaleByMapSize(8, 20)])
|
||||
for (let size of [scaleByMapSize(8, 20), scaleByMapSize(13, 35), scaleByMapSize(25, 60)])
|
||||
createAreas(
|
||||
new ChainPlacer(1, Math.floor(scaleByMapSize(3, 4)), size, 0.5),
|
||||
[new LayeredPainter([tGrassPatchB, tGrassPatchB], [1]), new TileClassPainter(clDryGrass)],
|
||||
avoidClasses(clRoad, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6),
|
||||
scaleByMapSize(10, 30)
|
||||
);
|
||||
Engine.SetProgress(61);
|
||||
|
||||
g_Map.log("Creating the bordering trees");
|
||||
var [borderForests, borderStragglers] = getTreeCounts(500, 2500, 0.7);
|
||||
/*createForestsCustom(
|
||||
[tGrass, tGrassDForest, tGrassPForest, pForestN, pForestN],
|
||||
new AndConstraint([avoidClasses(clPlayer, 15, clBorder, 2, clHill, 1, clRoad, 5), new BorderTileClassConstraint(clRoad, 0, 20)]),
|
||||
clBorder,
|
||||
borderForests);
|
||||
Engine.SetProgress(60);*/
|
||||
|
||||
g_Map.log("Creating player owned forest");
|
||||
for (let i = 0; i < numPlayers; ++i)
|
||||
createPlayerForests(
|
||||
[tGrass, tGrassDForest, tGrassPForest, pForestB, pForestO],
|
||||
new AndConstraint([avoidClasses(clPlayer, 12, clRoad, 30, clForest, 16, clHill, 1), borderClasses(clPlayer, 0, 30)]),
|
||||
clForest,
|
||||
surroundingPlayersAreas[i]);
|
||||
Engine.SetProgress(65);
|
||||
|
||||
g_Map.log("Creating the regular trees");
|
||||
var [forestTrees, stragglerTrees] = getTreeCounts(300, 1600, 0.7);
|
||||
createThickerForests(
|
||||
[tGrass, tGrassDForest, tGrassPForest, pForestB, pForestO],
|
||||
avoidClasses(clPlayer, 15, clRoad, 30, clForest, 16, clHill, 1),
|
||||
clForest,
|
||||
forestTrees);
|
||||
Engine.SetProgress(70);
|
||||
|
||||
/*g_Map.log("Creating dirt patches");
|
||||
for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)])
|
||||
createAreas(
|
||||
new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5),
|
||||
[
|
||||
new LayeredPainter([[tGrass,tGrassA], tGrassB, [tGrassB,tGrassC]], [1, 1]),
|
||||
new TileClassPainter(clDirt)
|
||||
],
|
||||
avoidClasses(clRoad, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6),
|
||||
scaleByMapSize(15, 45)
|
||||
);*/
|
||||
|
||||
g_Map.log("Creating additionnal mines for players (balance)");
|
||||
var minesAmountDistribution = [];
|
||||
|
||||
if (numPlayers <= 2)
|
||||
minesAmountDistribution = [0.2, 0.5, 0.2, 0.1];
|
||||
else
|
||||
minesAmountDistribution = [0.1, 0.6, 0.3];
|
||||
|
||||
var incrementedProbability = 0;
|
||||
var minesAmount = 0;
|
||||
var random = Math.random();
|
||||
for (let i = 0; i < minesAmountDistribution.length; ++i) {
|
||||
incrementedProbability += minesAmountDistribution[i];
|
||||
if (random < incrementedProbability) {
|
||||
minesAmount = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For now, equal probability for both mine types.
|
||||
// In 1v1, both players will have exactly the same mine types nearby. In games with more player the type can vary.
|
||||
var objects = [new SimpleObject(oStoneLarge, 1, 1, 0,4), new SimpleObject(oMetalLarge, 1, 1, 0,4)];
|
||||
var groups = [];
|
||||
for (let i = 0; i < minesAmount; i++)
|
||||
groups[i] = new RandomGroup(objects, true, clRock);
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i) {
|
||||
for (let j = 0; j < minesAmount; j++) {
|
||||
if (numPlayers <= 2) {
|
||||
createObjectGroupsByAreas(
|
||||
groups[j],
|
||||
0,
|
||||
[avoidClasses(clRoad, 20, clForest, 3, clPlayer, 15, clRock, 10, clHill, 1)],
|
||||
1,
|
||||
50,
|
||||
[surroundingPlayersAreas[i]]);
|
||||
}
|
||||
else {
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([pickRandom(objects)], true, clRock),
|
||||
0,
|
||||
[avoidClasses(clRoad, 20, clForest, 3, clPlayer, 15, clRock, 10, clHill, 1)],
|
||||
1,
|
||||
50,
|
||||
[surroundingPlayersAreas[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Engine.SetProgress(80);
|
||||
|
||||
|
||||
g_Map.log("Creating stone mines");
|
||||
var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
[avoidClasses(clRoad, 20, clForest, 1, clPlayer, surroundingPlayerAreaMax + 5, clRock, 10, clHill, 1)],
|
||||
scaleByMapSize(5,18), 100
|
||||
);
|
||||
|
||||
g_Map.log("Creating small stone quarries");
|
||||
group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
[avoidClasses(clRoad, 20, clForest, 1, clPlayer, surroundingPlayerAreaMax + 5, clRock, 10, clHill, 1)],
|
||||
scaleByMapSize(5,18), 100
|
||||
);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
[avoidClasses(clRoad, 20, clForest, 1, clPlayer, surroundingPlayerAreaMax + 5, clMetal, 10, clRock, 5, clHill, 1)],
|
||||
scaleByMapSize(5,18), 100
|
||||
);
|
||||
|
||||
Engine.SetProgress(86);
|
||||
|
||||
g_Map.log("Creating small decorative rocks");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aRockMedium, 1,3, 0,1)],
|
||||
true
|
||||
);
|
||||
createObjectGroupsDeprecated(
|
||||
group, 0,
|
||||
avoidClasses(clRoad, 0, clForest, 0, clPlayer, 0, clHill, 0),
|
||||
scaleByMapSize(16, 262), 50
|
||||
);
|
||||
|
||||
g_Map.log("Creating large decorative rocks");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
|
||||
true
|
||||
);
|
||||
createObjectGroupsDeprecated(
|
||||
group, 0,
|
||||
avoidClasses(clRoad, 0, clForest, 0, clPlayer, 0, clHill, 0),
|
||||
scaleByMapSize(8, 131), 50
|
||||
);
|
||||
|
||||
g_Map.log("Creating additionnal food for players (balance)");
|
||||
// Player ressource balance calculation
|
||||
var initialFoodAmount = randIntInclusive(0, 35)// * 100 // 1 unit = 100 food
|
||||
|
||||
// I want it likely that there is no additionnal food for the player.
|
||||
if (initialFoodAmount < 6)
|
||||
initialFoodAmount = 0;
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i) {
|
||||
let playerClass = clPlayers[i];
|
||||
let remainingFood = initialFoodAmount;
|
||||
while (remainingFood > 0) {
|
||||
// Not sure if i should remove groups of 1 / 2 sheep or not.
|
||||
if (remainingFood <= 2) {
|
||||
remainingFood = 0;
|
||||
}
|
||||
else if (remainingFood <= 4) {
|
||||
placeFood(oSheep, remainingFood, remainingFood, remainingFood, playerClass, i);
|
||||
remainingFood = 0;
|
||||
}
|
||||
else if (remainingFood <= 10) {
|
||||
remainingFood -= placeFood(oDeer, 5, 8, remainingFood, playerClass, i);
|
||||
}
|
||||
else {
|
||||
// There I want it more likely to pick berries since hunt will always be chosen for the lower remaining food amounts
|
||||
if (randBool(0.68)) {
|
||||
remainingFood -= 2 * placeFood(oBerryBush, 5, 7, Math.floor(remainingFood/2), playerClass, i);
|
||||
}
|
||||
else {
|
||||
remainingFood -= placeFood(oDeer, 5, 8, remainingFood, playerClass, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_Map.log("Creating deer");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oDeer, 5,7, 0,4)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clRoad, 0, clForest, 0, clPlayer, neighbouringPlayerTiles, clHill, 1, clMetal, 4, clRock, 4, clFood, 20),
|
||||
3 * numPlayers, 50
|
||||
);
|
||||
|
||||
g_Map.log("Creating rabbits");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oRabbit, 2,3, 0,2)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clRoad, 0, clForest, 0, clPlayer, neighbouringPlayerTiles, clHill, 1, clMetal, 4, clRock, 4, clFood, 20),
|
||||
3 * numPlayers, 50
|
||||
);
|
||||
|
||||
g_Map.log("Creating berry bush");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(oBerryBush, 5,7, 0,4)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clRoad, 20, clForest, 0, clPlayer, neighbouringPlayerTiles, clHill, 1, clMetal, 4, clRock, 4, clFood, 10),
|
||||
randIntInclusive(1, 4) * numPlayers + 2, 50
|
||||
);
|
||||
|
||||
createStragglerTrees(
|
||||
[oOak, oBeech],
|
||||
avoidClasses(clRoad, 30, clForest, 7, clHill, 1, clPlayer, 5, clMetal, 6, clRock, 6),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createAutomnalStragglerTrees(tGrassDForest,
|
||||
oOakBig,
|
||||
clForest,
|
||||
borderStragglers,
|
||||
new AndConstraint([avoidClasses(clForest, 7, clBorder, 4, clHill, 1, clPlayer, 5, clMetal, 6, clRock, 6, clRoad, 2), borderClasses(clRoad, 0, 20)]),
|
||||
10);
|
||||
|
||||
|
||||
g_Map.log("Creating dry grass");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aDryGrass, 4,6, 0,0.8, -Math.PI / 8, Math.PI / 8)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
new AndConstraint([avoidClasses(clRoad, 2, clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clDryGrass, 0)]),
|
||||
scaleByMapSize(125, 800)
|
||||
);
|
||||
|
||||
g_Map.log("Creating flowering grass");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aGrassFlower, 4,6, 0,1, -Math.PI / 8, Math.PI / 8)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clRoad, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0, clDryGrass, 2),
|
||||
scaleByMapSize(125, 1000)
|
||||
);
|
||||
|
||||
g_Map.log("Creating soft grass");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aGrassSoft, 1,2, 0,1.8, -Math.PI / 8, Math.PI / 8), new SimpleObject(aGrassSoftTall, 1,1, 1.2,2.5, -Math.PI / 8, Math.PI / 8)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clRoad, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0, clDryGrass, 2),
|
||||
scaleByMapSize(18, 150)
|
||||
);
|
||||
|
||||
g_Map.log("Creating bushes");
|
||||
group = new SimpleGroup(
|
||||
[new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)]
|
||||
);
|
||||
createObjectGroupsDeprecated(group, 0,
|
||||
avoidClasses(clRoad, 1, clHill, 1, clPlayer, 1, clDirt, 1),
|
||||
scaleByMapSize(13, 200), 50
|
||||
);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
|
||||
|
||||
setSkySet("sunset");
|
||||
setSunColor(1.17359, 1.01251, 0.478641);
|
||||
setSunElevation(0.297592);
|
||||
setSunRotation(3.14159);
|
||||
setAmbientColor(0.392157, 0.427451, 0.529412);
|
||||
setFogFactor(0.00298828);
|
||||
setFogThickness(0.00195313);
|
||||
setFogColor(0.886275, 0.811765, 0.576471);
|
||||
|
||||
g_Map.ExportMap();
|
||||
|
||||
function createAutomnalStragglerTrees(groundTexture, treeType, tileClass, count, constraints, retryFactor)
|
||||
{
|
||||
let placeFunc = function() {
|
||||
let center = g_Map.randomCoordinate(false);
|
||||
let centeredPlacer = new ClumpPlacer(randIntInclusive(2, 6), 0, 0.25);
|
||||
centeredPlacer.setCenterPosition(center);
|
||||
let area = createArea(centeredPlacer, new TerrainPainter(groundTexture), constraints);
|
||||
if (area)
|
||||
g_Map.placeEntityAnywhere(treeType, 0, center, randomAngle())
|
||||
return area;
|
||||
};
|
||||
|
||||
return retryPlacing(placeFunc, retryFactor, count, false);
|
||||
}
|
||||
|
||||
// Places a bounded amount of corresponding type food to the specified player and returns the amount placed.
|
||||
function placeFood(type, min, max, remainingFood, playerClass, areaId) {
|
||||
// Since the placing function doesn't specify (i think ?) the number of objects placed, randomization is done there.
|
||||
max = max < remainingFood ? max : remainingFood;
|
||||
let amountPlaced = randIntInclusive(min, max);
|
||||
|
||||
// Hunt should spawn farther from the CC in general.
|
||||
let minTileBound = 15;
|
||||
let maxTileBound = 25;
|
||||
if (type != oBerryBush) {
|
||||
minTileBound += 10;
|
||||
maxTileBound += 10;
|
||||
}
|
||||
|
||||
let group = new SimpleGroup(
|
||||
[new SimpleObject(type, amountPlaced, amountPlaced, 0,4)],
|
||||
true, clFood
|
||||
);
|
||||
createObjectGroupsByAreas(group, 0,
|
||||
new AndConstraint([avoidClasses(clRoad, 0, clForest, 0, clPlayer, minTileBound, clHill, 1, clMetal, 4, clRock, 4, clFood, 10), borderClasses(playerClass, 0, maxTileBound)]),
|
||||
1, 400, [surroundingPlayersAreas[areaId]]
|
||||
);
|
||||
|
||||
return amountPlaced;
|
||||
}
|
||||
|
||||
// If we move this function, add tileClass ids for each player in argument
|
||||
function placePlayerBasesCustom(playerBaseArgs)
|
||||
{
|
||||
g_Map.log("Creating playerbases");
|
||||
|
||||
let [playerIDs, playerPosition] = playerBaseArgs.PlayerPlacement;
|
||||
|
||||
for (let i = 0; i < getNumPlayers(); ++i)
|
||||
{
|
||||
playerBaseArgs.playerID = playerIDs[i];
|
||||
playerBaseArgs.playerPosition = playerPosition[i];
|
||||
playerBaseArgs.CityPatch.painters = [new TileClassPainter(clPlayer), new TileClassPainter(clPlayers[i])];
|
||||
placePlayerBase(playerBaseArgs);
|
||||
}
|
||||
}
|
||||
|
||||
function createForestsCustom(terrainSet, constraint, tileClass, treeCount, retryFactor)
|
||||
{
|
||||
if (!treeCount)
|
||||
return;
|
||||
|
||||
// Construct different forest types from the terrain textures and template names.
|
||||
let [mainTerrain, terrainForestFloor1, terrainForestFloor2, terrainForestTree1, terrainForestTree2] = terrainSet;
|
||||
|
||||
// The painter will pick a random Terrain for each part of the forest.
|
||||
let forestVariants = [
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor2, mainTerrain, terrainForestTree1],
|
||||
"interiorTerrains": [terrainForestFloor2, terrainForestTree1]
|
||||
},
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor1, mainTerrain, terrainForestTree2],
|
||||
"interiorTerrains": [terrainForestFloor1, terrainForestTree2]
|
||||
}
|
||||
];
|
||||
|
||||
let groundVariants = [
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor2, mainTerrain],
|
||||
"interiorTerrains": [terrainForestFloor2]
|
||||
},
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor1, mainTerrain],
|
||||
"interiorTerrains": [terrainForestFloor1]
|
||||
}
|
||||
];
|
||||
|
||||
g_Map.log("Creating forests");
|
||||
let numberOfForests = Math.floor(treeCount / (scaleByMapSize(3, 6) * getNumPlayers() * forestVariants.length));
|
||||
for (let forestVariant of forestVariants)
|
||||
createAreas(
|
||||
new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), treeCount / numberOfForests, 0.5),
|
||||
[
|
||||
//new LayeredPainter([groundVariants.borderTerrains, groundVariants.interiorTerrains], [2]),
|
||||
new TerrainPainter(terrainForestFloor1),
|
||||
new CustomLayeredPainter([forestVariant.borderTerrains, forestVariant.interiorTerrains], [2]),
|
||||
new TileClassPainter(tileClass)
|
||||
],
|
||||
constraint,
|
||||
numberOfForests,
|
||||
retryFactor);
|
||||
}
|
||||
|
||||
function createThickerForests(terrainSet, constraint, tileClass, treeCount, retryFactor)
|
||||
{
|
||||
if (!treeCount)
|
||||
return;
|
||||
|
||||
// Construct different forest types from the terrain textures and template names.
|
||||
let [mainTerrain, terrainForestFloor1, terrainForestFloor2, terrainForestTree1, terrainForestTree2] = terrainSet;
|
||||
|
||||
// The painter will pick a random Terrain for each part of the forest.
|
||||
let forestVariants = [
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor2, mainTerrain, terrainForestTree1],
|
||||
"interiorTerrains": [terrainForestFloor2, terrainForestTree1]
|
||||
},
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor1, mainTerrain, terrainForestTree2],
|
||||
"interiorTerrains": [terrainForestFloor1, terrainForestTree2]
|
||||
}
|
||||
];
|
||||
|
||||
//treeCount /= Math.floor(getNumPlayers() / 2);
|
||||
|
||||
g_Map.log("Creating forests");
|
||||
let numberOfForests = Math.floor(treeCount / (scaleByMapSize(24, 40) * forestVariants.length));
|
||||
for (let forestVariant of forestVariants)
|
||||
createAreas(
|
||||
new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), treeCount / numberOfForests, 0.5),
|
||||
[
|
||||
new LayeredPainter([forestVariant.borderTerrains, forestVariant.interiorTerrains], [2]),
|
||||
new TileClassPainter(tileClass)
|
||||
],
|
||||
constraint,
|
||||
numberOfForests,
|
||||
retryFactor);
|
||||
}
|
||||
|
||||
function createPlayerForests(terrainSet, constraint, tileClass, playerArea)
|
||||
{
|
||||
// Construct different forest types from the terrain textures and template names.
|
||||
let [mainTerrain, terrainForestFloor1, terrainForestFloor2, terrainForestTree1, terrainForestTree2] = terrainSet;
|
||||
|
||||
// The painter will pick a random Terrain for each part of the forest.
|
||||
let forestVariants = [
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor2, mainTerrain, terrainForestTree1],
|
||||
"interiorTerrains": [terrainForestFloor2, terrainForestTree1]
|
||||
},
|
||||
{
|
||||
"borderTerrains": [terrainForestFloor1, mainTerrain, terrainForestTree2],
|
||||
"interiorTerrains": [terrainForestFloor1, terrainForestTree2]
|
||||
}
|
||||
];
|
||||
|
||||
let forestVariant = pickRandom(forestVariants);
|
||||
let treeCount = 28;
|
||||
|
||||
createAreasInAreas(
|
||||
new ChainPlacer(1, /*Math.floor(scaleByMapSize(3, 5))*/3, treeCount, 0),
|
||||
[
|
||||
new LayeredPainter([forestVariant.borderTerrains, forestVariant.interiorTerrains], [2]),
|
||||
new TileClassPainter(tileClass)
|
||||
],
|
||||
constraint,
|
||||
1,
|
||||
100,
|
||||
[playerArea]);
|
||||
}
|
10
community-mod/maps/random/britannic_road.json
Normal file
10
community-mod/maps/random/britannic_road.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Britannic Road",
|
||||
"Script" : "britannic_road.js",
|
||||
"Description" : "Britannic Road",
|
||||
"Preview" : "britannic_road.png",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
338
community-mod/maps/random/cross.js
Normal file
338
community-mod/maps/random/cross.js
Normal file
@ -0,0 +1,338 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
const heightSeaGround = -3;
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tShore = g_Terrains.shore;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
const tWater = g_Terrains.water;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFish = g_Gaia.fish;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightLand = 3;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tMainTerrain);
|
||||
|
||||
const mapSize = g_Map.getSize();
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clWater = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
|
||||
var playerPlacements = playerPlacementCircle(fractionToTiles(0.26 + (numPlayers - 2) * 0.008));
|
||||
const mapCenter = g_Map.getCenter();
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 5
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
Engine.SetProgress(20);
|
||||
|
||||
const [playersOrder, playerPositions, playerAngles, startingAngle] = playerPlacements;
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i)
|
||||
{
|
||||
const playerPosition = playerPositions[i];
|
||||
const angle = playerAngles[i];
|
||||
const lakeRadius = 40;
|
||||
const lakePosition = Vector2D.add(playerPosition, new Vector2D(lakeRadius, 0).rotate(-angle)).round();
|
||||
const lakeSize = Math.round(scaleByMapSize(40, 70) - (numPlayers - 2) * 6);
|
||||
|
||||
createArea(
|
||||
new ChainPlacer(
|
||||
3,
|
||||
4,
|
||||
45,
|
||||
Infinity,
|
||||
lakePosition,
|
||||
lakeRadius - 5,
|
||||
[lakeSize]),
|
||||
[
|
||||
new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4),
|
||||
new TileClassPainter(clWater)
|
||||
],
|
||||
avoidClasses(clPlayer, 25));
|
||||
|
||||
let lakeArea = new Area(new DiskPlacer(30, lakePosition).place(new NullConstraint()));
|
||||
let fish = new SimpleGroup(
|
||||
[new SimpleObject(oFish, 2, 2, 0, 2)],
|
||||
true,
|
||||
clFood
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(fish, 0,
|
||||
new AndConstraint([avoidClasses(clFood, 10), stayClasses(clWater, 8)]),
|
||||
5, 400, [lakeArea]
|
||||
);
|
||||
|
||||
const offsetAngle = Math.PI / numPlayers;
|
||||
const sideLakeRadius = fractionToTiles(0.5) - 2;
|
||||
const sideLakePosition = Vector2D.add(mapCenter, new Vector2D(sideLakeRadius, 0).rotate(-angle - offsetAngle)).round();
|
||||
|
||||
if (mapSize > 128) {
|
||||
const sideMinesRadius = lakeSize + 10;
|
||||
const sideStonePosition = Vector2D.add(sideLakePosition, new Vector2D(sideMinesRadius, 0).rotate(-angle + -offsetAngle + Math.PI - Math.PI/5)).round();
|
||||
const sideMetalPosition = Vector2D.add(sideLakePosition, new Vector2D(sideMinesRadius, 0).rotate(-angle + -offsetAngle + Math.PI + Math.PI/5)).round();
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock),
|
||||
0,
|
||||
avoidClasses(clForest, 10, clWater, 3),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(2, sideStonePosition).place(new NullConstraint()))]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal),
|
||||
0,
|
||||
avoidClasses(clForest, 10, clWater, 3, clRock, 4),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(3, sideMetalPosition).place(new NullConstraint()))]
|
||||
);
|
||||
}
|
||||
|
||||
createArea(
|
||||
new ChainPlacer(
|
||||
3,
|
||||
4,
|
||||
45,
|
||||
Infinity,
|
||||
sideLakePosition,
|
||||
lakeRadius - 5,
|
||||
[lakeSize + 5]),
|
||||
[
|
||||
new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4),
|
||||
new TileClassPainter(clWater)
|
||||
],
|
||||
avoidClasses(clPlayer, 25, clRock, 5, clMetal, 5));
|
||||
|
||||
const sideLakeArea = new Area(new DiskPlacer(35, sideLakePosition).place(stayClasses(clWater, 1)));
|
||||
createObjectGroupsByAreas(fish, 0,
|
||||
new AndConstraint([avoidClasses(clFood, 10), stayClasses(clWater, 8)]),
|
||||
randIntInclusive(7, 10), 400, [sideLakeArea]
|
||||
);
|
||||
|
||||
Engine.SetProgress(20 + 2 * i);
|
||||
}
|
||||
|
||||
const constraints = avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10, clWater, 2);
|
||||
const foodMultiplier = 0.5; // Fishing is map dynamic 0.5 causes errors?
|
||||
placeBalancedFood(playerPlacements, constraints, foodMultiplier);
|
||||
|
||||
Engine.SetProgress(35);
|
||||
|
||||
if (numPlayers <= 2 && mapSize > 192) {
|
||||
placeBalancedMinerals(playerPositions, avoidClasses(clWater, 6, clMetal, 40, clRock, 40));
|
||||
}
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
paintTerrainBasedOnHeight(2.4, 3.4, 3, tMainTerrain);
|
||||
paintTerrainBasedOnHeight(1, 2.4, 0, tShore);
|
||||
paintTerrainBasedOnHeight(-8, 1, 2, tWater);
|
||||
paintTileClassBasedOnHeight(-6, 0, 1, clWater);
|
||||
|
||||
createBumps(avoidClasses(clPlayer, 20, clWater, 1));
|
||||
|
||||
Engine.SetProgress(45);
|
||||
|
||||
if (randBool())
|
||||
createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 35, clHill, 15, clWater, 6, clFood, 4, clMetal, 6, clRock, 6), clHill, scaleByMapSize(2, 11));
|
||||
else
|
||||
createMountains(tCliff, avoidClasses(clPlayer, 35, clHill, 15, clWater, 6, clFood, 4, clMetal, 6, clRock, 6), clHill, scaleByMapSize(2, 11));
|
||||
|
||||
Engine.SetProgress(50);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
avoidClasses(clForest, 18, clHill, 0, clMetal, 4, clRock, 4, clFood, 4, clWater, 4),
|
||||
clForest);
|
||||
}
|
||||
|
||||
Engine.SetProgress(55);
|
||||
|
||||
var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
|
||||
createForests(
|
||||
[tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
|
||||
avoidClasses(clPlayer, 18, clForest, 15, clHill, 0, clMetal, 4, clRock, 4, clWater, 4),
|
||||
clForest,
|
||||
forestTrees);
|
||||
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1, 1],
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWater, 1),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(63);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWater, 1),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
Engine.SetProgress(65);
|
||||
|
||||
const mineralAvoidance = numPlayers > 2 ? 10 : 30;
|
||||
const playerMineralAvoidance = numPlayers > 2 ? 50 : 65;
|
||||
|
||||
g_Map.log("Creating stone mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, playerMineralAvoidance, clMetal, mineralAvoidance, clRock, mineralAvoidance, clHill, 1, clWater, 6),
|
||||
clRock,
|
||||
scaleByMapSize(4, 16) - 1
|
||||
);
|
||||
Engine.SetProgress(68);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oMetalLarge, 1, 1, 0, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, playerMineralAvoidance, clMetal, mineralAvoidance, clRock, mineralAvoidance, clHill, 1, clWater, 6),
|
||||
clMetal,
|
||||
scaleByMapSize(4, 16) - 1
|
||||
);
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clWater, 0));
|
||||
|
||||
|
||||
Engine.SetProgress(73);
|
||||
|
||||
createBadFood(avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20, clWater, 4));
|
||||
|
||||
Engine.SetProgress(75);
|
||||
|
||||
createFood(
|
||||
[
|
||||
[new SimpleObject(oFruitBush, 5, 7, 0, 4)]
|
||||
],
|
||||
[
|
||||
2 * numPlayers
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 45, clHill, 1, clMetal, 4, clRock, 4, clFood, 10, clWater, 4),
|
||||
clFood);
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(
|
||||
clForest, 8, clHill, 1, clPlayer,
|
||||
currentBiome() === "generic/savanna" ? 12 : 30,
|
||||
clMetal, 6, clRock, 6, clFood, 1, clWater, 4
|
||||
),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createBalancedPlayerStragglerTrees(
|
||||
playerPositions,
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(clForest, 8, clHill, 1, clMetal, 6, clRock, 6, clFood, 1, clWater, 2, clBaseResource, 2),
|
||||
25,
|
||||
clForest
|
||||
)
|
||||
|
||||
Engine.SetProgress(95);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 6));
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/cross.json
Normal file
11
community-mod/maps/random/cross.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Cross",
|
||||
"Script" : "cross.js",
|
||||
"Description" : "Players start with lake behind the base with plenty of fishing.",
|
||||
"Preview" : "cross.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* The LayeredPainter sets different Terrains within the Area.
|
||||
* It choses the Terrain depending on the distance to the border of the Area.
|
||||
*
|
||||
* The Terrains given in the first array are painted from the border of the area towards the center (outermost first).
|
||||
* The widths array has one item less than the Terrains array.
|
||||
* Each width specifies how many tiles the corresponding Terrain should be wide (distance to the prior Terrain border).
|
||||
* The remaining area is filled with the last terrain.
|
||||
*/
|
||||
function CustomLayeredPainter(terrainArray, widths)
|
||||
{
|
||||
if (!(terrainArray instanceof Array))
|
||||
throw new Error("CustomLayeredPainter: terrains must be an array!");
|
||||
|
||||
this.terrains = terrainArray.map(terrain => createTerrain(terrain));
|
||||
this.widths = widths;
|
||||
}
|
||||
|
||||
CustomLayeredPainter.prototype.paint = function(area)
|
||||
{
|
||||
breadthFirstSearchPaint({
|
||||
"area": area,
|
||||
"brushSize": 1,
|
||||
"gridSize": g_Map.getSize(),
|
||||
"withinArea": (area, position) => area.contains(position),
|
||||
"paintTile": (point, distance) => {
|
||||
let width = 0;
|
||||
let i = 0;
|
||||
|
||||
for (; i < this.widths.length; ++i)
|
||||
{
|
||||
width += this.widths[i];
|
||||
if (width >= distance)
|
||||
break;
|
||||
}
|
||||
|
||||
if (randBool(0.3))
|
||||
this.terrains[i].place(point);
|
||||
}
|
||||
});
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
function AnnulusPlacer(minRadius, maxRadius, centerPosition = undefined)
|
||||
{
|
||||
this.minRadiusSquared = Math.square(minRadius);
|
||||
this.maxRadiusSquared = Math.square(maxRadius);
|
||||
this.maxRadius = maxRadius;
|
||||
this.centerPosition = undefined;
|
||||
|
||||
if (centerPosition)
|
||||
this.setCenterPosition(centerPosition);
|
||||
}
|
||||
|
||||
AnnulusPlacer.prototype.setCenterPosition = function(position)
|
||||
{
|
||||
this.centerPosition = deepfreeze(position.clone().round());
|
||||
};
|
||||
|
||||
AnnulusPlacer.prototype.place = function(constraint = new NullConstraint())
|
||||
{
|
||||
let points = [];
|
||||
|
||||
const xMin = Math.floor(Math.max(0, this.centerPosition.x - this.maxRadius));
|
||||
const yMin = Math.floor(Math.max(0, this.centerPosition.y - this.maxRadius));
|
||||
const xMax = Math.ceil(Math.min(g_Map.getSize() - 1, this.centerPosition.x + this.maxRadius));
|
||||
const yMax = Math.ceil(Math.min(g_Map.getSize() - 1, this.centerPosition.y + this.maxRadius));
|
||||
|
||||
let it = new Vector2D();
|
||||
for (it.x = xMin; it.x <= xMax; ++it.x)
|
||||
for (it.y = yMin; it.y <= yMax; ++it.y)
|
||||
{
|
||||
const distance = this.centerPosition.distanceToSquared(it);
|
||||
|
||||
if (this.minRadiusSquared <= distance && this.maxRadiusSquared >= distance && constraint.allows(it))
|
||||
points.push(it.clone());
|
||||
}
|
||||
|
||||
return points;
|
||||
};
|
406
community-mod/maps/random/slopes.js
Normal file
406
community-mod/maps/random/slopes.js
Normal file
@ -0,0 +1,406 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
const tWater = g_Terrains.water;
|
||||
const tShore = g_Terrains.shore;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFish = g_Gaia.fish;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightLand = 0;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tMainTerrain);
|
||||
const center = g_Map.getCenter();
|
||||
const mapSize = g_Map.getSize();
|
||||
const halfMapSize = g_Map.getSize() / 2;
|
||||
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clFish = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
const clRamp = g_Map.createTileClass();
|
||||
const clWater = g_Map.createTileClass();
|
||||
|
||||
const playerDistance = fractionToTiles(0.29);
|
||||
const [playerIDs, playerPositions] = placeOpposingTeams(playerDistance, Math.PI / 2, center);
|
||||
const playerPlacements = [playerIDs, playerPositions];
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 5
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
|
||||
Engine.SetProgress(10);
|
||||
|
||||
const heightTop = heightLand + 5;
|
||||
const lowlandsWidth = fractionToTiles(0.36);
|
||||
const rampWidth = fractionToTiles(0.05);
|
||||
const elevationPainter = new ElevationPainter(heightTop);
|
||||
|
||||
const rightRampStartX = halfMapSize + lowlandsWidth / 2;
|
||||
const rightRampEndX = rightRampStartX + rampWidth;
|
||||
const leftRampStartX = halfMapSize - lowlandsWidth / 2;
|
||||
const leftRampEndX = leftRampStartX - rampWidth;
|
||||
|
||||
const rightPlateauPlacer = new RectPlacer(new Vector2D(rightRampEndX, mapSize), new Vector2D(mapSize, 0));
|
||||
const leftPlateauPlacer = new RectPlacer(new Vector2D(0, mapSize), new Vector2D(leftRampEndX, 0));
|
||||
|
||||
createArea(rightPlateauPlacer, elevationPainter);
|
||||
Engine.SetProgress(12);
|
||||
createArea(leftPlateauPlacer, elevationPainter);
|
||||
Engine.SetProgress(14);
|
||||
|
||||
createPassage({
|
||||
"start": new Vector2D(rightRampStartX, halfMapSize),
|
||||
"end": new Vector2D(rightRampEndX, halfMapSize),
|
||||
"startWidth": mapSize,
|
||||
"endWidth": mapSize,
|
||||
"smoothWidth": 2,
|
||||
"tileClass": clRamp,
|
||||
"terrain": tCliff,
|
||||
"edgeTerrain": tHill
|
||||
});
|
||||
Engine.SetProgress(16);
|
||||
|
||||
createPassage({
|
||||
"start": new Vector2D(leftRampStartX, halfMapSize),
|
||||
"end": new Vector2D(leftRampEndX, halfMapSize),
|
||||
"startWidth": mapSize,
|
||||
"endWidth": mapSize,
|
||||
"smoothWidth": 2,
|
||||
"tileClass": clRamp,
|
||||
"terrain": tCliff,
|
||||
"edgeTerrain": tHill
|
||||
});
|
||||
Engine.SetProgress(18);
|
||||
|
||||
const heightWaterLevel = heightTop - 7;
|
||||
|
||||
const fish = new SimpleGroup([new SimpleObject(oFish, 2, 2, 0, 2)], true, clFish);
|
||||
const stone = new SimpleGroup(
|
||||
[new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)],
|
||||
true,
|
||||
clRock
|
||||
);
|
||||
const metal = new SimpleGroup(
|
||||
[new SimpleObject(oMetalLarge, 1, 1, 0, 4)],
|
||||
true,
|
||||
clMetal
|
||||
);
|
||||
|
||||
|
||||
function createSideLakes(xDistance, yDistance) {
|
||||
const stoneRight = randBool();
|
||||
let mineralDistribution = [stoneRight, !stoneRight];
|
||||
|
||||
for (let x of [halfMapSize + xDistance, halfMapSize - xDistance]) {
|
||||
const position = new Vector2D(x, halfMapSize + yDistance);
|
||||
const lakeSize = scaleByMapSize(14, 38);
|
||||
const placer = new ChainPlacer(
|
||||
2,
|
||||
Math.floor(scaleByMapSize(3, 8)),
|
||||
Math.floor(scaleByMapSize(8, 20)),
|
||||
Infinity,
|
||||
position,
|
||||
0,
|
||||
[lakeSize]
|
||||
);
|
||||
|
||||
createArea(
|
||||
placer,
|
||||
[
|
||||
new SmoothElevationPainter(ELEVATION_SET, heightWaterLevel - 3, 4),
|
||||
new TileClassPainter(clWater),
|
||||
],
|
||||
new NullConstraint()
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(fish, 0,
|
||||
avoidClasses(clFish, 6),
|
||||
scaleByMapSize(3, 9), 1000,
|
||||
[new Area(placer.place(stayClasses(clWater, 1)))]
|
||||
);
|
||||
|
||||
const lowerRadius = lakeSize + 2;
|
||||
const maxRadius = lakeSize + 4;
|
||||
|
||||
createObjectGroupsByAreas(mineralDistribution.pop() ? stone : metal, 0,
|
||||
avoidClasses(clWater, 4, clPlayer, 50),
|
||||
1, 400, [getAnnulusArea(lowerRadius, maxRadius, position)]
|
||||
);
|
||||
|
||||
placeFoodAmount(oMainHuntableAnimal, 4, 4, position, avoidClasses(clWater, 2, clFood, 25, clRock, 4, clMetal, 4, clPlayer, 50), lowerRadius, maxRadius);
|
||||
placeFoodAmount(oMainHuntableAnimal, 4, 4, position, avoidClasses(clWater, 2, clFood, 25, clRock, 4, clMetal, 4, clPlayer, 50), lowerRadius, maxRadius);
|
||||
}
|
||||
}
|
||||
|
||||
const lakeDistance = rampWidth + lowlandsWidth / 2 + fractionToTiles(0.11);
|
||||
|
||||
createSideLakes(lakeDistance, fractionToTiles(0.31));
|
||||
Engine.SetProgress(22);
|
||||
createSideLakes(lakeDistance, -fractionToTiles(0.31));
|
||||
Engine.SetProgress(24);
|
||||
|
||||
createArea(
|
||||
leftPlateauPlacer,
|
||||
new TerrainPainter(tWater),
|
||||
new HeightConstraint(-Infinity, heightTop - 1.5));
|
||||
Engine.SetProgress(26);
|
||||
createArea(
|
||||
leftPlateauPlacer,
|
||||
new TerrainPainter(tShore),
|
||||
new HeightConstraint(heightTop - 1, heightTop - 2));
|
||||
Engine.SetProgress(27);
|
||||
|
||||
createArea(
|
||||
rightPlateauPlacer,
|
||||
new TerrainPainter(tWater),
|
||||
new HeightConstraint(-Infinity, heightTop - 1.5));
|
||||
Engine.SetProgress(28);
|
||||
createArea(
|
||||
rightPlateauPlacer,
|
||||
new TerrainPainter(tShore),
|
||||
new HeightConstraint(heightTop - 1, heightTop - 2));
|
||||
Engine.SetProgress(29);
|
||||
|
||||
createBumps(avoidClasses(clPlayer, 20));
|
||||
|
||||
Engine.SetProgress(30);
|
||||
|
||||
const mineralPlacer = new DiskPlacer(4, center);
|
||||
const centerMineralsArea = new Area(mineralPlacer.place(new NullConstraint()));
|
||||
|
||||
createObjectGroupsByAreas(stone, 0,
|
||||
new NullConstraint(),
|
||||
1, 400, [centerMineralsArea]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(metal, 0,
|
||||
avoidClasses(clRock, 6),
|
||||
1, 400, [centerMineralsArea]
|
||||
);
|
||||
|
||||
Engine.SetProgress(32);
|
||||
|
||||
if (randBool())
|
||||
createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 35, clHill, 15, clMetal, 4, clRock, 4, clWater, 8), clHill, scaleByMapSize(2, 11));
|
||||
else
|
||||
createMountains(tCliff, avoidClasses(clPlayer, 35, clHill, 15, clMetal, 4, clRock, 4, clWater, 8), clHill, scaleByMapSize(2, 11));
|
||||
|
||||
Engine.SetProgress(34);
|
||||
|
||||
placeBalancedFood(playerPlacements,
|
||||
avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10, clWater, 4),
|
||||
0.5
|
||||
);
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
avoidClasses(clForest, 18, clHill, 1, clMetal, 4, clRock, 4, clFood, 4, clWater, 4, clBaseResource, 8),
|
||||
clForest);
|
||||
}
|
||||
|
||||
Engine.SetProgress(44);
|
||||
|
||||
const [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(0.7));
|
||||
const leftPlateauArea = new Area(leftPlateauPlacer.place(avoidClasses(clWater, 4, clPlayer, 40)));
|
||||
const rightPlateauArea = new Area(rightPlateauPlacer.place(avoidClasses(clWater, 4, clPlayer, 40)));
|
||||
|
||||
createForestsInArea(
|
||||
leftPlateauArea,
|
||||
avoidClasses(clForest, 13, clHill, 1, clMetal, 4, clRock, 4, clFood, 4, clWater, 3, clPlayer, 40),
|
||||
clForest,
|
||||
forestTrees,
|
||||
2);
|
||||
|
||||
Engine.SetProgress(48);
|
||||
|
||||
createForestsInArea(
|
||||
rightPlateauArea,
|
||||
avoidClasses(clForest, 13, clHill, 1, clMetal, 4, clRock, 4, clFood, 4, clWater, 3, clPlayer, 40),
|
||||
clForest,
|
||||
forestTrees,
|
||||
2);
|
||||
|
||||
Engine.SetProgress(52);
|
||||
|
||||
const lowlandsPlacer = new RectPlacer(new Vector2D(leftRampStartX, 0), new Vector2D(rightRampStartX, mapSize));
|
||||
const lowlandsArea = new Area(lowlandsPlacer.place(avoidClasses(clPlayer, 40)));
|
||||
|
||||
createForestsInArea(
|
||||
lowlandsArea,
|
||||
avoidClasses(clForest, 14, clHill, 1, clMetal, 4, clRock, 4, clFood, 4, clPlayer, 38),
|
||||
clForest,
|
||||
Math.round(forestTrees),
|
||||
2,
|
||||
2
|
||||
);
|
||||
Engine.SetProgress(55);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1, 1],
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWater, 3),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(57);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWater, 3, clRamp, 0),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
Engine.SetProgress(59);
|
||||
|
||||
g_Map.log("Creating stone mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, 60, clRock, 22, clHill, 1, clWater, 30),
|
||||
clRock,
|
||||
scaleByMapSize(4, 16) - 2
|
||||
);
|
||||
Engine.SetProgress(62);
|
||||
|
||||
g_Map.log("Creating metal mines");
|
||||
createMines(
|
||||
[
|
||||
[new SimpleObject(oMetalLarge, 1, 1, 0, 4)]
|
||||
],
|
||||
avoidClasses(clForest, 1, clPlayer, 60, clMetal, 22, clRock, 5, clHill, 1, clWater, 30),
|
||||
clMetal,
|
||||
scaleByMapSize(4, 16) - 2
|
||||
);
|
||||
|
||||
Engine.SetProgress(65);
|
||||
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clWater, 0));
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
createBadFood(avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20, clWater, 20));
|
||||
|
||||
Engine.SetProgress(75);
|
||||
|
||||
createFood(
|
||||
[
|
||||
[new SimpleObject(oFruitBush, 5, 7, 0, 4)]
|
||||
],
|
||||
[
|
||||
2 * numPlayers
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 45, clHill, 1, clMetal, 4, clRock, 4, clFood, 10, clWater, 14),
|
||||
clFood);
|
||||
|
||||
Engine.SetProgress(80);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(
|
||||
clForest, 8, clHill, 1, clPlayer,
|
||||
(currentBiome() == "generic/savanna") ? 12 : 30,
|
||||
clMetal, 6, clRock, 6, clFood, 1, clWater, 4
|
||||
),
|
||||
clForest,
|
||||
(currentBiome() == "generic/savanna") ? stragglerTrees * 1.5 : stragglerTrees);
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 6));
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/slopes.json
Normal file
11
community-mod/maps/random/slopes.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Slopes",
|
||||
"Script" : "slopes.js",
|
||||
"Description" : "Teams are placed in opposite sides, surrounded by plateaus with plenty of wood and fish from lakes.",
|
||||
"Preview" : "slopes.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : false
|
||||
}
|
||||
}
|
280
community-mod/maps/random/wrench.js
Normal file
280
community-mod/maps/random/wrench.js
Normal file
@ -0,0 +1,280 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightLand = 3;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tMainTerrain);
|
||||
|
||||
const mapSize = g_Map.getSize();
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clWrenchHead = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
|
||||
const wrenchScaling = 10 * (numPlayers - 2);
|
||||
const playersCircleRadius = 28 + wrenchScaling;
|
||||
const playerPlacements = playerPlacementCircle(playersCircleRadius);
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 5
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
Engine.SetProgress(20);
|
||||
|
||||
var [playersOrder, playerPositions, playerAngles, startingAngle] = playerPlacements;
|
||||
const mapCenter = g_Map.getCenter();
|
||||
|
||||
const minesVariation = randIntInclusive(2, 12);
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i) {
|
||||
const playerAngle = playerAngles[i];
|
||||
const offsetAngle = Math.PI / numPlayers;
|
||||
const minesRadius = playersCircleRadius + numPlayers * 3 + minesVariation;
|
||||
const minesPoint = new Vector2D(minesRadius).rotate(- playerAngle - offsetAngle);
|
||||
const minesArea = new Area(
|
||||
new DiskPlacer(2.2, Vector2D.add(mapCenter, minesPoint).round()).place(new NullConstraint())
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7),
|
||||
1, 400,
|
||||
[minesArea]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7, clMetal, 6),
|
||||
1, 400,
|
||||
[minesArea]
|
||||
);
|
||||
|
||||
const minesClumpPosition = new Vector2D(minesRadius - 15).rotate(- playerAngle - offsetAngle);
|
||||
const wrenchHeadSize = 20;
|
||||
createArea(
|
||||
new DiskPlacer(wrenchHeadSize, Vector2D.add(mapCenter, minesClumpPosition).round()),
|
||||
[
|
||||
new TerrainPainter(tCliff),
|
||||
new SmoothElevationPainter(ELEVATION_SET, 24, 1),
|
||||
new TileClassPainter(clWrenchHead)
|
||||
],
|
||||
avoidClasses(clPlayer, 18, clMetal, 9, clRock, 9)
|
||||
);
|
||||
|
||||
// If map is not tiny, create metal and stone far from each player near edges
|
||||
if (mapSize > 128) {
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(3, Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.42), 0).rotate(- playerAngle + offsetAngle / 3)).round()).place(new NullConstraint()))]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(3, Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.42), 0).rotate(- playerAngle - offsetAngle / 3)).round()).place(new NullConstraint()))]
|
||||
);
|
||||
}
|
||||
|
||||
Engine.SetProgress(20 + i);
|
||||
}
|
||||
|
||||
const handleSize = 30 + 11.5 * (numPlayers - 2);
|
||||
createArea(
|
||||
new DiskPlacer(handleSize, mapCenter),
|
||||
[
|
||||
new TerrainPainter(tCliff),
|
||||
new SmoothElevationPainter(ELEVATION_SET, 24, 1),
|
||||
new TileClassPainter(clHill)
|
||||
],
|
||||
avoidClasses(clPlayer, 18, clMetal, 10, clRock, 10)
|
||||
);
|
||||
|
||||
Engine.SetProgress(35);
|
||||
|
||||
createBumps(avoidClasses(clPlayer, 20, clMetal, 6, clRock, 6));
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
placeBalancedFood(playerPlacements,
|
||||
avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10, clWrenchHead, 1),
|
||||
1.2 - numPlayers * 0.1
|
||||
);
|
||||
|
||||
Engine.SetProgress(45);
|
||||
|
||||
if (randBool())
|
||||
createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 42, clHill, 15, clMetal, 10, clRock, 10, clWrenchHead, 20, clFood, 4), clHill, scaleByMapSize(2, 11));
|
||||
else
|
||||
createMountains(tCliff, avoidClasses(clPlayer, 42, clHill, 15, clMetal, 10, clRock, 10, clWrenchHead, 20, clFood, 4), clHill, scaleByMapSize(2, 11));
|
||||
|
||||
Engine.SetProgress(48);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
avoidClasses(clForest, 4, clHill, 2, clMetal, 4, clRock, 4, clFood, 2, clWrenchHead, 2, clBaseResource, 1),
|
||||
clForest, 4 - Math.round((numPlayers - 2) / 4), 39 - numPlayers * 2
|
||||
);
|
||||
}
|
||||
|
||||
Engine.SetProgress(50);
|
||||
|
||||
const [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
|
||||
|
||||
createForests(
|
||||
[tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
|
||||
avoidClasses(clPlayer, 18, clForest, 14, clHill, 1, clMetal, 6, clRock, 6, clFood, 6, clWrenchHead, 9),
|
||||
clForest,
|
||||
forestTrees);
|
||||
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1, 1],
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWrenchHead, 2),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(63);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWrenchHead, 2),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(65);
|
||||
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clWrenchHead, 0));
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
createBadFood(avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20, clWrenchHead, 5));
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(
|
||||
clForest, 8, clHill, 1, clPlayer,
|
||||
currentBiome() === "generic/savanna" ? 12 : 30,
|
||||
clMetal, 6, clRock, 6, clFood, 1, clWrenchHead, 10
|
||||
),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createBalancedPlayerStragglerTrees(
|
||||
playerPositions,
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(clForest, 8, clHill, 1, clMetal, 6, clRock, 6, clFood, 1, clWrenchHead, 2, clBaseResource, 2),
|
||||
25 - numPlayers,
|
||||
clForest
|
||||
)
|
||||
|
||||
Engine.SetProgress(90);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWrenchHead, 10));
|
||||
|
||||
Engine.SetProgress(95);
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/wrench.json
Normal file
11
community-mod/maps/random/wrench.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Wrench",
|
||||
"Script" : "wrench.js",
|
||||
"Description" : "Players start side by side, protected by mountains. Extra minerals on border.",
|
||||
"Preview" : "wrench.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
286
community-mod/maps/random/wrench_fixed.js
Normal file
286
community-mod/maps/random/wrench_fixed.js
Normal file
@ -0,0 +1,286 @@
|
||||
Engine.LoadLibrary("rmgen");
|
||||
Engine.LoadLibrary("rmgen-common");
|
||||
Engine.LoadLibrary("rmbiome");
|
||||
Engine.LoadLibrary("balancedHelpers");
|
||||
|
||||
setSelectedBiome();
|
||||
|
||||
const tMainTerrain = g_Terrains.mainTerrain;
|
||||
const tForestFloor1 = g_Terrains.forestFloor1;
|
||||
const tForestFloor2 = g_Terrains.forestFloor2;
|
||||
const tCliff = g_Terrains.cliff;
|
||||
const tTier1Terrain = g_Terrains.tier1Terrain;
|
||||
const tTier2Terrain = g_Terrains.tier2Terrain;
|
||||
const tTier3Terrain = g_Terrains.tier3Terrain;
|
||||
const tHill = g_Terrains.hill;
|
||||
const tRoad = g_Terrains.road;
|
||||
const tRoadWild = g_Terrains.roadWild;
|
||||
const tTier4Terrain = g_Terrains.tier4Terrain;
|
||||
|
||||
const oTree1 = g_Gaia.tree1;
|
||||
const oTree2 = g_Gaia.tree2;
|
||||
const oTree3 = g_Gaia.tree3;
|
||||
const oTree4 = g_Gaia.tree4;
|
||||
const oTree5 = g_Gaia.tree5;
|
||||
const oFruitBush = g_Gaia.fruitBush;
|
||||
const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
|
||||
const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
|
||||
const oStoneLarge = g_Gaia.stoneLarge;
|
||||
const oStoneSmall = g_Gaia.stoneSmall;
|
||||
const oMetalLarge = g_Gaia.metalLarge;
|
||||
|
||||
const aGrass = g_Decoratives.grass;
|
||||
const aGrassShort = g_Decoratives.grassShort;
|
||||
const aRockLarge = g_Decoratives.rockLarge;
|
||||
const aRockMedium = g_Decoratives.rockMedium;
|
||||
const aBushMedium = g_Decoratives.bushMedium;
|
||||
const aBushSmall = g_Decoratives.bushSmall;
|
||||
|
||||
const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
|
||||
const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
|
||||
|
||||
const heightLand = 3;
|
||||
|
||||
var g_Map = new RandomMap(heightLand, tMainTerrain);
|
||||
|
||||
const mapSize = g_Map.getSize();
|
||||
const numPlayers = getNumPlayers();
|
||||
|
||||
const clPlayer = g_Map.createTileClass();
|
||||
const clHill = g_Map.createTileClass();
|
||||
const clWrenchHead = g_Map.createTileClass();
|
||||
const clForest = g_Map.createTileClass();
|
||||
const clDirt = g_Map.createTileClass();
|
||||
const clRock = g_Map.createTileClass();
|
||||
const clMetal = g_Map.createTileClass();
|
||||
const clFood = g_Map.createTileClass();
|
||||
const clBaseResource = g_Map.createTileClass();
|
||||
|
||||
const wrenchScaling = 10 * (numPlayers - 2);
|
||||
const playersCircleRadius = 28 + wrenchScaling;
|
||||
let playerPlacements = playerPlacementCircle(playersCircleRadius);
|
||||
let [playersOrder, playerPositions, playerAngles, startingAngle] = playerPlacements;
|
||||
|
||||
let playerIDs = [];
|
||||
for (let i = 0; i < numPlayers; ++i)
|
||||
playerIDs.push(i+1);
|
||||
|
||||
playerPlacements[0] = playerIDs;
|
||||
|
||||
placePlayerBases({
|
||||
"PlayerPlacement": playerPlacements,
|
||||
"PlayerTileClass": clPlayer,
|
||||
"BaseResourceClass": clBaseResource,
|
||||
"CityPatch": {
|
||||
"outerTerrain": tRoadWild,
|
||||
"innerTerrain": tRoad
|
||||
},
|
||||
"StartingAnimal": {
|
||||
},
|
||||
"Berries": {
|
||||
"template": oFruitBush
|
||||
},
|
||||
"Mines": {
|
||||
"types": [
|
||||
{ "template": oMetalLarge },
|
||||
{ "template": oStoneLarge }
|
||||
]
|
||||
},
|
||||
"Trees": {
|
||||
"template": oTree1,
|
||||
"count": 5
|
||||
},
|
||||
"Decoratives": {
|
||||
"template": aGrassShort
|
||||
}
|
||||
});
|
||||
Engine.SetProgress(20);
|
||||
|
||||
const mapCenter = g_Map.getCenter();
|
||||
|
||||
const minesVariation = randIntInclusive(2, 12);
|
||||
|
||||
for (let i = 0; i < numPlayers; ++i) {
|
||||
const playerAngle = playerAngles[i];
|
||||
const offsetAngle = Math.PI / numPlayers;
|
||||
const minesRadius = playersCircleRadius + numPlayers * 3 + minesVariation;
|
||||
const minesPoint = new Vector2D(minesRadius).rotate(- playerAngle - offsetAngle);
|
||||
const minesArea = new Area(
|
||||
new DiskPlacer(2.2, Vector2D.add(mapCenter, minesPoint).round()).place(new NullConstraint())
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7),
|
||||
1, 400,
|
||||
[minesArea]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7, clMetal, 6),
|
||||
1, 400,
|
||||
[minesArea]
|
||||
);
|
||||
|
||||
const minesClumpPosition = new Vector2D(minesRadius - 15).rotate(- playerAngle - offsetAngle);
|
||||
const wrenchHeadSize = 20;
|
||||
createArea(
|
||||
new DiskPlacer(wrenchHeadSize, Vector2D.add(mapCenter, minesClumpPosition).round()),
|
||||
[
|
||||
new TerrainPainter(tCliff),
|
||||
new SmoothElevationPainter(ELEVATION_SET, 24, 1),
|
||||
new TileClassPainter(clWrenchHead)
|
||||
],
|
||||
avoidClasses(clPlayer, 18, clMetal, 9, clRock, 9)
|
||||
);
|
||||
|
||||
// If map is not tiny, create metal and stone far from each player near edges
|
||||
if (mapSize > 128) {
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(3, Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.42), 0).rotate(- playerAngle + offsetAngle / 3)).round()).place(new NullConstraint()))]
|
||||
);
|
||||
|
||||
createObjectGroupsByAreas(
|
||||
new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal),
|
||||
0,
|
||||
avoidClasses(clForest, 6, clHill, 7),
|
||||
1, 400,
|
||||
[new Area(new DiskPlacer(3, Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.42), 0).rotate(- playerAngle - offsetAngle / 3)).round()).place(new NullConstraint()))]
|
||||
);
|
||||
}
|
||||
|
||||
Engine.SetProgress(20 + i);
|
||||
}
|
||||
|
||||
const handleSize = 30 + 11.5 * (numPlayers - 2);
|
||||
createArea(
|
||||
new DiskPlacer(handleSize, mapCenter),
|
||||
[
|
||||
new TerrainPainter(tCliff),
|
||||
new SmoothElevationPainter(ELEVATION_SET, 24, 1),
|
||||
new TileClassPainter(clHill)
|
||||
],
|
||||
avoidClasses(clPlayer, 18, clMetal, 10, clRock, 10)
|
||||
);
|
||||
|
||||
Engine.SetProgress(35);
|
||||
|
||||
createBumps(avoidClasses(clPlayer, 20, clMetal, 6, clRock, 6));
|
||||
|
||||
Engine.SetProgress(40);
|
||||
|
||||
placeBalancedFood(playerPlacements,
|
||||
avoidClasses(clHill, 1, clMetal, 4, clRock, 4, clBaseResource, 10, clFood, 10, clWrenchHead, 1),
|
||||
1.2 - numPlayers * 0.1
|
||||
);
|
||||
|
||||
Engine.SetProgress(45);
|
||||
|
||||
if (randBool())
|
||||
createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 42, clHill, 15, clMetal, 10, clRock, 10, clWrenchHead, 20, clFood, 4), clHill, scaleByMapSize(2, 11));
|
||||
else
|
||||
createMountains(tCliff, avoidClasses(clPlayer, 42, clHill, 15, clMetal, 10, clRock, 10, clWrenchHead, 20, clFood, 4), clHill, scaleByMapSize(2, 11));
|
||||
|
||||
Engine.SetProgress(48);
|
||||
|
||||
if (currentBiome() != "generic/savanna") {
|
||||
createBalancedPlayerForests(
|
||||
playerPositions,
|
||||
avoidClasses(clForest, 4, clHill, 2, clMetal, 4, clRock, 4, clFood, 2, clWrenchHead, 2, clBaseResource, 1),
|
||||
clForest, 4 - Math.round((numPlayers - 2) / 4), 39 - numPlayers * 2
|
||||
);
|
||||
}
|
||||
|
||||
Engine.SetProgress(50);
|
||||
|
||||
const [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
|
||||
|
||||
createForests(
|
||||
[tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
|
||||
avoidClasses(clPlayer, 18, clForest, 14, clHill, 1, clMetal, 6, clRock, 6, clFood, 6, clWrenchHead, 9),
|
||||
clForest,
|
||||
forestTrees);
|
||||
|
||||
Engine.SetProgress(60);
|
||||
|
||||
g_Map.log("Creating dirt patches");
|
||||
createLayeredPatches(
|
||||
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
|
||||
[[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],
|
||||
[1, 1],
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWrenchHead, 2),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(63);
|
||||
|
||||
g_Map.log("Creating grass patches");
|
||||
createPatches(
|
||||
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
|
||||
tTier4Terrain,
|
||||
avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWrenchHead, 2),
|
||||
scaleByMapSize(15, 45),
|
||||
clDirt);
|
||||
|
||||
Engine.SetProgress(65);
|
||||
|
||||
var planetm = 1;
|
||||
|
||||
if (currentBiome() == "generic/tropic")
|
||||
planetm = 8;
|
||||
|
||||
createDecoration(
|
||||
[
|
||||
[new SimpleObject(aRockMedium, 1, 3, 0, 1)],
|
||||
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
|
||||
[new SimpleObject(aGrassShort, 1, 2, 0, 1)],
|
||||
[new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)],
|
||||
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
|
||||
],
|
||||
[
|
||||
scaleByMapSize(16, 262),
|
||||
scaleByMapSize(8, 131),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200),
|
||||
planetm * scaleByMapSize(13, 200)
|
||||
],
|
||||
avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clWrenchHead, 0));
|
||||
|
||||
Engine.SetProgress(70);
|
||||
|
||||
createBadFood(avoidClasses(clForest, 0, clHill, 1, clMetal, 4, clRock, 4, clFood, 20, clWrenchHead, 5));
|
||||
|
||||
Engine.SetProgress(85);
|
||||
|
||||
createStragglerTrees(
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(
|
||||
clForest, 8, clHill, 1, clPlayer,
|
||||
currentBiome() === "generic/savanna" ? 12 : 30,
|
||||
clMetal, 6, clRock, 6, clFood, 1, clWrenchHead, 10
|
||||
),
|
||||
clForest,
|
||||
stragglerTrees);
|
||||
|
||||
createBalancedPlayerStragglerTrees(
|
||||
playerPositions,
|
||||
[oTree1, oTree2, oTree4, oTree3],
|
||||
avoidClasses(clForest, 8, clHill, 1, clMetal, 6, clRock, 6, clFood, 1, clWrenchHead, 2, clBaseResource, 2),
|
||||
25 - numPlayers,
|
||||
clForest
|
||||
)
|
||||
|
||||
Engine.SetProgress(90);
|
||||
|
||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWrenchHead, 10));
|
||||
|
||||
Engine.SetProgress(95);
|
||||
|
||||
g_Map.ExportMap();
|
11
community-mod/maps/random/wrench_fixed.json
Normal file
11
community-mod/maps/random/wrench_fixed.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"settings" : {
|
||||
"Name" : "Wrench (fixed)",
|
||||
"Script" : "wrench_fixed.js",
|
||||
"Description" : "Players start side by side, protected by mountains, extra minerals on border. Positions defined by players",
|
||||
"Preview" : "wrench.png",
|
||||
"SupportedBiomes": "generic/",
|
||||
"Keywords": ["badmod"],
|
||||
"CircularMap" : true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user