Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/maps/random/rmgen-common/gaia_terrain.js
Context not available. | |||||
let state = gotRet[ix][iz]; | let state = gotRet[ix][iz]; | ||||
if (state == -1) | if (state == -1) | ||||
{ | |||||
gotRet[ix][iz] = -2; | gotRet[ix][iz] = -2; | ||||
} | |||||
else if (state >= 0) | else if (state >= 0) | ||||
{ | { | ||||
edges.splice(state, 1); | edges.splice(state, 1); | ||||
Context not available. | |||||
for (let ix = sx; ix <= lx; ++ix) | for (let ix = sx; ix <= lx; ++ix) | ||||
for (let iz = sz; iz <= lz; ++iz) | for (let iz = sz; iz <= lz; ++iz) | ||||
{ | { | ||||
let position = new Vector2D(ix, iz); | position = new Vector2D(ix, iz); | ||||
let distance = position.distanceTo(circlePosition); | let distance = position.distanceTo(circlePosition); | ||||
let newHeight = | let newHeight = | ||||
Context not available. | |||||
new SmoothElevationPainter(elevationType, layers[i].elevation, layers[i].steepness), | new SmoothElevationPainter(elevationType, layers[i].elevation, layers[i].steepness), | ||||
new TileClassPainter(layers[i].tileClass) | new TileClassPainter(layers[i].tileClass) | ||||
], | ], | ||||
i == 0 ? null : stayClasses(layers[i - 1].tileClass, 1)); | i == 0 ? null : getConstraints({ stay: [layers[i - 1].tileClass, 1] }) | ||||
); | |||||
if (smoke) | if (smoke) | ||||
{ | { | ||||
Context not available. | |||||
clLava, | clLava, | ||||
position), | position), | ||||
0, | 0, | ||||
stayClasses(tileClass, 1)); | getConstraints({ stay: [tileClass, 1] }) | ||||
); | |||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* This function creates random lines of mountains ensuring that there are enough breaks to pass between them. | |||||
* | |||||
* To determine their location, random points are connected in shortest-cycle order and then trimmed to max length. | |||||
* | |||||
* Arguments: | |||||
* @param {number} "height": how tall the mountains should be, in absolute height (ie set not modify). | |||||
* @param {number} "width": How wide the mountains will be. | |||||
* @param {number} "count": How many mountain range segments to create. | |||||
* @param {number} "maxLength": The longest that any connected mountain strip is allowed to be. Use to ensure that passable gaps are created. | |||||
* @param {number} "bumpiness": (0..1) How much the height of each peak should vary. | |||||
* @param {number} "waviness": (0..1) How much the mountain ranges should deviate from a straight line. | |||||
* @param {number} "mode": What elevation mode to use (ELEVATION_SET/ELEVATION_MODIFY). | |||||
* @param {array strings} "terrain": String or array of two or more strings specifying terrain textures to paint. | |||||
* @param {number} "tileclass": The tileclass that the mountains should be assigned. | |||||
* @param {array constraints} "constraint": List of tileclasses to avoid painting over. | |||||
*/ | |||||
function createMountainRanges(args) | |||||
{ | |||||
// These parameters paint the mountainranges after their location was determined. | |||||
let height = args.height || scaleByMapSize(60, 120); | |||||
let mountainWidth = args.width || height/4; | |||||
let pathplacer = new PathPlacer(undefined, undefined, undefined, args.bumpiness || 0.4, scaleByMapSize(10, 25), args.waviness || 0.75, 0.2, 0.1); | |||||
let painters = [ | |||||
new TerrainPainter(args.terrain), | |||||
new SmoothElevationPainter(args.mode || ELEVATION_SET, height, mountainWidth/2, 3), | |||||
new TileClassPainter(args.tileclass) | |||||
]; | |||||
let constraint = args.constraint; | |||||
// Array of Vector2D locations where a mountainrange can start or end. | |||||
let vertices = new Array(2 * (args.count || 16)).fill(0).map(() => g_Map.randomCoordinate(false)); | |||||
// Maximum length that a mountain path can have. | |||||
let maxLength = args.maxLength || fractionToTiles(0.6); | |||||
// Number of mountainranges starting or ending at the given point. | |||||
let vertexDegree = vertices.map(p => 0); | |||||
// Init possible edges. | |||||
let possibleEdges = []; | |||||
let order = sortPointsShortestCycle(vertices); | |||||
let length = 0; | |||||
for (let i = 0; i < order.length - 1; ++i) | |||||
{ | |||||
length += vertices[order[i]].distanceTo(vertices[order[i+1]]); | |||||
if (length <= maxLength) | |||||
possibleEdges.push([order[i], order[i+1]]); | |||||
else | |||||
length = 0; | |||||
} | |||||
g_Map.log("Creating mountain ranges with " + possibleEdges.length + " possible edges"); | |||||
// Create the mountain ranges. | |||||
for (let i = 0; i < possibleEdges.length; ++i) | |||||
{ | |||||
let currentEdge = possibleEdges[i]; | |||||
pathplacer.start = vertices[currentEdge[0]]; | |||||
pathplacer.end = vertices[currentEdge[1]]; | |||||
pathplacer.width = mountainWidth; | |||||
if (createArea(pathplacer, painters, constraint)) | |||||
{ | |||||
++vertexDegree[currentEdge[0]]; | |||||
++vertexDegree[currentEdge[1]]; | |||||
} | |||||
} | |||||
// Create circular mountains to connect ranges that share vertices. | |||||
for (let i = 0; i < vertexDegree.length; ++i) | |||||
if (vertexDegree[i] > 1) | |||||
createArea( | |||||
new ClumpPlacer(diskArea(mountainWidth / 2), 0.95, 0.6, Infinity, vertices[i]), | |||||
painters, | |||||
constraint); | |||||
} | |||||
elexis: Those were the ones from that one alpine labyrinth replacement map? (That code is justified by… | |||||
aeoniosAuthorUnsubmitted Done Inline Actionsyes I probably will end up splitting this off. It's not really related to the changes to constraints. aeonios: yes I probably will end up splitting this off. It's not really related to the changes to… | |||||
/** | |||||
* Paint the given terrain texture in the given sizes at random places of the map to diversify monotone land texturing. | * Paint the given terrain texture in the given sizes at random places of the map to diversify monotone land texturing. | ||||
*/ | */ | ||||
function createPatches(sizes, terrain, constraints, count, tileClass, failFraction = 0.5) | function createPatches(sizes, terrain, constraints, count, tileClass, failFraction = 0.5) | ||||
{ | { | ||||
for (let size of sizes) | for (let size of sizes) | ||||
createAreas( | createAreas( | ||||
Context not available. | |||||
let mapCenter = g_Map.getCenter(); | let mapCenter = g_Map.getCenter(); | ||||
let mapBounds = g_Map.getBounds(); | let mapBounds = g_Map.getBounds(); | ||||
let riverConstraint = avoidClasses(tributaryRiverTileClass, 3); | let riverConstraint = getConstraints({ avoid: [tributaryRiverTileClass, 3] }); | ||||
if (shallowTileClass) | if (shallowTileClass) | ||||
riverConstraint = new AndConstraint([riverConstraint, avoidClasses(shallowTileClass, 2)]); | riverConstraint = new AndConstraint([riverConstraint, getConstraints({ avoid: [shallowTileClass, 2] })]); | ||||
elexisUnsubmitted Not Done Inline Actionsnew AvoidClassesConstraint(a1, a2, b1, b2, ...) would be more in line with the rest of the codebase, no? elexis: `new AvoidClassesConstraint(a1, a2, b1, b2, ...)` would be more in line with the rest of the… | |||||
aeoniosAuthorUnsubmitted Done Inline ActionsI changed the way it worked to a single constructor getConstraints that's more consistent and which should be more efficient when combining multiple constraints, iirc. Basically it saves you from having to type "new" 50 times when you want more than one type of constraint at a time. Based on this particular example it might pay to get rid of the AndConstraint as well and just merge it into getConstraints, if it works the way I think it does, anyway. aeonios: I changed the way it worked to a single constructor getConstraints that's more consistent and… | |||||
for (let i = 0; i < riverCount; ++i) | for (let i = 0; i < riverCount; ++i) | ||||
{ | { | ||||
Context not available. |
Wildfire Games · Phabricator
Those were the ones from that one alpine labyrinth replacement map? (That code is justified by an argument unrelated from the possible arguments of the rest of this code, i.e. who wants to review and or commit this code could split it into two patches, which might not be me today)