1
0
forked from mirrors/0ad

Nomad mode on all random map scripts (except Survival of the Fittest), fixes #3591.

Fine-tune random map scripts if nomad mode is enabled by omitting gaia
attackers and vast voids.
Fix nomad units on the Unknown sometimes being stuck on mountains or
tiny islands, refs #3140.

Discussed with: bb

This was SVN commit r20866.
This commit is contained in:
elexis
2018-01-14 00:59:06 +00:00
parent 7dfa4bda24
commit c74bd3425f
73 changed files with 557 additions and 335 deletions
@@ -342,6 +342,15 @@ function getGameDescription(extended = false)
translate("Sorry, no description available.")
});
if (extended || g_GameAttributes.settings.Nomad)
titles.push({
"label": g_GameAttributes.settings.Nomad ? translate("Nomad Mode") : translate("Civic Centers"),
"value":
g_GameAttributes.settings.Nomad ?
translate("Players start with only few units and have to find a suitable place to build their city.") :
translate("Players start with a Civic Center.")
});
if (g_GameAttributes.settings.Biome)
{
let biome = g_Settings.Biomes.find(b => b.Id == g_GameAttributes.settings.Biome);
@@ -367,6 +367,7 @@ var g_OptionOrderGUI = {
"populationCap",
"startingResources",
"ceasefire",
"nomad",
"regicideGarrison",
"exploreMap",
"revealMap",
@@ -768,6 +769,18 @@ var g_Checkboxes = {
"enabled": () => g_GameAttributes.mapType != "scenario",
"initOrder": 1000
},
"nomad": {
"title": () => translate("Nomad"),
"tooltip": () => translate("In Nomad mode, players start with only few units and have to find a suitable place to build their city. Ceasefire is recommended."),
"default": () => false,
"defined": () => g_GameAttributes.settings.Nomad !== undefined,
"get": () => g_GameAttributes.settings.Nomad,
"set": checked => {
g_GameAttributes.settings.Nomad = checked;
},
"hidden": () => g_GameAttributes.mapType != "random",
"initOrder": 1000
},
"revealMap": {
"title": () =>
// Translation: Make sure to differentiate between the revealed map and explored map options!
@@ -1796,9 +1809,10 @@ function selectMap(name)
let mapData = loadMapData(name);
let mapSettings = mapData && mapData.settings ? clone(mapData.settings) : {};
// Reset victory conditions
if (g_GameAttributes.mapType != "random")
{
delete g_GameAttributes.settings.Nomad;
let victoryIdx = g_VictoryConditions.Name.indexOf(mapSettings.GameType || "") != -1 ? g_VictoryConditions.Name.indexOf(mapSettings.GameType) : g_VictoryConditions.Default;
g_GameAttributes.settings.GameType = g_VictoryConditions.Name[victoryIdx];
g_GameAttributes.settings.VictoryScripts = g_VictoryConditions.Scripts[victoryIdx];
@@ -283,6 +283,8 @@ createStragglerTrees(
clForest,
stragglerTrees * 10);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clIsland, 10, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("cumulus");
setSunColor(0.866667, 0.776471, 0.486275);
setWaterColor(0, 0.501961, 1);
@@ -269,6 +269,8 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setPPEffect("hdr");
setPPSaturation(0.48);
setPPContrast(0.53);
@@ -288,6 +288,8 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet(pickRandom(["cirrus", "cumulus", "sunny"]));
setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(Math.PI * randFloat(1/5, 1/3));
@@ -533,6 +533,8 @@ createObjectGroupsDeprecated(group, 0,
planetm * scaleByMapSize(13, 200), 50
);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet(pickRandom(["cirrus", "cumulus", "sunny"]));
setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(Math.PI * randFloat(1/5, 1/3));
@@ -190,4 +190,15 @@ addElements(shuffleArray([
]));
Engine.SetProgress(90);
placePlayersNomad(
g_TileClasses.player,
avoidClasses(
g_TileClasses.bluff, 4,
g_TileClasses.water, 4,
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.mountain, 4,
g_TileClasses.animals, 2));
ExportMap();
@@ -231,6 +231,8 @@ createObjectGroupsDeprecated(group, 0,
scaleByMapSize(13, 200), 50
);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setFogThickness(0.1);
setFogFactor(0.2);
@@ -256,6 +256,12 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(
clPlayer,
new AndConstraint([
stayClasses(clLand, 4),
avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]));
setWaterWaviness(4.0);
setWaterType("ocean");
@@ -305,6 +305,8 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clWater, 4, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("sunset 1");
setSunRotation(randFloat(0, 2 * Math.PI));
setSunColor(0.8, 0.7, 0.6);
@@ -452,6 +452,8 @@ createObjectGroupsByAreasDeprecated(group, 0,
[explorableArea]
);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setTerrainAmbientColor(0.44,0.51,0.56);
setUnitsAmbientColor(0.44,0.51,0.56);
@@ -206,6 +206,8 @@ createStragglerTrees(
clForest,
stragglerTrees / 5);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setFogFactor(0.2);
setFogThickness(0.14);
@@ -94,6 +94,8 @@ var goodStartPositionsFound = false;
var minDistBetweenPlayers = 16 + mapSize / 16; // Don't set this higher than 25 for tiny maps! It will take forever with 8 players!
var enoughTiles = false;
var tries = 0;
var lowerHeightLimit = textueByHeight[3].upperHeightLimit;
var upperHeightLimit = textueByHeight[6].upperHeightLimit;
while (!goodStartPositionsFound)
{
@@ -113,8 +115,6 @@ while (!goodStartPositionsFound)
var possibleStartPositions = [];
var neededDistance = 7;
var distToBorder = 2 * neededDistance; // Has to be greater than neededDistance! Otherwise the check if low/high ground is near will fail...
var lowerHeightLimit = textueByHeight[3].upperHeightLimit;
var upperHeightLimit = textueByHeight[6].upperHeightLimit;
// Check for valid points by height
for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; x++)
@@ -369,8 +369,12 @@ for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++)
Engine.SetProgress(90);
if (isNomad())
placePlayersNomad(createTileClass(), new HeightConstraint(lowerHeightLimit, upperHeightLimit));
else
{
log("Placing players and starting resources...");
let playerIDs = sortAllPlayers();
let resourceDistance = 8;
let resourceSpacing = 1;
@@ -371,6 +371,8 @@ createObjectGroupsDeprecated(
scaleByMapSize(13, 200),
50);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("cirrus");
setWaterColor(0.553, 0.635, 0.345);
setWaterTint(0.161, 0.514, 0.635);
@@ -421,15 +421,16 @@ for (let h = 0; h < heighLimits.length; ++h)
}
Engine.SetProgress(80);
/**
* Add start locations and resource spots after terrain texture and path painting
*/
for (let p = 0; p < playerIDs.length; ++p)
{
let point = startLocations[p];
placeCivDefaultStartingEntities(point.x, point.y, playerIDs[p], "walls");
placeStartLocationResources(startLocations[p]);
}
log("Placing players...");
if (isNomad())
placePlayersNomad(createTileClass(), new HeightConstraint(heighLimits[4], heighLimits[5]));
else
for (let p = 0; p < playerIDs.length; ++p)
{
let point = startLocations[p];
placeCivDefaultStartingEntities(point.x, point.y, playerIDs[p], true);
placeStartLocationResources(startLocations[p]);
}
log("Placing resources, farmsteads, groves and camps...");
for (let i = 0; i < resourceSpots.length; ++i)
@@ -56,7 +56,7 @@ var clMetal = createTileClass();
var clFood = createTileClass();
var clBaseResource = createTileClass();
var playerHillRadius = defaultPlayerBaseRadius();
var playerHillRadius = defaultPlayerBaseRadius() / (isNomad() ? 1.5 : 1);
var playerHillElevation = 20;
var [playerIDs, playerX, playerZ, playerAngle] = playerPlacementCircle(0.35);
@@ -259,6 +259,8 @@ createStragglerTrees(
stragglerTrees);
Engine.SetProgress(90);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("cirrus");
setWaterColor(0.447, 0.412, 0.322); // muddy brown
setWaterTint(0.447, 0.412, 0.322);
@@ -80,9 +80,8 @@ for (let i = 0; i < numPlayers; ++i)
[
new LayeredPainter([tMainTerrain, tMainTerrain], [2]),
new SmoothElevationPainter(ELEVATION_SET, landHeight, 2),
paintClass(j == 1 ? clLand : clPlayer)
],
null);
paintClass(j == 1 || isNomad() ? clLand : clPlayer)
]);
log("Creating center area...");
var center = Math.round(fractionToTiles(0.5));
@@ -370,4 +369,8 @@ for (let i = 0; i < randIntInclusive(3, 8); ++i)
for (let template of [oFoodTreasure, oWoodTreasure])
placeObject(center + randFloat(-7, 7), center + randFloat(-7, 7), template, 0, randFloat(0, 2 * Math.PI));
placePlayersNomad(
clPlayer,
[stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clHill2, 4, clFood, 2)]);
ExportMap();
@@ -245,6 +245,10 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(
clPlayer,
[stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]);
setWaterWaviness(1.0);
setWaterType("ocean");
@@ -252,6 +252,8 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("sunny");
setSunColor(0.917, 0.828, 0.734);
setWaterColor(0, 0.501961, 1);
@@ -500,6 +500,8 @@ createObjectGroupsDeprecated(
Engine.SetProgress(95);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clBaseResource, 4, clCliffs, 4));
setSkySet(pickRandom(["cumulus", "sunny"]));
setSunColor(0.8, 0.66, 0.48);
@@ -360,6 +360,8 @@ createObjectGroupsDeprecated(group, 0,
);
Engine.SetProgress(99);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clBaseResource, 4, clHill, 4));
setSkySet("sunny");
setWaterColor(0.2,0.294,0.49);
setWaterTint(0.208, 0.659, 0.925);
@@ -55,7 +55,8 @@ const oCivicCenter = "structures/gaul_civil_centre";
const oHouse = "structures/gaul_house";
const oTemple = "structures/gaul_temple";
const oTavern = "structures/gaul_tavern";
const oTower= "structures/gaul_defense_tower";
const oTower = "structures/gaul_defense_tower";
const oSentryTower = "structures/gaul_sentry_tower";
const oOutpost = "structures/gaul_outpost";
const oHut = "other/celt_hut";
@@ -268,7 +269,7 @@ if (gallicCC)
g_WallStyles.gaul.longhouse = { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oLongHouse };
g_WallStyles.gaul.tavern = { "angle": Math.PI * 3/2, "length": 0, "indent": 4, "bend": 0, "templateName": oTavern };
g_WallStyles.gaul.temple = { "angle": Math.PI * 3/2, "length": 0, "indent": 4, "bend": 0, "templateName": oTemple };
g_WallStyles.gaul.defense_tower = { "angle": Math.PI / 2, "length": 0, "indent": 4, "bend": 0, "templateName": mapSize >= normalMapSize ? oTower : oPalisadeTower };
g_WallStyles.gaul.defense_tower = { "angle": Math.PI / 2, "length": 0, "indent": 4, "bend": 0, "templateName": mapSize >= normalMapSize ? (isNomad() ? oSentryTower : oTower) : oPalisadeTower };
// Replace stone walls with palisade walls
for (let element of ["gate", "long", "short", "cornerIn", "cornerOut", "tower"])
@@ -569,19 +570,20 @@ createFood(
clFood);
log("Creating violent animals...");
createFood(
[
[new SimpleObject(oWolf, 1, 3, 0, 4)],
[new SimpleObject(oBoar, 1, 1, 0, 4)],
[new SimpleObject(oBear, 1, 1, 0, 4)]
],
[
scaleByMapSize(5, 20),
scaleByMapSize(5, 20),
scaleByMapSize(5, 20)
],
avoidClasses(clIsland, 2, clFood, 10, clWater, 5, clPlayer, 24, clHill, 2, clGauls, 5, clPath, 1),
clFood);
if (!isNomad())
createFood(
[
[new SimpleObject(oWolf, 1, 3, 0, 4)],
[new SimpleObject(oBoar, 1, 1, 0, 4)],
[new SimpleObject(oBear, 1, 1, 0, 4)]
],
[
scaleByMapSize(5, 20),
scaleByMapSize(5, 20),
scaleByMapSize(5, 20)
],
avoidClasses(clIsland, 2, clFood, 10, clWater, 5, clPlayer, 24, clHill, 2, clGauls, 5, clPath, 1),
clFood);
Engine.SetProgress(85);
@@ -757,6 +759,8 @@ createObjectGroupsDeprecated(
100
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clIsland, 4, clGauls, 20, clRitualPlace, 20, clForest, 1, clBaseResource, 4, clHill, 4, clFood, 2));
if (randBool(2/3))
{
// Day
@@ -222,6 +222,7 @@ Engine.SetProgress(60);
// Place eyecandy
placeObject(mapCenterX, mapCenterZ, templateEC, 0, randFloat(0, 2 * Math.PI));
addToClass(mapCenterX, mapCenterZ, clBaseResource);
createArea(
new ClumpPlacer(Math.square(radiusEC), 1/2, 1/8, 1, mapCenterX, mapCenterZ),
[
@@ -268,4 +269,6 @@ for (var x = 0; x < mapSize; x++)
}
Engine.SetProgress(95);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clBaseResource, 4));
ExportMap();
@@ -216,4 +216,14 @@ addElements(shuffleArray([
]));
Engine.SetProgress(90);
placePlayersNomad(
g_TileClasses.player,
avoidClasses(
g_TileClasses.plateau, 4,
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.mountain, 4,
g_TileClasses.animals, 2));
ExportMap();
@@ -257,4 +257,6 @@ setPPSaturation(0.62);
setPPContrast(0.62);
setPPBloom(0.37);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
ExportMap();
@@ -74,34 +74,35 @@ var ccMountainSize = defaultPlayerBaseRadius();
var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35);
log("Creating CC mountains...");
for (let i = 0; i < numPlayers; ++i)
{
let ix = Math.round(fractionToTiles(playerX[i]));
let iz = Math.round(fractionToTiles(playerZ[i]));
if (!isNomad())
for (let i = 0; i < numPlayers; ++i)
{
let ix = Math.round(fractionToTiles(playerX[i]));
let iz = Math.round(fractionToTiles(playerZ[i]));
// This one consists of many bumps, creating an omnidirectional ramp
createMountain(
ccMountainHeight,
Math.floor(scaleByMapSize(15, 15)),
Math.floor(scaleByMapSize(15, 15)),
Math.floor(scaleByMapSize(4, 10)),
avoidClasses(),
ix,
iz,
tHillDark,
clPlayer,
14);
// This one consists of many bumps, creating an omnidirectional ramp
createMountain(
ccMountainHeight,
ccMountainSize,
ccMountainSize,
Math.floor(scaleByMapSize(4, 10)),
undefined,
ix,
iz,
tHillDark,
clPlayer,
14);
// Flatten the initial CC area
createArea(
new ClumpPlacer(diskArea(ccMountainSize), 0.95, 0.6, 10, ix, iz),
[
new LayeredPainter([tHillVeryDark, tHillMedium1], [ccMountainSize]),
new SmoothElevationPainter(ELEVATION_SET, ccMountainHeight, ccMountainSize),
paintClass(clPlayer)
]);
}
// Flatten the initial CC area
createArea(
new ClumpPlacer(diskArea(ccMountainSize), 0.95, 0.6, 10, ix, iz),
[
new LayeredPainter([tHillVeryDark, tHillMedium1], [ccMountainSize]),
new SmoothElevationPainter(ELEVATION_SET, ccMountainHeight, ccMountainSize),
paintClass(clPlayer)
],
null);
}
Engine.SetProgress(8);
placePlayerBases({
@@ -277,22 +278,25 @@ createObjectGroupsDeprecated(
100);
Engine.SetProgress(65);
log("Creating towers...");
createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(oTower, 1, 1, 0, 4)], true, clTower),
0,
[
stayClasses(clBumps, 3),
avoidClasses(
clMetal, 5,
clRock, 5,
clHill, 0,
clTower, 60,
clPlayer, 10,
clForest, 2)
],
500,
1);
if (!isNomad())
{
log("Creating towers...");
createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(oTower, 1, 1, 0, 4)], true, clTower),
0,
[
stayClasses(clBumps, 3),
avoidClasses(
clMetal, 5,
clRock, 5,
clHill, 0,
clTower, 60,
clPlayer, 10,
clForest, 2)
],
500,
1);
}
Engine.SetProgress(67);
createDecoration(
@@ -445,6 +449,8 @@ createObjectGroupsDeprecated(
scaleByMapSize(80, 250));
Engine.SetProgress(95);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("rain");
setWaterType("lake");
setWaterWaviness(2);
@@ -312,6 +312,12 @@ createObjectGroupsDeprecated(
[avoidClasses(clMountain, 2, clPlayer, 2, clDirt, 0), stayClasses(clHill, 8)],
planetm * scaleByMapSize(13, 200));
placePlayersNomad(
clPlayer,
new AndConstraint([
stayClasses(clHill, 2),
avoidClasses(clMountain, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]));
setSkySet(pickRandom(["cloudless", "cumulus", "overcast"]));
setWaterMurkiness(0.4);
@@ -59,6 +59,9 @@ var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35);
for (var i=0; i < numPlayers; i++)
{
if (isNomad())
break;
log("Creating base for player " + playerIDs[i] + "...");
playerX[i] *= mapSize;
playerZ[i] *= mapSize;
@@ -304,6 +307,8 @@ createStragglerTrees(
stragglerTrees);
Engine.SetProgress(95);
placePlayersNomad(clPlayer, avoidClasses(clWater, 2, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("sunny");
setWaterColor(0.157, 0.149, 0.443);
setWaterTint(0.443,0.42,0.824);
@@ -95,7 +95,7 @@ if (randElevation < 4)
g_TileClasses.valley, 10,
g_TileClasses.water, 25
],
"sizes": g_AllSizes,
"sizes": ["small"],
"mixes": g_AllMixes,
"amounts": g_AllAmounts
});
@@ -264,4 +264,16 @@ addElements(shuffleArray([
]));
Engine.SetProgress(90);
placePlayersNomad(
g_TileClasses.player,
avoidClasses(
g_TileClasses.bluff, 4,
g_TileClasses.water, 4,
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.mountain, 4,
g_TileClasses.plateau, 4,
g_TileClasses.animals, 2));
ExportMap();
@@ -316,4 +316,6 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
ExportMap();
@@ -260,6 +260,12 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(
clPlayer,
new AndConstraint([
stayClasses(clLand, 4),
avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]));
setSkySet("cumulus");
setWaterColor(0.2,0.312,0.522);
setWaterTint(0.1,0.1,0.8);
@@ -308,6 +308,9 @@ createStragglerTrees(
clForest,
stragglerTrees);
// Avoid the lake, even if frozen
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("stormy");
setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(Math.PI * randFloat(1/6, 1/4));
@@ -249,6 +249,19 @@ addElements([
Engine.SetProgress(90);
placePlayersNomad(
g_TileClasses.player,
avoidClasses(
g_TileClasses.bluff, 4,
g_TileClasses.water, 4,
g_TileClasses.spine, 4,
g_TileClasses.plateau, 4,
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.mountain, 4,
g_TileClasses.animals, 2));
ExportMap();
function addCenterLake()
@@ -222,6 +222,19 @@ addElements(shuffleArray([
]));
Engine.SetProgress(90);
placePlayersNomad(
g_TileClasses.player,
avoidClasses(
g_TileClasses.bluff, 4,
g_TileClasses.water, 4,
g_TileClasses.spine, 4,
g_TileClasses.plateau, 4,
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.mountain, 4,
g_TileClasses.animals, 2));
ExportMap();
function placeBarriers()
@@ -237,7 +250,9 @@ function placeBarriers()
if (currentBiome() == "autumn")
spineTerrain = g_Terrains.tier4Terrain;
for (let i = 0; i < teamsArray.length; ++i)
let spineCount = isNomad() ? randIntInclusive(1, 4) : teamsArray.length;
for (let i = 0; i < spineCount; ++i)
{
var mStartCo = 0.07;
var mStopCo = 0.42;
@@ -246,14 +261,14 @@ function placeBarriers()
var mOffset = 0.5;
var mTaper = -1.5;
if (teamsArray.length > 3 || getMapSize() <= 192)
if (spineCount > 3 || getMapSize() <= 192)
{
mWaviness = 0.2;
mOffset = 0.2;
mTaper = -1;
}
if (teamsArray.length >= 5)
if (spineCount >= 5)
{
mSize = 4;
mWaviness = 0.2;
@@ -261,7 +276,7 @@ function placeBarriers()
mTaper = -0.7;
}
let angle = startAngle + (i + 0.5) * 2 * Math.PI / teamsArray.length;
let angle = startAngle + (i + 0.5) * 2 * Math.PI / spineCount;
createArea(
new PathPlacer(
fractionToTiles(0.5 + mStartCo * Math.cos(angle)),
@@ -320,6 +320,8 @@ createObjectGroupsDeprecated(group, 0,
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);
@@ -248,6 +248,8 @@ createObjectGroupsDeprecated(
scaleByMapSize(100, 1200)
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSunColor(0.87451, 0.847059, 0.647059);
setWaterColor(0.741176, 0.592157, 0.27451);
setWaterTint(0.741176, 0.592157, 0.27451);
@@ -87,7 +87,7 @@ var numTeams = teams.filter(team => team).length;
var teamNo = 0;
for (let i = 0; i < teams.length; ++i)
{
if (!teams[i])
if (!teams[i] || isNomad())
continue;
++teamNo;
@@ -209,7 +209,7 @@ for (let x = 0; x < mapSize; ++x)
landAreas.push([x, z]);
log("Creating big islands...");
let numIslands = scaleByMapSize(4, 14);
let numIslands = scaleByMapSize(4, 14) * (isNomad() ? 2 : 1);
for (let i = 0; i < numIslands; ++i)
{
let landAreaLen = landAreas.length;
@@ -219,7 +219,14 @@ for (let i = 0; i < numIslands; ++i)
let chosenPoint = pickRandom(landAreas);
let newIsland = createAreas(
new ChainPlacer(Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(8, 14)), Math.floor(scaleByMapSize(25, 60)), 0.07, chosenPoint[0], chosenPoint[1], scaleByMapSize(30, 70)),
new ChainPlacer(
Math.floor(scaleByMapSize(4, 8) * (isNomad() ? 2 : 1)),
Math.floor(scaleByMapSize(8, 16) * (isNomad() ? 2 : 1)),
Math.floor(scaleByMapSize(25, 60)),
0.07,
chosenPoint[0],
chosenPoint[1],
scaleByMapSize(30, 70)),
[
new LayeredPainter([tMainTerrain, tMainTerrain], [2]),
new SmoothElevationPainter(ELEVATION_SET, landHeight, 6),
@@ -480,6 +487,8 @@ createObjectGroupsDeprecated(group, 0,
paintTerrainBasedOnHeight(1, 2, 0, tShore);
paintTerrainBasedOnHeight(getMapBaseHeight(), 1, 3, tWater);
placePlayersNomad(clPlayer, [stayClasses(clLand, 4), avoidClasses(clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]);
setSkySet(pickRandom(["cloudless", "cumulus", "overcast"]));
setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(randFloat(1/5, 1/3) * Math.PI);
@@ -65,21 +65,24 @@ var playerIslandRadius = scaleByMapSize(20, 29);
var [playerIDs, playerX, playerZ, playerAngle] = playerPlacementCircle(0.35);
log("Creating player islands and docks...");
for (let i = 0; i < numPlayers; i++)
if (!isNomad())
{
let playerPos = new Vector2D(playerX[i], playerZ[i]).mult(mapSize);
createArea(
new ClumpPlacer(diskArea(playerIslandRadius), 0.8, 0.1, 10, playerPos.x, playerPos.y),
[
new LayeredPainter([tMainTerrain , tMainTerrain, tMainTerrain], [1, 6]),
new SmoothElevationPainter(ELEVATION_SET, landHeight, 6),
paintClass(clLand),
paintClass(clPlayer)
]);
log("Creating player islands and docks...");
for (let i = 0; i < numPlayers; i++)
{
let playerPos = new Vector2D(playerX[i], playerZ[i]).mult(mapSize);
createArea(
new ClumpPlacer(diskArea(playerIslandRadius), 0.8, 0.1, 10, playerPos.x, playerPos.y),
[
new LayeredPainter([tMainTerrain , tMainTerrain, tMainTerrain], [1, 6]),
new SmoothElevationPainter(ELEVATION_SET, landHeight, 6),
paintClass(clLand),
paintClass(clPlayer)
]);
let dockLocation = findLocationInDirectionBasedOnHeight(playerPos, mapCenter, -3 , landHeight - 0.5, landHeight);
placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI);
let dockLocation = findLocationInDirectionBasedOnHeight(playerPos, mapCenter, -3 , landHeight - 0.5, landHeight);
placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI);
}
}
log("Creating big islands...");
@@ -348,6 +351,8 @@ createObjectGroupsDeprecated(group, 0,
planetm * scaleByMapSize(13, 200), 50
);
placePlayersNomad(clPlayer, [stayClasses(clLand, 4), avoidClasses(clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]);
setSkySet(pickRandom(["cirrus", "cumulus", "sunny"]));
setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(randFloat(1/5, 1/3) * Math.PI);
@@ -308,6 +308,8 @@ createObjectGroupsDeprecated(group, 0,
25 * numPlayers, 60
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSunColor(0.6, 0.6, 0.6);
setSunElevation(Math.PI / 3);
@@ -246,6 +246,8 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setWaterWaviness(4.0);
setWaterType("lake");
@@ -454,6 +454,8 @@ createObjectGroupsDeprecated(group, 0,
1.5 * numPlayers, 100
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clCliff, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSkySet("sunny");
setWaterColor(0.024,0.262,0.224);
setWaterTint(0.133, 0.325,0.255);
@@ -408,6 +408,17 @@ addElements([
]);
Engine.SetProgress(95);
placePlayersNomad(
g_TileClasses.player,
[
new HeightConstraint(valleyHeight, pathHeight),
avoidClasses(
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.animals, 2)
]);
ExportMap();
function createSunkenTerrain()
@@ -519,7 +530,7 @@ function createSunkenTerrain()
log("Creating the den of the player...");
createArea(
new ClumpPlacer(mapArea * 0.03, 0.9, 0.3, 1, ...playerCoords),
new ClumpPlacer(mapArea * 0.03 / (isNomad() ? 2 : 1), 0.9, 0.3, 1, ...playerCoords),
[
new LayeredPainter([g_Terrains.cliff, base], [3]),
new SmoothElevationPainter(ELEVATION_SET, denHeight, 3),
@@ -298,6 +298,8 @@ createObjectGroupsDeprecated(group, 0,
60 * scaleByMapSize(13, 200), 80
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("cirrus");
setWaterColor(0.1,0.212,0.422);
setWaterTint(0.3,0.1,0.949);
@@ -191,4 +191,6 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
ExportMap();
@@ -58,6 +58,7 @@ var clMetal = createTileClass();
var clFood = createTileClass();
var clBaseResource = createTileClass();
var clLand = createTileClass();
var clIsland = createTileClass();
var landHeight = 3;
@@ -79,9 +80,13 @@ for (let i = 0; i < numPlayers; ++i)
[
new LayeredPainter([tWater, tShore, tMainTerrain], [1, 4]),
new SmoothElevationPainter(ELEVATION_SET, landHeight, 4),
paintClass(clPlayer)
paintClass(clIsland),
paintClass(isNomad() ? clLand : clPlayer)
]);
if (isNomad())
continue;
let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition, mapCenter, -3 , 2.6, 3);
placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI);
}
@@ -130,7 +135,7 @@ createArea(
new SmoothElevationPainter(ELEVATION_SET, landHeight, 4),
paintClass(clLand)
],
avoidClasses(clPlayer, 8));
avoidClasses(clIsland, 8));
Engine.SetProgress(20);
log("Creating shore jaggedness...");
@@ -143,7 +148,7 @@ createAreas(
],
[
borderClasses(clLand, 6, 3),
avoidClasses(clPlayer, 8)
avoidClasses(clIsland, 8)
],
scaleByMapSize(2, 15) * 20,
150);
@@ -156,7 +161,7 @@ log("Creating bumps...");
createAreas(
new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1),
new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2),
[avoidClasses(clPlayer, 10), stayClasses(clLand, 3)],
[avoidClasses(clIsland, 10), stayClasses(clLand, 3)],
scaleByMapSize(100, 200)
);
Engine.SetProgress(30);
@@ -169,7 +174,7 @@ createAreas(
new SmoothElevationPainter(ELEVATION_SET, 18, 2),
paintClass(clHill)
],
[avoidClasses(clPlayer, 10, clHill, 15), stayClasses(clLand, 7)],
[avoidClasses(clIsland, 10, clHill, 15), stayClasses(clLand, 7)],
scaleByMapSize(1, 4) * numPlayers
);
Engine.SetProgress(34);
@@ -211,7 +216,7 @@ for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8
clForest, 0,
clHill, 0,
clDirt, 5,
clPlayer, 0),
clIsland, 0),
stayClasses(clLand, 7)
],
scaleByMapSize(15, 45));
@@ -223,7 +228,7 @@ for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5
createAreas(
new ClumpPlacer(size, 0.3, 0.06, 0.5),
new TerrainPainter(tTier4Terrain),
[avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 7)],
[avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clIsland, 0), stayClasses(clLand, 7)],
scaleByMapSize(15, 45));
Engine.SetProgress(46);
@@ -362,4 +367,6 @@ setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(randFloat(1/5, 1/3) * Math.PI);
setWaterWaviness(2);
placePlayersNomad(clPlayer, [stayClasses(clIsland, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]);
ExportMap();
@@ -61,16 +61,17 @@ var hillHeight3 = 16;
var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35);
for (let i = 0; i < numPlayers; ++i)
createArea(
new ClumpPlacer(
diskArea(defaultPlayerBaseRadius()),
0.9,
0.5,
10,
Math.round(fractionToTiles(playerX[i])),
Math.round(fractionToTiles(playerZ[i]))),
paintClass(clPlayer));
if (!isNomad())
for (let i = 0; i < numPlayers; ++i)
createArea(
new ClumpPlacer(
diskArea(defaultPlayerBaseRadius()),
0.9,
0.5,
10,
Math.round(fractionToTiles(playerX[i])),
Math.round(fractionToTiles(playerZ[i]))),
paintClass(clPlayer));
placePlayerBases({
"PlayerPlacement": [playerIDs, playerX, playerZ],
@@ -350,6 +351,8 @@ createObjectGroupsDeprecated(group, 0,
scaleByMapSize(16, 262)
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill1, 4, clFood, 2));
setWaterColor(0, 0.227, 0.843);
setWaterTint(0, 0.545, 0.859);
setWaterWaviness(1.0);
@@ -2,8 +2,11 @@ Engine.LoadLibrary("rmgen");
InitMap();
placePlayerBases({
"PlayerPlacement": playerPlacementCircle(0.39)
});
if (isNomad())
placePlayersNomad(createTileClass());
else
placePlayerBases({
"PlayerPlacement": playerPlacementCircle(0.39)
});
ExportMap();
@@ -35,6 +35,7 @@ var clPlayer = createTileClass();
var clHill = createTileClass();
var clForest = createTileClass();
var clWater = createTileClass();
var clIsland = createTileClass();
var clDirt = createTileClass();
var clRock = createTileClass();
var clMetal = createTileClass();
@@ -108,6 +109,7 @@ createAreas(
[
new LayeredPainter([tSnowA, tSnowA], [3]),
new SmoothElevationPainter(ELEVATION_SET, 3, 3),
paintClass(clIsland),
unPaintClass(clWater)
],
stayClasses(clWater, 7),
@@ -264,6 +266,8 @@ createObjectGroupsDeprecated(group, 0,
25 * numPlayers, 60
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clIsland, 4));
setSunColor(0.6, 0.6, 0.6);
setSunElevation(Math.PI/ 6);
@@ -315,6 +315,8 @@ for (var sandx = 0; sandx < mapSize; sandx += 4)
}
}
placePlayersNomad(clPlayer, avoidClasses(clOasis, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("sunny");
setSunColor(0.914,0.827,0.639);
setSunRotation(Math.PI/3);
@@ -323,4 +323,6 @@ setPPContrast(0.75);
setPPSaturation(0.45);
setPPBloom(0.3);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
ExportMap();
@@ -177,7 +177,8 @@ createAreas(
[
new LayeredPainter([tShore, tHill], [12]),
new SmoothElevationPainter(ELEVATION_SET, 6, 8),
paintClass(clIsland)
paintClass(clIsland),
unPaintClass(clWater)
],
[stayClasses (clWater, 8)],
1,
@@ -318,4 +319,6 @@ setPPContrast(0.53);
setPPSaturation(0.47);
setPPBloom(0.52);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
ExportMap();
@@ -45,14 +45,19 @@ var clArcticWolf = createTileClass();
var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35);
var treasures = [{
"template": oWoodTreasure,
"count": isNomad() ? 16 : 14
}];
log("Creating player markets...");
var marketDist = 12;
for (let i = 0; i < numPlayers; ++i)
{
let marketPos = Vector2D.add(new Vector2D(playerX[i], playerZ[i]).mult(mapSize), new Vector2D(marketDist, 0).rotate(randFloat(0, 2 * Math.PI))).round();
placeObject(marketPos.x, marketPos.y, oMarket, playerIDs[i], BUILDING_ORIENTATION);
addCivicCenterAreaToClass(marketPos.x, marketPos.y, clBaseResource);
}
if (!isNomad())
for (let i = 0; i < numPlayers; ++i)
{
let marketPos = Vector2D.add(new Vector2D(playerX[i], playerZ[i]).mult(mapSize), new Vector2D(12, 0).rotate(randFloat(0, 2 * Math.PI))).round();
placeObject(marketPos.x, marketPos.y, oMarket, playerIDs[i], BUILDING_ORIENTATION);
addCivicCenterAreaToClass(marketPos.x, marketPos.y, clBaseResource);
}
placePlayerBases({
"PlayerPlacement": [playerIDs, playerX, playerZ],
@@ -74,12 +79,7 @@ placePlayerBases({
]
},
"Treasures": {
"types": [
{
"template": oWoodTreasure,
"count": 14
}
]
"types": treasures
},
});
Engine.SetProgress(30);
@@ -216,7 +216,7 @@ Engine.SetProgress(80);
createFood(
[
[new SimpleObject(oArcticFox, 1, 2, 0, 3)],
[new SimpleObject(oArcticWolf, 4, 6, 0, 4)],
[new SimpleObject(isNomad() ? oArcticFox : oArcticWolf, 4, 6, 0, 4)],
[new SimpleObject(oWalrus, 2, 3, 0, 2)],
[new SimpleObject(oMuskox, 2, 3, 0, 2)]
],
@@ -275,6 +275,22 @@ else
setSunElevation(Math.PI * randFloat(1/9, 1/7));
}
if (isNomad())
{
let constraint = avoidClasses(clWater, 4, clMetal, 4, clRock, 4, clHill, 4, clFood, 2);
[playerIDs, playerX, playerZ] = placePlayersNomad(clPlayer, constraint);
for (let i = 0; i < numPlayers; ++i)
placePlayerBaseTreasures({
"playerID": playerIDs[i],
"playerX": tilesToFraction(playerX[i]),
"playerZ": tilesToFraction(playerZ[i]),
"BaseResourceClass": clBaseResource,
"baseResourceConstraint": constraint,
"types": treasures
});
}
setSunRotation(randFloat(0, 2 * Math.PI));
setWaterColor(0.3, 0.3, 0.4);
@@ -449,6 +449,8 @@ log("Creating fish...");
group = new SimpleGroup( [new SimpleObject(oFish, 2,3, 0,2)], true, clFood );
createObjectGroupsDeprecated(group, 0, [avoidClasses(clFood, 15), stayClasses(clWater, 6)], 20 * numPlayers, 60 );
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clPyrenneans, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSunElevation(Math.PI * randFloat(1/5, 1/3));
setSunRotation(randFloat(0, 2 * Math.PI));
@@ -284,6 +284,8 @@ createObjectGroupsDeprecated(
scaleByMapSize(13, 200),
50);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSkySet("cirrus");
setWaterColor(0.753,0.635,0.345); // muddy brown
setWaterTint(0.161,0.514,0.635); // clear blue for blueness
@@ -141,37 +141,40 @@ placePlayerBases({
});
Engine.SetProgress(35);
log("Creating gaia...");
for (let i = 0; i < 2; ++i)
for (let j = 0; j < scaleByMapSize(1, 8); ++j)
createObjectGroupsDeprecated(
new SimpleGroup(
[
new SimpleObject(oSpearman, 8, 12, 2, 3),
new SimpleObject(oArcher, 8, 12, 2, 3),
new SimpleObject(oArcherElephant, 2, 3, 4, 5)
],
true,
clGaia),
0,
[
avoidClasses(
clWater, 2,
clForest, 1,
clPlayerTerritory, 0,
clHill, 1,
clGaia, 15),
stayClasses(clStrip[i == 0 ? 0 : stripWidths.length - 1], 1)
],
scaleByMapSize(5, 10),
50);
paintTerrainBasedOnHeight(-10, 0, 1, tWater);
paintTileClassBasedOnHeight(-10, 0, 1, clWater);
paintTerrainBasedOnHeight(1, 2.8, 1, tShoreBlend);
paintTerrainBasedOnHeight(0, 1, 1, tShore);
Engine.SetProgress(40);
if (!isNomad())
{
log("Creating gaia...");
for (let i = 0; i < 2; ++i)
for (let j = 0; j < scaleByMapSize(1, 8); ++j)
createObjectGroupsDeprecated(
new SimpleGroup(
[
new SimpleObject(oSpearman, 8, 12, 2, 3),
new SimpleObject(oArcher, 8, 12, 2, 3),
new SimpleObject(oArcherElephant, 2, 3, 4, 5)
],
true,
clGaia),
0,
[
avoidClasses(
clWater, 2,
clForest, 1,
clPlayerTerritory, 0,
clHill, 1,
clGaia, 15),
stayClasses(clStrip[i == 0 ? 0 : stripWidths.length - 1], 1)
],
scaleByMapSize(5, 10),
50);
}
log("Creating hills...");
createAreas(
new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.1),
@@ -463,6 +466,8 @@ createObjectGroupsDeprecated(
200,
100);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSunColor(0.6, 0.6, 0.6);
setSunElevation(Math.PI/ 3);
@@ -116,10 +116,11 @@ createArea(
null);
log("Creating rivers between opponents...");
let rivers = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0];
for (let i = 0; i < numPlayers; ++i)
let numRivers = isNomad() ? randIntInclusive(4, 8) : numPlayers;
let rivers = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numRivers, fractionToTiles(0.5), mapCenter)[0];
for (let i = 0; i < numRivers; ++i)
{
if (areAllies(playerIDs[i], playerIDs[(i + 1) % numPlayers]))
if (isNomad() ? randBool() : areAllies(playerIDs[i], playerIDs[(i + 1) % numPlayers]))
continue;
let shallowLocation = randFloat(0.2, 0.7);
@@ -291,6 +292,8 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setWaterWaviness(3.0);
setWaterType("lake");
@@ -314,6 +314,11 @@ function getMapCenter()
return deepfreeze(new Vector2D(g_Map.size / 2, g_Map.size / 2));
}
function isNomad()
{
return !!g_MapSettings.Nomad;
}
function getNumPlayers()
{
return g_MapSettings.PlayerData.length - 1;
@@ -2,6 +2,13 @@
* @file These functions locate and place the starting entities of players.
*/
var g_NomadTreasureTemplates = {
"food": "gaia/special_treasure_food_jars",
"wood": "gaia/special_treasure_wood",
"stone": "gaia/special_treasure_stone",
"metal": "gaia/special_treasure_metal"
};
/**
* These are identifiers of functions that can generate parts of a player base.
* There must be a function starting with placePlayerBase and ending with this name.
@@ -106,6 +113,9 @@ function placePlayerBases(playerBaseArgs)
*/
function placePlayerBase(playerBaseArgs)
{
if (isNomad())
return;
log("Creating base for player " + playerBaseArgs.playerID + "...");
let fx = fractionToTiles(playerBaseArgs.playerX);
@@ -400,6 +410,58 @@ function placePlayerBaseDecoratives(args)
}
}
function placePlayersNomad(playerClass, constraints)
{
if (!isNomad())
return;
let distance = scaleByMapSize(60, 240);
let constraint = new AndConstraint(constraints);
let numPlayers = getNumPlayers();
let playerIDs = shuffleArray(sortAllPlayers());
let playerX = [];
let playerZ = [];
for (let i = 0; i < numPlayers; ++i)
{
log("Determine starting units for player " + playerIDs[i] + "...");
let objects = getStartingEntities(playerIDs[i]).filter(ents => ents.Template.startsWith("units/")).map(
ents => new SimpleObject(ents.Template, ents.Count || 1, ents.Count || 1, 1, 3));
log("Ensure resources for a civic center...");
let ccCost = Engine.GetTemplate("structures/" + getCivCode(playerIDs[i]) + "_civil_centre").Cost.Resources;
for (let resourceType in ccCost)
{
let treasureTemplate = g_NomadTreasureTemplates[resourceType];
let count = Math.max(0, Math.ceil(
(ccCost[resourceType] - (g_MapSettings.StartingResources || 0)) /
Engine.GetTemplate(treasureTemplate).ResourceSupply.Amount));
objects.push(new SimpleObject(treasureTemplate, count, count, 3, 5));
}
log("Placing player units...");
let group = new SimpleGroup(objects, true, playerClass);
let success = false;
for (let distanceFactor of [1, 1/2, 1/4, 0])
{
if (createObjectGroups(group, playerIDs[i], new AndConstraint([constraint, avoidClasses(playerClass, distance * distanceFactor)]), 1, 200, false))
{
success = true;
playerX[i] = group.x;
playerZ[i] = group.z;
break;
}
}
if (!success)
throw new Error("Could not place starting units for player " + playerIDs[i] + "!");
}
return [playerIDs, playerX, playerZ];
}
/**
* Sorts an array of player IDs by team index. Players without teams come first.
* Randomize order for players of the same team.
@@ -224,6 +224,8 @@ createObjectGroupsDeprecated(group, 0,
5*scaleByMapSize(5,20), 50
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2, clTreasure, 2));
setSkySet("sunny");
setSunColor(0.746, 0.718, 0.539);
setWaterColor(0, 0.227, 0.843);
@@ -219,6 +219,8 @@ createObjectGroupsDeprecated(group, 0,
scaleByMapSize(100, 1200)
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSunColor(0.87451, 0.847059, 0.647059);
setWaterColor(0.741176, 0.592157, 0.27451);
setWaterTint(0.741176, 0.592157, 0.27451);
@@ -372,6 +372,8 @@ createObjectGroupsDeprecated(group, 0,
planetm * scaleByMapSize(13, 200), 50
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSkySet("sunny");
setSunRotation(randFloat(0, 2 * Math.PI));
@@ -405,6 +405,8 @@ for (var x = 0; x < mapSize; x++)
avoidClasses(clPath, 2, clOpen, 3, clWater, 4, clMetal, 4, clRock, 4));
}
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clFood, 2, clMetal, 4, clRock, 4));
Engine.SetProgress(100);
ExportMap();
@@ -214,7 +214,7 @@ log("Creating player islands...");
for (let i = 0; i < numPlayers; ++i)
{
islandPos[i] = new Vector2D(playerX[i], playerZ[i]).mult(mapSize).round();
createIsland(i, 1, clPlayer);
createIsland(i, 1, isNomad() ? clLand : clPlayer);
}
placePlayerBases({
@@ -426,6 +426,13 @@ createObjectGroupsDeprecated(group, 0,
planetm * scaleByMapSize(13, 200), 50
);
placePlayersNomad(
clPlayer,
[
stayClasses(clLand, 8),
avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clFood, 2)
]);
setSkySet(pickRandom(["cirrus", "cumulus", "sunny"]));
setSunRotation(randFloat(0, 2 * Math.PI));
setSunElevation(Math.PI * randFloat(1/5, 1/3));
@@ -239,4 +239,15 @@ addElements(shuffleArray([
]));
Engine.SetProgress(90);
placePlayersNomad(
g_TileClasses.player,
avoidClasses(
g_TileClasses.bluff, 4,
g_TileClasses.plateau, 4,
g_TileClasses.forest, 1,
g_TileClasses.metal, 4,
g_TileClasses.rock, 4,
g_TileClasses.mountain, 4,
g_TileClasses.animals, 2));
ExportMap();
+16 -5
View File
@@ -52,13 +52,22 @@ for (let i = 0; i < numPlayers; ++i)
let iz = Math.round(fractionToTiles(playerZ[i]));
log("Marking player territory larger than the city patch...");
createArea(
new ClumpPlacer(diskArea(scaleByMapSize(15, 25)), 0.9, 0.5, 10, ix, iz),
paintClass(clPlayer));
if (!isNomad())
createArea(
new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.9, 0.5, 10, ix, iz),
paintClass(clPlayer));
log("Creating big grass patches surrounding the city patches...");
createArea(
new ChainPlacer(2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(25, 60)), 1, ix, iz, 0, [Math.floor(scaleByMapSize(16, 30))]),
new ChainPlacer(
2,
Math.floor(scaleByMapSize(5, 12)),
Math.floor(scaleByMapSize(25, 60)) / (isNomad() ? 2 : 1),
1,
ix,
iz,
0,
[Math.floor(scaleByMapSize(16, 30))]),
[
new LayeredPainter([tGrassSands, tGrass], [3]),
paintClass(clGrass)
@@ -243,7 +252,9 @@ createStragglerTrees(
[oPalm, oTamarix, oPine],
[avoidClasses(clForest, 1, clHill, 1, clPlayer, 1, clMetal, 6, clRock, 6), stayClasses(clGrass, 3)],
clForest,
stragglerTrees);
stragglerTrees * (isNomad() ? 3 : 1));
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
setSkySet("sunny");
setSunElevation(Math.PI / 8);
@@ -384,6 +384,8 @@ createObjectGroupsDeprecated(
scaleByMapSize(2, 6), 50
);
placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2));
setSkySet("sunny");
setSunColor(0.711, 0.746, 0.574);
setWaterColor(0.541,0.506,0.416);
@@ -2,11 +2,6 @@
* @file This library is used to generate different map variations on the map Unknown, Unknown Land and Unknown Nomad.
*/
/**
* True if city centers should be placed or false for nomad.
*/
var g_PlayerBases;
/**
* True if all players should be connected via land and false if river or islands can split some if not all the players.
*/
@@ -122,7 +117,9 @@ function createUnknownMap()
paintUnknownMapBasedOnHeight();
if (g_PlayerBases)
if (isNomad())
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2));
else
createUnknownPlayerBases();
}
@@ -135,7 +132,7 @@ function unknownArchipelago()
g_StartingTreasures = true;
let [pIDs, islandX, islandZ] = playerPlacementCircle(0.35);
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ] = [pIDs, islandX, islandZ];
markPlayerArea("large");
@@ -148,7 +145,7 @@ function unknownArchipelago()
new ClumpPlacer(islandSize, 0.8, 0.1, 10, fractionToTiles(islandX[i]), fractionToTiles(islandZ[i])),
landElevationPainter);
let type = randIntInclusive(1, 3);
let type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3);
if (type == 1)
{
log("Creating archipelago...");
@@ -216,7 +213,7 @@ function unknownContinent()
{
let waterHeight = -5;
if (g_PlayerBases)
if (!isNomad())
{
log("Ensuring player area...");
[playerIDs, playerX, playerZ] = playerPlacementCircle(0.25);
@@ -311,7 +308,7 @@ function unknownCentralSea()
}
});
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ] = playerPlacementRiver(horizontal ? Math.PI / 2 : 0, 0.6);
markPlayerArea("small");
@@ -354,7 +351,7 @@ function unknownCentralRiver()
let horizontal = randBool();
let riverAngle = horizontal ? 0 : Math.PI / 2;
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ] = playerPlacementRiver(horizontal ? Math.PI / 2 : 0, 0.5);
markPlayerArea("large");
@@ -416,7 +413,7 @@ function unknownRiversAndLake()
initHeight(landHeight);
let startAngle;
if (g_PlayerBases)
if (!isNomad())
{
let playerAngle;
[playerIDs, playerX, playerZ, playerAngle, startAngle] = playerPlacementCircle(0.35);
@@ -438,7 +435,7 @@ function unknownRiversAndLake()
}
// Don't do this on nomad because the imbalances on the different islands are too drastic
if (g_PlayerBases && (!lake || randBool(1/3)))
if (!isNomad() && (!lake || randBool(1/3)))
{
log("Creating small rivers separating players...");
for (let river of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0])
@@ -469,7 +466,7 @@ function unknownRiversAndLake()
]);
}
if (lake && randBool())
if (!isNomad && lake && randBool())
{
log("Creating small central island...");
createArea(
@@ -490,7 +487,7 @@ function unknownEdgeSeas()
initHeight(landHeight);
let horizontal = randBool();
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ] = playerPlacementLine(horizontal, 0.5, 0.2);
// Don't place the shoreline inside the CC, but possibly into the players territory
@@ -535,7 +532,7 @@ function unknownGulf()
initHeight(landHeight);
let startAngle = randFloat(0, 2) * Math.PI;
if (g_PlayerBases)
if (!isNomad())
{
log("Determining player locations...");
@@ -573,7 +570,7 @@ function unknownLakes()
initHeight(landHeight);
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ] = playerPlacementCircle(0.35);
markPlayerArea("large");
@@ -601,7 +598,7 @@ function unknownPasses()
let playerAngle;
let startAngle;
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ, playerAngle, startAngle] = playerPlacementCircle(0.35);
markPlayerArea("small");
@@ -680,7 +677,7 @@ function unknownLowlands()
let playerAngle;
let startAngle;
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ, playerAngle, startAngle] = playerPlacementCircle(0.35);
markPlayerArea("small");
@@ -732,7 +729,7 @@ function unknownMainland()
{
initHeight(3);
if (g_PlayerBases)
if (!isNomad())
{
[playerIDs, playerX, playerZ] = playerPlacementCircle(0.35);
markPlayerArea("small");
@@ -2,7 +2,6 @@ Engine.LoadLibrary("rmgen");
Engine.LoadLibrary("rmbiome");
Engine.LoadLibrary("the_unknown");
g_PlayerBases = true;
g_AllowNaval = true;
createUnknownMap();
@@ -2,7 +2,6 @@ Engine.LoadLibrary("rmgen");
Engine.LoadLibrary("rmbiome");
Engine.LoadLibrary("the_unknown");
g_PlayerBases = true;
g_AllowNaval = false;
createUnknownMap();
@@ -1,126 +0,0 @@
Engine.LoadLibrary("rmgen");
Engine.LoadLibrary("rmbiome");
Engine.LoadLibrary("the_unknown");
g_PlayerBases = false;
g_AllowNaval = true;
createUnknownMap();
var distmin = Math.square(scaleByMapSize(60, 240));
playerIDs = sortAllPlayers();
for (var i = 0; i < numPlayers; i++)
{
var placableArea = [];
for (var mx = 0; mx < mapSize; mx++)
{
for (var mz = 0; mz < mapSize; mz++)
{
if (!g_Map.validT(mx, mz, 3))
continue;
var placable = true;
for (var c = 0; c < i; c++)
if ((playerX[c] - mx)*(playerX[c] - mx) + (playerZ[c] - mz)*(playerZ[c] - mz) < distmin)
placable = false;
if (!placable)
continue;
if (g_Map.getHeight(mx, mz) >= 3 && g_Map.getHeight(mx, mz) <= 3.12)
placableArea.push([mx, mz]);
}
}
if (!placableArea.length)
{
for (var mx = 0; mx < mapSize; ++mx)
{
for (var mz = 0; mz < mapSize; mz++)
{
if (!g_Map.validT(mx, mz, 3))
continue;
var placable = true;
for (var c = 0; c < i; c++)
if ((playerX[c] - mx)*(playerX[c] - mx) + (playerZ[c] - mz)*(playerZ[c] - mz) < distmin/4)
placable = false;
if (!placable)
continue;
if (g_Map.getHeight(mx, mz) >= 3 && g_Map.getHeight(mx, mz) <= 3.12)
placableArea.push([mx, mz]);
}
}
}
if (!placableArea.length)
for (var mx = 0; mx < mapSize; ++mx)
for (var mz = 0; mz < mapSize; ++mz)
if (g_Map.getHeight(mx, mz) >= 3 && g_Map.getHeight(mx, mz) <= 3.12)
placableArea.push([mx, mz]);
[playerX[i], playerZ[i]] = pickRandom(placableArea);
}
for (var i = 0; i < numPlayers; ++i)
{
var id = playerIDs[i];
log("Creating units for player " + id + "...");
// get the x and z in tiles
var ix = playerX[i];
var iz = playerZ[i];
playerX[i] = tilesToFraction(playerX[i]);
playerZ[i] = tilesToFraction(playerZ[i]);
var civEntities = getStartingEntities(playerIDs[i]);
var angle = randFloat(0, 2 * Math.PI);
for (var j = 0; j < civEntities.length; ++j)
{
// TODO: Make an rmlib function to get only non-structure starting entities and loop over those
if (!civEntities[j].Template.startsWith("units/"))
continue;
var count = civEntities[j].Count || 1;
var jx = ix + 2 * Math.cos(angle);
var jz = iz + 2 * Math.sin(angle);
var kAngle = randFloat(0, 2 * Math.PI);
for (var k = 0; k < count; ++k)
placeObject(jx + Math.cos(kAngle + k*2 * Math.PI/count), jz + Math.sin(kAngle + k*2 * Math.PI/count), civEntities[j].Template, id, randFloat(0, 2 * Math.PI));
angle += 2 * Math.PI / 3;
}
{
if (g_MapSettings.StartingResources < 500)
{
var loop = (g_MapSettings.StartingResources < 200) ? 2 : 1;
for (let l = 0; l < loop; ++l)
{
var angle = randFloat(0, 2 * Math.PI);
var rad = randFloat(3, 5);
var jx = ix + rad * Math.cos(angle);
var jz = iz + rad * Math.sin(angle);
placeObject(jx, jz, "gaia/special_treasure_wood", 0, randFloat(0, 2 * Math.PI));
var angle = randFloat(0, 2 * Math.PI);
var rad = randFloat(3, 5);
var jx = ix + rad * Math.cos(angle);
var jz = iz + rad * Math.sin(angle);
placeObject(jx, jz, "gaia/special_treasure_stone", 0, randFloat(0, 2 * Math.PI));
var angle = randFloat(0, 2 * Math.PI);
var rad = randFloat(3, 5);
var jx = ix + rad * Math.cos(angle);
var jz = iz + rad * Math.sin(angle);
placeObject(jx, jz, "gaia/special_treasure_metal", 0, randFloat(0, 2 * Math.PI));
}
}
}
}
// Don't place resources into the starting units
markPlayerArea("small");
createUnknownObjects();
ExportMap();
@@ -1,12 +0,0 @@
{
"settings" : {
"Name" : "Unknown Nomad",
"Script" : "unknown_nomad.js",
"Description" : "The unknown. Players start with only some citizen soldiers and female citizens. [color=\"red\"]Warning: The starting resources should be set at least at Medium.[/color]",
"BaseTerrain" : ["medit_sand_wet"],
"BaseHeight" : -5,
"Preview" : "unknown.png",
"SupportedBiomes": true,
"CircularMap" : true
}
}
@@ -176,4 +176,6 @@ createStragglerTrees(
clForest,
stragglerTrees);
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4));
ExportMap();
@@ -588,18 +588,19 @@ for (let i = 0; i < avoidPoints.length; ++i)
let resourceSpots = getPointsByHeight(resourceSpotHeightRange, avoidPoints, clPath);
Engine.SetProgress(55);
/**
* Add start locations and resource spots after terrain texture and path painting
*/
for (let p = 0; p < playerIDs.length; ++p)
{
let point = startLocations[p];
placeCivDefaultStartingEntities(point.x, point.y, playerIDs[p], g_Map.size > 192);
placeStartLocationResources(point);
}
log("Placing players...");
if (isNomad())
placePlayersNomad(createTileClass(), new HeightConstraint(playerHeightRange.min, playerHeightRange.max));
else
for (let p = 0; p < playerIDs.length; ++p)
{
let point = startLocations[p];
placeCivDefaultStartingEntities(point.x, point.y, playerIDs[p], g_Map.size > 192);
placeStartLocationResources(point);
}
let mercenaryCamps = Math.ceil(g_Map.size / 256);
log("Maximum number of mercenary camps: " + uneval(mercenaryCamps));
let mercenaryCamps = isNomad() ? 0 : Math.ceil(g_Map.size / 256);
log("Maximum number of mercenary camps: " + mercenaryCamps);
for (let i = 0; i < resourceSpots.length; ++i)
{
let choice = i % 5;