| 1 | RMS.LoadLibrary("rmgen"); |
| 2 | RMS.LoadLibrary("rmgen2"); |
| 3 | |
| 4 | InitMap(); |
| 5 | |
| 6 | randomizeBiome([6]); |
| 7 | initMapSettings(); |
| 8 | initTileClasses(); |
| 9 | var mapSize = getMapSize(); |
| 10 | |
| 11 | // Get the a single player's slice of the map in radians |
| 12 | var playerRadians = 2 * PI / g_MapInfo.numPlayers; |
| 13 | |
| 14 | // If there is an odd number we halve the slice so we stay symmetrical |
| 15 | if (g_MapInfo.teams.length % 2 != 0) |
| 16 | playerRadians = playerRadians / 2; |
| 17 | |
| 18 | g_MapInfo.startAngle = playerRadians / 2; |
| 19 | |
| 20 | RMS.SetProgress(10); |
| 21 | |
| 22 | // Pick a random elevation |
| 23 | var randElevation = randIntInclusive(0,4); |
| 24 | |
| 25 | resetTerrain(g_Terrains.mainTerrain, g_TileClasses.land, randElevation); |
| 26 | RMS.SetProgress(20); |
| 27 | |
| 28 | // Find the starting locations |
| 29 | let playerDist = (randIntInclusive(0,10) + 30) / 100; |
| 30 | var players = placeRadial(randomizePlayers(), playerDist) |
| 31 | for (let p = 0; p < players.length; ++p) |
| 32 | { |
| 33 | var fx = fractionToTiles(players[p].x); |
| 34 | var fz = fractionToTiles(players[p].z); |
| 35 | var ix = round(fx); |
| 36 | var iz = round(fz); |
| 37 | addToClass(ix, iz, g_TileClasses.player); |
| 38 | addToClass(ix + 5, iz, g_TileClasses.player); |
| 39 | addToClass(ix, iz + 5, g_TileClasses.player); |
| 40 | addToClass(ix - 5, iz, g_TileClasses.player); |
| 41 | addToClass(ix, iz - 5, g_TileClasses.player); |
| 42 | } |
| 43 | |
| 44 | RMS.SetProgress(40); |
| 45 | |
| 46 | addElements(shuffleArray([ |
| 47 | { |
| 48 | "func": addBluffs, |
| 49 | "avoid": [ |
| 50 | g_TileClasses.bluff, 10, |
| 51 | g_TileClasses.hill, 10, |
| 52 | g_TileClasses.mountain, 10, |
| 53 | g_TileClasses.plateau, 10, |
| 54 | g_TileClasses.player, 30, |
| 55 | g_TileClasses.valley, 10, |
| 56 | g_TileClasses.water, 10 |
| 57 | ], |
| 58 | "sizes": ["small"], |
| 59 | "mixes": ["similar"], |
| 60 | "amounts": ["few"] |
| 61 | }, |
| 62 | { |
| 63 | "func": addMountains, |
| 64 | "avoid": [ |
| 65 | g_TileClasses.bluff, 10, |
| 66 | g_TileClasses.hill, 10, |
| 67 | g_TileClasses.mountain, 10, |
| 68 | g_TileClasses.plateau, 10, |
| 69 | g_TileClasses.player, 30, |
| 70 | g_TileClasses.valley, 10, |
| 71 | g_TileClasses.water, 10 |
| 72 | ], |
| 73 | "sizes": ["small"], |
| 74 | "mixes": ["similar"], |
| 75 | "amounts": ["few"] |
| 76 | }, |
| 77 | { |
| 78 | "func": addPlateaus, |
| 79 | "avoid": [ |
| 80 | g_TileClasses.bluff, 10, |
| 81 | g_TileClasses.hill, 10, |
| 82 | g_TileClasses.mountain, 10, |
| 83 | g_TileClasses.plateau, 10, |
| 84 | g_TileClasses.player, 30, |
| 85 | g_TileClasses.valley, 10, |
| 86 | g_TileClasses.water, 10 |
| 87 | ], |
| 88 | "sizes": ["small"], |
| 89 | "mixes": ["similar"], |
| 90 | "amounts": ["few"] |
| 91 | }, |
| 92 | { |
| 93 | "func": addLakes, |
| 94 | "avoid": [ |
| 95 | g_TileClasses.bluff, 10, |
| 96 | g_TileClasses.hill, 10, |
| 97 | g_TileClasses.mountain, 10, |
| 98 | g_TileClasses.plateau, 10, |
| 99 | g_TileClasses.player, 30, |
| 100 | g_TileClasses.valley, 10, |
| 101 | g_TileClasses.water, 10 |
| 102 | ], |
| 103 | "sizes": ["small"], |
| 104 | "mixes": ["similar"], |
| 105 | "amounts": ["few"] |
| 106 | } |
| 107 | ])); |
| 108 | |
| 109 | RMS.SetProgress(50); |
| 110 | |
| 111 | addElements(shuffleArray([ |
| 112 | { |
| 113 | "func": addForests, |
| 114 | "avoid": [ |
| 115 | g_TileClasses.berries, 5, |
| 116 | g_TileClasses.bluff, 5, |
| 117 | g_TileClasses.forest, 6, |
| 118 | g_TileClasses.metal, 3, |
| 119 | g_TileClasses.mountain, 5, |
| 120 | g_TileClasses.plateau, 5, |
| 121 | g_TileClasses.player, 20, |
| 122 | g_TileClasses.rock, 3, |
| 123 | g_TileClasses.water, 2 |
| 124 | ], |
| 125 | "sizes": ["big"], |
| 126 | "mixes": ["similar"], |
| 127 | "amounts": ["normal"] |
| 128 | }, |
| 129 | { |
| 130 | "func": addStragglerTrees, |
| 131 | "avoid": [ |
| 132 | g_TileClasses.berries, 5, |
| 133 | g_TileClasses.bluff, 5, |
| 134 | g_TileClasses.forest, 5, |
| 135 | g_TileClasses.metal, 3, |
| 136 | g_TileClasses.mountain, 5, |
| 137 | g_TileClasses.plateau, 5, |
| 138 | g_TileClasses.player, 20, |
| 139 | g_TileClasses.rock, 3, |
| 140 | g_TileClasses.water, 2 |
| 141 | ], |
| 142 | "sizes": ["big"], |
| 143 | "mixes": ["similar"], |
| 144 | "amounts": ["normal"] |
| 145 | }, |
| 146 | { |
| 147 | "func": addBerries, |
| 148 | "avoid": [ |
| 149 | g_TileClasses.berries, 30, |
| 150 | g_TileClasses.bluff, 5, |
| 151 | g_TileClasses.forest, 5, |
| 152 | g_TileClasses.metal, 10, |
| 153 | g_TileClasses.mountain, 2, |
| 154 | g_TileClasses.plateau, 2, |
| 155 | g_TileClasses.player, 20, |
| 156 | g_TileClasses.rock, 10, |
| 157 | g_TileClasses.water, 3 |
| 158 | ], |
| 159 | "sizes": ["normal"], |
| 160 | "mixes": ["same"], |
| 161 | "amounts": ["normal", "many"] |
| 162 | }, |
| 163 | { |
| 164 | "func": addAnimals, |
| 165 | "avoid": [ |
| 166 | g_TileClasses.animals, 20, |
| 167 | g_TileClasses.bluff, 5, |
| 168 | g_TileClasses.forest, 2, |
| 169 | g_TileClasses.metal, 2, |
| 170 | g_TileClasses.mountain, 1, |
| 171 | g_TileClasses.plateau, 2, |
| 172 | g_TileClasses.player, 20, |
| 173 | g_TileClasses.rock, 2, |
| 174 | g_TileClasses.water, 3 |
| 175 | ], |
| 176 | "sizes": ["normal"], |
| 177 | "mixes": ["same"], |
| 178 | "amounts": ["many"] |
| 179 | }, |
| 180 | { |
| 181 | "func": addFish, |
| 182 | "avoid": [ |
| 183 | g_TileClasses.fish, 12, |
| 184 | g_TileClasses.player, 8 |
| 185 | ], |
| 186 | "stay": [g_TileClasses.water, 4], |
| 187 | "sizes": ["normal"], |
| 188 | "mixes": ["same"], |
| 189 | "amounts": ["many"] |
| 190 | }, |
| 191 | { |
| 192 | "func": addMetal, |
| 193 | "avoid": [ |
| 194 | g_TileClasses.berries, 5, |
| 195 | g_TileClasses.bluff, 5, |
| 196 | g_TileClasses.forest, 3, |
| 197 | g_TileClasses.mountain, 2, |
| 198 | g_TileClasses.plateau, 2, |
| 199 | g_TileClasses.player, 30, |
| 200 | g_TileClasses.rock, 10, |
| 201 | g_TileClasses.metal, 20, |
| 202 | g_TileClasses.water, 3 |
| 203 | ], |
| 204 | "sizes": ["normal"], |
| 205 | "mixes": ["same"], |
| 206 | "amounts": ["tons"] |
| 207 | }, |
| 208 | { |
| 209 | "func": addStone, |
| 210 | "avoid": [ |
| 211 | g_TileClasses.berries, 5, |
| 212 | g_TileClasses.bluff, 5, |
| 213 | g_TileClasses.forest, 3, |
| 214 | g_TileClasses.mountain, 2, |
| 215 | g_TileClasses.plateau, 2, |
| 216 | g_TileClasses.player, 30, |
| 217 | g_TileClasses.rock, 20, |
| 218 | g_TileClasses.metal, 10, |
| 219 | g_TileClasses.water, 3 |
| 220 | ], |
| 221 | "sizes": ["normal"], |
| 222 | "mixes": ["same"], |
| 223 | "amounts": ["tons"] |
| 224 | } |
| 225 | ])); |
| 226 | RMS.SetProgress(60); |
| 227 | |
| 228 | addElements([ |
| 229 | { |
| 230 | "func": addLayeredPatches, |
| 231 | "avoid": [ |
| 232 | g_TileClasses.bluff, 2, |
| 233 | g_TileClasses.dirt, 5, |
| 234 | g_TileClasses.forest, 2, |
| 235 | g_TileClasses.mountain, 2, |
| 236 | g_TileClasses.plateau, 2, |
| 237 | g_TileClasses.player, 12, |
| 238 | g_TileClasses.water, 3 |
| 239 | ], |
| 240 | "sizes": ["normal"], |
| 241 | "mixes": ["normal"], |
| 242 | "amounts": ["normal"] |
| 243 | }, |
| 244 | { |
| 245 | "func": addDecoration, |
| 246 | "avoid": [ |
| 247 | g_TileClasses.bluff, 2, |
| 248 | g_TileClasses.forest, 2, |
| 249 | g_TileClasses.mountain, 2, |
| 250 | g_TileClasses.plateau, 2, |
| 251 | g_TileClasses.player, 12, |
| 252 | g_TileClasses.water, 3 |
| 253 | ], |
| 254 | "sizes": ["normal"], |
| 255 | "mixes": ["normal"], |
| 256 | "amounts": ["normal"] |
| 257 | } |
| 258 | ]); |
| 259 | RMS.SetProgress(70); |
| 260 | |
| 261 | // Find all entities placed on the map |
| 262 | var templateObjects = {}; |
| 263 | var newObjects = g_Map.objects; |
| 264 | for (let o = 0; o < g_Map.objects.length; ++o) |
| 265 | { |
| 266 | let tileX = Math.round(g_Map.objects[o].position.x / 4); |
| 267 | let tileZ = Math.round(g_Map.objects[o].position.z / 4); |
| 268 | let radians = Math.atan2(tileZ - g_MapInfo.centerOfMap, tileX - g_MapInfo.centerOfMap) |
| 269 | |
| 270 | // If an entity is in the reference player's slice, save it |
| 271 | if (radians >= 0 && radians <= playerRadians) |
| 272 | templateObjects[tileX + "," + tileZ] = g_Map.objects[o]; |
| 273 | } |
| 274 | |
| 275 | // Clear the map of entities |
| 276 | g_Map.objects = []; |
| 277 | |
| 278 | // Add all the entities in the reference player's slice to the map |
| 279 | for (let key in templateObjects) { |
| 280 | if (templateObjects.hasOwnProperty(key)) { |
| 281 | g_Map.addObject(new Entity(templateObjects[key].templateName, templateObjects[key].player, Math.floor(templateObjects[key].position.x/4), Math.floor(templateObjects[key].position.z/4), templateObjects[key].rotation.y)); |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | // Cycle through each tile |
| 286 | for (let x = 0; x < mapSize; ++x) |
| 287 | for (let z = 0; z < mapSize; ++z) |
| 288 | { |
| 289 | if(g_Map.validH(x, z)) |
| 290 | { |
| 291 | // Find the angle in radians from the current point to the center of the map |
| 292 | // TODO: see if g_MapInfo.centerOfMap - 0.5 helps center things |
| 293 | let radians = Math.atan2(z - g_MapInfo.centerOfMap, x - g_MapInfo.centerOfMap) |
| 294 | |
| 295 | // Check if we're outside of the reference player's slice |
| 296 | if (radians < 0 || radians > playerRadians) |
| 297 | { |
| 298 | // If a tree was placed outside the reference slice, remove it |
| 299 | if (g_Map.terrainObjects[x][z] !== undefined) |
| 300 | g_Map.terrainObjects[x][z] = undefined |
| 301 | |
| 302 | // determine which direction we're replicating in |
| 303 | let flips = Math.floor(Math.abs(radians) / playerRadians); |
| 304 | var relRadians = playerRadians - Math.abs(radians) % playerRadians; |
| 305 | if (flips % 2 == 0) |
| 306 | relRadians = Math.abs(radians) % playerRadians; |
| 307 | |
| 308 | // find the distance from the current tile to the center |
| 309 | let dist = Math.sqrt(Math.pow((g_MapInfo.centerOfMap - x),2) + Math.pow((g_MapInfo.centerOfMap - z),2)) |
| 310 | |
| 311 | // match the distance to a similar angle in the reference slice |
| 312 | let relX = Math.round(dist * Math.cos(relRadians)) + g_MapInfo.centerOfMap; |
| 313 | let relZ = Math.round(dist * Math.sin(relRadians)) + g_MapInfo.centerOfMap; |
| 314 | |
| 315 | // set the height to that of the height in the reference slice |
| 316 | if(g_Map.validT(x, z)) |
| 317 | setHeight(x, z, getHeight(relX, relZ)); |
| 318 | |
| 319 | // set the terrain texture and trees to that of the reference slice |
| 320 | // we don't need to copy classes because we're adding objects directly to g_Map |
| 321 | if(g_Map.validT(x, z, 2)) |
| 322 | { |
| 323 | let texture = getTerrainTexture(relX, relZ); |
| 324 | placeTerrain(x, z, texture); |
| 325 | |
| 326 | if (g_Map.terrainObjects[relX][relZ] !== undefined) |
| 327 | g_Map.addObject(new Entity(g_Map.terrainObjects[relX][relZ].templateName, 0, x, z, 0)); |
| 328 | } |
| 329 | |
| 330 | // if there was an entity (metal, stone, decoration, animal, etc.), replicate it |
| 331 | let key = relX + "," + relZ; |
| 332 | if (templateObjects[key] != undefined) |
| 333 | g_Map.addObject(new Entity(templateObjects[key].templateName, templateObjects[key].player, x, z, templateObjects[key].rotation.y)); |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | // Place the players |
| 339 | addBases("radial", playerDist); |
| 340 | |
| 341 | RMS.SetProgress(90); |
| 342 | |
| 343 | ExportMap(); |