Ticket #658: RMS_JS_Implementation.2.patch

File RMS_JS_Implementation.2.patch, 145.9 KB (added by historic_bruno, 13 years ago)
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

     
    7575   
    7676    // Init map types
    7777    var mapTypes = getGUIObjectByName("mapTypeSelection");
    78     mapTypes.list = ["Scenario"];   // TODO: May offer saved game type for multiplayer games?
    79     mapTypes.list_data = ["scenario"];
     78    mapTypes.list = ["Scenario", "Random"]; // TODO: May offer saved game type for multiplayer games?
     79    mapTypes.list_data = ["scenario", "random"];
    8080   
    8181    // Setup controls for host only
    8282    if (g_IsController)
  • binaries/data/mods/public/maps/mapgen/area.js

     
     1function Area(points)
     2{
     3    this.points = (points !== undefined ? points : []);
     4}
  • binaries/data/mods/public/maps/mapgen/constraint.js

     
     1
     2///////////////////////////////////////////////////////////////////////////
     3//  NullConstraints: No constraint - always return true
     4///////////////////////////////////////////////////////////////////////////
     5function NullConstraint() {}
     6
     7NullConstraint.prototype.allows = function(x, y)
     8{
     9    return true;
     10};
     11
     12///////////////////////////////////////////////////////////////////////////
     13//  AndConstraints: Check multiple constraints 
     14///////////////////////////////////////////////////////////////////////////
     15function AndConstraint(constraints)
     16{
     17    this.constraints = constraints;
     18}
     19
     20AndConstraint.prototype.allows = function(x, y)
     21{
     22    for (var i=0; i < this.constraints.length; ++i)
     23    {
     24        if (!this.constraints[i].allows(x, y))
     25            return false;
     26    }
     27   
     28    return true;
     29};
     30
     31///////////////////////////////////////////////////////////////////////////
     32//  AvoidAreaConstraint
     33///////////////////////////////////////////////////////////////////////////
     34function AvoidAreaConstraint(area)
     35{
     36    this.area = area;
     37}
     38
     39AvoidAreaConstraint.prototype.allows = function(x, y)
     40{
     41    return g_Map.area[x][y] != this.area;
     42};
     43
     44///////////////////////////////////////////////////////////////////////////
     45//  AvoidTextureConstraint
     46///////////////////////////////////////////////////////////////////////////
     47function AvoidTextureConstraint(textureID)
     48{
     49    this.textureID = textureID;
     50}
     51
     52AvoidTextureConstraint.prototype.allows = function(x, y)
     53{
     54    return g_Map.texture[x][y] != this.textureID;
     55};
     56
     57///////////////////////////////////////////////////////////////////////////
     58//  AvoidTileClassConstraint
     59///////////////////////////////////////////////////////////////////////////
     60function AvoidTileClassConstraint(tileClassID, distance)
     61{
     62    this.tileClass = getTileClass(tileClassID);
     63    this.distance = distance;
     64}
     65
     66AvoidTileClassConstraint.prototype.allows = function(x, y)
     67{
     68    return this.tileClass.countMembersInRadius(x, y, this.distance) == 0;
     69};
     70
     71///////////////////////////////////////////////////////////////////////////
     72//  StayInTileClassConstraint
     73///////////////////////////////////////////////////////////////////////////
     74function StayInTileClassConstraint(tileClassID, distance)
     75{
     76    this.tileClass = getTileClass(tileClassID);
     77    this.distance = distance;
     78}
     79
     80StayInTileClassConstraint.prototype.allows = function(x, y)
     81{
     82    return this.tileClass.countNonMembersInRadius(x, y, this.distance) == 0;
     83};
     84
     85///////////////////////////////////////////////////////////////////////////
     86//  BorderTileClassConstraint
     87///////////////////////////////////////////////////////////////////////////
     88function BorderTileClassConstraint(tileClassID, distanceInside, distanceOutside)
     89{
     90    this.tileClass = getTileClass(tileClassID);
     91    this.distanceInside = distanceInside;
     92    this.distanceOutside = distanceOutside;
     93}
     94
     95BorderTileClassConstraint.prototype.allows = function(x, y)
     96{
     97    return (this.tileClass.countMembersInRadius(x, y, this.distanceOutside) > 0
     98        && this.tileClass.countNonMembersInRadius(x, y, this.distanceInside) > 0);
     99};
  • binaries/data/mods/public/maps/mapgen/library.js

     
     1
     2// PI
     3const PI = Math.PI;
     4
     5const SEA_LEVEL = 20.0;
     6
     7const TERRAIN_SEPARATOR = "|";
     8
     9const TILES_PER_PATCH = 16;
     10
     11/////////////////////////////////////////////////////////////////////////////////////////////
     12//  Utility functions
     13/////////////////////////////////////////////////////////////////////////////////////////////
     14
     15function fractionToTiles(f) {
     16    return getMapSize() * f;
     17}
     18
     19function tilesToFraction(t) {
     20    return t / getMapSize();
     21}
     22
     23function fractionToSize(f) {
     24    return getMapSize() * getMapSize() * f;
     25}
     26
     27function sizeToFraction(s) {
     28    return s / getMapSize() / getMapSize();
     29}
     30
     31function cos(x) {
     32    return Math.cos(x);
     33}
     34
     35function sin(x) {
     36    return Math.sin(x);
     37}
     38
     39function tan(x) {
     40    return Math.tan(x);
     41}
     42
     43function abs(x) {
     44    return Math.abs(x);
     45}
     46
     47function round(x) {
     48    return Math.round(x);
     49}
     50
     51function lerp(a, b, t) {
     52    return a + (b-a) * t;
     53}
     54
     55function sqrt(x) {
     56    return Math.sqrt(x);
     57}
     58
     59function ceil(x) {
     60    return Math.ceil(x);
     61}
     62
     63function floor(x) {
     64    return Math.floor(x);
     65}
     66
     67function max(x, y) {
     68    return x > y ? x : y;
     69}
     70
     71function min(x, y) {
     72    return x < y ? x : y;
     73}
     74
     75function println(x) {
     76    print(x);
     77    print("\n");
     78}
     79
     80function argsToArray(x) {
     81    if (x.length!=1) {
     82        var ret = new Array();
     83        for (var i=0; i<x.length; i++) {
     84            ret[i] = x[i];
     85        }
     86        return ret;
     87    }
     88    else {
     89        return x[0];
     90    }
     91}
     92
     93function chooseRand() {
     94    if (arguments.length==0) {
     95        error("chooseRand: requires at least 1 argument");
     96    }
     97    var ar = argsToArray(arguments);
     98    return ar[randInt(ar.length)];
     99}
     100
     101function createAreas(centeredPlacer, painter, constraint, num, retryFactor)
     102{
     103    if (retryFactor === undefined)
     104        retryFactor = 10;
     105   
     106    var maxFail = num * retryFactor;
     107    var good = 0;
     108    var bad = 0;
     109    var ret = [];
     110    while(good < num && bad <= maxFail)
     111    {
     112        centeredPlacer.x = randInt(getMapSize());
     113        centeredPlacer.y = randInt(getMapSize());
     114        var r = g_Map.createArea(centeredPlacer, painter, constraint);
     115        if (r !== undefined)
     116        {
     117            good++;
     118            ret.push(r);
     119        }
     120        else
     121        {
     122            bad++;
     123        }
     124    }
     125   
     126    return ret;
     127}
     128
     129function createObjectGroups(placer, player, constraint, num, retryFactor)
     130{
     131    if (retryFactor === undefined)
     132        retryFactor = 10;
     133   
     134    var maxFail = num * retryFactor;
     135    var good = 0;
     136    var bad = 0;
     137    while(good < num && bad <= maxFail)
     138    {
     139        placer.x = randInt(getMapSize());
     140        placer.y = randInt(getMapSize());
     141        var r = createObjectGroup(placer, player, constraint);
     142       
     143        if (r !== undefined)
     144        {
     145            good++;
     146        }
     147        else
     148        {
     149            bad++;
     150        }
     151    }
     152    return good;
     153}
     154
     155function createTerrain(terrain)
     156{
     157    if (terrain instanceof Array)
     158    {
     159        var terrainList = [];
     160       
     161        for (var i = 0; i < terrain.length; ++i)
     162            terrainList.push(createTerrain(terrain[i]));
     163       
     164        return new RandomTerrain(terrainList);
     165    }
     166    else
     167    {
     168        return createSimpleTerrain(terrain);
     169    }
     170}
     171
     172function createSimpleTerrain(terrain)
     173{
     174    if (typeof(terrain) == "string")
     175    {   // Split string by pipe | character, this allows specifying terrain + tree type in single string
     176        var params = terrain.split(TERRAIN_SEPARATOR, 2);
     177       
     178        if (params.length != 2)
     179        {
     180            return new SimpleTerrain(terrain);
     181        }
     182        else
     183        {
     184            return new SimpleTerrain(params[0], params[1]);
     185        }
     186    }
     187    else
     188    {
     189        error("createSimpleTerrain expects string as input, received "+terrain);
     190        return undefined;
     191    }
     192}
     193
     194function placeObject(type, player, x, y, angle)
     195{
     196    g_Map.addObjects(new Entity(type, player, x, y, angle));
     197}
     198
     199function placeTerrain(x, y, terrain)
     200{
     201    // convert terrain param into terrain object
     202    g_Map.placeTerrain(x, y, createTerrain(terrain));
     203   
     204}
     205
     206/////////////////////////////////////////////////////////////////////////////////////////////
     207//  Access global map variable
     208/////////////////////////////////////////////////////////////////////////////////////////////
     209
     210function createTileClass()
     211{
     212    return g_Map.createTileClass();
     213}
     214
     215function getTileClass(id)
     216{
     217    // Check for valid class id
     218    if (id < 1 || id > g_Map.tileClasses.length)
     219    {
     220        //error("Invalid tile class id: "+id);
     221        return null;
     222    }
     223   
     224    return g_Map.tileClasses[id - 1];
     225}
     226
     227function createArea(placer, painter, constraint)
     228{
     229    return g_Map.createArea(placer, painter, constraint);
     230}
     231
     232function createObjectGroup(placer, player, constraint)
     233{
     234    return g_Map.createObjectGroup(placer, player, constraint);
     235}
     236
     237function getMapSize()
     238{
     239    return g_Map.size;
     240}
     241
     242function getNumPlayers()
     243{
     244    return g_MapSettings.PlayerData.length;
     245}
     246
     247function getCivCode(player)
     248{
     249    return g_MapSettings.PlayerData[player].Civ;
     250}
     251
     252function getHeight(x, y)
     253{
     254    g_Map.getHeight(x, y);
     255}
     256
     257function setHeight(x, y, height)
     258{
     259    g_Map.setHeight(x, y, height);
     260}
     261
     262/////////////////////////////////////////////////////////////////////////////////////////////
     263//  Utility functions for classes
     264/////////////////////////////////////////////////////////////////////////////////////////////
     265
     266
     267// Add point to given class by id
     268function addToClass(x, y, id)
     269{
     270    var tileClass = getTileClass(id);
     271   
     272    if (tileClass !== null)
     273        tileClass.add(x, y);
     274}
     275
     276// Create a painter for the given class
     277function paintClass(id)
     278{
     279    return new TileClassPainter(getTileClass(id));
     280}
     281
     282// Create an avoid constraint for the given classes by the given distances
     283function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
     284{
     285    var ar = new Array(arguments.length/2);
     286    for (var i=0; i < arguments.length/2; i++)
     287    {
     288        ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
     289    }
     290    // Return single constraint
     291    return new AndConstraint(ar);
     292}
  • binaries/data/mods/public/maps/mapgen/map.js

     
     1//////////////////////////////////////////////////////////////////////
     2//  Map
     3//////////////////////////////////////////////////////////////////////
     4
     5function Map(size, baseHeight)
     6{
     7    // Size must be 0 to 1024, divisible by 16
     8    this.size = size;
     9   
     10    // Create 2D arrays for texture, object, and area maps
     11    this.texture = new Array(size);
     12    this.terrainObjects = new Array(size);
     13    this.area = new Array(size);
     14   
     15    for (var i=0; i < size; i++)
     16    {
     17        this.texture[i] = new Uint16Array(size);        // uint16
     18        this.terrainObjects[i] = new Array(size);       // entity
     19        this.area[i] = new Array(size);         // area
     20       
     21        for (var j = 0; j < size; j++)
     22        {
     23            this.terrainObjects[i][j] = [];
     24        }
     25    }
     26   
     27    var mapSize = size+1;
     28
     29    // Create 2D array for heightmap
     30    this.height = new Array(mapSize);
     31    for (var i=0; i < mapSize; i++)
     32    {
     33        this.height[i] = new Float32Array(mapSize);
     34        for (var j=0; j < mapSize; j++)
     35        {   // Initialize height map to baseHeight
     36            this.height[i][j] = baseHeight;
     37        }
     38    }
     39
     40    // Create name <-> id maps for textures
     41    this.nameToID = {};
     42    this.IDToName = [];             //string
     43   
     44    // Other arrays
     45    this.objects = [];              //object
     46    this.areas = [];                    //area
     47    this.tileClasses = [];              //int
     48   
     49    // Starting entity ID
     50    this.entityCount = 150;
     51}
     52
     53Map.prototype.initTerrain = function(baseTerrain)
     54{
     55    // Initialize base terrain
     56    var size = this.size;
     57    for (var i=0; i < size; i++)
     58    {
     59        for (var j=0; j < size; j++)
     60        {
     61            baseTerrain.place(i, j);
     62        }
     63    }
     64};
     65
     66// Return ID of texture (by name)
     67Map.prototype.getID = function(texture)
     68{
     69    if (texture in (this.nameToID))
     70    {
     71        return this.nameToID[texture];
     72    }
     73   
     74    // Add new texture
     75    var id = this.IDToName.length;
     76    this.nameToID[texture] = id;
     77    this.IDToName[id] = texture;
     78   
     79    return id;
     80};
     81
     82// Return next free entity ID
     83Map.prototype.getEntityID = function()
     84{
     85    return this.entityCount++;
     86}
     87
     88// Check bounds
     89Map.prototype.validT = function(x, y)
     90{
     91    return x >= 0 && y >= 0 && x < this.size && y < this.size;
     92};
     93
     94// Check bounds on height map (size + 1 by size + 1)
     95Map.prototype.validH = function(x, y)
     96{
     97    return x >= 0 && y >= 0 && x <= this.size && y <= this.size;
     98};
     99
     100// Check bounds on tile class
     101Map.prototype.validClass = function(c)
     102{
     103    return c >= 0 && c < this.tileClasses.length;
     104};
     105
     106Map.prototype.getTexture = function(x, y)
     107{
     108    if (!this.validT(x, y))
     109        error("getTexture: invalid tile position ("+x+", "+y+")");
     110   
     111    return this.IDToName[this.texture[x][y]];
     112};
     113
     114Map.prototype.setTexture = function(x, y, texture)
     115{
     116    if (!this.validT(x, y))
     117        error("setTexture: invalid tile position ("+x+", "+y+")");
     118   
     119     this.texture[x][y] = this.getID(texture);
     120};
     121
     122Map.prototype.getHeight = function(x, y)
     123{
     124    if (!this.validH(x, y))
     125        error("getHeight: invalid vertex position ("+x+", "+y+")");
     126   
     127    return this.height[x][y];
     128};
     129
     130Map.prototype.setHeight = function(x, y, height)
     131{
     132    if (!this.validH(x, y))
     133        error("setHeight: invalid vertex position ("+x+", "+y+")");
     134   
     135    this.height[x][y] = height;
     136};
     137
     138Map.prototype.getTerrainObjects = function(x, y)
     139{
     140    if (!this.validT(x, y))
     141        error("getTerrainObjects: invalid tile position ("+x+", "+y+")");
     142
     143    return this.terrainObjects[x][y];
     144};
     145
     146Map.prototype.setTerrainObjects = function(x, y, objects)
     147{
     148    if (!this.validT(x, y))
     149        error("setTerrainObjects: invalid tile position ("+x+", "+y+")");
     150
     151    this.terrainObjects[x][y] = objects;
     152};
     153
     154Map.prototype.placeTerrain = function(x, y, terrain)
     155{
     156    terrain.place(x, y);
     157};
     158
     159Map.prototype.addObjects = function(obj)
     160{
     161    this.objects = this.objects.concat(obj);
     162};
     163
     164Map.prototype.createArea = function(placer, painter, constraint)
     165{
     166    // Check for multiple painters
     167    if (painter instanceof Array)
     168    {
     169        var painterArray = painter;
     170        painter = new MultiPainter(painterArray);
     171    }
     172   
     173    // Check for null constraint
     174    if (constraint === undefined || constraint === null)
     175    {
     176        constraint = new NullConstraint();
     177    }
     178    else if (constraint instanceof Array)
     179    {   // Check for multiple constraints
     180        var constraintArray = constraint;
     181        constraint = new AndConstraint(constraintArray);
     182    }
     183   
     184    var points = placer.place(constraint);
     185    if (!points)
     186        return undefined;
     187   
     188    var a = new Area(points);
     189    for (var i=0; i < points.length; i++)
     190    {
     191        this.area[points[i].x][points[i].y] = a;
     192    }
     193   
     194    painter.paint(a);
     195    this.areas.push(a);
     196   
     197    return a;
     198};
     199
     200Map.prototype.createObjectGroup = function(placer, player, constraint)
     201{
     202    // Check for null constraint
     203    if (constraint === undefined || constraint === null)
     204    {
     205        constraint = new NullConstraint();
     206    }
     207    else if (constraint instanceof Array)
     208    {   // Check for multiple constraints
     209        var constraintArray = constraint;
     210        constraint = new AndConstraint(constraintArray);
     211    }
     212   
     213    return placer.place(player, constraint);
     214};
     215
     216Map.prototype.createTileClass = function()
     217{
     218    this.tileClasses.push(new TileClass(this.size));
     219   
     220    return this.tileClasses.length;
     221};
     222
     223// Get height taking into account terrain curvature
     224Map.prototype.getExactHeight = function(x, y)
     225{
     226    var xi = min(floor(x), this.size);
     227    var yi = min(floor(y), this.size);
     228    var xf = x - xi;
     229    var yf = y - yi;
     230
     231    var h00 = this.height[xi][yi];
     232    var h01 = this.height[xi][yi+1];
     233    var h10 = this.height[xi+1][yi];
     234    var h11 = this.height[xi+1][yi+1];
     235
     236    return ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ;
     237};
     238
     239Map.prototype.getMapData = function()
     240{
     241    var data = {};
     242   
     243    // Build entity array
     244    var entities = [];
     245   
     246    // Terrain objects first (trees)
     247    var size = this.size;
     248    for (var x=0; x < size; ++x)
     249    {
     250        for (var y=0; y < size; ++y)
     251        {
     252            if (this.terrainObjects[x][y].length)
     253                entities = entities.concat(this.terrainObjects[x][y]);
     254        }
     255    }
     256   
     257    // Now other entities
     258    for (var n in this.objects)
     259    {
     260        entities = entities.concat(this.objects[n]);
     261    }
     262   
     263    // Convert from tiles to map coordinates
     264    for (var n in entities)
     265    {
     266        var e = entities[n];
     267        e.x *= 4;
     268        e.y *= 4;
     269       
     270        entities[n] = e;
     271    }
     272    data["entities"] = entities;
     273   
     274    // Terrain
     275    data["size"] = this.size;
     276   
     277    // Convert 2D heightmap array to flat array
     278    //  Flat because it's easier to handle by the engine
     279    var mapSize = size+1;
     280    var height16 = new Array(mapSize*mapSize);      // uint16
     281    for (var x=0; x < mapSize; x++)
     282    {
     283        for (var y=0; y < mapSize; y++)
     284        {
     285            var intHeight = ((this.height[x][y] + SEA_LEVEL) * 256.0 / 0.35)|0; // floor
     286           
     287            if (intHeight > 65000)
     288                intHeight = 65000;
     289            else if (intHeight < 0)
     290                intHeight = 0;
     291           
     292            height16[y*mapSize + x] = intHeight;
     293        }
     294    }
     295    data["height"] = height16;
     296    data["seaLevel"] = SEA_LEVEL;
     297   
     298    // Get array of textures used in this map
     299    var textureNames = [];
     300    for (var name in this.nameToID)
     301        textureNames.push(name);
     302   
     303    data["textureNames"] = textureNames;
     304    data["numTextures"] = textureNames.length;
     305   
     306    //  Convert 2D tile data to flat array, reodering into patches as expected by MapReader
     307    var tiles = new Array(size*size);
     308    var patches = size/16;
     309    for (var x=0; x < size; x++)
     310    {
     311        var patchX = floor(x/16);
     312        var offX = x%16;
     313        for (var y=0; y < size; y++)
     314        {
     315            var patchY = floor(y/16);
     316            var offY = y%16;
     317            tiles[(patchY*patches + patchX)*256 + (offY*16 + offX)] = this.texture[x][y];
     318        }
     319    }
     320    data["tileData"] = tiles;
     321   
     322    return data;
     323};
  • binaries/data/mods/public/maps/mapgen/mapgen.js

     
     1// TODO: Since there's only one map anyway, just use this global variable
     2var g_Map;
     3
     4// Map settings - once initialized, has all the game setup data, including player array
     5var g_MapSettings = {
     6    Size : 13,
     7    Seed : 0,
     8    BaseTerrain: "grass1_spring",
     9    BaseHeight: 0,
     10    PlayerData : [ {}, {} ]
     11};
     12
     13var g_Environment = {
     14    SkySet: "cirrus",
     15    SunColour: {r: 1.47461, g: 1.47461, b: 1.47461},
     16    SunElevation: 0.951868,
     17    SunRotation: -0.532844,
     18    TerrainAmbientColour: {r: 0.337255, g: 0.403922, b: 0.466667},
     19    UnitsAmbientColour: {r: 0.501961, g: 0.501961, b: 0.501961},
     20    Water: {
     21        WaterBody: {
     22            Type: "default",
     23            Colour: {r: 0.294118, g: 0.34902, b: 0.694118},
     24            Height: 17.6262,
     25            Shininess: 150,
     26            Waviness: 8,
     27            Murkiness: 0.458008,
     28            Tint: {r: 0.447059, g: 0.411765, b: 0.321569},
     29            ReflectionTint: {r: 0.619608, g: 0.584314, b: 0.47451},
     30            ReflectionTintStrength: 0.298828
     31        }
     32    }
     33};
     34
     35var g_Camera = {
     36    Position: {x: 100, y: 150, z: -100},
     37    Rotation: 0,
     38    Declination: 0.523599
     39};
     40
     41function InitMapGen(settings)
     42{
     43    if (settings === undefined || settings == {})
     44    {
     45        warn("InitMapGen: settings missing");
     46    }
     47    else
     48    {
     49        g_MapSettings = settings;
     50    }
     51   
     52    // Init RNG with seed value
     53    seedRand(g_MapSettings.Seed);
     54
     55    // Create new map
     56    log("Creating new map...");
     57    var terrain = createTerrain(g_MapSettings.BaseTerrain);
     58   
     59    g_Map = new Map(g_MapSettings.Size * TILES_PER_PATCH, g_MapSettings.BaseHeight);
     60    g_Map.initTerrain(terrain);
     61}
     62
     63function SaveMap()
     64{
     65    log("Saving map...");
     66   
     67    // Get necessary data from map
     68    var data = g_Map.getMapData();
     69   
     70    // Add environment and camera settings
     71    g_Environment.Water.WaterBody.Height = SEA_LEVEL - 0.1;
     72    data.Environment = g_Environment;
     73    data.Camera = g_Camera;
     74   
     75    return data;
     76}
  • binaries/data/mods/public/maps/mapgen/noise.js

     
     1// Utility function used in both noises as an ease curve
     2function easeCurve(t)
     3{
     4    return t*t*t*(t*(t*6-15)+10);
     5}
     6
     7// Find mod of number but only positive values
     8function modPos(num, m)
     9{
     10    var p = num % m;
     11    if (p < 0)
     12        p += m;
     13   
     14    return p;
     15}
     16
     17/////////////////////////////////////////////////////////////////////
     18//  Noise2D
     19/////////////////////////////////////////////////////////////////////
     20
     21function Noise2D(freq)
     22{
     23    freq = floor(freq);
     24    this.freq = freq;
     25    this.grads = new Array(freq);
     26   
     27    for (var i=0; i < freq; ++i)
     28    {
     29        this.grads[i] = new Array(freq);
     30        for (var j=0; j < freq; ++j)
     31        {
     32            var a = randFloat() * 2 * PI;
     33           
     34            this.grads[i][j] = new Vector2D(cos(a), sin(a));
     35        }
     36    }
     37}
     38
     39Noise2D.prototype.get = function(x, y)
     40{
     41    x *= this.freq;
     42    y *= this.freq;
     43   
     44    var ix = modPos(floor(x), this.freq);
     45    var iy = modPos(floor(y), this.freq);
     46   
     47    var fx = x - ix;
     48    var fy = y - iy;
     49   
     50    var ix1 = (ix+1) % this.freq;
     51    var iy1 = (iy+1) % this.freq;
     52   
     53    var s = this.grads[ix][iy].dot(new Vector2D(fx, fy));
     54    var t = this.grads[ix1][iy].dot(new Vector2D(fx-1, fy));
     55    var u = this.grads[ix][iy1].dot(new Vector2D(fx, fy-1));
     56    var v = this.grads[ix1][iy1].dot(new Vector2D(fx-1, fy-1));
     57   
     58    var ex = easeCurve(fx);
     59    var ey = easeCurve(fy);
     60    var a = s + ex*(t-s);
     61    var b = u + ex*(v-u);
     62    return (a + ey*(b-a)) * 0.5 + 0.5;
     63};
     64
     65/////////////////////////////////////////////////////////////////////
     66//  Noise3D
     67/////////////////////////////////////////////////////////////////////
     68
     69function Noise3D(freq, vfreq)
     70{
     71    freq = floor(freq);
     72    vfreq = floor(vfreq);
     73    this.freq = freq;
     74    this.vfreq = vfreq;
     75    this.grads = new Array(freq);
     76   
     77    for (var i=0; i < freq; ++i)
     78    {
     79        this.grads[i] = new Array(freq);
     80        for (var j=0; j < freq; ++j)
     81        {
     82            this.grads[i][j] = new Array(vfreq);
     83            for(var k=0; k < vfreq; ++k)
     84            {
     85                var v = new Vector3D();
     86                do
     87                {
     88                    v.set(2*randFloat()-1, 2*randFloat()-1, 2*randFloat()-1);
     89                }
     90                while(v.lengthSquared() > 1 || v.lengthSquared() < 0.1);
     91               
     92                v.normalize();
     93               
     94                this.grads[i][j][k] = v;
     95            }
     96        }
     97    }
     98}
     99
     100Noise3D.prototype.get = function(x, y, z)
     101{
     102    x *= this.freq;
     103    y *= this.freq;
     104    z *= this.vfreq;
     105   
     106    var ix =modPos(floor(x), this.freq);
     107    var iy = modPos(floor(y), this.freq);
     108    var iz = modPos(floor(z), this.vfreq);
     109   
     110    var fx = x - ix;
     111    var fy = y - iy;
     112    var fz = z - iz;
     113   
     114    var ix1 = (ix+1) % this.freq;
     115    var iy1 = (iy+1) % this.freq;
     116    var iz1 = (iz+1) % this.vfreq;
     117   
     118    var s0 = this.grads[ix][iy][iz].dot(new Vector3D(fx, fy, fz));
     119    var t0 = this.grads[ix1][iy][iz].dot(new Vector3D(fx-1, fy, fz));
     120    var u0 = this.grads[ix][iy1][iz].dot(new Vector3D(fx, fy-1, fz));
     121    var v0 = this.grads[ix1][iy1][iz].dot(new Vector3D(fx-1, fy-1, fz));
     122   
     123    var s1 = this.grads[ix][iy][iz1].dot(new Vector3D(fx, fy, fz-1));
     124    var t1 = this.grads[ix1][iy][iz1].dot(new Vector3D(fx-1, fy, fz-1));
     125    var u1 = this.grads[ix][iy1][iz1].dot(new Vector3D(fx, fy-1, fz-1));
     126    var v1 = this.grads[ix1][iy1][iz1].dot(new Vector3D(fx-1, fy-1, fz-1));
     127   
     128    var ex = easeCurve(fx);
     129    var ey = easeCurve(fy);
     130    var ez = easeCurve(fz);
     131   
     132    var a0 = s0 + ex*(t0-s0);
     133    var b0 = u0 + ex*(v0-u0);
     134    var c0 = a0 + ey*(b0-a0);
     135   
     136    var a1 = s1 + ex*(t1-s1);
     137    var b1 = u1 + ex*(v1-u1);
     138    var c1 = a1 + ey*(b1-a1);
     139   
     140    return (c0 + ez*(c1-c0)) * 0.5 + 0.5;
     141};
  • binaries/data/mods/public/maps/mapgen/painter.js

     
     1const ELEVATION_SET = 0;
     2const ELEVATION_MODIFY = 1;
     3
     4/////////////////////////////////////////////////////////////////////////////
     5//  ElevationPainter
     6/////////////////////////////////////////////////////////////////////////////
     7   
     8function ElevationPainter(elevation)
     9{
     10    this.elevation = elevation;
     11    this.DX = [0, 1, 1, 0];
     12    this.DY = [0, 0, 1, 1];
     13}
     14
     15ElevationPainter.prototype.paint = function(area)
     16{
     17    var length = area.points.length;
     18    var elevation = this.elevation;
     19   
     20    for (var i=0; i < length; i++)
     21    {
     22        var pt = area.points[i];
     23       
     24        for (var j=0; j < 4; j++)
     25        {
     26            g_Map.height[pt.x+this.DX[j]][pt.y+this.DY[j]] = elevation;
     27        }
     28    }
     29};
     30
     31/////////////////////////////////////////////////////////////////////////////
     32//  LayeredPainter
     33/////////////////////////////////////////////////////////////////////////////
     34
     35function LayeredPainter(terrainArray, widths)
     36{
     37    if (!(terrainArray instanceof Array))
     38        error("terrains must be an array!");
     39   
     40    this.terrains = [];
     41    for (var i = 0; i < terrainArray.length; ++i)
     42        this.terrains.push(createTerrain(terrainArray[i]));
     43   
     44    this.widths = widths;
     45}
     46
     47LayeredPainter.prototype.paint = function(area)
     48{
     49    var size = getMapSize();
     50    var saw = new Array(size);
     51    var dist = new Array(size);
     52   
     53    // init typed arrays
     54    for (var i = 0; i < size; ++i)
     55    {
     56        saw[i] = new Uint8Array(size);      // bool / uint8
     57        dist[i] = new Uint16Array(size);        // uint16
     58    }
     59
     60    // Point queue (implemented with array)
     61    var pointQ = [];
     62
     63    // push edge points
     64    var pts = area.points;
     65    var length = pts.length;
     66   
     67    for (var i=0; i < length; i++)
     68    {
     69        var x = pts[i].x;
     70        var y = pts[i].y;
     71       
     72        for (var dx=-1; dx <= 1; dx++)
     73        {
     74            var nx = x+dx;
     75            for (var dy=-1; dy <= 1; dy++)
     76            {
     77                var ny = y+dy;
     78               
     79                if (g_Map.validT(nx, ny) && g_Map.area[nx][ny] && g_Map.area[nx][ny] != area && !saw[nx][ny])
     80                {
     81                    saw[nx][ny] = 1;
     82                    dist[nx][ny] = 0;
     83                    pointQ.push(new Point(nx, ny));
     84                }
     85            }
     86        }
     87    }
     88
     89    // do BFS inwards to find distances to edge
     90    while (pointQ.length)
     91    {
     92        var pt = pointQ.shift();    // Pop queue
     93        var px = pt.x;
     94        var py = pt.y;
     95        var d = dist[px][py];
     96
     97        // paint if in area
     98        if (g_Map.area[px][py] == area)
     99        {
     100            var w=0;
     101            var i=0;
     102           
     103            //~ while (i < this.widths.length && w < d)
     104            //~ {
     105                //~ w += this.widths[i];
     106                //~ ++i;
     107            //~ }
     108            for (; i < this.widths.length; i++)
     109            {
     110                w += this.widths[i];
     111                if (w >= d)
     112                {
     113                    break;
     114                }
     115            }
     116            this.terrains[i].place(px, py);
     117        }
     118
     119        // enqueue neighbours
     120        for (var dx=-1; dx<=1; dx++)
     121        {
     122            var nx = px+dx;
     123            for (var dy=-1; dy<=1; dy++)
     124            {
     125                var ny = py+dy;
     126               
     127                if (g_Map.validT(nx, ny) && g_Map.area[nx][ny] && g_Map.area[nx][ny] == area && !saw[nx][ny])
     128                {
     129                    saw[nx][ny] = 1;
     130                    dist[nx][ny] = d+1;
     131                    pointQ.push(new Point(nx, ny));
     132                }
     133            }
     134        }
     135    }
     136};
     137
     138/////////////////////////////////////////////////////////////////////////////
     139//  MultiPainter
     140/////////////////////////////////////////////////////////////////////////////
     141   
     142function MultiPainter(painters)
     143{
     144    this.painters = painters;
     145}
     146
     147MultiPainter.prototype.paint = function(area)
     148{
     149    for (var i=0; i < this.painters.length; i++)
     150    {
     151        this.painters[i].paint(area);
     152    }
     153};
     154
     155/////////////////////////////////////////////////////////////////////////////
     156//  SmoothElevationPainter
     157/////////////////////////////////////////////////////////////////////////////
     158
     159function SmoothElevationPainter(type, elevation, blendRadius)
     160{
     161    this.type = type;
     162    this.elevation = elevation;
     163    this.blendRadius = blendRadius;
     164   
     165    if (type != ELEVATION_SET && type != ELEVATION_MODIFY)
     166        error("SmoothElevationPainter: invalid type '"+type+"'");
     167}
     168
     169SmoothElevationPainter.prototype.checkInArea = function(area, x, y)
     170{
     171    if (g_Map.validT(x, y))
     172    {
     173        return (g_Map.area[x][y] && g_Map.area[x][y] == area);
     174    }
     175    else
     176    {
     177        return false;
     178    }
     179};
     180
     181SmoothElevationPainter.prototype.paint = function(area)
     182{
     183    var pointQ = [];
     184    var pts = area.points;
     185    var heightPts = [];
     186   
     187    var mapSize = getMapSize()+1;
     188   
     189    var saw = new  Array(mapSize);
     190    var dist = new Array(mapSize);
     191    var gotHeightPt = new Array(mapSize);
     192    var newHeight = new Array(mapSize);
     193   
     194    // init typed arrays
     195    for (var i = 0; i < mapSize; ++i)
     196    {
     197        saw[i] = new Uint8Array(mapSize);       // bool / uint8
     198        dist[i] = new Uint16Array(mapSize);     // uint16
     199        gotHeightPt[i] = new Uint8Array(mapSize);   // bool / uint8
     200        newHeight[i] = new Float32Array(mapSize);   // float32
     201    }
     202   
     203    var length = pts.length;
     204   
     205    // get a list of all points
     206    for (var i=0; i < length; i++)
     207    {
     208        var x = pts[i].x;
     209        var y = pts[i].y;
     210       
     211        for (var dx=-1; dx <= 2; dx++)
     212        {
     213            var nx = x+dx;
     214            for (var dy=-1; dy <= 2; dy++)
     215            {
     216                var ny = y+dy;
     217               
     218                if (g_Map.validH(nx, ny) && !gotHeightPt[nx][ny])
     219                {
     220                    gotHeightPt[nx][ny] = 1;
     221                    heightPts.push(new Point(nx, ny));
     222                    newHeight[nx][ny] = g_Map.height[nx][ny];
     223                }
     224            }
     225        }
     226    }
     227
     228    // push edge points
     229    for (var i=0; i < length; i++)
     230    {
     231        var x = pts[i].x, y = pts[i].y;
     232        for (var dx=-1; dx <= 2; dx++)
     233        {
     234            var nx = x+dx;
     235            for (var dy=-1; dy <= 2; dy++)
     236            {
     237                var ny = y+dy;
     238               
     239                if (g_Map.validH(nx, ny)
     240                    && !this.checkInArea(area, nx, ny)
     241                    && !this.checkInArea(area, nx-1, ny)
     242                    && !this.checkInArea(area, nx, ny-1)
     243                    && !this.checkInArea(area, nx-1, ny-1)
     244                    && !saw[nx][ny])
     245                {
     246                    saw[nx][ny]= 1;
     247                    dist[nx][ny] = 0;
     248                    pointQ.push(new Point(nx, ny));
     249                }
     250            }
     251        }
     252    }
     253
     254    // do BFS inwards to find distances to edge
     255    while(pointQ.length)
     256    {
     257        var pt = pointQ.shift();
     258        var px = pt.x;
     259        var py = pt.y;
     260        var d = dist[px][py];
     261
     262        // paint if in area
     263        if (g_Map.validH(px, py)
     264            && (this.checkInArea(area, px, py) || this.checkInArea(area, px-1, py)
     265            || this.checkInArea(area, px, py-1) || this.checkInArea(area, px-1, py-1)))
     266        {
     267            if (d <= this.blendRadius)
     268            {
     269                var a = (d-1) / this.blendRadius;
     270                if (this.type == ELEVATION_SET)
     271                {
     272                    newHeight[px][py] = a*this.elevation + (1-a)*g_Map.height[px][py];
     273                }
     274                else
     275                {   // type == MODIFY
     276                    newHeight[px][py] += a*this.elevation;
     277                }
     278            }
     279            else
     280            {   // also happens when blendRadius == 0
     281                if (this.type == ELEVATION_SET)
     282                {
     283                    newHeight[px][py] = this.elevation;
     284                }
     285                else
     286                {   // type == MODIFY
     287                    newHeight[px][py] += this.elevation;
     288                }
     289            }
     290        }
     291
     292        // enqueue neighbours
     293        for (var dx=-1; dx <= 1; dx++)
     294        {
     295            var nx = px+dx;
     296            for (var dy=-1; dy <= 1; dy++)
     297            {
     298                var ny = py+dy;
     299               
     300                if (g_Map.validH(nx, ny)
     301                    && (this.checkInArea(area, nx, ny) || this.checkInArea(area, nx-1, ny)
     302                        || this.checkInArea(area, nx, ny-1) || this.checkInArea(area, nx-1, ny-1))
     303                    && !saw[nx][ny])
     304                {
     305                    saw[nx][ny] = 1;
     306                    dist[nx][ny] = d+1;
     307                    pointQ.push(new Point(nx, ny));
     308                }
     309            }
     310        }
     311    }
     312
     313    length = heightPts.length;
     314   
     315    // smooth everything out
     316    for (var i = 0; i < length; ++i)
     317    {
     318        var pt = heightPts[i];
     319        var px = pt.x;
     320        var py = pt.y;
     321       
     322        if ((this.checkInArea(area, px, py) || this.checkInArea(area, px-1, py)
     323            || this.checkInArea(area, px, py-1) || this.checkInArea(area, px-1, py-1)))
     324        {
     325            var sum = 8 * newHeight[px][py];
     326            var count = 8;
     327           
     328            for (var dx=-1; dx <= 1; dx++)
     329            {
     330                var nx = px+dx;
     331                for (var dy=-1; dy <= 1; dy++)
     332                {
     333                    var ny = py+dy;
     334                   
     335                    if (g_Map.validH(nx, ny))
     336                    {
     337                        sum += newHeight[nx][ny];
     338                        count++;
     339                    }
     340                }
     341            }
     342           
     343            g_Map.height[px][py] = sum/count;
     344        }
     345    }
     346};
     347
     348/////////////////////////////////////////////////////////////////////////////
     349//  TerrainPainter
     350/////////////////////////////////////////////////////////////////////////////
     351
     352function TerrainPainter(terrain)
     353{
     354    this.terrain = createTerrain(terrain);
     355}
     356
     357TerrainPainter.prototype.paint = function(area)
     358{
     359    var length = area.points.length;
     360    for (var i=0; i < length; i++)
     361    {
     362        var pt = area.points[i];
     363        this.terrain.place(pt.x, pt.y);
     364    }
     365};
     366
     367/////////////////////////////////////////////////////////////////////////////
     368//  TileClassPainter
     369/////////////////////////////////////////////////////////////////////////////
     370
     371function TileClassPainter(tileClass)
     372{
     373    this.tileClass = tileClass;
     374}
     375
     376TileClassPainter.prototype.paint = function(area)
     377{
     378    var length = area.points.length;
     379    for (var i=0; i < length; i++)
     380    {
     381        var pt = area.points[i];
     382        this.tileClass.add(pt.x, pt.y);
     383    }
     384};
  • binaries/data/mods/public/maps/mapgen/placer.js

     
     1
     2/////////////////////////////////////////////////////////////////////////////////////////
     3//  ClumpPlacer
     4/////////////////////////////////////////////////////////////////////////////////////////
     5   
     6function ClumpPlacer(size, coherence, smoothness, failFraction, x, y)
     7{
     8    this.size = size;
     9    this.coherence = coherence;
     10    this.smoothness = smoothness;
     11    this.failFraction = (failFraction !== undefined ? failFraction : 0);
     12    this.x = (x !== undefined ? x : -1);
     13    this.y = (y !== undefined ? y : -1);
     14}
     15
     16ClumpPlacer.prototype.place = function(constraint)
     17{
     18    if (!g_Map.validT(this.x, this.y) || !constraint.allows(this.x, this.y))
     19    {
     20        return false;
     21    }
     22
     23    var retVec = [];
     24   
     25    var size = getMapSize();
     26    var gotRet = new Array(size);
     27    for (var i = 0; i < size; ++i)
     28    {
     29        gotRet[i] = new Uint8Array(size);       // bool / uint8
     30    }
     31   
     32    var radius = sqrt(this.size / PI);
     33    var perim = 4 * radius * 2 * PI;
     34    var intPerim = ceil(perim);
     35   
     36    var ctrlPts = 1 + Math.floor(1.0/Math.max(this.smoothness,1.0/intPerim));
     37   
     38    if (ctrlPts > radius * 2 * PI)
     39        ctrlPts = Math.floor(radius * 2 * PI) + 1; 
     40   
     41    var noise = new Float32Array(intPerim);     //float32
     42    var ctrlCoords = new Float32Array(ctrlPts+1);   //float32
     43    var ctrlVals = new Float32Array(ctrlPts+1); //float32
     44   
     45    for (var i=0; i < ctrlPts; i++)
     46    {
     47        ctrlCoords[i] = i * perim / ctrlPts;
     48        ctrlVals[i] = 2.0*randFloat();
     49    }
     50
     51    var c = 0;
     52    var looped = 0;
     53    for (var i=0; i < intPerim; i++)
     54    {
     55        if (ctrlCoords[(c+1) % ctrlPts] < i && !looped)
     56        {
     57            c = (c+1) % ctrlPts;
     58            if (c==ctrlPts-1)
     59                looped = 1;
     60        }
     61       
     62        var t = (i - ctrlCoords[c]) / ((looped ? perim : ctrlCoords[(c+1)%ctrlPts]) - ctrlCoords[c]);
     63        var v0 = ctrlVals[(c+ctrlPts-1)%ctrlPts];
     64        var v1 = ctrlVals[c];
     65        var v2 = ctrlVals[(c+1)%ctrlPts];
     66        var v3 = ctrlVals[(c+2)%ctrlPts];
     67        var P = (v3 - v2) - (v0 - v1);
     68        var Q = (v0 - v1) - P;
     69        var R = v2 - v0;
     70        var S = v1;
     71       
     72        noise[i] = P*t*t*t + Q*t*t + R*t + S;
     73    }
     74
     75    var failed = 0;
     76    for (var p=0; p < intPerim; p++)
     77    {
     78        var th = 2 * PI * p / perim;
     79        var r = radius * (1 + (1-this.coherence)*noise[p]);
     80        var s = sin(th);
     81        var c = cos(th);
     82        var xx=this.x;
     83        var yy=this.y;
     84       
     85        for (var k=0; k < r; k++)
     86        {
     87            var i = Math.floor(xx);
     88            var j = Math.floor(yy);
     89            if (g_Map.validT(i, j) && constraint.allows(i, j))
     90            {
     91                if (!gotRet[i][j])
     92                {   // Only include each point once
     93                    gotRet[i][j] = 1;
     94                    retVec.push(new Point(i, j));
     95                }
     96            }
     97            else
     98            {
     99                failed++;
     100            }
     101            xx += s;
     102            yy += c;
     103        }
     104    }
     105
     106    return ((failed > this.size*this.failFraction) ? undefined : retVec);
     107};
     108
     109/////////////////////////////////////////////////////////////////////////////////////////
     110//  RectPlacer
     111/////////////////////////////////////////////////////////////////////////////////////////
     112
     113function RectPlacer(x1, y1, x2, y2)
     114{
     115    this.x1 = x1;
     116    this.y1 = y1;
     117    this.x2 = x2;
     118    this.y2 = y2;
     119   
     120    if (x1 > x2 || y1 > y2)
     121        error("RectPlacer: incorrect bounds on rect");
     122}
     123
     124RectPlacer.prototype.place = function(constraint)
     125{
     126    var ret = [];
     127   
     128    var x2 = this.x2;
     129    var y2 = this.y2;
     130   
     131    for (var x=this.x1; x < x2; x++)
     132    {
     133        for (var y=this.y1; y < y2; y++)
     134        {
     135            if (g_Map.validT(x, y) && constraint.allows(x, y))
     136            {
     137                ret.push(new Point(x, y));
     138            }
     139            else
     140            {
     141                return undefined;
     142            }
     143        }
     144    }
     145   
     146    return ret;
     147   
     148};
     149
     150/////////////////////////////////////////////////////////////////////////////////////////
     151//  ObjectGroupPlacer
     152/////////////////////////////////////////////////////////////////////////////////////////
     153
     154function ObjectGroupPlacer() {}
     155   
     156/////////////////////////////////////////////////////////////////////////////////////////
     157//  SimpleGroup
     158/////////////////////////////////////////////////////////////////////////////////////////
     159
     160function SimpleObject(type, minCount, maxCount, minDistance, maxDistance, minAngle, maxAngle)
     161{
     162    this.type = type;
     163    this.minCount = minCount;
     164    this.maxCount = maxCount;
     165    this.minDistance = minDistance;
     166    this.maxDistance = maxDistance;
     167    this.minAngle = (minAngle !== undefined ? minAngle : 0);
     168    this.maxAngle = (maxAngle !== undefined ? maxAngle : 2*PI);
     169   
     170    if (minCount > maxCount)
     171        error("SimpleObject: minCount must be less than or equal to maxCount");
     172   
     173    if (minDistance > maxDistance)
     174        error("SimpleObject: minDistance must be less than or equal to maxDistance");
     175   
     176    if (minAngle > maxAngle)
     177        error("SimpleObject: minAngle must be less than or equal to maxAngle");
     178}
     179
     180SimpleObject.prototype.place = function(cx, cy, player, avoidSelf, constraint)
     181{
     182    var failCount = 0;
     183    var count = randInt(this.minCount, this.maxCount);
     184    var resultObjs = [];
     185   
     186    for (var i=0; i < count; i++)
     187    {
     188        while(true)
     189        {
     190            var distance = randFloat(this.minDistance, this.maxDistance);
     191            var direction = randFloat(0, 2*PI);
     192
     193            var x = cx + 0.5 + distance*cos(direction);
     194            var y = cy + 0.5 + distance*sin(direction);
     195            var fail = false; // reset place failure flag
     196
     197            if (x < 0 || y < 0 || x > g_Map.size || y > g_Map.size)
     198            {
     199                fail = true;
     200            }
     201            else
     202            {
     203                if (avoidSelf)
     204                {
     205                    var length = resultObjs.length;
     206                    for (var i = 0; (i < length) && !fail; i++)
     207                    {
     208                        var dx = x - resultObjs[i].x;
     209                        var dy = y - resultObjs[i].y;
     210                       
     211                        if ((dx*dx + dy*dy) < 1)
     212                        {
     213                            fail = true;
     214                        }
     215                    }
     216                }
     217               
     218                if (!fail)
     219                {
     220                    if (!constraint.allows(Math.floor(x), Math.floor(y)))
     221                    {
     222                        fail = true;
     223                    }
     224                    else
     225                    {   // if we got here, we're good
     226                        var angle = randFloat(this.minAngle, this.maxAngle);
     227                        resultObjs.push(new Entity(this.type, player, x, y, angle));
     228                        break;
     229                    }
     230                }
     231            }
     232           
     233            if (fail)
     234            {
     235                failCount++;
     236                if (failCount > 20) // TODO: Make this adjustable
     237                {
     238                    return undefined;
     239                }
     240            }
     241        }
     242    }
     243   
     244    return resultObjs;
     245};
     246
     247function SimpleGroup(elements, avoidSelf, tileClass, x, y)
     248{
     249    this.elements = elements;
     250    this.tileClass = (tileClass !== undefined ? getTileClass(tileClass) : null);
     251    this.avoidSelf = (avoidSelf !== undefined ? avoidSelf : false);
     252    this.x = (x !== undefined ? x : -1);
     253    this.y = (y !== undefined ? y : -1);
     254}
     255
     256SimpleGroup.prototype.place = function(player, constraint)
     257{
     258    var resultObjs = [];
     259
     260    // Try placement of objects
     261    var length = this.elements.length;
     262    for (var i=0; i < length; i++)
     263    {
     264        var objs = this.elements[i].place(this.x, this.y, player, this.avoidSelf, constraint);
     265        if (objs === undefined)
     266        {   // Failure
     267            return false;
     268        }
     269        else
     270        {
     271            resultObjs = resultObjs.concat(objs);
     272        }
     273    }
     274   
     275    // Add placed objects to map
     276    length = resultObjs.length;
     277    for (var i=0; i < length; i++)
     278    {
     279        g_Map.addObjects(resultObjs[i]);
     280       
     281        if (this.tileClass !== null)
     282        {   // Round object position to integer
     283            this.tileClass.add(Math.floor(resultObjs[i].x), Math.floor(resultObjs[i].y));
     284        }
     285    }
     286   
     287    return true;
     288};
     289
  • binaries/data/mods/public/maps/mapgen/point.js

     
     1function Point(x, y)
     2{
     3    this.x = (x !== undefined ? x : 0);
     4    this.y = (y !== undefined ? y : 0);
     5}
  • binaries/data/mods/public/maps/mapgen/random.js

     
     1
     2//~ function randFloat()
     3//~ {
     4    //~ if (arguments.length == 0)
     5    //~ {
     6        //~ return Generator.RandFloat0();
     7    //~ }
     8    //~ else if (arguments.length == 2)
     9    //~ {
     10        //~ return Generator.RandFloat2(arguments[0], arguments[1]);
     11    //~ }
     12    //~ else
     13    //~ {
     14        //~ return undefined;
     15    //~ }
     16//~ }
     17
     18//~ function randInt()
     19//~ {   
     20    //~ if (arguments.length == 1)
     21    //~ {
     22        //~ return Generator.RandInt1(arguments[0]);
     23    //~ }
     24    //~ else if (arguments.length == 2)
     25    //~ {
     26        //~ return Generator.RandInt2(arguments[0], arguments[1]);
     27    //~ }
     28    //~ else
     29    //~ {
     30        //~ return undefined;
     31    //~ }
     32//~ }
  • binaries/data/mods/public/maps/mapgen/terrain.js

     
     1//////////////////////////////////////////////////////////////////////
     2//  Terrain
     3//////////////////////////////////////////////////////////////////////
     4
     5function Terrain() {}
     6   
     7Terrain.prototype.place = function(x, y)
     8{
     9    // Clear old array
     10    g_Map.terrainObjects[x][y] = [];
     11   
     12    this.placeNew(x, y);
     13};
     14
     15Terrain.prototype.placeNew = function() {};
     16
     17//////////////////////////////////////////////////////////////////////
     18//  SimpleTerrain
     19//////////////////////////////////////////////////////////////////////
     20
     21function SimpleTerrain(texture, treeType)
     22{
     23    if (texture === undefined)
     24        error("SimpleTerrain: texture not defined");
     25   
     26    this.texture = texture;
     27    this.treeType = treeType;
     28}
     29
     30SimpleTerrain.prototype = new Terrain();
     31SimpleTerrain.prototype.constructor = SimpleTerrain;
     32SimpleTerrain.prototype.placeNew = function(x, y)
     33{
     34    if (this.treeType !== undefined)
     35        g_Map.terrainObjects[x][y].push(new Entity(this.treeType, 0, x+0.5, y+0.5, randFloat()*PI));
     36   
     37    g_Map.texture[x][y] = g_Map.getID(this.texture);
     38};
     39
     40//////////////////////////////////////////////////////////////////////
     41//  RandomTerrain
     42//////////////////////////////////////////////////////////////////////
     43
     44function RandomTerrain(terrains)
     45{
     46    if (!(terrains instanceof Array) || !terrains.length)
     47        error("Invalid terrains array");
     48   
     49    this.terrains = terrains;
     50}
     51
     52RandomTerrain.prototype = new Terrain();
     53RandomTerrain.prototype.constructor = RandomTerrain;
     54RandomTerrain.prototype.placeNew = function(x, y)
     55{
     56    this.terrains[randInt(this.terrains.length)].placeNew(x, y);
     57};
  • binaries/data/mods/public/maps/mapgen/tileclass.js

     
     1//////////////////////////////////////////////////////////////////////
     2//  RangeOp
     3//////////////////////////////////////////////////////////////////////
     4
     5function RangeOp(size)
     6{
     7    // Get smallest power of 2 which is greater than or equal to size
     8    this.nn = 1;
     9    while (this.nn < size) {
     10        this.nn *= 2;
     11    }
     12   
     13    this.vals = new Int16Array(2*this.nn);  // int16
     14}
     15
     16RangeOp.prototype.set = function(pos, amt)
     17{
     18    this.add(pos, amt - this.vals[this.nn + pos]);
     19};
     20
     21RangeOp.prototype.add = function(pos, amt)
     22{
     23    for(var s = this.nn; s >= 1; s /= 2)
     24    {
     25        this.vals[s + pos] += amt;
     26        pos = Math.floor(pos/2);
     27    }
     28};
     29
     30RangeOp.prototype.get = function(start, end)
     31{
     32    var ret = 0;
     33    var i;
     34    var nn = this.nn;
     35   
     36    // Count from start to end by powers of 2
     37    for (i = 1; start+i <= end; i *= 2)
     38    {
     39        if (start & i)
     40        {   // For each bit in start
     41            ret += this.vals[nn/i + Math.floor(start/i)];
     42            start += i;
     43        }
     44    }
     45   
     46    //
     47    while(i >= 1)
     48    {
     49        if(start+i <= end)
     50        {
     51            ret += this.vals[nn/i + Math.floor(start/i)];
     52            start += i;
     53        }
     54        i /= 2;
     55    }
     56   
     57    return ret;
     58};
     59
     60
     61//////////////////////////////////////////////////////////////////////
     62//  TileClass
     63//////////////////////////////////////////////////////////////////////
     64
     65function TileClass(size)
     66{
     67    this.size = size;
     68    this.inclusionCount = new Array(size);
     69    this.rangeCount = new Array(size);
     70   
     71    for (var i=0; i < size; ++i)
     72    {
     73        this.inclusionCount[i] = new Int16Array(size); //int16     
     74        this.rangeCount[i] = new RangeOp(size);
     75    }
     76}
     77
     78TileClass.prototype.add = function(x, y)
     79{
     80    if (!this.inclusionCount[x][y])
     81    {
     82        this.rangeCount[y].add(x, 1);
     83    }
     84   
     85    this.inclusionCount[x][y]++;
     86};
     87
     88TileClass.prototype.remove = function(x, y)
     89{
     90    this.inclusionCount[x][y]--;
     91    if(!this.inclusionCount[x][y])
     92    {
     93        this.rangeCount[y].add(x, -1);
     94    }
     95};
     96
     97TileClass.prototype.countInRadius = function(cx, cy, radius, returnMembers)
     98{
     99    var members = 0;
     100    var nonMembers = 0;
     101    var size = this.size;
     102
     103    var ymax = cy+radius;
     104   
     105    for (var y = cy-radius; y <= ymax; y++)
     106    {
     107        var iy = Math.floor(y);
     108        if(iy >= 0 && iy < size)
     109        {
     110            var dy = y - cy;
     111            var dx = Math.sqrt(radius*radius - dy*dy);
     112           
     113            var lowerX = Math.floor(cx - dx);
     114            var upperX = Math.floor(cx + dx);
     115           
     116            var minX = (lowerX > 0 ? lowerX : 0);       
     117            var maxX = (upperX < size ? upperX+1 : size);
     118           
     119            var total = maxX - minX;
     120            var mem = this.rangeCount[iy].get(minX, maxX);
     121           
     122            members += mem;
     123            nonMembers += total - mem;
     124        }
     125    }
     126   
     127    if (returnMembers)
     128        return members;
     129    else
     130        return nonMembers;
     131};
     132
     133TileClass.prototype.countMembersInRadius = function(cx, cy, radius)
     134{
     135    return this.countInRadius(cx, cy, radius, true);
     136};
     137
     138TileClass.prototype.countNonMembersInRadius = function(cx, cy, radius)
     139{
     140    return this.countInRadius(cx, cy, radius, false);
     141};
  • binaries/data/mods/public/maps/mapgen/vector.js

     
     1/////////////////////////////////////////////////////////////////////
     2//  Vector2D
     3/////////////////////////////////////////////////////////////////////
     4
     5// TODO: Type errors if v not instanceof Vector classes
     6// TODO: Possible implement in C++
     7
     8function Vector2D(x, y)
     9{
     10    if (arguments.length == 2)
     11    {
     12        this.set(x, y);
     13    }
     14    else
     15    {
     16        this.set(0, 0);
     17    }
     18}
     19
     20Vector2D.prototype.set = function(x, y)
     21{
     22    this.x = x;
     23    this.y = y;
     24};
     25
     26Vector2D.prototype.add = function(v)
     27{
     28    return new Vector2D(this.x + v.x, this.y + v.y);
     29};
     30
     31Vector2D.prototype.sub = function(v)
     32{
     33    return new Vector2D(this.x - v.x, this.y - v.y);
     34};
     35
     36Vector2D.prototype.mult = function(f)
     37{
     38    return new Vector2D(this.x * f, this.y * f);
     39};
     40
     41Vector2D.prototype.div = function(f)
     42{
     43    return new Vector2D(this.x / f, this.y / f);
     44};
     45
     46Vector2D.prototype.dot = function(v)
     47{
     48    return this.x * v.x + this.y * v.y;
     49};
     50
     51Vector2D.prototype.lengthSquared = function()
     52{
     53    return this.dot(this);
     54};
     55
     56Vector2D.prototype.length = function()
     57{
     58    return sqrt(this.lengthSquared());
     59};
     60
     61Vector2D.prototype.normalize = function()
     62{
     63    var mag = this.length();
     64   
     65    this.x /= mag;
     66    this.y /= mag;
     67};
     68
     69/////////////////////////////////////////////////////////////////////
     70//  Vector3D
     71/////////////////////////////////////////////////////////////////////
     72
     73function Vector3D(x, y, z)
     74{
     75    if (arguments.length == 3)
     76    {
     77        this.set(x, y, z);
     78    }
     79    else
     80    {
     81        this.set(0, 0, 0);
     82    }
     83}
     84
     85Vector3D.prototype.set = function(x, y, z)
     86{
     87    this.x = x;
     88    this.y = y;
     89    this.z = z;
     90};
     91
     92Vector3D.prototype.add = function(v)
     93{
     94    return new Vector3D(this.x + v.x, this.y + v.y, this.z + v.z);
     95};
     96
     97Vector3D.prototype.sub = function(v)
     98{
     99    return new Vector3D(this.x - v.x, this.y - v.y, this.z - v.z);
     100};
     101
     102Vector3D.prototype.mult = function(f)
     103{
     104    return new Vector3D(this.x * f, this.y * f, this.z * f);
     105};
     106
     107Vector3D.prototype.div = function(f)
     108{
     109    return new Vector3D(this.x / f, this.y / f, this.z / f);
     110};
     111
     112Vector3D.prototype.dot = function(v)
     113{
     114    return this.x * v.x + this.y * v.y + this.z * v.z;
     115};
     116
     117Vector3D.prototype.lengthSquared = function()
     118{
     119    return this.dot(this);
     120};
     121
     122Vector3D.prototype.length = function()
     123{
     124    return sqrt(this.lengthSquared());
     125};
     126
     127Vector3D.prototype.normalize = function()
     128{
     129    var mag = this.length();
     130   
     131    this.x /= mag;
     132    this.y /= mag;
     133    this.z /= mag;
     134};
     135
  • binaries/data/mods/public/maps/random/cantabrian_highlands.js

     
    1 // constants
    21
    3 const SIZE = 208;
    4 const NUM_PLAYERS = 4;
     2// terrain textures
     3const tGrass = ["medit_grass_field_a", "medit_grass_field_b"];
     4const tGrassForest = "medit_grass_wild";
     5const tCliff = ["medit_cliff_italia", "medit_cliff_italia_grass"];
     6const tForest = "medit_grass_field_a";
     7const tGrassDirt75 = "medit_dirt";
     8const tGrassDirt50 = "medit_dirt_b";
     9const tGrassDirt25 = "medit_dirt_c";
     10const tDirt = "medit_dirt_b";
     11const tGrassPatch = "medit_grass_wild";
     12const tShore = "medit_rocks";
     13const tShoreBlend = "medit_rocks_grass";
     14const tWater = "medit_rocks_wet";
    515
     16// gaia entities
     17const oTree = "gaia/flora_tree_oak";
     18const oTreeLarge = "gaia/flora_tree_oak";
     19const oBerryBush = "gaia/flora_bush_berry";
     20const oSheep = "gaia/fauna_sheep";
     21const oDeer = "gaia/fauna_deer";
     22const oMine = "gaia/geology_stone_temperate";
    623
    7 const tGrass = ["grass_temperate_pasture_a", "grass_temperate_pasture_b"];
    8 const tGrassForest = "grass_temperate_a";
    9 const tCliff = ["cliff_temperate_granite", "cliff_temperate_brown"];
    10 const tForest = "forestfloor_temperate_a";
    11 const tGrassDirt75 = "grass_temperate_dirt_2";
    12 const tGrassDirt50 = "grass_temperate_dirt_b";
    13 const tGrassDirt25 = "grass_temperate_dry_dirt";
    14 const tDirt = "dirt_temperate_b_dry";
    15 const tGrassPatch = "grass_temperate_field_wild";
    16 const tShore = "shoreline_temperate_rocks";
    17 const tShoreBlend = "shoreline_temperate_rocks_dirt";
    18 const tWater = "sand_temperate_vegetation";
     24// decorative props
     25const aGrass = "actor|props/flora/grass_temp_field.xml";
     26const aGrassShort = "actor|props/flora/grass_field_lush_short.xml";
     27const aReeds = "actor|props/flora/grass_temp_field_dry.xml";
     28const aRockLarge = "actor|geology/stone_granite_large.xml";
     29const aRockMedium = "actor|geology/stone_granite_med.xml";
     30const aBushMedium = "actor|props/flora/bush_tempe_me.xml";
     31const aBushSmall = "actor|props/flora/bush_tempe_sm.xml";
    1932
    20 const oTree = "flora_tree_oak";
    21 const oTreeLarge = "flora_tree_oak";
    22 const oBerryBush = "flora_bush_berry";
    23 const oSheep = "fauna_sheep";
    24 const oDeer = "fauna_deer";
    25 const oMine = "geology_stone_temperate";
    26 const oGrass = "props/flora/grass_temp_field.xml";
    27 const oGrassShort = "props/flora/grass_field_lush_short.xml";
    28 const oReeds = "props/flora/grass_temp_field_dry.xml";
    29 const oRockLarge = "geology/stone_granite_large.xml";
    30 const oRockMedium = "flora_bush_temperate";
    31 const oBushMedium = "props/flora/bush_tempe_me.xml";
    32 const oBushSmall = "props/flora/bush_tempe_sm.xml";
     33log("Initializing map...");
    3334
    34 // initialize map
     35var numPlayers = getNumPlayers();
     36var mapSize = getMapSize();
    3537
    36 println("Initializing map...");
    37 init(SIZE, tGrass, 3);
    38 
    3938// create tile classes
    4039
    41 clPlayer = createTileClass();
    42 clHill = createTileClass();
    43 clForest = createTileClass();
    44 clWater = createTileClass();
    45 clSettlement = createTileClass();
    46 clDirt = createTileClass();
    47 clRock = createTileClass();
    48 clFood = createTileClass();
    49 clBaseResource = createTileClass();
     40var clPlayer = createTileClass();
     41var clHill = createTileClass();
     42var clForest = createTileClass();
     43var clWater = createTileClass();
     44var clDirt = createTileClass();
     45var clRock = createTileClass();
     46var clFood = createTileClass();
     47var clBaseResource = createTileClass();
    5048
    5149// place players
    5250
    53 playerX = new Array(NUM_PLAYERS+1);
    54 playerY = new Array(NUM_PLAYERS+1);
    55 playerAngle = new Array(NUM_PLAYERS+1);
     51var playerX = new Array(numPlayers+1);
     52var playerY = new Array(numPlayers+1);
     53var playerAngle = new Array(numPlayers+1);
    5654
    57 startAngle = randFloat() * 2 * PI;
    58 for(i=1; i<=NUM_PLAYERS; i++) {
    59     playerAngle[i] = startAngle + i*2*PI/NUM_PLAYERS;
     55var startAngle = randFloat() * 2 * PI;
     56for (var i=1; i<=numPlayers; i++)
     57{
     58    playerAngle[i] = startAngle + i*2*PI/numPlayers;
    6059    playerX[i] = 0.5 + 0.35*cos(playerAngle[i]);
    6160    playerY[i] = 0.5 + 0.35*sin(playerAngle[i]);
    6261}
    6362
    64 for(i=1; i<=NUM_PLAYERS; i++) {
    65     println("Creating base for player " + i + "...");
     63for (var i=1; i<=numPlayers; i++)
     64{
     65    log("Creating base for player " + i + "...");
    6666   
    6767    // some constants
    68     radius = 17;
    69     cliffRadius = 2;
    70     elevation = 20;
     68    var radius = 17;
     69    var cliffRadius = 2;
     70    var elevation = 20;
    7171   
    7272    // get the x and y in tiles
    73     fx = fractionToTiles(playerX[i]);
    74     fy = fractionToTiles(playerY[i]);
    75     ix = round(fx);
    76     iy = round(fy);
     73    var fx = fractionToTiles(playerX[i]);
     74    var fy = fractionToTiles(playerY[i]);
     75    var ix = round(fx);
     76    var iy = round(fy);
    7777
    7878    // calculate size based on the radius
    79     size = PI * radius * radius;
     79    var size = PI * radius * radius;
    8080   
    8181    // create the hill
    82     placer = new ClumpPlacer(size, 0.95, 0.6, 0, ix, iy);
    83     terrainPainter = new LayeredPainter(
    84         [cliffRadius],      // widths
    85         [tCliff, tGrass]        // terrains
     82    var placer = new ClumpPlacer(size, 0.95, 0.6, 0, ix, iy);
     83    var terrainPainter = new LayeredPainter(
     84        [tCliff, tGrass],       // terrains
     85        [cliffRadius]       // widths
    8686    );
    87     elevationPainter = new SmoothElevationPainter(
     87    var elevationPainter = new SmoothElevationPainter(
    8888        ELEVATION_SET,          // type
    8989        elevation,              // elevation
    9090        cliffRadius             // blend radius
     
    9292    createArea(placer, [terrainPainter, elevationPainter, paintClass(clPlayer)], null);
    9393   
    9494    // create the ramp
    95     rampAngle = playerAngle[i] + PI + (2*randFloat()-1)*PI/8;
    96     rampDist = radius - 1;
    97     rampX = round(fx + rampDist * cos(rampAngle));
    98     rampY = round(fy + rampDist * sin(rampAngle));
     95    var rampAngle = playerAngle[i] + PI + (2*randFloat()-1)*PI/8;
     96    var rampDist = radius - 1;
     97    var rampX = round(fx + rampDist * cos(rampAngle));
     98    var rampY = round(fy + rampDist * sin(rampAngle));
    9999    placer = new ClumpPlacer(100, 0.9, 0.5, 0, rampX, rampY);
    100     painter = new SmoothElevationPainter(ELEVATION_SET, elevation-6, 5);
     100    var painter = new SmoothElevationPainter(ELEVATION_SET, elevation-6, 5);
    101101    createArea(placer, painter, null);
    102102    placer = new ClumpPlacer(75, 0.9, 0.5, 0, rampX, rampY);
    103103    painter = new TerrainPainter(tGrass);
     
    106106    // create the central dirt patch
    107107    placer = new ClumpPlacer(PI*3.5*3.5, 0.3, 0.1, 0, ix, iy);
    108108    painter = new LayeredPainter(
    109         [1,1,1],                                                // widths
    110         [tGrassDirt75, tGrassDirt50, tGrassDirt25, tDirt]       // terrains
     109        [tGrassDirt75, tGrassDirt50, tGrassDirt25, tDirt],      // terrains
     110        [1,1,1]                                 // widths
    111111    );
    112112    createArea(placer, painter, null);
    113113   
    114     // create the TC and the "villies"
    115     group = new SimpleGroup(
    116         [                           // elements (type, count, distance)
    117             new SimpleObject("hele_civil_centre", 1,1, 0,0),
    118             new SimpleObject("hele_infantry_javelinist_b", 3,3, 5,5)
    119         ],
    120         true, null, ix, iy
     114    // create the TC and citizens
     115    var civ = getCivCode(i - 1);
     116    var group = new SimpleGroup(    // elements (type, min/max count, min/max distance)
     117        [new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0), new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
     118        true, null, ix, iy
    121119    );
    122120    createObjectGroup(group, i);
    123121   
    124     // Create the Settlement under the TC
    125     group = new SimpleGroup(
    126         [new SimpleObject("special_settlement", 1,1, 0,0)],
    127         true, null, ix, iy
    128     );
    129     createObjectGroup(group, 0);
    130    
    131122    // create berry bushes
    132     bbAngle = randFloat()*2*PI;
    133     bbDist = 9;
    134     bbX = round(fx + bbDist * cos(bbAngle));
    135     bbY = round(fy + bbDist * sin(bbAngle));
     123    var bbAngle = randFloat()*2*PI;
     124    var bbDist = 9;
     125    var bbX = round(fx + bbDist * cos(bbAngle));
     126    var bbY = round(fy + bbDist * sin(bbAngle));
    136127    group = new SimpleGroup(
    137128        [new SimpleObject(oBerryBush, 5,5, 0,2)],
    138129        true, clBaseResource, bbX, bbY
     
    140131    createObjectGroup(group, 0);
    141132   
    142133    // create mines
    143     mAngle = bbAngle;
    144     while(abs(mAngle - bbAngle) < PI/3) {
     134    var mAngle = bbAngle;
     135    while(abs(mAngle - bbAngle) < PI/3)
     136    {
    145137        mAngle = randFloat()*2*PI;
    146138    }
    147     mDist = 9;
    148     mX = round(fx + mDist * cos(mAngle));
    149     mY = round(fy + mDist * sin(mAngle));
     139    var mDist = 9;
     140    var mX = round(fx + mDist * cos(mAngle));
     141    var mY = round(fy + mDist * sin(mAngle));
    150142    group = new SimpleGroup(
    151143        [new SimpleObject(oMine, 4,4, 0,2)],
    152144        true, clBaseResource, mX, mY
     
    161153    createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
    162154   
    163155    // create grass tufts
    164     for(j=0; j<10; j++) {
    165         gAngle = randFloat()*2*PI;
    166         gDist = 6 + randInt(9);
    167         gX = round(fx + gDist * cos(gAngle));
    168         gY = round(fy + gDist * sin(gAngle));
    169         group = new SimpleGroup([new SimpleObject(oGrassShort, 3,6, 0,1, -PI/8,PI/8)],
    170             false, clBaseResource, gX, gY);
    171         createObjectGroup(group, 0);
     156    for (var j=0; j < 10; j++)
     157    {
     158        var gAngle = randFloat()*2*PI;
     159        var gDist = 6 + randInt(9);
     160        var gX = round(fx + gDist * cos(gAngle));
     161        var gY = round(fy + gDist * sin(gAngle));
     162        group = new SimpleGroup(
     163            [new SimpleObject(aGrassShort, 3,6, 0,1, -PI/8,PI/8)],
     164            false, clBaseResource, gX, gY
     165        );
     166        createObjectGroup(group, undefined);
    172167    }
    173168}
    174169
    175170// create lakes
    176 println("Creating lakes...");
     171log("Creating lakes...");
     172//console.profile();
    177173placer = new ClumpPlacer(140, 0.8, 0.1, 0);
    178174terrainPainter = new LayeredPainter(
    179     [1,1],                                  // widths
    180     [tShoreBlend, tShore, tWater]       // terrains
     175    [tShoreBlend, tShore, tWater],      // terrains
     176    [1,1]                           // widths
    181177);
    182178elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -7, 3);
    183 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clWater)],
     179createAreas(
     180    placer,
     181    [terrainPainter, elevationPainter, paintClass(clWater)],
    184182    avoidClasses(clPlayer, 2, clWater, 20),
    185     round(1.3 * NUM_PLAYERS)
     183    round(1.3 * numPlayers)
    186184);
     185//console.profileEnd();
    187186
    188187// create bumps
    189 println("Creating bumps...");
     188log("Creating bumps...");
    190189placer = new ClumpPlacer(10, 0.3, 0.06, 0);
    191190painter = new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2);
    192 createAreas(placer, painter,
     191createAreas(
     192    placer,
     193    painter,
    193194    avoidClasses(clWater, 2, clPlayer, 0),
    194     SIZE*SIZE/100
     195    mapSize*mapSize/100
    195196);
    196197
    197198// create hills
    198 println("Creating hills...");
     199log("Creating hills...");
    199200placer = new ClumpPlacer(30, 0.2, 0.1, 0);
    200201terrainPainter = new LayeredPainter(
    201     [3],                    // widths
    202     [tCliff, [tGrass,tGrass,tGrassDirt75]]      // terrains
     202    [tCliff, [tGrass,tGrass,tGrassDirt75]],     // terrains
     203    [3]                             // widths
    203204);
    204205elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 12, 2);
    205 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill)],
     206createAreas(
     207    placer,
     208    [terrainPainter, elevationPainter, paintClass(clHill)],
    206209    avoidClasses(clPlayer, 2, clWater, 5, clHill, 15),
    207     2 * NUM_PLAYERS
     210    2 * numPlayers
    208211);
    209212
    210213// create forests
    211 println("Creating forests...");
     214log("Creating forests...");
    212215placer = new ClumpPlacer(32, 0.1, 0.1, 0);
    213 painter = new LayeredPainter([2], [[tGrassForest, tGrass, tForest],
    214     [tGrassForest, tForest]]);
    215 createAreas(placer, [painter, paintClass(clForest)],
     216painter = new LayeredPainter(
     217    [[tGrassForest, tGrass, tForest], [tGrassForest, tForest]],     // terrains
     218    [2]                                         // widths
     219    );
     220createAreas(
     221    placer,
     222    [painter, paintClass(clForest)],
    216223    avoidClasses(clPlayer, 1, clWater, 3, clForest, 10, clHill, 0),
    217     6 * NUM_PLAYERS
     224    6 * numPlayers
    218225);
    219226
    220227// create dirt patches
    221 println("Creating dirt patches...");
     228log("Creating dirt patches...");
    222229var sizes = [8,14,20];
    223 for(i=0; i<sizes.length; i++) {
     230for (i=0; i<sizes.length; i++)
     231{
    224232    placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0);
    225     painter = new LayeredPainter([1,1], [
    226         [tGrass,tGrassDirt75],[tGrassDirt75,tGrassDirt50],
    227         [tGrassDirt50,tGrassDirt25]]);
    228     createAreas(placer, [painter, paintClass(clDirt)],
     233    painter = new LayeredPainter(
     234        [[tGrass,tGrassDirt75],[tGrassDirt75,tGrassDirt50], [tGrassDirt50,tGrassDirt25]],       // terrains
     235        [1,1]                                                           // widths
     236    );
     237    createAreas(
     238        placer,
     239        [painter, paintClass(clDirt)],
    229240        avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0),
    230         SIZE*SIZE/4000
     241        mapSize*mapSize/4000
    231242    );
    232243}
    233244
    234245// create grass patches
    235 println("Creating grass patches...");
     246log("Creating grass patches...");
    236247var sizes = [5,9,13];
    237 for(i=0; i<sizes.length; i++) {
     248for (i=0; i<sizes.length; i++)
     249{
    238250    placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0);
    239251    painter = new TerrainPainter(tGrassPatch);
    240     createAreas(placer, painter,
     252    createAreas(
     253        placer,
     254        painter,
    241255        avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0),
    242         SIZE*SIZE/4000
     256        mapSize*mapSize/4000
    243257    );
    244258}
    245259
    246260// create mines
    247 println("Creating mines...");
    248 group = new SimpleGroup([new SimpleObject(oMine, 4,6, 0,2)], true, clRock);
    249 createObjectGroups(group, 0,
     261log("Creating mines...");
     262group = new SimpleGroup(
     263    [new SimpleObject(oMine, 4,6, 0,2)],
     264    true, clRock
     265);
     266createObjectGroups(
     267    group, 0,
    250268    [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clRock, 13),
    251269     new BorderTileClassConstraint(clHill, 0, 4)],
    252     3 * NUM_PLAYERS, 100
     270    3 * numPlayers, 100
    253271);
    254272
    255 // create settlements
    256 println("Creating settlements...");
    257 group = new SimpleGroup([new SimpleObject("special_settlement", 1,1, 0,0)], true, clSettlement);
    258 createObjectGroups(group, 0,
    259     avoidClasses(clWater, 0, clForest, 0, clPlayer, 15, clHill, 0, clRock, 5, clSettlement, 35),
    260     2 * NUM_PLAYERS, 50
    261 );
    262 
    263273// create small decorative rocks
    264 println("Creating large decorative rocks...");
    265 group = new SimpleGroup([new SimpleObject(oRockMedium, 1,3, 0,1)], true);
    266 createObjectGroups(group, 0,
    267     avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clSettlement, 3),
    268     SIZE*SIZE/1000, 50
     274log("Creating large decorative rocks...");
     275group = new SimpleGroup(
     276    [new SimpleObject(aRockMedium, 1,3, 0,1)],
     277    true
    269278);
     279createObjectGroups(
     280    group, undefined,
     281    avoidClasses(clForest, 0, clPlayer, 0, clHill, 0),
     282    mapSize*mapSize/1000, 50
     283);
    270284
    271285// create large decorative rocks
    272 println("Creating large decorative rocks...");
    273 group = new SimpleGroup([new SimpleObject(oRockLarge, 1,2, 0,1),
    274     new SimpleObject(oRockMedium, 1,3, 0,2)], true);
    275 createObjectGroups(group, 0,
    276     avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clSettlement, 5),
    277     SIZE*SIZE/2000, 50
     286log("Creating large decorative rocks...");
     287group = new SimpleGroup(
     288    [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
     289    true
    278290);
     291createObjectGroups(
     292    group, undefined,
     293    avoidClasses(clForest, 0, clPlayer, 0, clHill, 0),
     294    mapSize*mapSize/2000, 50
     295);
    279296
    280297// create deer
    281 println("Creating deer...");
    282 group = new SimpleGroup([new SimpleObject(oDeer, 5,7, 0,4)], true, clFood);
     298log("Creating deer...");
     299group = new SimpleGroup(
     300    [new SimpleObject(oDeer, 5,7, 0,4)],
     301    true, clFood
     302);
    283303createObjectGroups(group, 0,
    284     avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20, clSettlement, 5),
    285     3 * NUM_PLAYERS, 50
     304    avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20),
     305    3 * numPlayers, 50
    286306);
    287307
    288308// create sheep
    289 println("Creating sheep...");
    290 group = new SimpleGroup([new SimpleObject(oSheep, 2,3, 0,2)], true, clFood);
     309log("Creating sheep...");
     310group = new SimpleGroup(
     311    [new SimpleObject(oSheep, 2,3, 0,2)],
     312    true, clFood
     313);
    291314createObjectGroups(group, 0,
    292     avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20, clSettlement, 5),
    293     3 * NUM_PLAYERS, 50
     315    avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20),
     316    3 * numPlayers, 50
    294317);
    295318
    296319// create straggler trees
    297 println("Creating straggler trees...");
    298 group = new SimpleGroup([new SimpleObject(oTree, 1,1, 0,0)], true);
     320log("Creating straggler trees...");
     321group = new SimpleGroup(
     322    [new SimpleObject(oTree, 1,1, 0,0)],
     323    true
     324);
    299325createObjectGroups(group, 0,
    300     avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 1, clSettlement, 2),
    301     SIZE*SIZE/1100
     326    avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 1),
     327    mapSize*mapSize/1100
    302328);
    303329
    304330// create small grass tufts
    305 println("Creating small grass tufts...");
    306 group = new SimpleGroup([new SimpleObject(oGrassShort, 3,6, 0,1, -PI/8,PI/8)]);
    307 createObjectGroups(group, 0,
     331log("Creating small grass tufts...");
     332group = new SimpleGroup(
     333    [new SimpleObject(aGrassShort, 3,6, 0,1, -PI/8,PI/8)]
     334);
     335createObjectGroups(group, undefined,
    308336    avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0),
    309     SIZE*SIZE/90
     337    mapSize*mapSize/90
    310338);
    311339
    312340// create large grass tufts
    313 println("Creating large grass tufts...");
    314 group = new SimpleGroup([new SimpleObject(oGrass, 20,30, 0,1.8, -PI/8,PI/8),
    315     new SimpleObject(oGrassShort, 20,30, 1.2,2.5, -PI/8,PI/8)]);
    316 createObjectGroups(group, 0,
     341log("Creating large grass tufts...");
     342group = new SimpleGroup(
     343    [new SimpleObject(aGrass, 20,30, 0,1.8, -PI/8,PI/8), new SimpleObject(aGrassShort, 20,30, 1.2,2.5, -PI/8,PI/8)]
     344);
     345createObjectGroups(group, undefined,
    317346    avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0),
    318     SIZE*SIZE/900
     347    mapSize*mapSize/900
    319348);
    320349
    321350// create bushes
    322 println("Creating bushes...");
    323 group = new SimpleGroup([new SimpleObject(oBushSmall, 2,4, 0,2)]);
    324 createObjectGroups(group, 0,
     351log("Creating bushes...");
     352group = new SimpleGroup(
     353    [new SimpleObject(aBushSmall, 2,4, 0,2)]
     354);
     355createObjectGroups(group, undefined,
    325356    avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1),
    326     SIZE*SIZE/2000, 50
     357    mapSize*mapSize/2000, 50
    327358);
    328359
    329360// create reeds
    330 println("Creating reeds...");
    331 group = new SimpleGroup([new SimpleObject(oReeds, 5,10, 0,1.5, -PI/8,PI/8)]);
    332 createObjectGroups(group, 0,
     361log("Creating reeds...");
     362group = new SimpleGroup(
     363    [new SimpleObject(aReeds, 5,10, 0,1.5, -PI/8,PI/8)]
     364);
     365createObjectGroups(group, undefined,
    333366    [new BorderTileClassConstraint(clWater, 3, 0), new StayInTileClassConstraint(clWater, 1)],
    334     10 * NUM_PLAYERS, 100
     367    10 * numPlayers, 100
    335368);
    336 
  • binaries/data/mods/public/maps/random/cantabrian_highlands.json

     
     1{
     2    "settings" : {
     3        "Name" : "Cantabrian Highlands",
     4        "Script" : "cantabrian_highlands.js",
     5        "Description" : "A test of the Cantabrian Highlands script",
     6        "BaseTerrain" : ["medit_grass_field_a", "medit_grass_field_b"],
     7        "BaseHeight" : 3,
     8        "RevealMap": true,
     9        "GameType": "endless",
     10        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
     11    }
     12}
     13 No newline at end of file
  • binaries/data/mods/public/maps/random/latium.js

    Property changes on: binaries\data\mods\public\maps\random\cantabrian_highlands.json
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    1 const SIZE = 176;
    2 const NUM_PLAYERS = 4;
    3 const WATER_WIDTH = .2;
    4 
    5 // Terrain and object constants
    6 
    7 tOceanDepths = "ocean_medit_depths";
    8 tOceanRockDeep = "ocean_medit_rock_deep";
    9 tOceanRockShallow = "ocean_medit_rock_shallow";
    10 tOceanCoral = "ocean_medit_coral";
    11 tBeachWet = "beach_medit_wet";
    12 tBeachDry = "beach_medit_dry";
    13 tBeachGrass = "beach_medit_grass_50";
    14 tBeachCliff = "cliff_medit_beach";
    15 tGrassDry = ["grass_mediterranean_dry_a", "grass_mediterranean_dry_b", "grass_mediterranean_dry_c"];
    16 tGrass = ["grass_mediterranean_green_50", "grass_mediterranean_green_flowers"];
    17 tGrassLush = ["grass_temperate_dry_tufts", "grass_mediterranean_green_flowers"];
    18 tGrassShrubs = ["grass_mediterranean_green_shrubs", "grass_mediterranean_green_flowers"];
    19 tGrassRock = ["grass_mediterranean_green_rock"];
    20 tDirt = "dirt_medit_a";
    21 tDirtGrass = "dirt_medit_grass_50";
    22 tDirtCliff = "cliff_medit_dirt";
    23 tGrassCliff = "cliff_medit_grass_a";
    24 tCliff = ["cliff_medit_face_b", "cliff_medit_face_b", "cliff_medit_foliage_a"];
    25 tForestFloor = "forestfloor_medit_dirt";
    26 
    27 oPalm = "flora_tree_medit_fan_palm";
    28 oLombardyPoplar = "flora_tree_poplar_lombardy";
    29 oOak = "flora_tree_oak";
    30 oPoplar = "flora_tree_poplar";
    31 oCarob = "flora_tree_carob";
    32 oBeech = "flora_tree_euro_beech";
    33 oPine = "flora_tree_aleppo_pine";
    34 oBerryBush = "flora_bush_berry";
    35 oSheep = "fauna_sheep";
    36 oStone = "geology_stone_greek";
    37 oMetal = "geology_metal_greek";
    38 oBushLargeDry = "props/flora/bush_medit_la_dry.xml";
    39 oBushLarge = "props/flora/bush_medit_la.xml";
    40 oBushMedDry = "props/flora/bush_medit_me_dry.xml";
    41 oBushMed = "props/flora/bush_medit_me.xml";
    42 oBushSmall = "props/flora/bush_medit_sm.xml"
    43 oBushSmallDry = "props/flora/bush_medit_sm_dry.xml"
    44 oGrass = "props/flora/grass_medit_field.xml";
    45 oGrassDry = "props/flora/grass_soft_dry_small.xml";
    46 oRockLarge = "geology/stone_granite_greek_large.xml";
    47 oRockMed = "geology/stone_granite_greek_med.xml";
    48 oRockSmall = "geology/stone_granite_greek_small.xml";
    49 oWaterLog = "props/flora/water_log.xml";
    50 
    51 tPalmForest = [tForestFloor+"|"+oPalm, tGrass];
    52 tPineForest = [tForestFloor+"|"+oPine, tGrass];
    53 tMainForest = [tForestFloor+"|"+oCarob, tForestFloor+"|"+oBeech, tGrass, tGrass];
    54 tPoplarForest = [tForestFloor+"|"+oLombardyPoplar, tGrass];
    55 
    56 // Initialize world
    57 
    58 init(SIZE, tGrass, 0);
    59 
    60 // Create classes
    61 
    62 clWater = createTileClass();
    63 clCliff = createTileClass();
    64 clForest = createTileClass();
    65 clMetal = createTileClass();
    66 clStone = createTileClass();
    67 clFood = createTileClass();
    68 clPlayer = createTileClass();
    69 clBaseResource = createTileClass();
    70 clSettlement = createTileClass();
    71 
    72 // Place players
    73 
    74 println("Placing players...");
    75 
    76 playerX = new Array(NUM_PLAYERS+1);
    77 playerY = new Array(NUM_PLAYERS+1);
    78 
    79 numLeftPlayers = Math.floor(NUM_PLAYERS/2);
    80 for(i=1; i<=numLeftPlayers; i++) {
    81     playerX[i] = 0.28 + (2*randFloat()-1)*0.01;
    82     playerY[i] = (0.5+i-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
    83 }
    84 for(i=numLeftPlayers+1; i<=NUM_PLAYERS; i++) {
    85     playerX[i] = 0.72 + (2*randFloat()-1)*0.01;
    86     playerY[i] = (0.5+i-numLeftPlayers-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
    87 }
    88 
    89 for(i=1; i<=NUM_PLAYERS; i++) {
    90     // get fractional locations in tiles
    91     ix = round(fractionToTiles(playerX[i]));
    92     iy = round(fractionToTiles(playerY[i]));
    93     addToClass(ix, iy, clPlayer);
    94    
    95     // create TC and starting units
    96     placeObject("special_settlement", i, ix, iy, PI*3/4);
    97     placeObject("hele_civil_centre", i, ix, iy, PI*3/4);
    98     group = new SimpleGroup(
    99         [new SimpleObject("hele_infantry_javelinist_b", 3,3, 5,5)],
    100         true, null, ix, iy
    101     );
    102     createObjectGroup(group, i);
    103    
    104     // create starting berry bushes
    105     bbAngle = randFloat()*2*PI;
    106     bbDist = 9;
    107     bbX = round(ix + bbDist * cos(bbAngle));
    108     bbY = round(iy + bbDist * sin(bbAngle));
    109     group = new SimpleGroup(
    110         [new SimpleObject(oBerryBush, 5,5, 0,2)],
    111         true, clBaseResource, bbX, bbY
    112     );
    113     createObjectGroup(group, 0);
    114    
    115     // create starting mines
    116     mAngle = bbAngle;
    117     while(abs(mAngle - bbAngle) < PI/3) {
    118         mAngle = randFloat()*2*PI;
    119     }
    120     mDist = 9;
    121     mX = round(ix + mDist * cos(mAngle));
    122     mY = round(iy + mDist * sin(mAngle));
    123     group = new SimpleGroup(
    124         [new SimpleObject(oStone, 2,2, 0,3),
    125         new SimpleObject(oMetal, 2,2, 0,3)],
    126         true, clBaseResource, mX, mY
    127     );
    128     createObjectGroup(group, 0);
    129    
    130     // create starting straggler trees
    131     group = new SimpleGroup(
    132         [new SimpleObject(oPalm, 3,3, 7,10)],
    133         true, clBaseResource, ix, iy
    134     );
    135     createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
    136 }
    137 
    138 function distanceToPlayers(x, y) {
    139     var r = 10000;
    140     for(var i=1; i<=NUM_PLAYERS; i++) {
    141         var dx = x-playerX[i];
    142         var dy = y-playerY[i];
    143         r = min(r, dx*dx + dy*dy);
    144     }
    145     return Math.sqrt(r);
    146 }
    147 
    148 function playerNearness(x, y) {
    149     var d = fractionToTiles(distanceToPlayers(x,y));
    150     if(d < 13) return 0;
    151     else if(d < 19) return (d-13)/(19-13);
    152     else return 1;
    153 }
    154 
    155 function max(x, y) {
    156     return x > y ? x : y;
    157 }
    158 
    159 function min(x, y) {
    160     return x < y ? x : y;
    161 }
    162 
    163 // Paint elevation
    164 
    165 println("Painting elevation...");
    166 
    167 noise0 = new Noise2D(4 * SIZE/128);
    168 noise1 = new Noise2D(8 * SIZE/128);
    169 noise2 = new Noise2D(15 * SIZE/128);
    170 
    171 noise2a = new Noise2D(20 * SIZE/128);
    172 noise2b = new Noise2D(35 * SIZE/128);
    173 
    174 noise3 = new Noise2D(4 * SIZE/128);
    175 noise4 = new Noise2D(6 * SIZE/128);
    176 noise5 = new Noise2D(11 * SIZE/128);
    177 
    178 for(ix=0; ix<=SIZE; ix++) {
    179     for(iy=0; iy<=SIZE; iy++) {
    180         x = ix / (SIZE + 1.0);
    181         y = iy / (SIZE + 1.0);
    182         pn = playerNearness(x, y);
    183        
    184         h = 0;
    185         distToWater = 0;
    186        
    187         h = 32 * (x-.5);
    188        
    189        
    190         // add the rough shape of the water
    191         if(x < WATER_WIDTH) {
    192             h = max(-16.0, -28.0*(WATER_WIDTH-x)/WATER_WIDTH);
    193         }
    194         else if(x > 1.0-WATER_WIDTH) {
    195             h = max(-16.0, -28.0*(x-(1.0-WATER_WIDTH))/WATER_WIDTH);
    196         }
    197         else {
    198             distToWater = (0.5 - WATER_WIDTH - Math.abs(x-0.5));
    199             u = 1 - Math.abs(x-0.5) / (0.5-WATER_WIDTH);
    200             h = 12*u;
    201         }
    202        
    203         // add some base noise
    204         baseNoise = 16*noise0.eval(x,y) + 8*noise1.eval(x,y) + 4*noise2.eval(x,y) - (16+8+4)/2;
    205         if( baseNoise < 0 ) {
    206             baseNoise *= pn;
    207             baseNoise *= max(0.1, distToWater / (0.5-WATER_WIDTH));
    208         }
    209         oldH = h;
    210         h += baseNoise;
    211        
    212         // add some higher-frequency noise on land
    213         if( oldH > 0 )
    214         {
    215             h += (0.4*noise2a.eval(x,y) + 0.2*noise2b.eval(x,y)) * min(oldH/10.0, 1.0);
    216         }
    217        
    218         // create cliff noise
    219         if( h > -10 )
    220         {
    221             cliffNoise = (1*noise3.eval(x,y) + 0.5*noise4.eval(x,y)) / 1.5;
    222             if(h < 1) {
    223                 u = 1 - .3*((h-1)/-10);
    224                 cliffNoise *= u;
    225             }
    226             cliffNoise += .05 * distToWater / (0.5 - WATER_WIDTH);
    227             if(cliffNoise > .6) {
    228                 u = 0.8 * (cliffNoise-.6);
    229                 cliffNoise += u * noise5.eval(x,y);
    230                 cliffNoise /= (1+u);
    231             }
    232             cliffNoise -= 0.59;
    233             cliffNoise *= pn;
    234             if(cliffNoise > 0) {
    235                 h += 19 * min(cliffNoise, 0.045) / 0.045;
    236             }
    237         }
    238        
    239         // set the height
    240         setHeight(ix, iy, h);
    241     }
    242 }
    243 
    244 // Paint base terrain
    245 
    246 println("Painting terrain...");
    247 
    248 noise6 = new Noise2D(10 * SIZE/128);
    249 noise7 = new Noise2D(20 * SIZE/128);
    250 
    251 noise8 = new Noise2D(13 * SIZE/128);
    252 noise9 = new Noise2D(26 * SIZE/128);
    253 
    254 noise10 = new Noise2D(50 * SIZE/128);
    255 
    256 for(ix=0; ix<SIZE; ix++) {
    257     for(iy=0; iy<SIZE; iy++) {
    258         x = ix / (SIZE + 1.0);
    259         y = iy / (SIZE + 1.0);
    260         pn = playerNearness(x, y);
    261        
    262         // get heights of surrounding vertices
    263         h00 = getHeight(ix, iy);
    264         h01 = getHeight(ix, iy+1);
    265         h10 = getHeight(ix+1, iy);
    266         h11 = getHeight(ix+1, iy+1);
    267        
    268         // find min and max height
    269         maxH = max(h00, h01, h10, h11);
    270         minH = min(h00, h01, h10, h11);
    271        
    272         // figure out if we're at the top of a cliff using min adjacent height
    273         minAdjHeight = minH;
    274         if(maxH > 15) {
    275             for(nx=max(ix-1, 0); nx<=min(ix+2, SIZE); nx++) {
    276                 for(ny=max(iy-1, 0); ny<=min(iy+2, SIZE); ny++) {
    277                     minAdjHeight = min(minAdjHeight, getHeight(nx, ny));
    278                 }
    279             }
    280         }
    281        
    282         // choose a terrain based on elevation
    283         t = tGrass;
    284        
    285         // water
    286         if(maxH < -12) {
    287             t = tOceanDepths;
    288         }
    289         else if(maxH < -8.8) {
    290             t = tOceanRockDeep;
    291         }
    292         else if(maxH < -4.7) {
    293             t = tOceanCoral;
    294         }
    295         else if(maxH < -2.8) {
    296             t = tOceanRockShallow;
    297         }
    298         else if(maxH < .9 && minH < .35) {
    299             t = tBeachWet;
    300         }
    301         else if(maxH < 1.5 && minH < .9) {
    302             t = tBeachDry;
    303         }
    304         else if(maxH < 2.3 && minH < 1.3) {
    305             t = tBeachGrass;
    306         }
    307        
    308         if(minH < 0) {
    309             addToClass(ix, iy, clWater);
    310         }
    311        
    312         // cliffs
    313         if(maxH - minH > 2.9 && minH > -7) {
    314             t = tCliff;
    315             addToClass(ix, iy, clCliff);
    316         }
    317         else if((maxH - minH > 2.5 && minH > -5) || (maxH-minAdjHeight > 2.9 && minH > 0) ) {
    318             if(minH < -1) t = tCliff;
    319             else if(minH < .5) t = tBeachCliff;
    320             else t = [tDirtCliff, tGrassCliff, tGrassCliff, tGrassRock, tCliff];
    321             addToClass(ix, iy, clCliff);
    322         }
    323        
    324         // forests
    325         if(maxH - minH < 1 && minH > 1) {
    326             forestNoise = (noise6.eval(x,y) + 0.5*noise7.eval(x,y)) / 1.5 * pn;
    327             forestNoise -= 0.59;
    328             if(forestNoise > 0) {
    329                 if(minH > 5) {
    330                     typeNoise = noise10.eval(x,y);
    331                     if(typeNoise < .43 && forestNoise < .05) t = tPoplarForest;
    332                     else if(typeNoise < .63) t = tMainForest;
    333                     else t = tPineForest;
    334                     addToClass(ix, iy, clForest);
    335                 }
    336                 else if(minH < 3) {
    337                     t = tPalmForest;
    338                     addToClass(ix, iy, clForest);
    339                 }
    340             }
    341         }
    342        
    343         // grass variations
    344         if(t==tGrass)
    345         {
    346             grassNoise = (noise8.eval(x,y) + .6*noise9.eval(x,y)) / 1.6;
    347             if(grassNoise < .3) {
    348                 t = (maxH - minH > 1.2) ? tDirtCliff : tDirt;
    349             }
    350             else if(grassNoise < .34) {
    351                 t = (maxH - minH > 1.2) ? tGrassCliff : tGrassDry;
    352                 if(maxH - minH < .5 && randFloat() < .03) {
    353                     placeObject(oGrassDry, 0, ix+randFloat(), iy+randFloat(), randFloat()*2*Math.PI);
    354                 }
    355             }
    356             else if(grassNoise > .61) {
    357                 t = (maxH - minH > 1.2) ? tGrassRock : tGrassShrubs;
    358             }
    359             else {
    360                 if(maxH - minH < .5 && randFloat() < .05) {
    361                     placeObject(oGrass, 0, ix+randFloat(), iy+randFloat(), randFloat()*2*Math.PI);
    362                 }
    363             }
    364         }
    365        
    366         placeTerrain(ix, iy, t);
    367     }
    368 }
    369 
    370 println("Placing object groups...");
    371 
    372 // create settlements
    373 group = new SimpleGroup([new SimpleObject("special_settlement", 1,1, 0,0)], true, clSettlement);
    374 createObjectGroups(group, 0,
    375     avoidClasses(clWater, 5, clForest, 4, clPlayer, 25, clCliff, 4, clSettlement, 35),
    376     2 * NUM_PLAYERS, 50
    377 );
    378 
    379 // create straggler trees
    380 trees = [oCarob, oBeech, oLombardyPoplar, oLombardyPoplar, oPine]
    381 for(t in trees) {
    382     group = new SimpleGroup([new SimpleObject(trees[t], 1,1, 0,1)], true, clForest);
    383     createObjectGroups(group, 0,
    384         avoidClasses(clWater, 5, clCliff, 0, clForest, 1, clSettlement, 4, clPlayer, 15),
    385         SIZE*SIZE/7000, 50
    386     );
    387 }
    388 
    389 // create cypresses
    390 group = new SimpleGroup([
    391     new SimpleObject("flora/trees/cypress2.xml", 1,3, 0,3),
    392     new SimpleObject("flora/trees/cypress1.xml", 0,2, 0,2)]);
    393 createObjectGroups(group, 0,
    394     avoidClasses(clWater, 4, clCliff, 2, clForest, 1, clSettlement, 4, clPlayer, 15),
    395     SIZE*SIZE/3500, 50
    396 );
    397 
    398 // create bushes
    399 group = new SimpleGroup([
    400     new SimpleObject(oBushSmall, 0,2, 0,2),
    401     new SimpleObject(oBushSmallDry, 0,2, 0,2),
    402     new SimpleObject(oBushMed, 0,1, 0,2),
    403     new SimpleObject(oBushMedDry, 0,1, 0,2)]);
    404 createObjectGroups(group, 0,
    405     avoidClasses(clWater, 4, clCliff, 2),
    406     SIZE*SIZE/1800, 50
    407 );
    408 
    409 // create rocks
    410 group = new SimpleGroup([
    411     new SimpleObject(oRockSmall, 0,3, 0,2),
    412     new SimpleObject(oRockMed, 0,2, 0,2),
    413     new SimpleObject(oRockLarge, 0,1, 0,2)]);
    414 createObjectGroups(group, 0,
    415     avoidClasses(clWater, 0, clCliff, 0),
    416     SIZE*SIZE/1800, 50
    417 );
    418 
    419 // create stone
    420 group = new SimpleGroup([new SimpleObject(oStone, 2,3, 0,2)], true, clStone);
    421 createObjectGroups(group, 0,
    422     [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clStone, 15, clSettlement, 4),
    423      new BorderTileClassConstraint(clCliff, 0, 5)],
    424     3 * NUM_PLAYERS, 100
    425 );
    426 
    427 // create metal
    428 group = new SimpleGroup([new SimpleObject(oMetal, 2,3, 0,2)], true, clMetal);
    429 createObjectGroups(group, 0,
    430     [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clMetal, 15, clStone, 5, clSettlement, 4),
    431      new BorderTileClassConstraint(clCliff, 0, 5)],
    432     3 * NUM_PLAYERS, 100
    433 );
    434 
    435 // create sheep
    436 group = new SimpleGroup([new SimpleObject(oSheep, 2,4, 0,2)], true, clFood);
    437 createObjectGroups(group, 0,
    438     avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20,
    439         clMetal, 2, clStone, 2, clFood, 8, clSettlement, 4),
    440     3 * NUM_PLAYERS, 100
    441 );
    442 
    443 // create berry bushes
    444 group = new SimpleGroup([new SimpleObject(oBerryBush, 5,7, 0,3)], true, clFood);
    445 createObjectGroups(group, 0,
    446     avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20,
    447         clMetal, 2, clStone, 2, clFood, 8, clSettlement, 4),
    448     1.5 * NUM_PLAYERS, 100
    449 );
  • binaries/data/mods/public/maps/random/latium.js

     
     1const WATER_WIDTH = 0.2;
     2
     3// terrain textures
     4const tOceanDepths = "medit_sea_depths";
     5const tOceanRockDeep = "medit_sea_coral_deep";
     6const tOceanRockShallow = "medit_rocks_wet";
     7const tOceanCoral = "medit_sea_coral_plants";
     8const tBeachWet = "medit_sand_wet";
     9const tBeachDry = "medit_sand";
     10const tBeachGrass = "beach_medit_grass_50";
     11const tBeachCliff = "cliff_medit_beach";
     12const tGrassDry = ["medit_grass_field_brown", "medit_grass_field_dry", "medit_grass_field_b"];
     13const tGrass = ["medit_grass_field", "medit_grass_field_a", "medit_grass_flowers"];
     14const tGrassLush = ["grass_temperate_dry_tufts", "medit_grass_flowers"];
     15const tGrassShrubs = ["medit_grass_shrubs", "medit_grass_flowers"];
     16const tGrassRock = ["medit_rocks_grass"];
     17const tDirt = "medit_dirt";
     18const tDirtGrass = "medit_dirt_b";
     19const tDirtCliff = "medit_cliff_italia";
     20const tGrassCliff = "medit_cliff_italia_grass";
     21const tCliff = ["medit_cliff_italia", "medit_cliff_italia", "medit_cliff_italia_grass"];
     22const tForestFloor = "forestfloor_medit_dirt";
     23
     24// gaia entities
     25const oBeech = "gaia/flora_tree_euro_beech";
     26const oBerryBush = "gaia/flora_bush_berry";
     27const oCarob = "gaia/flora_tree_carob";
     28const oCypress1 = "gaia/flora_tree_cypress";
     29const oCypress2 = "gaia/flora_tree_cypress";
     30const oLombardyPoplar = "gaia/flora_tree_poplar_lombardy";
     31const oOak = "gaia/flora_tree_oak";
     32const oPalm = "gaia/flora_tree_medit_fan_palm";
     33const oPine = "gaia/flora_tree_aleppo_pine";
     34const oPoplar = "gaia/flora_tree_poplar";
     35const oSheep = "gaia/fauna_sheep";
     36const oStone = "gaia/geology_stone_greek";
     37const oMetal = "gaia/geology_metal_greek";
     38
     39// decorative props
     40const aBushLargeDry = "actor|props/flora/bush_medit_la_dry.xml";
     41const aBushLarge = "actor|props/flora/bush_medit_la.xml";
     42const aBushMedDry = "actor|props/flora/bush_medit_me_dry.xml";
     43const aBushMed = "actor|props/flora/bush_medit_me.xml";
     44const aBushSmall = "actor|props/flora/bush_medit_sm.xml";
     45const aBushSmallDry = "actor|props/flora/bush_medit_sm_dry.xml";
     46const aGrass = "actor|props/flora/grass_medit_field.xml";
     47const aGrassDry = "actor|props/flora/grass_soft_dry_small.xml";
     48const aRockLarge = "actor|geology/stone_granite_greek_large.xml";
     49const aRockMed = "actor|geology/stone_granite_greek_med.xml";
     50const aRockSmall = "actor|geology/stone_granite_greek_small.xml";
     51const aWaterLog = "actor|props/flora/water_log.xml";
     52
     53// forests - we have the option of specifying terrain and tree type in one string, using TERRAIN_SEPARATOR
     54var tPalmForest = [tForestFloor+TERRAIN_SEPARATOR+oPalm, tGrass];
     55var tPineForest = [tForestFloor+TERRAIN_SEPARATOR+oPine, tGrass];
     56var tMainForest = [tForestFloor+TERRAIN_SEPARATOR+oCarob, tForestFloor+TERRAIN_SEPARATOR+oBeech, tGrass, tGrass];
     57var tPoplarForest = [tForestFloor+TERRAIN_SEPARATOR+oLombardyPoplar, tGrass];
     58
     59// Initialize world
     60
     61log("Initializing map...");
     62
     63var numPlayers = getNumPlayers();
     64var mapSize = getMapSize();
     65
     66// Create classes
     67
     68var clWater = createTileClass();
     69var clCliff = createTileClass();
     70var clForest = createTileClass();
     71var clMetal = createTileClass();
     72var clStone = createTileClass();
     73var clFood = createTileClass();
     74var clPlayer = createTileClass();
     75var clBaseResource = createTileClass();
     76
     77// Place players
     78
     79log("Placing players...");
     80
     81var playerX = new Array(numPlayers+1);
     82var playerY = new Array(numPlayers+1);
     83
     84var numLeftPlayers = floor(numPlayers/2);
     85for (var i=1; i <= numLeftPlayers; i++)
     86{
     87    playerX[i] = 0.28 + (2*randFloat()-1)*0.01;
     88    playerY[i] = (0.5+i-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
     89}
     90for (var i=numLeftPlayers+1; i <= numPlayers; i++)
     91{
     92    playerX[i] = 0.72 + (2*randFloat()-1)*0.01;
     93    playerY[i] = (0.5+i-numLeftPlayers-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
     94}
     95
     96for (var i=1; i <= numPlayers; i++)
     97{
     98    log("Creating base for player " + i + "...");
     99   
     100    // get fractional locations in tiles
     101    var ix = round(fractionToTiles(playerX[i]));
     102    var iy = round(fractionToTiles(playerY[i]));
     103    addToClass(ix, iy, clPlayer);
     104   
     105    // create TC and starting units
     106    // TODO: Get civ specific starting units
     107    var civ = getCivCode(i - 1);
     108    placeObject("structures/"+civ + "_civil_centre", i, ix, iy, PI*3/4);
     109    var group = new SimpleGroup(
     110        [new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
     111        true, null, ix, iy
     112    );
     113    createObjectGroup(group, i);
     114   
     115    // create starting berry bushes
     116    var bbAngle = randFloat()*2*PI;
     117    var bbDist = 9;
     118    var bbX = round(ix + bbDist * cos(bbAngle));
     119    var bbY = round(iy + bbDist * sin(bbAngle));
     120    group = new SimpleGroup(
     121        [new SimpleObject(oBerryBush, 5,5, 0,2)],
     122        true, clBaseResource, bbX, bbY
     123    );
     124    createObjectGroup(group, 0);
     125   
     126    // create starting mines
     127    var mAngle = bbAngle;
     128    while(abs(mAngle - bbAngle) < PI/3) {
     129        mAngle = randFloat()*2*PI;
     130    }
     131    var mDist = 9;
     132    var mX = round(ix + mDist * cos(mAngle));
     133    var mY = round(iy + mDist * sin(mAngle));
     134    group = new SimpleGroup(
     135        [new SimpleObject(oStone, 2,2, 0,3),
     136        new SimpleObject(oMetal, 2,2, 0,3)],
     137        true, clBaseResource, mX, mY
     138    );
     139    createObjectGroup(group, 0);
     140   
     141    // create starting straggler trees
     142    group = new SimpleGroup(
     143        [new SimpleObject(oPalm, 3,3, 7,10)],
     144        true, clBaseResource, ix, iy
     145    );
     146    createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
     147}
     148
     149function distanceToPlayers(x, y)
     150{
     151    var r = 10000;
     152    for (var i=1; i <= numPlayers; i++)
     153    {
     154        var dx = x - playerX[i];
     155        var dy = y - playerY[i];
     156        r = min(r, dx*dx + dy*dy);
     157    }
     158    return sqrt(r);
     159}
     160
     161function playerNearness(x, y)
     162{
     163    var d = fractionToTiles(distanceToPlayers(x,y));
     164   
     165    if (d < 13)
     166        return 0;
     167    else if (d < 19)
     168        return (d-13)/(19-13);
     169    else
     170        return 1;
     171}
     172
     173// Paint elevation
     174
     175log("Painting elevation...");
     176
     177var noise0 = new Noise2D(4 * mapSize/128);
     178var noise1 = new Noise2D(8 * mapSize/128);
     179var noise2 = new Noise2D(15 * mapSize/128);
     180
     181var noise2a = new Noise2D(20 * mapSize/128);
     182var noise2b = new Noise2D(35 * mapSize/128);
     183
     184var noise3 = new Noise2D(4 * mapSize/128);
     185var noise4 = new Noise2D(6 * mapSize/128);
     186var noise5 = new Noise2D(11 * mapSize/128);
     187
     188for (var ix=0; ix<=mapSize; ix++)
     189{
     190    for (var iy=0; iy<=mapSize; iy++)
     191    {
     192        var x = ix / (mapSize + 1.0);
     193        var y = iy / (mapSize + 1.0);
     194        var pn = playerNearness(x, y);
     195       
     196        var h = 0;
     197        var distToWater = 0;
     198       
     199        h = 32 * (x - 0.5);
     200       
     201        // add the rough shape of the water
     202        if (x < WATER_WIDTH)
     203        {
     204            h = max(-16.0, -28.0*(WATER_WIDTH-x)/WATER_WIDTH);
     205        }
     206        else if (x > 1.0-WATER_WIDTH)
     207        {
     208            h = max(-16.0, -28.0*(x-(1.0-WATER_WIDTH))/WATER_WIDTH);
     209        }
     210        else
     211        {
     212            distToWater = (0.5 - WATER_WIDTH - abs(x-0.5));
     213            var u = 1 - abs(x-0.5) / (0.5-WATER_WIDTH);
     214            h = 12*u;
     215        }
     216       
     217        // add some base noise
     218        var baseNoise = 16*noise0.get(x,y) + 8*noise1.get(x,y) + 4*noise2.get(x,y) - (16+8+4)/2;
     219        if ( baseNoise < 0 )
     220        {
     221            baseNoise *= pn;
     222            baseNoise *= max(0.1, distToWater / (0.5-WATER_WIDTH));
     223        }
     224        var oldH = h;
     225        h += baseNoise;
     226       
     227        // add some higher-frequency noise on land
     228        if ( oldH > 0 )
     229        {
     230            h += (0.4*noise2a.get(x,y) + 0.2*noise2b.get(x,y)) * min(oldH/10.0, 1.0);
     231        }
     232       
     233        // create cliff noise
     234        if ( h > -10 )
     235        {
     236            var cliffNoise = (noise3.get(x,y) + 0.5*noise4.get(x,y)) / 1.5;
     237            if (h < 1)
     238            {
     239                var u = 1 - 0.3*((h-1)/-10);
     240                cliffNoise *= u;
     241            }
     242            cliffNoise += 0.05 * distToWater / (0.5 - WATER_WIDTH);
     243            if (cliffNoise > 0.6)
     244            {
     245                var u = 0.8 * (cliffNoise - 0.6);
     246                cliffNoise += u * noise5.get(x,y);
     247                cliffNoise /= (1 + u);
     248            }
     249            cliffNoise -= 0.59;
     250            cliffNoise *= pn;
     251            if (cliffNoise > 0)
     252            {
     253                h += 19 * min(cliffNoise, 0.045) / 0.045;
     254            }
     255        }
     256       
     257        // set the height
     258        setHeight(ix, iy, h);
     259    }
     260}
     261
     262// Paint base terrain
     263
     264log("Painting terrain...");
     265
     266var noise6 = new Noise2D(10 * mapSize/128);
     267var noise7 = new Noise2D(20 * mapSize/128);
     268
     269var noise8 = new Noise2D(13 * mapSize/128);
     270var noise9 = new Noise2D(26 * mapSize/128);
     271
     272var noise10 = new Noise2D(50 * mapSize/128);
     273
     274for (var ix=0; ix<mapSize; ix++)
     275{
     276    for (var iy=0; iy<mapSize; iy++)
     277    {
     278        var x = ix / (mapSize + 1.0);
     279        var y = iy / (mapSize + 1.0);
     280        var pn = playerNearness(x, y);
     281       
     282        // get heights of surrounding vertices
     283        var h00 = getHeight(ix, iy);
     284        var h01 = getHeight(ix, iy+1);
     285        var h10 = getHeight(ix+1, iy);
     286        var h11 = getHeight(ix+1, iy+1);
     287       
     288        // find min and max height
     289        var maxH = Math.max(h00, h01, h10, h11);
     290        var minH = Math.min(h00, h01, h10, h11);
     291       
     292        // figure out if we're at the top of a cliff using min adjacent height
     293        var minAdjHeight = minH;
     294        if (maxH > 15)
     295        {
     296            var maxNx = min(ix+2, mapSize);
     297            var maxNy = min(iy+2, mapSize);
     298            for (var nx=max(ix-1, 0); nx <= maxNx; nx++)
     299            {
     300                for (var ny=max(iy-1, 0); ny <= maxNy; ny++)
     301                {
     302                    minAdjHeight = min(minAdjHeight, getHeight(nx, ny));
     303                }
     304            }
     305        }
     306       
     307        // choose a terrain based on elevation
     308        var t = tGrass;
     309       
     310        // water
     311        if (maxH < -12)
     312        {
     313            t = tOceanDepths;
     314        }
     315        else if (maxH < -8.8)
     316        {
     317            t = tOceanRockDeep;
     318        }
     319        else if (maxH < -4.7)
     320        {
     321            t = tOceanCoral;
     322        }
     323        else if (maxH < -2.8)
     324        {
     325            t = tOceanRockShallow;
     326        }
     327        else if (maxH < 0.9 && minH < 0.35)
     328        {
     329            t = tBeachWet;
     330        }
     331        else if (maxH < 1.5 && minH < 0.9)
     332        {
     333            t = tBeachDry;
     334        }
     335        else if (maxH < 2.3 && minH < 1.3)
     336        {
     337            t = tBeachGrass;
     338        }
     339       
     340        if (minH < 0)
     341        {
     342            addToClass(ix, iy, clWater);
     343        }
     344       
     345        // cliffs
     346        if (maxH - minH > 2.9 && minH > -7)
     347        {
     348            t = tCliff;
     349            addToClass(ix, iy, clCliff);
     350        }
     351        else if ((maxH - minH > 2.5 && minH > -5) || (maxH-minAdjHeight > 2.9 && minH > 0) )
     352        {
     353            if (minH < -1)
     354                t = tCliff;
     355            else if (minH < 0.5)
     356                t = tBeachCliff;
     357            else
     358                t = [tDirtCliff, tGrassCliff, tGrassCliff, tGrassRock, tCliff];
     359           
     360            addToClass(ix, iy, clCliff);
     361        }
     362       
     363        // forests
     364        if (maxH - minH < 1 && minH > 1)
     365        {
     366            var forestNoise = (noise6.get(x,y) + 0.5*noise7.get(x,y)) / 1.5 * pn;
     367            forestNoise -= 0.59;
     368           
     369            if (forestNoise > 0)
     370            {
     371                if (minH > 5)
     372                {
     373                    var typeNoise = noise10.get(x,y);
     374                   
     375                    if (typeNoise < 0.43 && forestNoise < 0.05)
     376                        t = tPoplarForest;
     377                    else if (typeNoise < 0.63)
     378                        t = tMainForest;
     379                    else
     380                        t = tPineForest;
     381                   
     382                    addToClass(ix, iy, clForest);
     383                }
     384                else if (minH < 3)
     385                {
     386                    t = tPalmForest;
     387                    addToClass(ix, iy, clForest);
     388                }
     389            }
     390        }
     391       
     392        // grass variations
     393        if (t == tGrass)
     394        {
     395            var grassNoise = (noise8.get(x,y) + 0.6*noise9.get(x,y)) / 1.6;
     396            if (grassNoise < 0.3)
     397            {
     398                t = (maxH - minH > 1.2) ? tDirtCliff : tDirt;
     399            }
     400            else if (grassNoise < 0.34)
     401            {
     402                t = (maxH - minH > 1.2) ? tGrassCliff : tGrassDry;
     403                if (maxH - minH < 0.5 && randFloat() < 0.03)
     404                {
     405                    placeObject(aGrassDry, 0, ix+randFloat(), iy+randFloat(), randFloat()*2*PI);
     406                }
     407            }
     408            else if (grassNoise > 0.61)
     409            {
     410                t = ((maxH - minH) > 1.2 ? tGrassRock : tGrassShrubs);
     411            }
     412            else
     413            {
     414                if ((maxH - minH) < 0.5 && randFloat() < 0.05)
     415                {
     416                    placeObject(aGrass, 0, ix+randFloat(), iy+randFloat(), randFloat()*2*PI);
     417                }
     418            }
     419        }
     420       
     421        placeTerrain(ix, iy, t);
     422    }
     423}
     424
     425log("Placing straggler trees...");
     426// create straggler trees
     427var trees = [oCarob, oBeech, oLombardyPoplar, oLombardyPoplar, oPine];
     428for (var t in trees)
     429{
     430    group = new SimpleGroup([new SimpleObject(trees[t], 1,1, 0,1)], true, clForest);
     431    createObjectGroups(group, 0,
     432        avoidClasses(clWater, 5, clCliff, 0, clForest, 1, clPlayer, 15),
     433        mapSize*mapSize/7000, 50
     434    );
     435}
     436
     437log("Placing cypress trees...");
     438// create cypresses
     439group = new SimpleGroup(
     440    [new SimpleObject(oCypress2, 1,3, 0,3),
     441    new SimpleObject(oCypress1, 0,2, 0,2)]
     442);
     443createObjectGroups(group, 0,
     444    avoidClasses(clWater, 4, clCliff, 2, clForest, 1, clPlayer, 15),
     445    mapSize*mapSize/3500, 50
     446);
     447
     448log("Placing bushes...");
     449// create bushes
     450group = new SimpleGroup(
     451    [new SimpleObject(aBushSmall, 0,2, 0,2), new SimpleObject(aBushSmallDry, 0,2, 0,2),
     452    new SimpleObject(aBushMed, 0,1, 0,2), new SimpleObject(aBushMedDry, 0,1, 0,2)]
     453);
     454createObjectGroups(group, 0,
     455    avoidClasses(clWater, 4, clCliff, 2),
     456    mapSize*mapSize/1800, 50
     457);
     458
     459log("Placing rocks...");
     460// create rocks
     461group = new SimpleGroup(
     462    [new SimpleObject(aRockSmall, 0,3, 0,2), new SimpleObject(aRockMed, 0,2, 0,2),
     463    new SimpleObject(aRockLarge, 0,1, 0,2)]
     464);
     465createObjectGroups(group, 0,
     466    avoidClasses(clWater, 0, clCliff, 0),
     467    mapSize*mapSize/1800, 50
     468);
     469
     470log("Placing stone mines...");
     471// create stone
     472group = new SimpleGroup([new SimpleObject(oStone, 2,3, 0,2)], true, clStone);
     473createObjectGroups(group, 0,
     474    [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clStone, 15),
     475     new BorderTileClassConstraint(clCliff, 0, 5)],
     476    3 * numPlayers, 100
     477);
     478
     479log("Placing metal mines...");
     480// create metal
     481group = new SimpleGroup([new SimpleObject(oMetal, 2,3, 0,2)], true, clMetal);
     482createObjectGroups(group, 0,
     483    [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clMetal, 15, clStone, 5),
     484     new BorderTileClassConstraint(clCliff, 0, 5)],
     485    3 * numPlayers, 100
     486);
     487
     488log("Placing sheep...");
     489// create sheep
     490group = new SimpleGroup([new SimpleObject(oSheep, 2,4, 0,2)], true, clFood);
     491createObjectGroups(group, 0,
     492    avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20, clMetal, 2, clStone, 2, clFood, 8),
     493    3 * numPlayers, 100
     494);
     495
     496log("Placing berry bushes...");
     497// create berry bushes
     498group = new SimpleGroup([new SimpleObject(oBerryBush, 5,7, 0,3)], true, clFood);
     499createObjectGroups(group, 0,
     500    avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20, clMetal, 2, clStone, 2, clFood, 8),
     501    1.5 * numPlayers, 100
     502);
  • binaries/data/mods/public/maps/random/latium.json

    Property changes on: binaries\data\mods\public\maps\random\latium.js
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1{
     2    "settings" : {
     3        "Name" : "Latium",
     4        "Script" : "latium.js",
     5        "Description" : "A test of the Latium script",
     6        "BaseTerrain" : ["medit_grass_field", "medit_grass_field_a", "medit_grass_flowers"],
     7        "BaseHeight" : 0,
     8        "RevealMap": true,
     9        "GameType": "endless",
     10        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
     11    }
     12}
     13 No newline at end of file
  • binaries/data/mods/public/maps/random/neareastern_badlands.js

    Property changes on: binaries\data\mods\public\maps\random\latium.json
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    1 // constants
    2 
    3 const SIZE = 208;
    4 const NUM_PLAYERS = 4;
    5 
    6 const tSand = "desert_rough";
    7 const tDunes = "desert_wave";
    8 const tFineSand = "desert_sahara";
    9 const tCliff = "cliff_desert";
    10 const tForest = "grass_sand_75|flora/trees/palm_b.xml";
    11 const tGrassSand75 = "grass_sand_75";
    12 const tGrassSand50 = "grass_sand_50";
    13 const tGrassSand25 = "grass_sand_25_2";
    14 const tDirt = "dirt_hard";
    15 const tDirtCracks = "dirt_cracks";
    16 const tShore = "sand";
    17 const tWater = "water_2";
    18 const tWaterDeep = "water_3";
    19 
    20 const oTree = "flora/trees/palm_b.xml";
    21 const oBerryBush = "flora_bush_berry";
    22 const oBush = "props/flora/bush_dry_a.xml";
    23 const oSheep = "fauna_sheep";
    24 const oDeer = "fauna_deer";
    25 const oMine = "geology_stone_light";
    26 const oDecorativeRock = "geology/gray1.xml";
    27 
    28 // some utility functions to save typing
    29 
    30 function paintClass(cl) {
    31     return new TileClassPainter(cl);
    32 }
    33 
    34 function avoidClasses(/*class1, dist1, class2, dist2, etc*/) {
    35     var ar = new Array(arguments.length/2);
    36     for(var i=0; i<arguments.length/2; i++) {
    37         ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
    38     }
    39     return ar;
    40 }
    41 
    42 // initialize map
    43 
    44 println("Initializing map...");
    45 init(SIZE, tSand, 10);
    46 
    47 // create tile classes
    48 
    49 clPlayer = createTileClass();
    50 clHill1 = createTileClass();
    51 clHill2 = createTileClass();
    52 clHill3 = createTileClass();
    53 clForest = createTileClass();
    54 clWater = createTileClass();
    55 clPatch = createTileClass();
    56 clRock = createTileClass();
    57 clFood = createTileClass();
    58 clBaseResource = createTileClass();
    59 
    60 // place players
    61 
    62 playerX = new Array(NUM_PLAYERS);
    63 playerY = new Array(NUM_PLAYERS);
    64 playerAngle = new Array(NUM_PLAYERS);
    65 
    66 startAngle = randFloat() * 2 * PI;
    67 for(i=0; i<NUM_PLAYERS; i++) {
    68     playerAngle[i] = startAngle + i*2*PI/NUM_PLAYERS;
    69     playerX[i] = 0.5 + 0.39*cos(playerAngle[i]);
    70     playerY[i] = 0.5 + 0.39*sin(playerAngle[i]);
    71 }
    72 
    73 for(i=0; i<NUM_PLAYERS; i++) {
    74     println("Creating base for player " + i + "...");
    75    
    76     // some constants
    77     radius = 20;
    78     cliffRadius = 2;
    79     elevation = 30;
    80    
    81     // get the x and y in tiles
    82     fx = fractionToTiles(playerX[i]);
    83     fy = fractionToTiles(playerY[i]);
    84     ix = round(fx);
    85     iy = round(fy);
    86 
    87     // calculate size based on the radius
    88     size = PI * radius * radius;
    89    
    90     // create the hill
    91     placer = new ClumpPlacer(size, 0.9, 0.5, 0, ix, iy);
    92     createArea(placer, paintClass(clPlayer), null);
    93    
    94     // create the central road patch
    95     placer = new ClumpPlacer(PI*2*2, 0.6, 0.3, 0.5, ix, iy);
    96     painter = new TerrainPainter(tDirt);
    97     createArea(placer, painter, null);
    98    
    99     // create the TC and the villies
    100     group = new SimpleGroup(
    101         [                           // elements (type, count, distance)
    102             new SimpleObject("hele_civil_centre", 1,1, 0,0),
    103             new SimpleObject("hele_infantry_spearman_b", 3,3, 5,5)
    104         ],
    105         true, null, ix, iy
    106     );
    107     createObjectGroup(group, i);
    108    
    109     // create berry bushes
    110     bbAngle = randFloat()*2*PI;
    111     bbDist = 10;
    112     bbX = round(fx + bbDist * cos(bbAngle));
    113     bbY = round(fy + bbDist * sin(bbAngle));
    114     group = new SimpleGroup(
    115         [new SimpleObject(oSheep, 5,5, 0,2)],
    116         true, clBaseResource,   bbX, bbY
    117     );
    118     createObjectGroup(group, 0);
    119    
    120     // create mines
    121     mAngle = bbAngle;
    122     while(abs(mAngle - bbAngle) < PI/3) {
    123         mAngle = randFloat()*2*PI;
    124     }
    125     mDist = 12;
    126     mX = round(fx + mDist * cos(mAngle));
    127     mY = round(fy + mDist * sin(mAngle));
    128     group = new SimpleGroup(
    129         [new SimpleObject(oMine, 3,3, 0,2)],
    130         true, clBaseResource,   mX, mY
    131     );
    132     createObjectGroup(group, 0);
    133    
    134     // create starting straggler trees
    135     group = new SimpleGroup(
    136         [new SimpleObject(oTree, 2,2, 6,12)],
    137         true, null, ix, iy
    138     );
    139     createObjectGroup(group, 0, avoidClasses(clBaseResource,1));
    140 }
    141 
    142 // create patches
    143 println("Creating sand patches...");
    144 placer = new ClumpPlacer(30, 0.2, 0.1, 0);
    145 painter = new LayeredPainter([1], [[tSand, tFineSand], tFineSand]);
    146 createAreas(placer, [painter, paintClass(clPatch)],
    147     avoidClasses(clPatch, 5),
    148     (SIZE*SIZE)/600
    149 );
    150 
    151 println("Creating dirt patches...");
    152 placer = new ClumpPlacer(10, 0.2, 0.1, 0);
    153 painter = new TerrainPainter([tSand, tDirt]);
    154 createAreas(placer, [painter, paintClass(clPatch)],
    155     avoidClasses(clPatch, 5),
    156     (SIZE*SIZE)/600
    157 );
    158 
    159 // create the oasis
    160 println("Creating water...");
    161 placer = new ClumpPlacer(1200, 0.6, 0.1, 0, SIZE/2, SIZE/2);
    162 painter = new LayeredPainter([6,1], [[tSand, tForest], tShore, tWaterDeep]);
    163 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, -10, 5);
    164 createArea(placer, [painter, elevationPainter, paintClass(clForest)], null);
    165 
    166 // create hills
    167 println("Creating level 1 hills...");
    168 placer = new ClumpPlacer(150, 0.25, 0.1, 0.3);
    169 terrainPainter = new LayeredPainter(
    170     [1],                // widths
    171     [tCliff, tSand]     // terrains
    172 );
    173 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
    174 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
    175     avoidClasses(clForest, 2, clPlayer, 0, clHill1, 16),
    176     (SIZE*SIZE)/3800, 100
    177 );
    178 
    179 println("Creating small level 1 hills...");
    180 placer = new ClumpPlacer(60, 0.25, 0.1, 0.3);
    181 terrainPainter = new LayeredPainter(
    182     [1],                // widths
    183     [tCliff, tSand]     // terrains
    184 );
    185 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
    186 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
    187     avoidClasses(clForest, 2, clPlayer, 0, clHill1, 3),
    188     (SIZE*SIZE)/2800, 100
    189 );
    190 
    191 println("Creating level 2 hills...");
    192 placer = new ClumpPlacer(60, 0.2, 0.1, 0.9);
    193 terrainPainter = new LayeredPainter(
    194     [1],                // widths
    195     [tCliff, tSand]     // terrains
    196 );
    197 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
    198 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill2)],
    199     [avoidClasses(clHill2, 1), new StayInTileClassConstraint(clHill1, 0)],
    200     (SIZE*SIZE)/2800, 200
    201 );
    202 
    203 println("Creating level 3 hills...");
    204 placer = new ClumpPlacer(25, 0.2, 0.1, 0.9);
    205 terrainPainter = new LayeredPainter(
    206     [1],                // widths
    207     [tCliff, tSand]     // terrains
    208 );
    209 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
    210 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill3)],
    211     [avoidClasses(clHill3, 1), new StayInTileClassConstraint(clHill2, 0)],
    212     (SIZE*SIZE)/9000, 300
    213 );
    214 
    215 // create forests
    216 println("Creating forests...");
    217 placer = new ClumpPlacer(25, 0.15, 0.1, 0.3);
    218 painter = new TerrainPainter([tSand, tForest]);
    219 createAreas(placer, [painter, paintClass(clForest)],
    220     avoidClasses(clWater, 0, clPlayer, 1, clForest, 20, clHill1, 0),
    221     (SIZE*SIZE)/4000, 50
    222 );
    223 
    224 // create mines
    225 println("Creating mines...");
    226 group = new SimpleGroup([new SimpleObject(oMine, 4,6, 0,2)], true, clRock);
    227 createObjectGroups(group, 0,
    228     [avoidClasses(clWater, 2, clForest, 2, clPlayer, 0, clRock, 13),
    229      new BorderTileClassConstraint(clHill1, 0, 4)],
    230     (SIZE*SIZE)/4000, 100
    231 );
    232 
    233 // create decorative rocks for hills
    234 println("Creating decorative rocks...");
    235 group = new SimpleGroup([new SimpleObject(oDecorativeRock, 1,1, 0,0)], true);
    236 createObjectGroups(group, 0,
    237     new BorderTileClassConstraint(clHill1, 0, 3),
    238     (SIZE*SIZE)/2000, 100
    239 );
    240 
    241 // create deer
    242 println("Creating deer...");
    243 group = new SimpleGroup([new SimpleObject(oDeer, 5,7, 0,4)], true, clFood);
    244 createObjectGroups(group, 0,
    245     avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill1, 0, clFood, 25),
    246     (SIZE*SIZE)/5000, 50
    247 );
    248 
    249 // create sheep
    250 println("Creating sheep...");
    251 group = new SimpleGroup([new SimpleObject(oSheep, 1,3, 0,2)], true, clFood);
    252 createObjectGroups(group, 0,
    253     avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill1, 0, clFood, 15),
    254     (SIZE*SIZE)/5000, 50
    255 );
    256 
    257 // create straggler trees
    258 println("Creating straggler trees...");
    259 group = new SimpleGroup([new SimpleObject(oTree, 1,1, 0,0)], true);
    260 createObjectGroups(group, 0,
    261     avoidClasses(clWater, 0, clForest, 0, clHill1, 0, clPlayer, 0),
    262     SIZE*SIZE/1500
    263 );
    264 
    265 
    266 // create bushes
    267 println("Creating bushes...");
    268 group = new SimpleGroup([new SimpleObject(oBush, 2,3, 0,2)]);
    269 createObjectGroups(group, 0,
    270     avoidClasses(clWater, 3, clHill1, 0, clPlayer, 0, clForest, 0),
    271     SIZE*SIZE/1000
    272 );
    273 
    274 // create bushes
    275 println("Creating more decorative rocks...");
    276 group = new SimpleGroup([new SimpleObject(oDecorativeRock, 1,2, 0,2)]);
    277 createObjectGroups(group, 0,
    278     avoidClasses(clWater, 3, clHill1, 0, clPlayer, 0, clForest, 0),
    279     SIZE*SIZE/1000
    280 );
    281  No newline at end of file
  • binaries/data/mods/public/maps/random/neareastern_badlands.js

     
     1
     2// terrain textures
     3const tSand = "desert_dirt_rough";
     4const tDunes = "desert_sand_dunes_100";
     5const tFineSand = "desert_sand_smooth";
     6const tCliff = "desert_cliff_badlands";
     7const tGrassSand75 = "desert_grass_a";
     8const tGrassSand50 = "desert_grass_a_sand";
     9const tGrassSand25 = "desert_grass_a_stones";
     10const tDirt = "desert_dirt_rough";
     11const tDirtCracks = "desert_dirt_cracks";
     12const tShore = "desert_sand_wet";
     13const tWater = "desert_shore_stones";
     14const tWaterDeep = "desert_shore_stones_wet";
     15
     16// gaia entities
     17const oBerryBush = "gaia/flora_bush_berry";
     18const oSheep = "gaia/fauna_sheep";
     19const oDeer = "gaia/fauna_deer";
     20const oMine = "gaia/geology_stone_desert_small";
     21const oTree = "gaia/flora_tree_medit_fan_palm";
     22
     23// decorative props
     24const aBush = "actor|props/flora/bush_dry_a.xml";
     25const aDecorativeRock = "actor|geology/gray1.xml";
     26
     27var tForest = tGrassSand75 + TERRAIN_SEPARATOR + oTree;
     28
     29// initialize map
     30
     31log("Initializing map...");
     32
     33var numPlayers = getNumPlayers();
     34var mapSize = getMapSize();
     35
     36// create tile classes
     37
     38var clPlayer = createTileClass();
     39var clHill1 = createTileClass();
     40var clHill2 = createTileClass();
     41var clHill3 = createTileClass();
     42var clForest = createTileClass();
     43var clWater = createTileClass();
     44var clPatch = createTileClass();
     45var clRock = createTileClass();
     46var clFood = createTileClass();
     47var clBaseResource = createTileClass();
     48
     49// place players
     50
     51var playerX = new Array(numPlayers);
     52var playerY = new Array(numPlayers);
     53var playerAngle = new Array(numPlayers);
     54
     55var startAngle = randFloat() * 2 * PI;
     56for (var i=0; i < numPlayers; i++)
     57{
     58    playerAngle[i] = startAngle + i*2*PI/numPlayers;
     59    playerX[i] = 0.5 + 0.39*cos(playerAngle[i]);
     60    playerY[i] = 0.5 + 0.39*sin(playerAngle[i]);
     61}
     62
     63for (var i=0; i < numPlayers; i++)
     64{
     65    log("Creating base for player " + (i + 1) + "...");
     66   
     67    // some constants
     68    var radius = 20;
     69   
     70    // get the x and y in tiles
     71    var fx = fractionToTiles(playerX[i]);
     72    var fy = fractionToTiles(playerY[i]);
     73    var ix = round(fx);
     74    var iy = round(fy);
     75
     76    // calculate size based on the radius
     77    var size = PI * radius * radius;
     78   
     79    // create the hill
     80    log("Creating hill for player " + (i + 1) + "...");
     81    var placer = new ClumpPlacer(size, 0.9, 0.5, 0, ix, iy);
     82    createArea(placer, paintClass(clPlayer), null);
     83   
     84    // create the central road patch
     85    log("Creating central road for player " + (i + 1) + "...");
     86    placer = new ClumpPlacer(PI*2*2, 0.6, 0.3, 0.5, ix, iy);
     87    var painter = new TerrainPainter(tDirt);
     88    createArea(placer, painter, null);
     89   
     90    // create the TC and citizens
     91    log("Creating TC/citizens for player " + (i + 1) + "...");
     92    var civ = getCivCode(i);
     93    var group = new SimpleGroup(
     94        [                           // elements (type, count, distance)
     95            new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0),
     96            new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)
     97        ],
     98        true, null, ix, iy
     99    );
     100    createObjectGroup(group, i+1);
     101   
     102    // create berry bushes
     103    log("Creating berry bushes for player " + (i + 1) + "...");
     104    var bbAngle = randFloat()*2*PI;
     105    var bbDist = 10;
     106    var bbX = round(fx + bbDist * cos(bbAngle));
     107    var bbY = round(fy + bbDist * sin(bbAngle));
     108    group = new SimpleGroup(
     109        [new SimpleObject(oSheep, 5,5, 0,2)],
     110        true, clBaseResource,   bbX, bbY
     111    );
     112    createObjectGroup(group, 0);
     113   
     114    // create mines
     115    log("Creating mines for player " + (i + 1) + "...");
     116    var mAngle = bbAngle;
     117    while(abs(mAngle - bbAngle) < PI/3) {
     118        mAngle = randFloat()*2*PI;
     119    }
     120    var mDist = 12;
     121    var mX = round(fx + mDist * cos(mAngle));
     122    var mY = round(fy + mDist * sin(mAngle));
     123    group = new SimpleGroup(
     124        [new SimpleObject(oMine, 3,3, 0,2)],
     125        true, clBaseResource,   mX, mY
     126    );
     127    createObjectGroup(group, 0);
     128   
     129    // create starting straggler trees
     130    log("Creating trees for player " + (i + 1) + "...");
     131    group = new SimpleGroup(
     132        [new SimpleObject(oTree, 2,2, 6,12)],
     133        true, null, ix, iy
     134    );
     135    createObjectGroup(group, 0, avoidClasses(clBaseResource,1));
     136}
     137
     138// create patches
     139log("Creating sand patches...");
     140var placer = new ClumpPlacer(30, 0.2, 0.1, 0);
     141var painter = new LayeredPainter([[tSand, tFineSand], tFineSand], [1]);
     142createAreas(placer, [painter, paintClass(clPatch)],
     143    avoidClasses(clPatch, 5),
     144    (mapSize*mapSize)/600
     145);
     146
     147log("Creating dirt patches...");
     148placer = new ClumpPlacer(10, 0.2, 0.1, 0);
     149painter = new TerrainPainter([tSand, tDirt]);
     150createAreas(placer, [painter, paintClass(clPatch)],
     151    avoidClasses(clPatch, 5),
     152    (mapSize*mapSize)/600
     153);
     154
     155// create the oasis
     156log("Creating water...");
     157placer = new ClumpPlacer(1200, 0.6, 0.1, 0, mapSize/2, mapSize/2);
     158painter = new LayeredPainter([[tSand, tForest], tShore, tWaterDeep], [6,1]);
     159elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, -10, 5);
     160createArea(placer, [painter, elevationPainter, paintClass(clForest)], null);
     161
     162// create hills
     163log("Creating level 1 hills...");
     164placer = new ClumpPlacer(150, 0.25, 0.1, 0.3);
     165var terrainPainter = new LayeredPainter(
     166    [tCliff, tSand],        // terrains
     167    [1]             // widths
     168);
     169var elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
     170createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
     171    avoidClasses(clForest, 2, clPlayer, 0, clHill1, 16),
     172    (mapSize*mapSize)/3800, 100
     173);
     174
     175log("Creating small level 1 hills...");
     176placer = new ClumpPlacer(60, 0.25, 0.1, 0.3);
     177terrainPainter = new LayeredPainter(
     178    [tCliff, tSand],        // terrains
     179    [1]             // widths
     180);
     181elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
     182createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill1)],
     183    avoidClasses(clForest, 2, clPlayer, 0, clHill1, 3),
     184    (mapSize*mapSize)/2800, 100
     185);
     186
     187log("Creating level 2 hills...");
     188placer = new ClumpPlacer(60, 0.2, 0.1, 0.9);
     189terrainPainter = new LayeredPainter(
     190    [tCliff, tSand],        // terrains
     191    [1]             // widths
     192);
     193elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
     194createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill2)],
     195    [avoidClasses(clHill2, 1), new StayInTileClassConstraint(clHill1, 0)],
     196    (mapSize*mapSize)/2800, 200
     197);
     198
     199log("Creating level 3 hills...");
     200placer = new ClumpPlacer(25, 0.2, 0.1, 0.9);
     201terrainPainter = new LayeredPainter(
     202    [tCliff, tSand],        // terrains
     203    [1]             // widths
     204);
     205elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 16, 1);
     206createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill3)],
     207    [avoidClasses(clHill3, 1), new StayInTileClassConstraint(clHill2, 0)],
     208    (mapSize*mapSize)/9000, 300
     209);
     210
     211// create forests
     212log("Creating forests...");
     213placer = new ClumpPlacer(25, 0.15, 0.1, 0.3);
     214painter = new TerrainPainter([tSand, tForest]);
     215createAreas(placer, [painter, paintClass(clForest)],
     216    avoidClasses(clWater, 0, clPlayer, 1, clForest, 20, clHill1, 0),
     217    (mapSize*mapSize)/4000, 50
     218);
     219
     220// create mines
     221log("Creating mines...");
     222group = new SimpleGroup([new SimpleObject(oMine, 4,6, 0,2)], true, clRock);
     223createObjectGroups(group, 0,
     224    [avoidClasses(clWater, 2, clForest, 2, clPlayer, 0, clRock, 13),
     225     new BorderTileClassConstraint(clHill1, 0, 4)],
     226    (mapSize*mapSize)/4000, 100
     227);
     228
     229// create decorative rocks for hills
     230log("Creating decorative rocks...");
     231group = new SimpleGroup([new SimpleObject(aDecorativeRock, 1,1, 0,0)], true);
     232createObjectGroups(group, undefined,
     233    new BorderTileClassConstraint(clHill1, 0, 3),
     234    (mapSize*mapSize)/2000, 100
     235);
     236
     237// create deer
     238log("Creating deer...");
     239group = new SimpleGroup([new SimpleObject(oDeer, 5,7, 0,4)], true, clFood);
     240createObjectGroups(group, 0,
     241    avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill1, 0, clFood, 25),
     242    (mapSize*mapSize)/5000, 50
     243);
     244
     245// create sheep
     246log("Creating sheep...");
     247group = new SimpleGroup([new SimpleObject(oSheep, 1,3, 0,2)], true, clFood);
     248createObjectGroups(group, 0,
     249    avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill1, 0, clFood, 15),
     250    (mapSize*mapSize)/5000, 50
     251);
     252
     253// create straggler trees
     254log("Creating straggler trees...");
     255group = new SimpleGroup([new SimpleObject(oTree, 1,1, 0,0)], true);
     256createObjectGroups(group, 0,
     257    avoidClasses(clWater, 0, clForest, 0, clHill1, 0, clPlayer, 0),
     258    mapSize*mapSize/1500
     259);
     260
     261
     262// create bushes
     263log("Creating bushes...");
     264group = new SimpleGroup([new SimpleObject(aBush, 2,3, 0,2)]);
     265createObjectGroups(group, undefined,
     266    avoidClasses(clWater, 3, clHill1, 0, clPlayer, 0, clForest, 0),
     267    mapSize*mapSize/1000
     268);
     269
     270// create bushes
     271log("Creating more decorative rocks...");
     272group = new SimpleGroup([new SimpleObject(aDecorativeRock, 1,2, 0,2)]);
     273createObjectGroups(group, undefined,
     274    avoidClasses(clWater, 3, clHill1, 0, clPlayer, 0, clForest, 0),
     275    mapSize*mapSize/1000
     276);
     277 No newline at end of file
  • binaries/data/mods/public/maps/random/neareastern_badlands.json

    Property changes on: binaries\data\mods\public\maps\random\neareastern_badlands.js
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1{
     2    "settings" : {
     3        "Name" : "Neareastern Badlands",
     4        "Script" : "neareastern_badlands.js",
     5        "Description" : "A test of the Neareastern Badlands script",
     6        "BaseTerrain" : "desert_rough",
     7        "BaseHeight" : 10,
     8        "RevealMap": true,
     9        "GameType": "endless",
     10        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
     11    }
     12}
     13 No newline at end of file
  • binaries/data/mods/public/maps/random/new_rms_test.js

    Property changes on: binaries\data\mods\public\maps\random\neareastern_badlands.json
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1// New format RMS test
     2
     3
  • binaries/data/mods/public/maps/random/new_rms_test.json

    Property changes on: binaries\data\mods\public\maps\random\new_rms_test.js
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1{
     2    "settings" : {
     3        "Name" : "New RMS Test",
     4        "Script" : "new_rms_test.js",
     5        "Description" : "A test of the new integrated random map generator!",
     6        "BaseTerrain" : "grass1_spring",
     7        "BaseHeight" : 0,
     8        "RevealMap": true,
     9        "GameType": "endless",
     10        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
     11    }
     12}
     13 No newline at end of file
  • source/graphics/Entity.h

    Property changes on: binaries\data\mods\public\maps\random\new_rms_test.json
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1/* Copyright (C) 2010 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef INCLUDED_ENTITY
     19#define INCLUDED_ENTITY
     20
     21// Struct for parsing random map data
     22struct Entity
     23{
     24    std::wstring templateName;
     25    u16 entityID;
     26    u16 playerID;
     27    float positionX;
     28    float positionZ;
     29    float orientationY;
     30    bool isActor;
     31};
     32
     33
     34#endif
     35 No newline at end of file
  • source/graphics/MapGenerator.cpp

    Property changes on: source\graphics\Entity.h
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1/* Copyright (C) 2010 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#include "precompiled.h"
     19
     20#include "MapGenerator.h"
     21
     22#include "lib/timer.h"
     23#include "ps/CLogger.h"
     24
     25#define LOG_CATEGORY L"graphics"
     26
     27namespace MapGenRNG
     28{
     29    boost::mt19937 g_RNG;
     30
     31    static JSFunctionSpec global_functions[] = {
     32        JS_FS("seedRand",   SeedRand,   1, 0),
     33        JS_FS("randInt",  RandInt,  1, 0),
     34        JS_FS("randFloat", RandFloat, 0, 0),
     35        JS_FS_END
     36    };
     37}//namespace MapGenRNG
     38
     39
     40CMapGenerator::CMapGenerator() : m_ScriptInterface("Generator")
     41{
     42    // Register global functions
     43    JSObject* globalObj = JSVAL_TO_OBJECT(m_ScriptInterface.GetGlobalObject());
     44    if (!JS_DefineFunctions(m_ScriptInterface.GetContext(), globalObj, MapGenRNG::global_functions))
     45    {
     46        LOGERROR(L"GenerateMap: Error defining global functions");
     47    }
     48   
     49    // load mapgen libraries
     50    LoadLibraries();
     51}
     52
     53CScriptValRooted CMapGenerator::GenerateMap(const CStrW& scriptFile, const CScriptValRooted& settings)
     54{
     55    TIMER(L"GenerateMap");
     56
     57    // Init map generator
     58    jsval global = m_ScriptInterface.GetGlobalObject();
     59
     60    if (!m_ScriptInterface.CallFunctionVoid(global, "InitMapGen", settings))
     61    {
     62        LOGERROR(L"GenerateMap: Error calling 'InitMapGen' library function");
     63        return CScriptValRooted();
     64    }
     65
     66    // Load RMS
     67    // Check for blank file, this allows creating blank terrains
     68    if (scriptFile.length())
     69    {
     70        LoadScript(scriptFile);
     71    }
     72
     73    // Run save function
     74    CScriptValRooted ret;
     75    if (!m_ScriptInterface.CallFunction(global, "SaveMap", ret))
     76    {   
     77        LOGERROR(L"GenerateMap: Error calling 'SaveMap' library function");
     78        return CScriptValRooted();
     79    }
     80
     81    return ret;
     82}
     83
     84void CMapGenerator::LoadLibraries()
     85{
     86    VfsPaths pathnames;
     87
     88    // Load all scripts in mapgen directory
     89    if (fs_util::GetPathnames(g_VFS, VfsPath(L"maps/mapgen/"), L"*.js", pathnames) < 0)
     90        LOGERROR(L"Error reading scripts in directory: maps/mapgen/");
     91
     92    for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
     93    {
     94        LoadScript(it->string());
     95    }
     96}
     97
     98CScriptValRooted CMapGenerator::LoadScript(const std::wstring& filename)
     99{
     100    LOGMESSAGE(L"Loading map generator script '%ls'", filename.c_str());
     101
     102    VfsPath path(filename);
     103
     104    if (!FileExists(g_VFS, path))
     105    {
     106        LOGERROR(L"Script file '%ls' does not exist", filename.c_str());
     107        return CScriptValRooted();
     108    }
     109
     110    CVFSFile file;
     111
     112    PSRETURN ret = file.Load(g_VFS, path);
     113
     114    if (ret != PSRETURN_OK)
     115    {
     116        LOGERROR(L"Failed to load script '%ls': %hs", filename.c_str(), GetErrorString(ret));
     117        return CScriptValRooted();
     118    }
     119
     120    CScriptValRooted retVal;
     121    if (!m_ScriptInterface.Eval(file.GetAsString().c_str(), retVal))
     122    {
     123        LOGERROR(L"Failed to eval script '%ls'", filename.c_str());
     124        return CScriptValRooted();
     125    }
     126
     127    return retVal;
     128}
     129
     130ScriptInterface& CMapGenerator::GetScriptInterface()
     131{
     132    return m_ScriptInterface;
     133}
     134
     135//////////////////////////////////////////////////////////////////////////////
     136
     137JSBool MapGenRNG::SeedRand(JSContext *cx, uintN argc, jsval *vp)
     138{
     139    uint32 seed = 0;
     140
     141    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/u", &seed))
     142    {
     143        JS_ReportError(cx, "seedRand() cannot convert argument to integer");
     144        return JS_FALSE;
     145    }
     146
     147    g_RNG.seed(seed);
     148
     149    JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
     150    return JS_TRUE;
     151}
     152
     153JSBool MapGenRNG::RandInt(JSContext *cx, uintN argc, jsval *vp)
     154{
     155    int32 min, max, result;
     156
     157    if (argc == 1)
     158    {
     159        if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/i", &max))
     160        {
     161            JS_ReportError(cx, "randInt() cannot convert argument to integer");
     162            return JS_FALSE;
     163        }
     164
     165        result = randInt(max);
     166    }
     167    else if (argc == 2)
     168    {
     169        if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/i/i", &min, &max))
     170        {
     171            JS_ReportError(cx, "randInt() cannot convert arguments to integers");
     172            return JS_FALSE;
     173        }
     174
     175        result = min + randInt(max - min + 1);
     176    }
     177    else
     178    {
     179        JS_ReportError(cx, "randInt() received invalid number of arguments: %u", argc);
     180        return JS_FALSE;
     181    }
     182
     183    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(result));
     184    return JS_TRUE;
     185}
     186
     187JSBool MapGenRNG::RandFloat(JSContext *cx, uintN argc, jsval *vp)
     188{
     189    float min, max, result;
     190
     191    if (argc == 0)
     192    {
     193        result = randFloat();
     194    }
     195    else if (argc == 2)
     196    {
     197        if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/d/d", &min, &max))
     198        {
     199            JS_ReportError(cx, "randFloat() cannot convert arguments to doubles");
     200            return JS_FALSE;
     201        }
     202
     203        result = min + randFloat() * (max - min);
     204    }
     205    else
     206    {
     207        JS_ReportError(cx, "randFloat() received invalid number of arguments: %u", argc);
     208        return JS_FALSE;
     209    }
     210
     211    JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(result));
     212    return JS_TRUE;
     213}
     214
     215int32 MapGenRNG::randInt(int32 max)
     216{
     217    return g_RNG() % max;
     218}
     219
     220float MapGenRNG::randFloat()
     221{
     222    return float(g_RNG()) * (1.0f/4294967296.0f);
     223}
  • source/graphics/MapGenerator.h

    Property changes on: source\graphics\MapGenerator.cpp
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1/* Copyright (C) 2010 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef INCLUDED_MAPGENERATOR
     19#define INCLUDED_MAPGENERATOR
     20
     21#include "lib/res/handle.h"
     22#include "ps/CStr.h"
     23#include "ps/FileIo.h"
     24#include "scriptinterface/ScriptInterface.h"
     25#include "js/jsapi.h"
     26
     27#include <boost/random/mersenne_twister.hpp>
     28
     29class CMapGenerator
     30{
     31
     32public:
     33    // constructor
     34    CMapGenerator();
     35
     36    CScriptValRooted GenerateMap(const CStrW& scriptFile, const CScriptValRooted& settings);
     37
     38    ScriptInterface& GetScriptInterface();
     39
     40private:
     41
     42    void LoadLibraries();
     43
     44    CScriptValRooted LoadScript(const std::wstring& filename);
     45
     46    ScriptInterface m_ScriptInterface;
     47
     48};
     49
     50namespace MapGenRNG
     51{
     52    JSBool SeedRand(JSContext *cx, uintN argc, jsval *vp);
     53    JSBool RandInt(JSContext *cx, uintN argc, jsval *vp);
     54    JSBool RandFloat(JSContext *cx, uintN argc, jsval *vp);
     55
     56    int32 randInt(int32 max);
     57    float randFloat();
     58}//namespace MapGenRNG
     59
     60#endif
     61 No newline at end of file
  • source/graphics/MapReader.cpp

    Property changes on: source\graphics\MapGenerator.h
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    2121
    2222#include "graphics/Camera.h"
    2323#include "graphics/CinemaTrack.h"
     24#include "graphics/Entity.h"
    2425#include "graphics/GameView.h"
     26#include "graphics/MapGenerator.h"
    2527#include "graphics/Patch.h"
    2628#include "graphics/Terrain.h"
    2729#include "graphics/TerrainTextureEntry.h"
     
    125127    RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
    126128}
    127129
     130// LoadRandomMap: try to load the map data; reinitialise the scene to new data if successful
     131void CMapReader::LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted& settings, CTerrain *pTerrain_,
     132                         WaterManager* pWaterMan_, SkyManager* pSkyMan_,
     133                         CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_,
     134                         CSimulation2 *pSimulation2_, int playerID_)
     135{
     136    // latch parameters (held until DelayedLoadFinished)
     137    m_ScriptFile = scriptFile;
     138    m_ScriptSettings = settings;
     139    pTerrain = pTerrain_;
     140    pLightEnv = pLightEnv_;
     141    pGameView = pGameView_;
     142    pWaterMan = pWaterMan_;
     143    pSkyMan = pSkyMan_;
     144    pCinema = pCinema_;
     145    pTrigMan = pTrigMan_;
     146    pSimulation2 = pSimulation2_;
     147    m_PlayerID = playerID_;
     148
     149    m_CameraStartupTarget = INVALID_ENTITY;
     150
     151    // delete all existing entities
     152    if (pSimulation2)
     153        pSimulation2->ResetState();
     154
     155    only_xml = false;
     156
     157    // copy random map settings (before entity creation)
     158    RegMemFun(this, &CMapReader::LoadRMSettings, L"CMapReader::LoadRMSettings", 50);
     159
     160    // load player settings script (must be done before reading map)
     161    RegMemFun(this, &CMapReader::LoadPlayerSettings, L"CMapReader::LoadPlayerSettings", 50);
     162
     163    // load map generator with random map script
     164    RegMemFun(this, &CMapReader::GenerateMap, L"CMapReader::GenerateMap", 2000);
     165
     166    // parse RMS results into terrain structure
     167    RegMemFun(this, &CMapReader::ParseTerrain, L"CMapReader::ParseTerrain", 500);
     168
     169    // parse RMS results into environment settings
     170    RegMemFun(this, &CMapReader::ParseEnvironment, L"CMapReader::ParseEnvironment", 5);
     171
     172    // parse RMS results into camera settings
     173    RegMemFun(this, &CMapReader::ParseCamera, L"CMapReader::ParseCamera", 5);
     174
     175    // parse RMS results into entities
     176    RegMemFun(this, &CMapReader::ParseEntities, L"CMapReader::ParseEntities", 1000);
     177
     178    // apply data to the world
     179    RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 5);
     180
     181    // load map settings script (must be done after reading map)
     182    RegMemFun(this, &CMapReader::LoadMapSettings, L"CMapReader::LoadMapSettings", 5);
     183
     184    RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
     185}
     186
    128187// UnpackMap: unpack the given data from the raw data stream into local variables
    129188int CMapReader::UnpackMap()
    130189{
     
    13401399
    13411400    return 0;
    13421401}
     1402
     1403int CMapReader::LoadRMSettings()
     1404{
     1405    // copy random map settings over to sim
     1406    pSimulation2->SetMapSettings(m_ScriptSettings);
     1407
     1408    return 0;
     1409}
     1410
     1411int CMapReader::GenerateMap()
     1412{
     1413    CMapGenerator mapGen;
     1414
     1415    CStrW scriptPath;
     1416   
     1417    if (m_ScriptFile.length())
     1418        scriptPath = L"maps/random/"+m_ScriptFile;
     1419
     1420    // Copy map settings from simulator to mapgen context
     1421    CScriptValRooted scriptSettings(mapGen.GetScriptInterface().GetContext(), mapGen.GetScriptInterface().CloneValueFromOtherContext(pSimulation2->GetScriptInterface(), m_ScriptSettings.get()));
     1422
     1423    CScriptValRooted mapData = mapGen.GenerateMap(scriptPath, scriptSettings);
     1424
     1425    // No map data, something bad happened
     1426    if(mapData.undefined())
     1427        throw PSERROR_File_ReadFailed("CMapReader::GenerateMap() failed to generate map");
     1428
     1429    // Copy data from mapgen to simulator context
     1430    m_MapData = CScriptValRooted(pSimulation2->GetScriptInterface().GetContext(), pSimulation2->GetScriptInterface().CloneValueFromOtherContext(mapGen.GetScriptInterface(), mapData.get()));
     1431
     1432    return 0;
     1433};
     1434
     1435
     1436int CMapReader::ParseTerrain()
     1437{
     1438    // TODO: Progressive loading
     1439
     1440    // parse terrain from map data
     1441
     1442#define GET_TERRAIN_PROPERTY(prop, out)\
     1443    if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), #prop, out))\
     1444        LOGERROR(L"CMapReader::ParseTerrain() failed to get '%hs' property", #prop);\
     1445
     1446    size_t size;
     1447    GET_TERRAIN_PROPERTY(size, size)
     1448
     1449    m_PatchesPerSide = size / PATCH_SIZE;
     1450   
     1451    // flat heightmap of u16 data
     1452    GET_TERRAIN_PROPERTY(height, m_Heightmap)
     1453
     1454    // load textures
     1455    GET_TERRAIN_PROPERTY(numTextures, num_terrain_tex)
     1456
     1457    std::vector<std::string> textureNames;
     1458    GET_TERRAIN_PROPERTY(textureNames, textureNames)
     1459
     1460    while (cur_terrain_tex < num_terrain_tex)
     1461    {
     1462        debug_assert(CTerrainTextureManager::IsInitialised()); // we need this for the terrain properties (even when graphics are disabled)
     1463        CTerrainTextureEntry* texentry = g_TexMan.FindTexture(textureNames[cur_terrain_tex]);
     1464        m_TerrainTextures.push_back(texentry);
     1465
     1466        cur_terrain_tex++;
     1467        //LDR_CHECK_TIMEOUT(cur_terrain_tex, num_terrain_tex);
     1468    }
     1469
     1470    // build tile data
     1471    m_Tiles.resize(SQR(size));
     1472
     1473    std::vector<u16> tileData;
     1474    GET_TERRAIN_PROPERTY(tileData, tileData)
     1475
     1476    size_t i;
     1477    CMapIO::STileDesc tileDesc = {0, 0xFFFF, 0};
     1478    for (i = 0; i < tileData.size(); ++i)
     1479    {
     1480        tileDesc.m_Tex1Index = tileData[i];
     1481
     1482        m_Tiles[i] = tileDesc;
     1483    }
     1484
     1485    // reset generator state
     1486    cur_terrain_tex = 0;
     1487
     1488#undef GET_TERRAIN_PROPERTY
     1489
     1490    return 0;
     1491}
     1492
     1493int CMapReader::ParseEntities()
     1494{
     1495    // parse entities from map data
     1496    std::vector<Entity> entities;
     1497
     1498    if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), "entities", entities))
     1499        LOGWARNING(L"CMapReader::ParseEntities() failed to get 'entities' property");
     1500
     1501    size_t entity_idx = 0;
     1502    size_t num_entities = entities.size();
     1503   
     1504    Entity currEnt;
     1505
     1506    while (entity_idx < num_entities)
     1507    {
     1508        // Get current entity struct
     1509        currEnt = entities[entity_idx];
     1510
     1511        entity_id_t ent = pSimulation2->AddEntity(currEnt.templateName, currEnt.entityID);
     1512        // Check that entity was added
     1513        if (ent == INVALID_ENTITY)
     1514        {
     1515            LOGERROR(L"Failed to load entity template '%ls'", currEnt.templateName.c_str());
     1516        }
     1517        else
     1518        {
     1519            CmpPtr<ICmpPosition> cmpPosition(*pSimulation2, ent);
     1520            if (!cmpPosition.null())
     1521            {
     1522                cmpPosition->JumpTo(entity_pos_t::FromFloat(currEnt.positionX), entity_pos_t::FromFloat(currEnt.positionZ));
     1523                cmpPosition->SetYRotation(entity_angle_t::FromFloat(currEnt.orientationY));
     1524                // TODO: other parts of the position
     1525            }
     1526
     1527            CmpPtr<ICmpOwnership> cmpOwner(*pSimulation2, ent);
     1528            if (!cmpOwner.null())
     1529                cmpOwner->SetOwner(currEnt.playerID);
     1530
     1531            if (boost::algorithm::ends_with(currEnt.templateName, L"civil_centre"))
     1532            {
     1533                // HACK: we special-case civil centre files to initialise the camera.
     1534                // This ought to be based on a more generic mechanism for indicating
     1535                // per-player camera start locations.
     1536                if (m_CameraStartupTarget == INVALID_ENTITY && currEnt.playerID == m_PlayerID && !cmpPosition.null())
     1537                    m_CameraStartupTarget = ent;
     1538
     1539            }
     1540        }
     1541
     1542        entity_idx++;
     1543    }
     1544
     1545    return 0;
     1546}
     1547
     1548int CMapReader::ParseEnvironment()
     1549{
     1550    // parse environment settings from map data
     1551
     1552#define GET_ENVIRONMENT_PROPERTY(val, prop, out)\
     1553    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
     1554        LOGWARNING(L"CMapReader::ParseEnvironment() failed to get '%hs' property", #prop);\
     1555
     1556    CScriptValRooted envObj;
     1557    GET_ENVIRONMENT_PROPERTY(m_MapData.get(), Environment, envObj)
     1558
     1559    if (envObj.undefined())
     1560    {
     1561        LOGWARNING(L"CMapReader::ParseEnvironment(): Environment settings not found");
     1562        return 0;
     1563    }
     1564
     1565    std::wstring skySet;
     1566    GET_ENVIRONMENT_PROPERTY(envObj.get(), SkySet, skySet)
     1567    pSkyMan->SetSkySet(skySet);
     1568
     1569    GET_ENVIRONMENT_PROPERTY(envObj.get(), SunColour, m_LightEnv.m_SunColor)
     1570    GET_ENVIRONMENT_PROPERTY(envObj.get(), SunElevation, m_LightEnv.m_Elevation)
     1571    GET_ENVIRONMENT_PROPERTY(envObj.get(), SunRotation, m_LightEnv.m_Rotation)
     1572    GET_ENVIRONMENT_PROPERTY(envObj.get(), TerrainAmbientColour, m_LightEnv.m_TerrainAmbientColor)
     1573    GET_ENVIRONMENT_PROPERTY(envObj.get(), UnitsAmbientColour, m_LightEnv.m_UnitsAmbientColor)
     1574
     1575
     1576    // Water properties
     1577    CScriptValRooted waterObj;
     1578    GET_ENVIRONMENT_PROPERTY(envObj.get(), Water, waterObj)
     1579
     1580    CScriptValRooted waterBodyObj;
     1581    GET_ENVIRONMENT_PROPERTY(waterObj.get(), WaterBody, waterBodyObj)
     1582
     1583    // Water level - necessary
     1584    float waterHeight;
     1585    GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Height, waterHeight)
     1586
     1587    CmpPtr<ICmpWaterManager> cmpWaterMan(*pSimulation2, SYSTEM_ENTITY);
     1588    debug_assert(!cmpWaterMan.null());
     1589    cmpWaterMan->SetWaterLevel(entity_pos_t::FromFloat(waterHeight));
     1590
     1591    // If we have graphics, get rest of settings
     1592    if (pWaterMan)
     1593    {
     1594        std::wstring waterType;
     1595        // TODO: Water type unimplemented
     1596        //GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Type, waterType)
     1597
     1598        RGBColor waterColour;
     1599        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Colour, waterColour)
     1600        pWaterMan->m_WaterColor = CColor(waterColour.X, waterColour.Y, waterColour.Z, 1.0f);
     1601
     1602        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Shininess, pWaterMan->m_Shininess)
     1603        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Waviness, pWaterMan->m_Waviness)
     1604        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Murkiness, pWaterMan->m_Murkiness)
     1605
     1606        RGBColor waterTint;
     1607        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Tint, waterTint)
     1608        pWaterMan->m_WaterTint = CColor(waterTint.X, waterTint.Y, waterTint.Z, 1.0f);
     1609
     1610        RGBColor reflectTint;
     1611        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), ReflectionTint, reflectTint)
     1612        pWaterMan->m_ReflectionTint = CColor(reflectTint.X, reflectTint.Y, reflectTint.Z, 1.0f);
     1613
     1614        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), ReflectionTintStrength, pWaterMan->m_ReflectionTintStrength)
     1615    }
     1616
     1617    m_LightEnv.CalculateSunDirection();
     1618
     1619#undef GET_ENVIRONMENT_PROPERTY
     1620
     1621    return 0;
     1622}
     1623
     1624int CMapReader::ParseCamera()
     1625{
     1626    // parse camera settings from map data
     1627    // defaults if we don't find camera
     1628    float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
     1629    CVector3D translation = CVector3D(100, 150, -100);
     1630
     1631#define GET_CAMERA_PROPERTY(val, prop, out)\
     1632    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
     1633        LOGWARNING(L"CMapReader::ParseCamera() failed to get '%hs' property", #prop);\
     1634
     1635    CScriptValRooted cameraObj;
     1636    GET_CAMERA_PROPERTY(m_MapData.get(), Camera, cameraObj)
     1637
     1638    if (!cameraObj.undefined())
     1639    {   // If camera property exists, read values
     1640        CFixedVector3D pos;
     1641        GET_CAMERA_PROPERTY(cameraObj.get(), Position, pos)
     1642        translation = pos;
     1643
     1644        GET_CAMERA_PROPERTY(cameraObj.get(), Rotation, rotation)
     1645        GET_CAMERA_PROPERTY(cameraObj.get(), Declination, declination)
     1646    }
     1647#undef GET_CAMERA_PROPERTY
     1648
     1649    if (pGameView)
     1650    {
     1651        pGameView->GetCamera()->m_Orientation.SetXRotation(declination);
     1652        pGameView->GetCamera()->m_Orientation.RotateY(rotation);
     1653        pGameView->GetCamera()->m_Orientation.Translate(translation);
     1654        pGameView->GetCamera()->UpdateFrustum();
     1655    }
     1656
     1657    return 0;
     1658}
  • source/graphics/MapReader.h

     
    8282    // clean up everything used during delayed load
    8383    int DelayLoadFinished();
    8484
     85    // Copy random map settings over to sim
     86    int LoadRMSettings();
     87
     88    // Generate random map
     89    int GenerateMap();
     90
     91    // Parse script data into terrain
     92    int ParseTerrain();
     93
     94    // Parse script data into entities
     95    int ParseEntities();
     96
     97    // Parse script data into environment
     98    int ParseEnvironment();
     99
     100    // Parse script data into camera
     101    int ParseCamera();
     102
     103
    85104    // size of map
    86105    ssize_t m_PatchesPerSide;
    87106    // heightmap for map
     
    95114    // startup script
    96115    CStrW m_Script;
    97116
     117    // random map data
     118    CStrW m_ScriptFile;
     119    CScriptValRooted m_ScriptSettings;
     120    CScriptValRooted m_MapData;
     121
    98122    // state latched by LoadMap and held until DelayedLoadFinished
    99123    CFileUnpacker unpacker;
    100124    CTerrain* pTerrain;
  • source/ps/Game.cpp

     
    144144    }
    145145    else if (mapType == "random")
    146146    {
    147         // TODO: Coming in another patch
     147        // Load random map attributes
     148        std::wstring scriptFile;
     149        CScriptValRooted settings;
     150
     151        m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "script", scriptFile);
     152        m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "settings", settings);
     153
     154        m_World->RegisterInit(scriptFile, settings, m_PlayerID);
    148155    }
    149156
    150157
  • source/ps/GameSetup/GameSetup.cpp

     
    711711
    712712static bool Autostart(const CmdLineArgs& args);
    713713
    714 void Init(const CmdLineArgs& args, int flags)
     714void Init(const CmdLineArgs& args, int UNUSED(flags))
    715715{
    716716    h_mgr_init();
    717717
     
    871871
    872872    ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
    873873    CScriptValRooted attrs;
    874     scriptInterface.Eval("({})", attrs);
    875     scriptInterface.SetProperty(attrs.get(), "mapType", std::string("scenario"), false);
    876     scriptInterface.SetProperty(attrs.get(), "map", std::string(autostartMap), false);
     874    scriptInterface.Eval("({settings: { Size: 208, Seed: 0, BaseTerrain: 'grass1_spring', BaseHeight: 0, PlayerData: [{Civ:'hele'},{Civ:'hele'}], RevealMap: false, LockTeams: false, GameType: 'conquest' } })", attrs);
     875    if (args.Has("autostart-random"))
     876    {
     877        scriptInterface.SetProperty(attrs.get(), "script", std::string(autostartMap), false);
     878        scriptInterface.SetProperty(attrs.get(), "mapType", std::string("random"), false);
     879    }
     880    else
     881    {
     882        scriptInterface.SetProperty(attrs.get(), "map", std::string(autostartMap), false);
     883        scriptInterface.SetProperty(attrs.get(), "mapType", std::string("scenario"), false);
     884    }
    877885
    878886    CScriptValRooted mpInitData;
    879887    g_GUI->GetScriptInterface().Eval("({isNetworked:true, playerAssignments:{}})", mpInitData);
  • source/ps/World.cpp

     
    9494    }
    9595}
    9696
     97void CWorld::RegisterInit(const CStrW& scriptFile, const CScriptValRooted& settings, int playerID)
     98{
     99    // If scriptFile is empty, a blank map will be generated using settings (no RMS run)
     100    CMapReader* reader = 0;
     101
     102    try
     103    {
     104        reader = new CMapReader;
     105        CTriggerManager* pTriggerManager = NULL;
     106        reader->LoadRandomMap(scriptFile, settings, m_Terrain,
     107            CRenderer::IsInitialised() ? g_Renderer.GetWaterManager() : NULL,
     108            CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL,
     109            &g_LightEnv, m_pGame->GetView(),
     110            m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL,
     111            pTriggerManager, m_pGame->GetSimulation2(), playerID);
     112            // fails immediately, or registers for delay loading
     113    }
     114    catch (PSERROR_File& err)
     115    {
     116        delete reader;
     117        LOGERROR(L"Failed to generate random map %ls: %hs", scriptFile.c_str(), err.what());
     118        throw PSERROR_Game_World_MapLoadFailed();
     119    }
     120}
     121
     122
    97123/**
    98124 * Destructor.
    99125 *
  • source/ps/World.h

     
    2525#define INCLUDED_WORLD
    2626
    2727#include "ps/Errors.h"
     28#include "scriptinterface/ScriptInterface.h"
    2829
    2930#ifndef ERROR_GROUP_GAME_DEFINED
    3031#define ERROR_GROUP_GAME_DEFINED
     
    7475    */
    7576    void RegisterInit(const CStrW& mapFile, int playerID);
    7677
     78    void RegisterInit(const CStrW& scriptFile, const CScriptValRooted& settings, int playerID);
     79
    7780    /**
    7881     * Get the pointer to the terrain object.
    7982     *
  • source/scriptinterface/ScriptConversions.cpp

     
    2222#include "ps/utf16string.h"
    2323#include "ps/CLogger.h"
    2424#include "ps/CStr.h"
     25#include "graphics/Color.h"
     26#include "graphics/Entity.h"
    2527
    2628#include "js/jsapi.h"
    2729
     
    7072    return true;
    7173}
    7274
     75template<> bool ScriptInterface::FromJSVal<u64>(JSContext* cx, jsval v, u64& out)
     76{
     77    uint32 ret;
     78    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
     79    if (!JS_ValueToECMAUint32(cx, v, &ret))
     80        return false;
     81    out = ret;
     82    return true;
     83}
     84
    7385template<> bool ScriptInterface::FromJSVal<u32>(JSContext* cx, jsval v, u32& out)
    7486{
    7587    uint32 ret;
     
    8092    return true;
    8193}
    8294
     95template<> bool ScriptInterface::FromJSVal<u16>(JSContext* cx, jsval v, u16& out)
     96{
     97    uint16 ret;
     98    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
     99    if (!JS_ValueToUint16(cx, v, &ret))
     100        return false;
     101    out = ret;
     102    return true;
     103}
     104
    83105// NOTE: we can't define a jsval specialisation, because that conflicts with integer types
    84106template<> bool ScriptInterface::FromJSVal<CScriptVal>(JSContext* UNUSED(cx), jsval v, CScriptVal& out)
    85107{
     
    268290{
    269291    return FromJSVal_vector(cx, v, out);
    270292}
     293
     294template<> bool ScriptInterface::FromJSVal<std::vector<u16> >(JSContext* cx, jsval v, std::vector<u16>& out)
     295{
     296    return FromJSVal_vector(cx, v, out);
     297}
     298
     299template<> bool ScriptInterface::FromJSVal<std::vector<std::string> >(JSContext* cx, jsval v, std::vector<std::string>& out)
     300{
     301    return FromJSVal_vector(cx, v, out);
     302}
     303
     304
     305template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, jsval v, Entity& out)
     306{
     307    JSObject* obj;
     308    if (!JS_ValueToObject(cx, v, &obj) || obj == NULL)
     309        FAIL("Argument must be an object");
     310
     311    jsval name, id, player, x, z, orient, actor;
     312
     313    if(!JS_GetProperty(cx, obj, "isActor", &actor) || !FromJSVal(cx, actor, out.isActor))
     314        FAIL("Failed to read Entity.isActor property");
     315
     316    if (!out.isActor)
     317        if(!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID))
     318            FAIL("Failed to read Entity.player property");
     319   
     320    if (!JS_GetProperty(cx, obj, "name", &name) || !FromJSVal(cx, name, out.templateName))
     321        FAIL("Failed to read Entity.name property");
     322    if (!JS_GetProperty(cx, obj, "id", &id) || !FromJSVal(cx, id, out.entityID))
     323        FAIL("Failed to read Entity.id property");
     324    if (!JS_GetProperty(cx, obj, "x", &x) || !FromJSVal(cx, x, out.positionX))
     325        FAIL("Failed to read Entity.x property");
     326    if (!JS_GetProperty(cx, obj, "y", &z) || !FromJSVal(cx, z, out.positionZ))
     327        FAIL("Failed to read Entity.y property");
     328    if (!JS_GetProperty(cx, obj, "orientation", &orient) || !FromJSVal(cx, orient, out.orientationY))
     329        FAIL("Failed to read Entity.orientation property");
     330
     331    return true;
     332}
     333
     334template<> bool ScriptInterface::FromJSVal<std::vector<Entity> >(JSContext* cx, jsval v, std::vector<Entity>& out)
     335{
     336    return FromJSVal_vector(cx, v, out);
     337}
     338
     339template<> bool ScriptInterface::FromJSVal<RGBColor>(JSContext* cx, jsval v, RGBColor& out)
     340{
     341    JSObject* obj;
     342    if (!JS_ValueToObject(cx, v, &obj) || obj == NULL)
     343        FAIL("Argument must be an object");
     344
     345    jsval r, g, b;
     346    if (!JS_GetProperty(cx, obj, "r", &r) || !FromJSVal(cx, r, out.X))
     347        FAIL("Failed to read RGBColor.r property");
     348    if (!JS_GetProperty(cx, obj, "g", &g) || !FromJSVal(cx, g, out.Y))
     349        FAIL("Failed to read RGBColor.g property");
     350    if (!JS_GetProperty(cx, obj, "b", &b) || !FromJSVal(cx, b, out.Z))
     351        FAIL("Failed to read RGBColor.b property");
     352   
     353    return true;
     354}
     355 No newline at end of file
  • source/scriptinterface/ScriptInterface.cpp

     
    3636
    3737#include "valgrind.h"
    3838
    39 const int RUNTIME_SIZE = 16 * 1024 * 1024; // TODO: how much memory is needed?
     39const int RUNTIME_SIZE = 32 * 1024 * 1024; // TODO: how much memory is needed?
    4040const int STACK_CHUNK_SIZE = 8192;
    4141
    4242#if ENABLE_SCRIPT_PROFILING
     
    280280                | JSOPTION_VAROBJFIX // "recommended" (fixes variable scoping)
    281281
    282282                // Enable all the JIT features:
    283 //              | JSOPTION_JIT
     283                | JSOPTION_JIT
    284284//              | JSOPTION_METHODJIT
    285285//              | JSOPTION_PROFILING
    286286        );