FeXoR Posted March 21, 2012 Report Share Posted March 21, 2012 (edited) I noticed that some placers/painters does not work in combination.- avoidClasses does not seam to work for centered placers.- SmoothElevationPainter does not seam to work for non-centered placers (at least not properly for a ClumpPlacer of size 1).- TileClassPainter does not seam to work at all. Edited March 21, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
Spahbod Posted March 21, 2012 Report Share Posted March 21, 2012 I noticed that some placers/painters does not work in combination.- avoidClasses does not seam to work for centered placers.- SmoothElevationPainter does not seam to work for non-centered placers (at least not properly for a ClumpPlacer of size 1).- TileClassPainter does not seam to work at all.Well, according to this, none of the current maps should work. Quote Link to comment Share on other sites More sharing options...
FeXoR Posted March 21, 2012 Author Report Share Posted March 21, 2012 (edited) Well, according to this, none of the current maps should work.OK ^^Then what do I do wrong when:var placer = new ClumpPlacer(pathWidth, 1, 1, 1, x, z);var painter = [new TerrainPainter(terrainPath), new ElevationPainter(-randFloat())]; createArea(placer, painter, avoidClasses(clHill, 20)); // AVOID CLASS DOES NOT WORK!!! Because of centred placer???Here:var placer = new ClumpPlacer(1, 1, 1, 1, x, z);var painter = [new TerrainPainter(terrainWood), new ElevationPainter(randFloat())]; // new TileClassPainter(clForest) RAISES ERROR!!! SmoothElevationPainter(ELEVATION_MODIFY, randFloat(1), 1) STRANGE ACTING!createArea(placer, painter, avoidClasses(clPath, 2));If I add SmoothElevationPainter here it's only lowering the terrain when I set elevation AND blendRadius negative.However, when used with a bigger ClumpPlacerit seams to work much better though even if the elevation is positive it sometimes lowers the terrain on the right. Edited March 21, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
Spahbod Posted March 22, 2012 Report Share Posted March 22, 2012 OK ^^Then what do I do wrong when:var placer = new ClumpPlacer(pathWidth, 1, 1, 1, x, z);var painter = [new TerrainPainter(terrainPath), new ElevationPainter(-randFloat())]; createArea(placer, painter, avoidClasses(clHill, 20)); // AVOID CLASS DOES NOT WORK!!! Because of centred placer???First of all, how are you defining x and z?And second: coherence and smoothness should be floats to ints. use 1.0 instead of 1. I had the same problem before.pathWidth is not technically correct. Size parameter defines the area of placer not it's width.But your overall code should work. What do you want to do exactly?Here:var placer = new ClumpPlacer(1, 1, 1, 1, x, z);var painter = [new TerrainPainter(terrainWood), new ElevationPainter(randFloat())]; // new TileClassPainter(clForest) RAISES ERROR!!! SmoothElevationPainter(ELEVATION_MODIFY, randFloat(1), 1) STRANGE ACTING!createArea(placer, painter, avoidClasses(clPath, 2));If I add SmoothElevationPainter here it's only lowering the terrain when I set elevation AND blendRadius negative.However, when used with a bigger ClumpPlacerit seams to work much better though even if the elevation is positive it sometimes lowers the terrain on the right.I should see your complete code this time. Could you show it to me in PM? Quote Link to comment Share on other sites More sharing options...
FeXoR Posted March 22, 2012 Author Report Share Posted March 22, 2012 (edited) First of all, how are you defining x and z?Half the code needed for that so see the full code further below.And second: coherence and smoothness should be floats to ints. use 1.0 instead of 1. I had the same problem before.I'll do that but it works for now...pathWidth is not technically correct. Size parameter defines the area of placer not it's width.I know:var pathWidth = 5; // This is not really the path's sickness in tiles but the number of tiles in the clumbs of the pathBut your overall code should work.It does, but the uncommented stuff is the thing in question. So in this code it's the 'avoidClasses' and I have no idea why. I fixed this by painting the hills after the path, so don't tell me that it will not work because no tiles are added to 'clHill' at this point . I just wanted to tell that 'avoidClasses' sometimes fails (maybe because of the centered placer with given coordinated, I don't have a clue)What do you want to do exactly?For the dark forest map I want the forest to be placed differently from the other maps to really make it dark (well, at least in theory possible). So I add it on every tile if a random check vs the 'actual density' succeeds. This 'actual density' is mainly the 'maxTreeDensity' (constant for a single map dependent on map size to avoid out of memory errors) scaled by other density modifiers (Dependent on distance to next start location or the center eye candy and the radius to have room to place additional resources at the given radius). This works fine and as I want it.However, to enable the players to reach the center and each other on more than 1 path I added paths that should cut through the woods (I think that would just be possible by adding the paths after the woods, but I wanted to get used to the painter/placer/constraint/area usage that is in most cases the perfect thing).I noticed that the paths sometimes run in the non-starting-resource-hills and that looked bad so I added an TileClassPainter(clHill) to the resource area and the avoidClasses(clHill) constraint to the paths. But it didn't avoid the hills. So I placed the hills after the paths.That was most likely a bug in my code that I didn't find because for the woods (that avoids paths) it works and it's a centered placer, too.Besides: As it is now only the center of the paths and the resource terrain clumbs are in the corresponding classes not all terrain clumb's tiles.I should see your complete code this time. Could you show it to me in PM?Here it is though not in a PM, someone might find it useful (like your suggestion to use float, not int):RMS.LoadLibrary("rmgen");// initialize maplog("Initializing map...");InitMap();// Setup tile classesvar clPlayer = createTileClass();var clPath = createTileClass();var clHill = createTileClass();var clForest = createTileClass();// var clWater = createTileClass();// var clRock = createTileClass();// var clFood = createTileClass();// var clBaseResource = createTileClass();// Setup Templatesvar templateStone = "gaia/geology_stone_temperate"var templateStoneMine = "gaia/geology_stonemine_temperate_quarry";var templateMetal = "gaia/geology_metal_temperate";var templateMetalMine = "gaia/geology_metal_temperate_slabs";var startingResourcees = ["gaia/flora_tree_oak_large", "gaia/flora_bush_temperate", templateStoneMine, "gaia/flora_bush_grapes", "gaia/flora_tree_apple", "gaia/flora_bush_berry", templateMetalMine, "gaia/flora_bush_temperate"];// Setup terrainvar terrainWood = ['temp_forestfloor_a|gaia/flora_tree_oak', 'temp_forestfloor_autumn|gaia/flora_tree_carob', 'temp_forestfloor_pine|gaia/flora_tree_pine'];var terrainWoodBorder = ['temp_grass_plants|gaia/flora_bush_berry', 'temp_grass_clovers_2|gaia/flora_bush_grapes', 'temp_grass_long_b|gaia/flora_tree_apple', 'temp_grass_long|gaia/flora_bush_temperate', 'temp_highlands|gaia/flora_bush_temperate', 'temp_grass_mossy|gaia/flora_bush_temperate', 'temp_grass_plants|gaia/fauna_deer', "temp_mud_plants|gaia/fauna_boar", "temp_grass_long_b|gaia/fauna_rabbit"];var terrainBase = ['temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_grass_b|gaia/fauna_pig', 'temp_dirt_gravel|gaia/fauna_chicken'];var terrainBaseBorder = ['temp_grass_b', 'temp_grass_b', 'temp_grass_c'];var terrainPath = ['temp_road', 'temp_grass_b', "temp_road_overgrown"];var terrainHill = ["temp_highlands", "temp_highlands", "temp_dirt_gravel_b"];var terrainHillBorder = ["temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_highlands", "temp_mud_plants", "temp_grass_clovers_2|gaia/fauna_goat"];// Setup map var mapSize = getMapSize();var mapRadius = mapSize/2;var playableMapRadius = mapRadius - 5;var mapCenterX = mapRadius;var mapCenterZ = mapRadius;// Setup players and basesvar fortresses = false;var numPlayers = getNumPlayers();var baseRadius = 20;if (fortresses == true) baseRadius = 30;var minPlayerRadius = min(mapRadius-1.5*baseRadius, 5*mapRadius/8);var maxPlayerRadius = min(mapRadius-baseRadius, 3*mapRadius/4);const BUILDING_ANlE = 3*PI/4;var buildAngle = 3*PI/4;var playerStartLocX = new Array(numPlayers);var playerStartLocZ = new Array(numPlayers);var playerAngle = new Array(numPlayers);var playerAngleStart = randFloat(0, 2*PI);var playerAngleAddAvrg = 2*PI / numPlayers;var playerAngleMaxOff = playerAngleAddAvrg/4;// Setup eyecandyvar templateEC = "other/unfinished_greek_temple";var radiusEC = max(mapRadius/8, baseRadius/2);// Setup pathsvar pathSucsessRadius = baseRadius/2;var pathAngleOff = PI/2;var pathWidth = 5; // This is not really the path's sickness in tiles but the number of tiles in the clumbs of the pathif (fortresses == true) pathSucsessRadius = baseRadius;;// Setup additional resourcesvar resourceRadius = 2*mapRadius/3; // 3*mapRadius/8;var recourcePerPlayer = [];var resourcePerPlayer = 2;// Setup woodsvar maxTreeDensity = min(256*256/mapSize/mapSize, 1); // Has to be tweeked but works okvar bushChance = 0.5; // 1 means 50% chance in deepest wood, 0.5 means 25% chance in deepest wood// Place basesfor (var i=0; i < numPlayers; i++){ var civ = g_MapSettings.PlayerData[i].Civ; var startEntities = getStartingEntities(i); playerAngle[i] = (playerAngleStart + i*playerAngleAddAvrg + randFloat(0, playerAngleMaxOff))%(2*PI); var x = round(mapCenterX + randFloat(minPlayerRadius, maxPlayerRadius)*cos(playerAngle[i])); var z = round(mapCenterZ + randFloat(minPlayerRadius, maxPlayerRadius)*sin(playerAngle[i])); playerStartLocX[i] = x; playerStartLocZ[i] = z; // Place starting entities createStartingPlayerEntities(x, z, i+1, startEntities, buildAngle) // Place base texture var placer = new ClumpPlacer(baseRadius*baseRadius, 1/2, 1/8, 1, x, z); var painter = [new LayeredPainter([terrainBaseBorder, terrainBase], [2+randFloat()])]; createArea(placer, painter); addToClass(x, z, clPlayer); // Place fortresses if (fortresses == true) { // Place fortresses new wallTool(civ, "small").place(x, z, i+1, buildAngle); // if (civ == "iber") // new wallTool("iber").setGenericFortress(x, z, i+1, 20, PI/6); }; // Place starting resources var distToSL = 10; var resStartAngle = playerAngle[i] + PI; var resAddAngle = 2*PI / startingResourcees.length; for (var rIndex = 0; rIndex < startingResourcees.length; rIndex++) { var angleOff = randFloat(-resAddAngle/2, resAddAngle/2); var placeX = x + distToSL*cos(resStartAngle + rIndex*resAddAngle + angleOff); var placeZ = z + distToSL*sin(resStartAngle + rIndex*resAddAngle + angleOff); placeObject(placeX, placeZ, startingResourcees[rIndex], 0, randFloat(0, 2*PI)); };};// Place paths (2 path between each 2 players and each player and the eyecandy in the middle)for (var i = 0; i < numPlayers+1; i++){ for (var j = 0; j < numPlayers+1; j++) { if (i < numPlayers) { var x = playerStartLocX[i]; var z = playerStartLocZ[i]; } else { var x = mapCenterX; var z = mapCenterZ; }; if (j < numPlayers) { var targetX = playerStartLocX[j]; var targetZ = playerStartLocZ[j]; } else { var targetX = mapCenterX; var targetZ = mapCenterZ; }; var angle = getAngle(x, z, targetX, targetZ); x += round(pathSucsessRadius*cos(angle)); z += round(pathSucsessRadius*sin(angle)); var targetReached = false; var tries = 0; while (targetReached == false && tries < 2*mapSize) { var placer = new ClumpPlacer(pathWidth, 1, 1, 1, x, z); var painter = [new TerrainPainter(terrainPath), new ElevationPainter(-randFloat())]; createArea(placer, painter, avoidClasses(clHill, 20)); // DOES NOT WORK!!! Because of centred placer??? addToClass(x, z, clPath); // Set vars for next loop angle = getAngle(x, z, targetX, targetZ); x += round(cos(angle + randFloat(-pathAngleOff/2, 3*pathAngleOff/2))); z += round(sin(angle + randFloat(-pathAngleOff/2, 3*pathAngleOff/2))); if (getDistance(x, z, targetX, targetZ) < pathSucsessRadius) targetReached = true; tries++; }; };};// Place expansion resourcesfor (var i=0; i < numPlayers; i++){ for (var rIndex = 0; rIndex < resourcePerPlayer; rIndex++) { if (numPlayers > 1) var angleDist = (playerAngle[(i+1)%numPlayers] - playerAngle[i] + 2*PI)%(2*PI); else var angleDist = 2*PI; var placeX = round(mapCenterX + resourceRadius*cos(playerAngle[i] + (rIndex+1)*angleDist/(resourcePerPlayer+1))); var placeZ = round(mapCenterX + resourceRadius*sin(playerAngle[i] + (rIndex+1)*angleDist/(resourcePerPlayer+1))); if (rIndex%2 == 0) placeObject(placeX, placeZ, templateStone, 0, randFloat(0, 2*PI)); else placeObject(placeX, placeZ, templateMetalMine, 0, randFloat(0, 2*PI)); var placer = new ClumpPlacer(40, 1/2, 1/8, 1, placeX, placeZ); var painter = [new LayeredPainter([terrainHillBorder, terrainHill], [1]), new ElevationPainter(1+randFloat())]; createArea(placer, painter); // addToClass(placeX, placeX, clHill); };};// Place eyecandyplaceObject(mapCenterX, mapCenterZ, templateEC, 0, randFloat(0, 2*PI));var placer = new ClumpPlacer(radiusEC*radiusEC, 1/2, 1/8, 1, mapCenterX, mapCenterZ);var painter = [new LayeredPainter([terrainHillBorder, terrainHill], [radiusEC/4]), new ElevationPainter(1+randFloat())];createArea(placer, painter);addToClass(mapCenterX, mapCenterZ, clHill);// Woods and hillsfor (var x = 0; x < mapSize; x++){ for (var z = 0;z < mapSize;z++) { // Some variables var radius = Math.pow(Math.pow(mapCenterX - x, 2) + Math.pow(mapCenterZ - z, 2), 1/2); var minDistToSL = mapSize; for (var i=0; i < numPlayers; i++) minDistToSL = min(minDistToSL, getDistance(playerStartLocX[i], playerStartLocZ[i], x, z)) // Woods tile based var tDensFactSL = max(min((minDistToSL - baseRadius) / baseRadius, 1), 0); var tDensFactRad = abs((resourceRadius - radius) / resourceRadius); var tDensFactEC = max(min((radius - radiusEC) / radiusEC, 1), 0); var tDensActual = maxTreeDensity * tDensFactSL * tDensFactRad * tDensFactEC; if (randFloat() < tDensActual && radius < playableMapRadius) { if (tDensActual < bushChance*randFloat()*maxTreeDensity) { var placer = new ClumpPlacer(1, 1, 1, 1, x, z); var painter = [new TerrainPainter(terrainWoodBorder), new ElevationPainter(randFloat())]; createArea(placer, painter, avoidClasses(clPath, 1)); } else { var placer = new ClumpPlacer(1, 1, 1, 1, x, z); var painter = [new TerrainPainter(terrainWood), new ElevationPainter(randFloat())]; // new TileClassPainter(clForest) createArea(placer, painter, avoidClasses(clPath, 2)); }; addToClass(x, z, clForest); }; // Hills var hVarMiddleHill = mapSize/64 * (1+cos(3*PI/2 * radius/mapRadius)); var hVarHills = 5*(1+sin(x/10)*sin(z/10)); setHeight(x, z, getHeight(x, z) + hVarMiddleHill + hVarHills + 1); };};// Export map dataExportMap();And a download: fexor_simple2012-3-22.zipBy the way, NONE of the existing maps use 'TileClassPainter' so I'm quite sure it doesn't work properly.For SmoothElevationPainter: I can't reproduce this on a simple map (why ever) but just replace line 223 with:var painter = [new TerrainPainter(terrainWoodBorder), new SmoothElevationPainter(ELEVATION_MODIFY, 0.0, 10.0)];And play around with the 'ClumpPlacer' and 'SmoothElevationPainter' arguments. Then generate the map and watch the terrain elevation below bushes/wild animals/apple trees (all in 'terrainWoodBorder')I recommend to generate it with 3 players on a small map. It generates relatively fast then and has enough wood/wood border to play around with the variables and see the results.Writing a test map... Edited March 22, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
Spahbod Posted March 22, 2012 Report Share Posted March 22, 2012 Really strange. But answer this first: Did you add the hill tiles into clHill? You don't do this right now and this can be the reason avoidClasses didn't work. I think all of these are caused by your hardcoded map generation. That's why I think you should create your own random map generation library based on some "areas" that have a chance of having trees/special terrain/ etc. I personally use paintClass() instead of TileClassPainter(). It seems it is buggy. Use paintClass() instead and you may find out that avoidClasses works for the first part. Quote Link to comment Share on other sites More sharing options...
FeXoR Posted March 22, 2012 Author Report Share Posted March 22, 2012 (edited) Really strange. But answer this first: Did you add the hill tiles into clHill? You don't do this right now and this can be the reason avoidClasses didn't work. I think all of these are caused by your hardcoded map generation. That's why I think you should create your own random map generation library based on some "areas" that have a chance of having trees/special terrain/ etc. I personally use paintClass() instead of TileClassPainter(). It seems it is buggy. Use paintClass() instead and you may find out that avoidClasses works for the first part.@ avoidClasses: Yes, I think that was a bug in my script (though I added the center of the resource clump to clHill with addToClass).@ own libs: Yes, I may do this. But for now I want to finalize my wall tool (circle and generic fortress allrdy working without rotation yet, 'placeSimple wall' that places a wall of given wall elements from 1 point to another will be added too). Than I will look into the coordinate change that effects the unit placement as well and so has wide effects (see this and following posts). To add placement functionality like in my map I have to look deeper into the code to make it compatible with the existing ones if possible (would be nice).@ paintClass(): Thx, that might help. Testing though unneeded at the moment.Some other questions:1.) What do you mean by 'hard-coded'? Beyond the forest placement (which is IMO unique and might not be generally useful for other maps) and the paths (there need is somehow a consequence of the deep forest) I don't see any hard-coded things. When I'm satisfied think of rewriting them for libs though. Of course the player's start position placement could be generalized for different types of maps but it is done like that in other maps too. If I had access to the SVN repository I would really be more inspired to add library functions and total new libraries than I am now. I don't want to ask someone regularly to add an SVN update! However, Please tell me what other parts belong into libs.2.) Why are the rmgen libs written in a style that prevents refactoring? If something is a class in many cases there is a function that gives back the class but by reading the function you are not closer to understand what the function does because it just gives back an other class object for example. Then, reading the class's construction code, you are not much closer because it uses another class though the used class is exclusively used by 1 other class (or function). Sometimes it appears to me someone wanted to avoid people refactoring the code. That might be an issue only appearing to me, though. As I said before the functions available does reflect the needs of a random map API quite well. Sometimes I just want to stir around in their guts and have to find out that the code needed for that is longer, slower, more complex and less readable than hard-coding the functionality in the given map itself. Edited March 23, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
Spahbod Posted March 23, 2012 Report Share Posted March 23, 2012 @ avoidClasses: Yes, I think that was a bug in my script (though I added the center of the resource clump to clHill with addToClass).@ own libs: Yes, I may do this. But for now I want to finalize my wall tool (circle and generic fortress allrdy working without rotation yet, 'placeSimple wall' that places a wall of given wall elements from 1 point to another will be added too). Than I will look into the coordinate change that effects the unit placement as well and so has wide effects (see this and following posts). To add placement functionality like in my map I have to look deeper into the code to make it compatible with the existing ones if possible (would be nice).@ paintClass(): Thx, that might help. Testing though unneeded at the moment.Some other questions:1.) What do you mean by 'hard-coded'? Beyond the forest placement (which is IMO unique and might not be generally useful for other maps) and the paths (there need is somehow a consequence of the deep forest) I don't see any hard-coded things. When I'm satisfied think of rewriting them for libs tough. Of course the player's start position placement could be generalized for different types of maps but it is done like that in other maps too. If I had access to the SVN repository I would really be more inspired to add library functions and total new libraries than I am now. I don't want to ask someone regularly to add an SVN update! However, Please tell me what other parts belong into libs.2.) Why are the rmgen libs written in a style that prevents refactoring? If something is a class in many cases there is a function that gives back the class but by reading the function you are not closer to understand what the function does because it just gives back an other class object for example. Then, reading the class's construction code, you are not much closer because it uses another class though the used class is exclusively used by 1 other class (or function). Sometimes it appears to me someone wanted to avoid people refactoring the code. That might be an issue only appearing to me, though. As I said before the functions available does reflect the needs of a random map API quite well. Sometimes I just want to stir around in their guts and have to find out that the code needed for that is longer, slower, more complex and less readable than hard-coding the functionality in the given map itself.1: I mean your hill and forest codes are complex enough to cause strange bugs like these. I use a combination of both rmgen functions and my own codes but I try to write my codes in a way to generate content very similar to rmgen functions in structure so that it doesn't cause such errors. One of the best examples of such a thing is Snowflake Searocks.But there are two solutions for a problem like the one you have. Completely use rmgen functions (which doesn't have the flexibility and beauty of the current system) or completely use your own hardcoded ones (like what is done in the current Latium map but is very hard and time consuming).2: The whole code is like that. I tried working on some tickets and found such refactoring very common. In fact it is much worse in the code because it uses functions to send values into main engine (C++ one) and vice verse. For a simple patch like "set trading goods for all selected traders" I had to scan 5 different files until I found two appreciate ones. Quote Link to comment Share on other sites More sharing options...
FeXoR Posted March 23, 2012 Author Report Share Posted March 23, 2012 (edited) 1: I mean your hill and forest codes are complex enough to cause strange bugs like these. I use a combination of both rmgen functions and my own codes but I try to write my codes in a way to generate content very similar to rmgen functions in structure so that it doesn't cause such errors. One of the best examples of such a thing is Snowflake Searocks.But there are two solutions for a problem like the one you have. Completely use rmgen functions (which doesn't have the flexibility and beauty of the current system) or completely use your own hardcoded ones (like what is done in the current Latium map but is very hard and time consuming).2: The whole code is like that. I tried working on some tickets and found such refactoring very common. In fact it is much worse in the code because it uses functions to send values into main engine (C++ one) and vice verse. For a simple patch like "set trading goods for all selected traders" I had to scan 5 different files until I found two appreciate ones.1: Oh, yes, my hills (renamed them to general hight map, I guess that's what you mean). That is not really finalized and could be added to a lib as well if finished. Indeed they cause bugs when changing the order in which paths and hills are placed. May be the reason for the strange acting SmoothElevationPainter. Somehow forgot about them ^^2: Hm, not so good. Maybe it's worth a clean up mission.Using paintClass() to add areas to classes works well, by the way. Edited March 23, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.