Ticket #658: RMS_JS_Implementation.patch

File RMS_JS_Implementation.patch, 149.6 KB (added by historic_bruno, 14 years ago)

For experimental use

  • 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
     9/////////////////////////////////////////////////////////////////////////////////////////////
     10//  Utility functions
     11/////////////////////////////////////////////////////////////////////////////////////////////
     12
     13function fractionToTiles(f) {
     14    return getMapSize() * f;
     15}
     16
     17function tilesToFraction(t) {
     18    return t / getMapSize();
     19}
     20
     21function fractionToSize(f) {
     22    return getMapSize() * getMapSize() * f;
     23}
     24
     25function sizeToFraction(s) {
     26    return s / getMapSize() / getMapSize();
     27}
     28
     29function cos(x) {
     30    return Math.cos(x);
     31}
     32
     33function sin(x) {
     34    return Math.sin(x);
     35}
     36
     37function tan(x) {
     38    return Math.tan(x);
     39}
     40
     41function abs(x) {
     42    return Math.abs(x);
     43}
     44
     45function round(x) {
     46    return Math.round(x);
     47}
     48
     49function lerp(a, b, t) {
     50    return a + (b-a) * t;
     51}
     52
     53function sqrt(x) {
     54    return Math.sqrt(x);
     55}
     56
     57function ceil(x) {
     58    return Math.ceil(x);
     59}
     60
     61function floor(x) {
     62    return Math.floor(x);
     63}
     64
     65function max(x, y) {
     66    return x > y ? x : y;
     67}
     68
     69function min(x, y) {
     70    return x < y ? x : y;
     71}
     72
     73function println(x) {
     74    print(x);
     75    print("\n");
     76}
     77
     78function argsToArray(x) {
     79    if (x.length!=1) {
     80        var ret = new Array();
     81        for (var i=0; i<x.length; i++) {
     82            ret[i] = x[i];
     83        }
     84        return ret;
     85    }
     86    else {
     87        return x[0];
     88    }
     89}
     90
     91function chooseRand() {
     92    if (arguments.length==0) {
     93        error("chooseRand: requires at least 1 argument");
     94    }
     95    var ar = argsToArray(arguments);
     96    return ar[randInt(ar.length)];
     97}
     98
     99function createAreas(centeredPlacer, painter, constraint, num, retryFactor)
     100{
     101    if (retryFactor === undefined)
     102        retryFactor = 10;
     103   
     104    var maxFail = num * retryFactor;
     105    var good = 0;
     106    var bad = 0;
     107    var ret = [];
     108    while(good < num && bad <= maxFail)
     109    {
     110        centeredPlacer.x = randInt(getMapSize());
     111        centeredPlacer.y = randInt(getMapSize());
     112        var r = g_Map.createArea(centeredPlacer, painter, constraint);
     113        if (r !== undefined)
     114        {
     115            good++;
     116            ret.push(r);
     117        }
     118        else
     119        {
     120            bad++;
     121        }
     122    }
     123   
     124    return ret;
     125}
     126
     127function createObjectGroups(placer, player, constraint, num, retryFactor)
     128{
     129    if (retryFactor === undefined)
     130        retryFactor = 10;
     131   
     132    var maxFail = num * retryFactor;
     133    var good = 0;
     134    var bad = 0;
     135    while(good < num && bad <= maxFail)
     136    {
     137        placer.x = randInt(getMapSize());
     138        placer.y = randInt(getMapSize());
     139        var r = createObjectGroup(placer, player, constraint);
     140       
     141        if (r !== undefined)
     142        {
     143            good++;
     144        }
     145        else
     146        {
     147            bad++;
     148        }
     149    }
     150    return good;
     151}
     152
     153function createTerrain(terrain)
     154{
     155    if (terrain instanceof Array)
     156    {
     157        var terrainList = [];
     158       
     159        for (var i = 0; i < terrain.length; ++i)
     160            terrainList.push(createSimpleTerrain(terrain[i]));
     161       
     162        return new RandomTerrain(terrainList);
     163    }
     164    else
     165    {
     166        return createSimpleTerrain(terrain);
     167    }
     168}
     169
     170function createSimpleTerrain(terrain)
     171{
     172    // Split string by pipe | character, this allows specifying terrain + tree type in single string
     173    var params = terrain.split(TERRAIN_SEPARATOR, 2);
     174   
     175    if (params.length != 2)
     176    {
     177        return new SimpleTerrain(terrain);
     178    }
     179    else
     180    {
     181        return new SimpleTerrain(params[0], params[1]);
     182    }
     183}
     184
     185function placeObject(type, player, x, y, angle)
     186{
     187    g_Map.addObjects(new Entity(type, player, x, y, angle));
     188}
     189
     190function placeTerrain(x, y, terrain)
     191{
     192    // convert terrain param into terrain object
     193    g_Map.placeTerrain(x, y, createTerrain(terrain));
     194   
     195}
     196
     197/////////////////////////////////////////////////////////////////////////////////////////////
     198//  Access global map variable
     199/////////////////////////////////////////////////////////////////////////////////////////////
     200
     201function createTileClass()
     202{
     203    return g_Map.createTileClass();
     204}
     205
     206function getTileClass(id)
     207{
     208    // Check for valid class id
     209    if (id < 1 || id > g_Map.tileClasses.length)
     210    {
     211        //error("Invalid tile class id: "+id);
     212        return null;
     213    }
     214   
     215    return g_Map.tileClasses[id - 1];
     216}
     217
     218function createArea(placer, painter, constraint)
     219{
     220    return g_Map.createArea(placer, painter, constraint);
     221}
     222
     223function createObjectGroup(placer, player, constraint)
     224{
     225    return g_Map.createObjectGroup(placer, player, constraint);
     226}
     227
     228function getMapSize()
     229{
     230    return g_Map.size;
     231}
     232
     233function getNumPlayers()
     234{
     235    return g_MapSettings.PlayerData.length;
     236}
     237
     238function getCivCode(player)
     239{
     240    return g_MapSettings.PlayerData[player].Civ;
     241}
     242
     243function getHeight(x, y)
     244{
     245    g_Map.getHeight(x, y);
     246}
     247
     248function setHeight(x, y, height)
     249{
     250    g_Map.setHeight(x, y, height);
     251}
     252
     253/////////////////////////////////////////////////////////////////////////////////////////////
     254//  Utility functions for classes
     255/////////////////////////////////////////////////////////////////////////////////////////////
     256
     257
     258// Add point to given class by id
     259function addToClass(x, y, id)
     260{
     261    var tileClass = getTileClass(id);
     262   
     263    if (tileClass !== null)
     264        tileClass.add(x, y);
     265}
     266
     267// Create a painter for the given class
     268function paintClass(id)
     269{
     270    return new TileClassPainter(getTileClass(id));
     271}
     272
     273// Create an avoid constraint for the given classes by the given distances
     274function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
     275{
     276    var ar = new Array(arguments.length/2);
     277    for (var i=0; i < arguments.length/2; i++)
     278    {
     279        ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
     280    }
     281    // Return single constraint
     282    return new AndConstraint(ar);
     283}
  • 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
     247    var size = this.size;
     248    for (var i=0; i < size; ++i)
     249    {
     250        for (var j=0; j < size; ++j)
     251        {
     252            if (this.terrainObjects[i][j].length)
     253                entities = entities.concat(this.terrainObjects[i][j]);
     254        }
     255    }
     256   
     257    // Now other objects
     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        var temp = e.x; // Somehow x = z, and y = x
     270        e.x = 4*e.y;
     271        e.y = 4*temp;
     272       
     273        entities[n] = e;
     274    }
     275    data["entities"] = entities;
     276   
     277    // Terrain
     278    data["size"] = this.size;
     279   
     280    // Convert 2D heightmap array to flat array
     281    //  Flat because it's easier to handle by the engine
     282    var mapSize = size+1;
     283    var height16 = new Array(mapSize*mapSize);      // uint16
     284    for (var i=0; i < mapSize; i++)
     285    {
     286        var di = i*mapSize;
     287       
     288        for (var j=0; j < mapSize; j++)
     289        {
     290            var intHeight = ((this.height[i][j] + SEA_LEVEL) * 256.0 / 0.35)|0; // floor
     291           
     292            if (intHeight > 65000)
     293                intHeight = 65000;
     294            else if (intHeight < 0)
     295                intHeight = 0;
     296           
     297            height16[di + j] = intHeight;
     298        }
     299    }
     300    data["height"] = height16;
     301    data["seaLevel"] = SEA_LEVEL;
     302   
     303    // Get array of textures used in this map
     304    var textureNames = [];
     305    for (var name in this.nameToID)
     306        textureNames.push(name);
     307   
     308    data["textureNames"] = textureNames;
     309    data["numTextures"] = textureNames.length;
     310   
     311    //  Convert 2D tile data to flat array
     312    var tiles = new Array(size*size);
     313    for (var i=0; i < size; i++)
     314    {
     315        var di = i*size;
     316        for (var j=0; j < size; j++)
     317        {
     318            tiles[di + j] = this.texture[i][j];
     319        }
     320    }
     321    data["tileData"] = tiles;
     322   
     323    return data;
     324};
  • 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// Global RNG (Mersenne Twister)
     5var g_MT;
     6
     7// Map settings - once initialized, has all the game setup data, including player array
     8var g_MapSettings = {
     9    Size : 208,
     10    Seed : 0,
     11    BaseTerrain: "grass1_spring",
     12    BaseHeight: 0,
     13    PlayerData : [ {}, {} ]
     14};
     15
     16var g_Environment = {
     17    SkySet: "cirrus",
     18    SunColour: {r: 1.47461, g: 1.47461, b: 1.47461},
     19    SunElevation: 0.951868,
     20    SunRotation: -0.532844,
     21    TerrainAmbientColour: {r: 0.337255, g: 0.403922, b: 0.466667},
     22    UnitsAmbientColour: {r: 0.501961, g: 0.501961, b: 0.501961},
     23    Water: {
     24        WaterBody: {
     25            Type: "default",
     26            Colour: {r: 0.294118, g: 0.34902, b: 0.694118},
     27            Height: 17.6262,
     28            Shininess: 150,
     29            Waviness: 8,
     30            Murkiness: 0.458008,
     31            Tint: {r: 0.447059, g: 0.411765, b: 0.321569},
     32            ReflectionTint: {r: 0.619608, g: 0.584314, b: 0.47451},
     33            ReflectionTintStrength: 0.298828
     34        }
     35    }
     36};
     37
     38var g_Camera = {
     39    Position: {x: 601.962, y: 117.579, z: 471.135},
     40    Rotation: 0,
     41    Declination: 0.523599
     42};
     43
     44function InitMapGen(settings)
     45{
     46    g_MT = new MersenneTwister19937();
     47   
     48    if (settings === undefined || settings == {})
     49    {
     50        warn("InitMapGen: settings missing");
     51    }
     52    else
     53    {
     54        g_MapSettings = settings;
     55    }
     56   
     57    seedRand(g_MapSettings.Seed);
     58
     59    // Create new map
     60    log("Creating new map...");
     61    var terrain = createTerrain(g_MapSettings.BaseTerrain);
     62   
     63    g_Map = new Map(g_MapSettings.Size, g_MapSettings.BaseHeight);
     64    g_Map.initTerrain(terrain);
     65}
     66
     67function SaveMap()
     68{
     69    log("Saving map...");
     70   
     71    // Get necessary data from map
     72    var data = g_Map.getMapData();
     73   
     74    // Add environment and camera settings
     75    g_Environment.Water.WaterBody.Height = SEA_LEVEL - 0.1;
     76    data.Environment = g_Environment;
     77    data.Camera = g_Camera;
     78   
     79    return data;
     80}
  • binaries/data/mods/public/maps/mapgen/MersenneTwister19937.js

     
     1// this program is a JavaScript version of Mersenne Twister, with concealment and encapsulation in class,
     2// an almost straight conversion from the original program, mt19937ar.c,
     3// translated by y. okada on July 17, 2006.
     4// and modified a little at july 20, 2006, but there are not any substantial differences.
     5// in this program, procedure descriptions and comments of original source code were not removed.
     6// lines commented with //c// were originally descriptions of c procedure. and a few following lines are appropriate JavaScript descriptions.
     7// lines commented with /* and */ are original comments.
     8// lines commented with // are additional comments in this JavaScript version.
     9// before using this version, create at least one instance of MersenneTwister19937 class, and initialize the each state, given below in c comments, of all the instances.
     10/*
     11   A C-program for MT19937, with initialization improved 2002/1/26.
     12   Coded by Takuji Nishimura and Makoto Matsumoto.
     13
     14   Before using, initialize the state by using init_genrand(seed)
     15   or init_by_array(init_key, key_length).
     16
     17   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
     18   All rights reserved.
     19
     20   Redistribution and use in source and binary forms, with or without
     21   modification, are permitted provided that the following conditions
     22   are met:
     23
     24     1. Redistributions of source code must retain the above copyright
     25        notice, this list of conditions and the following disclaimer.
     26
     27     2. Redistributions in binary form must reproduce the above copyright
     28        notice, this list of conditions and the following disclaimer in the
     29        documentation and/or other materials provided with the distribution.
     30
     31     3. The names of its contributors may not be used to endorse or promote
     32        products derived from this software without specific prior written
     33        permission.
     34
     35   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     36   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     37   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     38   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     39   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     40   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     41   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     42   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     43   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     44   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     45   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     46
     47
     48   Any feedback is very welcome.
     49   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
     50   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
     51*/
     52
     53function MersenneTwister19937()
     54{
     55    /* Period parameters */
     56    //c//#define N 624
     57    //c//#define M 397
     58    //c//#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
     59    //c//#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
     60    //c//#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
     61    const N = 624;
     62    const M = 397;
     63    const MATRIX_A = 0x9908b0df;   /* constant vector a */
     64    const UPPER_MASK = 0x80000000; /* most significant w-r bits */
     65    const LOWER_MASK = 0x7fffffff; /* least significant r bits */
     66    //c//static unsigned long mt[N]; /* the array for the state vector  */
     67    //c//static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
     68    var mt = new Array(N);   /* the array for the state vector  */
     69    var mti = N+1;           /* mti==N+1 means mt[N] is not initialized */
     70
     71    function unsigned32 (n1) // returns a 32-bits unsiged integer from an operand to which applied a bit operator.
     72    {
     73        return n1 < 0 ? (n1 ^ UPPER_MASK) + UPPER_MASK : n1;
     74    }
     75
     76    function subtraction32 (n1, n2) // emulates lowerflow of a c 32-bits unsiged integer variable, instead of the operator -. these both arguments must be non-negative integers expressible using unsigned 32 bits.
     77    {
     78        return n1 < n2 ? unsigned32((0x100000000 - (n2 - n1)) & 0xffffffff) : n1 - n2;
     79    }
     80
     81    function addition32 (n1, n2) // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator +. these both arguments must be non-negative integers expressible using unsigned 32 bits.
     82    {
     83        return unsigned32((n1 + n2) & 0xffffffff)
     84    }
     85
     86    function multiplication32 (n1, n2) // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator *. these both arguments must be non-negative integers expressible using unsigned 32 bits.
     87    {
     88        var sum = 0;
     89        for (var i = 0; i < 32; ++i){
     90            if ((n1 >>> i) & 0x1){
     91                sum = addition32(sum, unsigned32(n2 << i));
     92            }
     93        }
     94        return sum;
     95    }
     96
     97    /* initializes mt[N] with a seed */
     98    //c//void init_genrand(unsigned long s)
     99    this.init_genrand = function (s)
     100    {
     101        //c//mt[0]= s & 0xffffffff;
     102        mt[0]= unsigned32(s & 0xffffffff);
     103        for (mti=1; mti<N; mti++) {
     104            mt[mti] =
     105            //c//(1812433253 * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
     106            addition32(multiplication32(1812433253, unsigned32(mt[mti-1] ^ (mt[mti-1] >>> 30))), mti);
     107            /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
     108            /* In the previous versions, MSBs of the seed affect   */
     109            /* only MSBs of the array mt[].                        */
     110            /* 2002/01/09 modified by Makoto Matsumoto             */
     111            //c//mt[mti] &= 0xffffffff;
     112            mt[mti] = unsigned32(mt[mti] & 0xffffffff);
     113            /* for >32 bit machines */
     114        }
     115    }
     116
     117    /* initialize by an array with array-length */
     118    /* init_key is the array for initializing keys */
     119    /* key_length is its length */
     120    /* slight change for C++, 2004/2/26 */
     121    //c//void init_by_array(unsigned long init_key[], int key_length)
     122    this.init_by_array = function (init_key, key_length)
     123    {
     124        //c//int i, j, k;
     125        var i, j, k;
     126        //c//init_genrand(19650218);
     127        this.init_genrand(19650218);
     128        i=1; j=0;
     129        k = (N>key_length ? N : key_length);
     130        for (; k; k--) {
     131            //c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525))
     132            //c//   + init_key[j] + j; /* non linear */
     133            mt[i] = addition32(addition32(unsigned32(mt[i] ^ multiplication32(unsigned32(mt[i-1] ^ (mt[i-1] >>> 30)), 1664525)), init_key[j]), j);
     134            mt[i] =
     135            //c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
     136            unsigned32(mt[i] & 0xffffffff);
     137            i++; j++;
     138            if (i>=N) { mt[0] = mt[N-1]; i=1; }
     139            if (j>=key_length) j=0;
     140        }
     141        for (k=N-1; k; k--) {
     142            //c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941))
     143            //c//- i; /* non linear */
     144            mt[i] = subtraction32(unsigned32((dbg=mt[i]) ^ multiplication32(unsigned32(mt[i-1] ^ (mt[i-1] >>> 30)), 1566083941)), i);
     145            //c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
     146            mt[i] = unsigned32(mt[i] & 0xffffffff);
     147            i++;
     148            if (i>=N) { mt[0] = mt[N-1]; i=1; }
     149        }
     150        mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
     151    }
     152
     153    /* generates a random number on [0,0xffffffff]-interval */
     154    //c//unsigned long genrand_int32(void)
     155    this.genrand_int32 = function ()
     156    {
     157        //c//unsigned long y;
     158        //c//static unsigned long mag01[2]={0x0UL, MATRIX_A};
     159        var y;
     160        var mag01 = new Array(0x0, MATRIX_A);
     161        /* mag01[x] = x * MATRIX_A  for x=0,1 */
     162
     163        if (mti >= N) { /* generate N words at one time */
     164            //c//int kk;
     165            var kk;
     166
     167            if (mti == N+1)   /* if init_genrand() has not been called, */
     168                //c//init_genrand(5489); /* a default initial seed is used */
     169                this.init_genrand(5489); /* a default initial seed is used */
     170
     171            for (kk=0;kk<N-M;kk++) {
     172                //c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
     173                //c//mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
     174                y = unsigned32((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK));
     175                mt[kk] = unsigned32(mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]);
     176            }
     177            for (;kk<N-1;kk++) {
     178                //c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
     179                //c//mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
     180                y = unsigned32((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK));
     181                mt[kk] = unsigned32(mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]);
     182            }
     183            //c//y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
     184            //c//mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
     185            y = unsigned32((mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK));
     186            mt[N-1] = unsigned32(mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]);
     187            mti = 0;
     188        }
     189
     190        y = mt[mti++];
     191
     192        /* Tempering */
     193        //c//y ^= (y >> 11);
     194        //c//y ^= (y << 7) & 0x9d2c5680;
     195        //c//y ^= (y << 15) & 0xefc60000;
     196        //c//y ^= (y >> 18);
     197        y = unsigned32(y ^ (y >>> 11));
     198        y = unsigned32(y ^ ((y << 7) & 0x9d2c5680));
     199        y = unsigned32(y ^ ((y << 15) & 0xefc60000));
     200        y = unsigned32(y ^ (y >>> 18));
     201
     202        return y;
     203    }
     204
     205    /* generates a random number on [0,0x7fffffff]-interval */
     206    //c//long genrand_int31(void)
     207    this.genrand_int31 = function ()
     208    {
     209        //c//return (genrand_int32()>>1);
     210        return (this.genrand_int32()>>>1);
     211    }
     212
     213    /* generates a random number on [0,1]-real-interval */
     214    //c//double genrand_real1(void)
     215    this.genrand_real1 = function ()
     216    {
     217        //c//return genrand_int32()*(1.0/4294967295.0);
     218        return this.genrand_int32()*(1.0/4294967295.0);
     219        /* divided by 2^32-1 */
     220    }
     221
     222    /* generates a random number on [0,1)-real-interval */
     223    //c//double genrand_real2(void)
     224    this.genrand_real2 = function ()
     225    {
     226        //c//return genrand_int32()*(1.0/4294967296.0);
     227        return this.genrand_int32()*(1.0/4294967296.0);
     228        /* divided by 2^32 */
     229    }
     230
     231    /* generates a random number on (0,1)-real-interval */
     232    //c//double genrand_real3(void)
     233    this.genrand_real3 = function ()
     234    {
     235        //c//return ((genrand_int32()) + 0.5)*(1.0/4294967296.0);
     236        return ((this.genrand_int32()) + 0.5)*(1.0/4294967296.0);
     237        /* divided by 2^32 */
     238    }
     239
     240    /* generates a random number on [0,1) with 53-bit resolution*/
     241    //c//double genrand_res53(void)
     242    this.genrand_res53 = function ()
     243    {
     244        //c//unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
     245        var a=this.genrand_int32()>>>5, b=this.genrand_int32()>>>6;
     246        return(a*67108864.0+b)*(1.0/9007199254740992.0);
     247    }
     248    /* These real versions are due to Isaku Wada, 2002/01/09 added */
     249}
  • 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/object.js

     
     1function Entity(name, player, x, y, angle)
     2{
     3    // Get unique ID
     4    this.id = g_Map.getEntityID();
     5    this.name = name;
     6   
     7    // Convert from tile coords to map coords
     8    this.x = x;
     9    this.y = y;
     10   
     11    if (player !== undefined)
     12    {
     13        this.player = player;
     14        this.isActor = false;
     15    }
     16    else
     17    {   // Actors  have no player ID
     18        this.isActor = true;
     19    }
     20   
     21    this.orientation = (angle !== undefined ? angle : 0);
     22}
  • 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] != 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            for (; i < this.widths.length; i++)
     104            {
     105                w += this.widths[i];
     106                if (w >= d)
     107                {
     108                    break;
     109                }
     110            }
     111            this.terrains[i].place(px, py);
     112        }
     113
     114        // enqueue neighbours
     115        for (var dx=-1; dx<=1; dx++)
     116        {
     117            var nx = px+dx;
     118            for (var dy=-1; dy<=1; dy++)
     119            {
     120                var ny = py+dy;
     121               
     122                if (g_Map.validT(nx, ny) && g_Map.area[nx][ny] == area && !saw[nx][ny])
     123                {
     124                    saw[nx][ny] = 1;
     125                    dist[nx][ny] = d+1;
     126                    pointQ.push(new Point(nx, ny));
     127                }
     128            }
     129        }
     130    }
     131};
     132
     133/////////////////////////////////////////////////////////////////////////////
     134//  MultiPainter
     135/////////////////////////////////////////////////////////////////////////////
     136   
     137function MultiPainter(painters)
     138{
     139    this.painters = painters;
     140}
     141
     142MultiPainter.prototype.paint = function(area)
     143{
     144    for (var i=0; i < this.painters.length; i++)
     145    {
     146        this.painters[i].paint(area);
     147    }
     148};
     149
     150/////////////////////////////////////////////////////////////////////////////
     151//  SmoothElevationPainter
     152/////////////////////////////////////////////////////////////////////////////
     153
     154function SmoothElevationPainter(type, elevation, blendRadius)
     155{
     156    this.type = type;
     157    this.elevation = elevation;
     158    this.blendRadius = blendRadius;
     159   
     160    if (type != ELEVATION_SET && type != ELEVATION_MODIFY)
     161        error("SmoothElevationPainter: invalid type '"+type+"'");
     162}
     163
     164SmoothElevationPainter.prototype.checkInArea = function(area, x, y)
     165{
     166    if (g_Map.validT(x, y))
     167    {
     168        return g_Map.area[x][y] == area;
     169    }
     170    else
     171    {
     172        return false;
     173    }
     174};
     175
     176SmoothElevationPainter.prototype.paint = function(area)
     177{
     178    var pointQ = [];
     179    var pts = area.points;
     180    var heightPts = [];
     181   
     182    var mapSize = getMapSize()+1;
     183   
     184    var saw = new  Array(mapSize);
     185    var dist = new Array(mapSize);
     186    var gotHeightPt = new Array(mapSize);
     187    var newHeight = new Array(mapSize);
     188   
     189    // init typed arrays
     190    for (var i = 0; i < mapSize; ++i)
     191    {
     192        saw[i] = new Uint8Array(mapSize);       // bool / uint8
     193        dist[i] = new Uint16Array(mapSize);     // uint16
     194        gotHeightPt[i] = new Uint8Array(mapSize);   // bool / uint8
     195        newHeight[i] = new Float32Array(mapSize);   // float32
     196    }
     197   
     198    var length = pts.length;
     199   
     200    // get a list of all points
     201    for (var i=0; i < length; i++)
     202    {
     203        var x = pts[i].x;
     204        var y = pts[i].y;
     205       
     206        for (var dx=-1; dx <= 2; dx++)
     207        {
     208            var nx = x+dx;
     209            for (var dy=-1; dy <= 2; dy++)
     210            {
     211                var ny = y+dy;
     212               
     213                if (g_Map.validH(nx, ny) && !gotHeightPt[nx][ny])
     214                {
     215                    gotHeightPt[nx][ny] = 1;
     216                    heightPts.push(new Point(nx, ny));
     217                    newHeight[nx][ny] = g_Map.height[nx][ny];
     218                }
     219            }
     220        }
     221    }
     222
     223    // push edge points
     224    for (var i=0; i < length; i++)
     225    {
     226        var x = pts[i].x, y = pts[i].y;
     227        for (var dx=-1; dx <= 2; dx++)
     228        {
     229            var nx = x+dx;
     230            for (var dy=-1; dy <= 2; dy++)
     231            {
     232                var ny = y+dy;
     233               
     234                if (g_Map.validH(nx, ny)
     235                    && !this.checkInArea(area, nx, ny)
     236                    && !this.checkInArea(area, nx-1, ny)
     237                    && !this.checkInArea(area, nx, ny-1)
     238                    && !this.checkInArea(area, nx-1, ny-1)
     239                    && !saw[nx][ny])
     240                {
     241                    saw[nx][ny]= 1;
     242                    dist[nx][ny] = 0;
     243                    pointQ.push(new Point(nx, ny));
     244                }
     245            }
     246        }
     247    }
     248
     249    // do BFS inwards to find distances to edge
     250    while(pointQ.length)
     251    {
     252        var pt = pointQ.shift();
     253        var px = pt.x;
     254        var py = pt.y;
     255        var d = dist[px][py];
     256
     257        // paint if in area
     258        if (g_Map.validH(px, py)
     259            && (this.checkInArea(area, px, py) || this.checkInArea(area, px-1, py)
     260            || this.checkInArea(area, px, py-1) || this.checkInArea(area, px-1, py-1)))
     261        {
     262            if (d <= this.blendRadius)
     263            {
     264                var a = (d-1) / this.blendRadius;
     265                if (this.type == ELEVATION_SET)
     266                {
     267                    newHeight[px][py] = a*this.elevation + (1-a)*g_Map.height[px][py];
     268                }
     269                else
     270                {   // type == MODIFY
     271                    newHeight[px][py] += a*this.elevation;
     272                }
     273            }
     274            else
     275            {   // also happens when blendRadius == 0
     276                if (this.type == ELEVATION_SET)
     277                {
     278                    newHeight[px][py] = this.elevation;
     279                }
     280                else
     281                {   // type == MODIFY
     282                    newHeight[px][py] += this.elevation;
     283                }
     284            }
     285        }
     286
     287        // enqueue neighbours
     288        for (var dx=-1; dx <= 1; dx++)
     289        {
     290            var nx = px+dx;
     291            for (var dy=-1; dy <= 1; dy++)
     292            {
     293                var ny = py+dy;
     294               
     295                if (g_Map.validH(nx, ny)
     296                    && (this.checkInArea(area, nx, ny) || this.checkInArea(area, nx-1, ny)
     297                        || this.checkInArea(area, nx, ny-1) || this.checkInArea(area, nx-1, ny-1))
     298                    && !saw[nx][ny])
     299                {
     300                    saw[nx][ny] = 1;
     301                    dist[nx][ny] = d+1;
     302                    pointQ.push(new Point(nx, ny));
     303                }
     304            }
     305        }
     306    }
     307
     308    length = heightPts.length;
     309   
     310    // smooth everything out
     311    for (var i = 0; i < length; ++i)
     312    {
     313        var pt = heightPts[i];
     314        var px = pt.x;
     315        var py = pt.y;
     316       
     317        if ((this.checkInArea(area, px, py) || this.checkInArea(area, px-1, py)
     318            || this.checkInArea(area, px, py-1) || this.checkInArea(area, px-1, py-1)))
     319        {
     320            var sum = 8 * newHeight[px][py];
     321            var count = 8;
     322           
     323            for (var dx=-1; dx <= 1; dx++)
     324            {
     325                var nx = px+dx;
     326                for (var dy=-1; dy <= 1; dy++)
     327                {
     328                    var ny = py+dy;
     329                   
     330                    if (g_Map.validH(nx, ny))
     331                    {
     332                        sum += newHeight[nx][ny];
     333                        count++;
     334                    }
     335                }
     336            }
     337           
     338            g_Map.height[px][py] = sum/count;
     339        }
     340    }
     341};
     342
     343/////////////////////////////////////////////////////////////////////////////
     344//  TerrainPainter
     345/////////////////////////////////////////////////////////////////////////////
     346
     347function TerrainPainter(terrain)
     348{
     349    this.terrain = createTerrain(terrain);
     350}
     351
     352TerrainPainter.prototype.paint = function(area)
     353{
     354    var length = area.points.length;
     355    for (var i=0; i < length; i++)
     356    {
     357        var pt = area.points[i];
     358        this.terrain.place(pt.x, pt.y);
     359    }
     360};
     361
     362/////////////////////////////////////////////////////////////////////////////
     363//  TileClassPainter
     364/////////////////////////////////////////////////////////////////////////////
     365
     366function TileClassPainter(tileClass)
     367{
     368    this.tileClass = tileClass;
     369}
     370
     371TileClassPainter.prototype.paint = function(area)
     372{
     373    var length = area.points.length;
     374    for (var i=0; i < length; i++)
     375    {
     376        var pt = area.points[i];
     377        this.tileClass.add(pt.x, pt.y);
     378    }
     379};
  • 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 + (1.0/Math.max(this.smoothness,1.0/intPerim))|0;   // floor
     37   
     38    if (ctrlPts > radius * 2 * PI)
     39        ctrlPts = (radius * 2 * PI)|0 + 1;  // floor
     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 = xx|0;   // floor
     88            var j = yy|0;
     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(x|0, y|0)) // floor
     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(resultObjs[i].x|0, resultObjs[i].y|0);   // floor
     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}
     6
     7///////////////////////////////////////////////////////////
     8//  PointMap: Hash table for keeping track of points
     9
     10//~ function PointMap(size)
     11//~ {
     12    //~ this.points = new Array(size);
     13    //~ for (var i = 0; i < size; ++i)
     14    //~ {
     15        //~ this.points[i] = new Uint16Array(size);
     16    //~ }
     17//~ }
     18
     19//~ PointMap.prototype.get = function(pt)
     20//~ {
     21    //~ if (pt instanceof Point)
     22        //~ return this.points[pt.x][pt.y];
     23    //~ else
     24        //~ return undefined;
     25//~ };
     26
     27//~ PointMap.prototype.set = function(pt, val)
     28//~ {
     29    //~ if (pt instanceof Point)
     30        //~ this.points[pt.x][pt.y] = val;
     31//~ };
     32
     33//~ PointMap.prototype.add = function(pt, val)
     34//~ {
     35    //~ if (pt instanceof Point)
     36        //~ this.points[pt.x][pt.y] += val;
     37//~ };
     38 No newline at end of file
  • binaries/data/mods/public/maps/mapgen/random.js

     
     1
     2function seedRand(s)
     3{
     4    g_MT.init_genrand(s);
     5}
     6
     7function randFloat()
     8{
     9    if (arguments.length == 0)
     10    {
     11        return g_MT.genrand_real1();
     12    }
     13    else
     14    {
     15        var minVal = arguments[0];
     16        var maxVal = arguments[1];
     17       
     18        return minVal + randFloat() * (maxVal - minVal);
     19    }
     20}
     21
     22function randInt()
     23{   
     24    if (arguments.length == 1)
     25    {
     26        var maxVal = arguments[0];
     27       
     28        return g_MT.genrand_int32()%maxVal;
     29    }
     30    else
     31    {
     32        var minVal = arguments[0];
     33        var maxVal = arguments[1];
     34       
     35        return minVal + randInt(maxVal - minVal + 1);
     36    }
     37}
     38
  • 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 > 0; s = (s/2)|0)  // floor
     24    {
     25        this.vals[s + pos] += amt;
     26        pos = (pos/2)|0;    // floor
     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 + start)/i)|0];   // floor
     42            start += i;
     43        }
     44    }
     45   
     46    //
     47    while(i)
     48    {
     49        if(start+i <= end)
     50        {
     51            ret += this.vals[((nn + start)/i)|0];   // floor
     52            start += i;
     53        }
     54        i = (i/2)|0;    // floor
     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 = y|0;   // floor
     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 = (cx - dx)|0;   // floor
     114            var upperX = (cx + dx)|0;   // floor
     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
     7function Vector2D(x, y)
     8{
     9    if (arguments.length == 2)
     10    {
     11        this.set(x, y);
     12    }
     13    else
     14    {
     15        this.set(0, 0);
     16    }
     17}
     18
     19Vector2D.prototype.set = function(x, y)
     20{
     21    this.x = x;
     22    this.y = y;
     23};
     24
     25Vector2D.prototype.add = function(v)
     26{
     27    return new Vector2D(this.x + v.x, this.y + v.y);
     28};
     29
     30Vector2D.prototype.sub = function(v)
     31{
     32    return new Vector2D(this.x - v.x, this.y - v.y);
     33};
     34
     35Vector2D.prototype.mult = function(f)
     36{
     37    return new Vector2D(this.x * f, this.y * f);
     38};
     39
     40Vector2D.prototype.div = function(f)
     41{
     42    return new Vector2D(this.x / f, this.y / f);
     43};
     44
     45Vector2D.prototype.dot = function(v)
     46{
     47    return this.x * v.x + this.y * v.y;
     48};
     49
     50Vector2D.prototype.lengthSquared = function()
     51{
     52    return this.dot(this);
     53};
     54
     55Vector2D.prototype.length = function()
     56{
     57    return sqrt(this.lengthSquared());
     58};
     59
     60Vector2D.prototype.normalize = function()
     61{
     62    var mag = this.length();
     63   
     64    this.x /= mag;
     65    this.y /= mag;
     66};
     67
     68/////////////////////////////////////////////////////////////////////
     69//  Vector3D
     70/////////////////////////////////////////////////////////////////////
     71
     72function Vector3D(x, y, z)
     73{
     74    if (arguments.length == 3)
     75    {
     76        this.set(x, y, z);
     77    }
     78    else
     79    {
     80        this.set(0, 0, 0);
     81    }
     82}
     83
     84Vector3D.prototype.set = function(x, y, z)
     85{
     86    this.x = x;
     87    this.y = y;
     88    this.z = z;
     89};
     90
     91Vector3D.prototype.add = function(v)
     92{
     93    return new Vector3D(this.x + v.x, this.y + v.y, this.z + v.z);
     94};
     95
     96Vector3D.prototype.sub = function(v)
     97{
     98    return new Vector3D(this.x - v.x, this.y - v.y, this.z - v.z);
     99};
     100
     101Vector3D.prototype.mult = function(f)
     102{
     103    return new Vector3D(this.x * f, this.y * f, this.z * f);
     104};
     105
     106Vector3D.prototype.div = function(f)
     107{
     108    return new Vector3D(this.x / f, this.y / f, this.z / f);
     109};
     110
     111Vector3D.prototype.dot = function(v)
     112{
     113    return this.x * v.x + this.y * v.y + this.z * v.z;
     114};
     115
     116Vector3D.prototype.lengthSquared = function()
     117{
     118    return this.dot(this);
     119};
     120
     121Vector3D.prototype.length = function()
     122{
     123    return sqrt(this.lengthSquared());
     124};
     125
     126Vector3D.prototype.normalize = function()
     127{
     128    var mag = this.length();
     129   
     130    this.x /= mag;
     131    this.y /= mag;
     132    this.z /= mag;
     133};
     134
  • 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// actor / 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 clSettlement = createTileClass();
     45var clDirt = createTileClass();
     46var clRock = createTileClass();
     47var clFood = createTileClass();
     48var clBaseResource = createTileClass();
    5049
    5150// place players
    5251
    53 playerX = new Array(NUM_PLAYERS+1);
    54 playerY = new Array(NUM_PLAYERS+1);
    55 playerAngle = new Array(NUM_PLAYERS+1);
     52var playerX = new Array(numPlayers+1);
     53var playerY = new Array(numPlayers+1);
     54var playerAngle = new Array(numPlayers+1);
    5655
    57 startAngle = randFloat() * 2 * PI;
    58 for(i=1; i<=NUM_PLAYERS; i++) {
    59     playerAngle[i] = startAngle + i*2*PI/NUM_PLAYERS;
     56var startAngle = randFloat() * 2 * PI;
     57for (var i=1; i<=numPlayers; i++)
     58{
     59    playerAngle[i] = startAngle + i*2*PI/numPlayers;
    6060    playerX[i] = 0.5 + 0.35*cos(playerAngle[i]);
    6161    playerY[i] = 0.5 + 0.35*sin(playerAngle[i]);
    6262}
    6363
    64 for(i=1; i<=NUM_PLAYERS; i++) {
    65     println("Creating base for player " + i + "...");
     64for (var i=1; i<=numPlayers; i++)
     65{
     66    log("Creating base for player " + i + "...");
    6667   
    6768    // some constants
    68     radius = 17;
    69     cliffRadius = 2;
    70     elevation = 20;
     69    var radius = 17;
     70    var cliffRadius = 2;
     71    var elevation = 20;
    7172   
    7273    // 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);
     74    var fx = fractionToTiles(playerX[i]);
     75    var fy = fractionToTiles(playerY[i]);
     76    var ix = round(fx);
     77    var iy = round(fy);
    7778
    7879    // calculate size based on the radius
    79     size = PI * radius * radius;
     80    var size = PI * radius * radius;
    8081   
    8182    // 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
     83    var placer = new ClumpPlacer(size, 0.95, 0.6, 0, ix, iy);
     84    var terrainPainter = new LayeredPainter(
     85        [tCliff, tGrass],       // terrains
     86        [cliffRadius]       // widths
    8687    );
    87     elevationPainter = new SmoothElevationPainter(
     88    var elevationPainter = new SmoothElevationPainter(
    8889        ELEVATION_SET,          // type
    8990        elevation,              // elevation
    9091        cliffRadius             // blend radius
     
    9293    createArea(placer, [terrainPainter, elevationPainter, paintClass(clPlayer)], null);
    9394   
    9495    // 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));
     96    var rampAngle = playerAngle[i] + PI + (2*randFloat()-1)*PI/8;
     97    var rampDist = radius - 1;
     98    var rampX = round(fx + rampDist * cos(rampAngle));
     99    var rampY = round(fy + rampDist * sin(rampAngle));
    99100    placer = new ClumpPlacer(100, 0.9, 0.5, 0, rampX, rampY);
    100     painter = new SmoothElevationPainter(ELEVATION_SET, elevation-6, 5);
     101    var painter = new SmoothElevationPainter(ELEVATION_SET, elevation-6, 5);
    101102    createArea(placer, painter, null);
    102103    placer = new ClumpPlacer(75, 0.9, 0.5, 0, rampX, rampY);
    103104    painter = new TerrainPainter(tGrass);
     
    106107    // create the central dirt patch
    107108    placer = new ClumpPlacer(PI*3.5*3.5, 0.3, 0.1, 0, ix, iy);
    108109    painter = new LayeredPainter(
    109         [1,1,1],                                                // widths
    110         [tGrassDirt75, tGrassDirt50, tGrassDirt25, tDirt]       // terrains
     110        [tGrassDirt75, tGrassDirt50, tGrassDirt25, tDirt],      // terrains
     111        [1,1,1]                                 // widths
    111112    );
    112113    createArea(placer, painter, null);
    113114   
    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
     115    // create the TC and citizens
     116    var civ = getCivCode(i - 1);
     117    var group = new SimpleGroup(    // elements (type, min/max count, min/max distance)
     118        [new SimpleObject("structures/"+civ+"_civil_centre", 1,1, 0,0), new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
     119        true, null, ix, iy
    121120    );
    122121    createObjectGroup(group, i);
    123122   
    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    
    131123    // 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));
     124    var bbAngle = randFloat()*2*PI;
     125    var bbDist = 9;
     126    var bbX = round(fx + bbDist * cos(bbAngle));
     127    var bbY = round(fy + bbDist * sin(bbAngle));
    136128    group = new SimpleGroup(
    137129        [new SimpleObject(oBerryBush, 5,5, 0,2)],
    138130        true, clBaseResource, bbX, bbY
     
    140132    createObjectGroup(group, 0);
    141133   
    142134    // create mines
    143     mAngle = bbAngle;
    144     while(abs(mAngle - bbAngle) < PI/3) {
     135    var mAngle = bbAngle;
     136    while(abs(mAngle - bbAngle) < PI/3)
     137    {
    145138        mAngle = randFloat()*2*PI;
    146139    }
    147     mDist = 9;
    148     mX = round(fx + mDist * cos(mAngle));
    149     mY = round(fy + mDist * sin(mAngle));
     140    var mDist = 9;
     141    var mX = round(fx + mDist * cos(mAngle));
     142    var mY = round(fy + mDist * sin(mAngle));
    150143    group = new SimpleGroup(
    151144        [new SimpleObject(oMine, 4,4, 0,2)],
    152145        true, clBaseResource, mX, mY
     
    161154    createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
    162155   
    163156    // 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);
     157    for (var j=0; j < 10; j++)
     158    {
     159        var gAngle = randFloat()*2*PI;
     160        var gDist = 6 + randInt(9);
     161        var gX = round(fx + gDist * cos(gAngle));
     162        var gY = round(fy + gDist * sin(gAngle));
     163        group = new SimpleGroup(
     164            [new SimpleObject(aGrassShort, 3,6, 0,1, -PI/8,PI/8)],
     165            false, clBaseResource, gX, gY
     166        );
     167        createObjectGroup(group, undefined);
    172168    }
    173169}
    174170
    175171// create lakes
    176 println("Creating lakes...");
     172log("Creating lakes...");
     173//console.profile();
    177174placer = new ClumpPlacer(140, 0.8, 0.1, 0);
    178175terrainPainter = new LayeredPainter(
    179     [1,1],                                  // widths
    180     [tShoreBlend, tShore, tWater]       // terrains
     176    [tShoreBlend, tShore, tWater],      // terrains
     177    [1,1]                           // widths
    181178);
    182179elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -7, 3);
    183 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clWater)],
     180createAreas(
     181    placer,
     182    [terrainPainter, elevationPainter, paintClass(clWater)],
    184183    avoidClasses(clPlayer, 2, clWater, 20),
    185     round(1.3 * NUM_PLAYERS)
     184    round(1.3 * numPlayers)
    186185);
     186//console.profileEnd();
    187187
    188188// create bumps
    189 println("Creating bumps...");
     189log("Creating bumps...");
    190190placer = new ClumpPlacer(10, 0.3, 0.06, 0);
    191191painter = new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2);
    192 createAreas(placer, painter,
     192createAreas(
     193    placer,
     194    painter,
    193195    avoidClasses(clWater, 2, clPlayer, 0),
    194     SIZE*SIZE/100
     196    mapSize*mapSize/100
    195197);
    196198
    197199// create hills
    198 println("Creating hills...");
     200log("Creating hills...");
    199201placer = new ClumpPlacer(30, 0.2, 0.1, 0);
    200202terrainPainter = new LayeredPainter(
    201     [3],                    // widths
    202     [tCliff, [tGrass,tGrass,tGrassDirt75]]      // terrains
     203    [tCliff, [tGrass,tGrass,tGrassDirt75]],     // terrains
     204    [3]                             // widths
    203205);
    204206elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 12, 2);
    205 createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill)],
     207createAreas(
     208    placer,
     209    [terrainPainter, elevationPainter, paintClass(clHill)],
    206210    avoidClasses(clPlayer, 2, clWater, 5, clHill, 15),
    207     2 * NUM_PLAYERS
     211    2 * numPlayers
    208212);
    209213
    210214// create forests
    211 println("Creating forests...");
     215log("Creating forests...");
    212216placer = 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)],
     217painter = new LayeredPainter(
     218    [[tGrassForest, tGrass, tForest], [tGrassForest, tForest]],     // terrains
     219    [2]                                         // widths
     220    );
     221createAreas(
     222    placer,
     223    [painter, paintClass(clForest)],
    216224    avoidClasses(clPlayer, 1, clWater, 3, clForest, 10, clHill, 0),
    217     6 * NUM_PLAYERS
     225    6 * numPlayers
    218226);
    219227
    220228// create dirt patches
    221 println("Creating dirt patches...");
     229log("Creating dirt patches...");
    222230var sizes = [8,14,20];
    223 for(i=0; i<sizes.length; i++) {
     231for (i=0; i<sizes.length; i++)
     232{
    224233    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)],
     234    painter = new LayeredPainter(
     235        [[tGrass,tGrassDirt75],[tGrassDirt75,tGrassDirt50], [tGrassDirt50,tGrassDirt25]],       // terrains
     236        [1,1]                                                           // widths
     237    );
     238    createAreas(
     239        placer,
     240        [painter, paintClass(clDirt)],
    229241        avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0),
    230         SIZE*SIZE/4000
     242        mapSize*mapSize/4000
    231243    );
    232244}
    233245
    234246// create grass patches
    235 println("Creating grass patches...");
     247log("Creating grass patches...");
    236248var sizes = [5,9,13];
    237 for(i=0; i<sizes.length; i++) {
     249for (i=0; i<sizes.length; i++)
     250{
    238251    placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0);
    239252    painter = new TerrainPainter(tGrassPatch);
    240     createAreas(placer, painter,
     253    createAreas(
     254        placer,
     255        painter,
    241256        avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0),
    242         SIZE*SIZE/4000
     257        mapSize*mapSize/4000
    243258    );
    244259}
    245260
    246261// create mines
    247 println("Creating mines...");
    248 group = new SimpleGroup([new SimpleObject(oMine, 4,6, 0,2)], true, clRock);
    249 createObjectGroups(group, 0,
     262log("Creating mines...");
     263group = new SimpleGroup(
     264    [new SimpleObject(oMine, 4,6, 0,2)],
     265    true, clRock
     266);
     267createObjectGroups(
     268    group, 0,
    250269    [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clRock, 13),
    251270     new BorderTileClassConstraint(clHill, 0, 4)],
    252     3 * NUM_PLAYERS, 100
     271    3 * numPlayers, 100
    253272);
    254273
    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
     274// create small decorative rocks
     275log("Creating large decorative rocks...");
     276group = new SimpleGroup(
     277    [new SimpleObject(aRockMedium, 1,3, 0,1)],
     278    true
    261279);
    262 
    263 // 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,
     280createObjectGroups(
     281    group, undefined,
    267282    avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clSettlement, 3),
    268     SIZE*SIZE/1000, 50
     283    mapSize*mapSize/1000, 50
    269284);
    270285
    271286// 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,
     287log("Creating large decorative rocks...");
     288group = new SimpleGroup(
     289    [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
     290    true
     291);
     292createObjectGroups(
     293    group, undefined,
    276294    avoidClasses(clForest, 0, clPlayer, 0, clHill, 0, clSettlement, 5),
    277     SIZE*SIZE/2000, 50
     295    mapSize*mapSize/2000, 50
    278296);
    279297
    280298// create deer
    281 println("Creating deer...");
    282 group = new SimpleGroup([new SimpleObject(oDeer, 5,7, 0,4)], true, clFood);
     299log("Creating deer...");
     300group = new SimpleGroup(
     301    [new SimpleObject(oDeer, 5,7, 0,4)],
     302    true, clFood
     303);
    283304createObjectGroups(group, 0,
    284305    avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20, clSettlement, 5),
    285     3 * NUM_PLAYERS, 50
     306    3 * numPlayers, 50
    286307);
    287308
    288309// create sheep
    289 println("Creating sheep...");
    290 group = new SimpleGroup([new SimpleObject(oSheep, 2,3, 0,2)], true, clFood);
     310log("Creating sheep...");
     311group = new SimpleGroup(
     312    [new SimpleObject(oSheep, 2,3, 0,2)],
     313    true, clFood
     314);
    291315createObjectGroups(group, 0,
    292316    avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20, clSettlement, 5),
    293     3 * NUM_PLAYERS, 50
     317    3 * numPlayers, 50
    294318);
    295319
    296320// create straggler trees
    297 println("Creating straggler trees...");
    298 group = new SimpleGroup([new SimpleObject(oTree, 1,1, 0,0)], true);
     321log("Creating straggler trees...");
     322group = new SimpleGroup(
     323    [new SimpleObject(oTree, 1,1, 0,0)],
     324    true
     325);
    299326createObjectGroups(group, 0,
    300327    avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 1, clSettlement, 2),
    301     SIZE*SIZE/1100
     328    mapSize*mapSize/1100
    302329);
    303330
    304331// 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,
     332log("Creating small grass tufts...");
     333group = new SimpleGroup(
     334    [new SimpleObject(aGrassShort, 3,6, 0,1, -PI/8,PI/8)]
     335);
     336createObjectGroups(group, undefined,
    308337    avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0),
    309     SIZE*SIZE/90
     338    mapSize*mapSize/90
    310339);
    311340
    312341// 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,
     342log("Creating large grass tufts...");
     343group = new SimpleGroup(
     344    [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)]
     345);
     346createObjectGroups(group, undefined,
    317347    avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0),
    318     SIZE*SIZE/900
     348    mapSize*mapSize/900
    319349);
    320350
    321351// create bushes
    322 println("Creating bushes...");
    323 group = new SimpleGroup([new SimpleObject(oBushSmall, 2,4, 0,2)]);
    324 createObjectGroups(group, 0,
     352log("Creating bushes...");
     353group = new SimpleGroup(
     354    [new SimpleObject(aBushSmall, 2,4, 0,2)]
     355);
     356createObjectGroups(group, undefined,
    325357    avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1),
    326     SIZE*SIZE/2000, 50
     358    mapSize*mapSize/2000, 50
    327359);
    328360
    329361// 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,
     362log("Creating reeds...");
     363group = new SimpleGroup(
     364    [new SimpleObject(aReeds, 5,10, 0,1.5, -PI/8,PI/8)]
     365);
     366createObjectGroups(group, undefined,
    333367    [new BorderTileClassConstraint(clWater, 3, 0), new StayInTileClassConstraint(clWater, 1)],
    334     10 * NUM_PLAYERS, 100
     368    10 * numPlayers, 100
    335369);
    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
     4var tOceanDepths = "medit_sea_depths";
     5var tOceanRockDeep = "medit_sea_coral_deep";
     6var tOceanRockShallow = "medit_rocks_wet";
     7var tOceanCoral = "medit_sea_coral_plants";
     8var tBeachWet = "medit_sand_wet";
     9var tBeachDry = "medit_sand";
     10var tBeachGrass = "beach_medit_grass_50";
     11var tBeachCliff = "cliff_medit_beach";
     12var tGrassDry = ["medit_grass_field_brown", "medit_grass_field_dry", "medit_grass_field_b"];
     13var tGrass = ["medit_grass_field", "medit_grass_field_a", "medit_grass_flowers"];
     14var tGrassLush = ["grass_temperate_dry_tufts", "medit_grass_flowers"];
     15var tGrassShrubs = ["medit_grass_shrubs", "medit_grass_flowers"];
     16var tGrassRock = ["medit_rocks_grass"];
     17var tDirt = "medit_dirt";
     18var tDirtGrass = "medit_dirt_b";
     19var tDirtCliff = "medit_cliff_italia";
     20var tGrassCliff = "medit_cliff_italia_grass";
     21var tCliff = ["medit_cliff_italia", "medit_cliff_italia", "medit_cliff_italia_grass"];
     22var tForestFloor = "forestfloor_medit_dirt";
     23
     24// gaia entities
     25var oBeech = "gaia/flora_tree_euro_beech";
     26var oBerryBush = "gaia/flora_bush_berry";
     27var oCarob = "gaia/flora_tree_carob";
     28var oCypress1 = "gaia/flora_tree_cypress";
     29var oCypress2 = "gaia/flora_tree_cypress";
     30var oLombardyPoplar = "gaia/flora_tree_poplar_lombardy";
     31var oOak = "gaia/flora_tree_oak";
     32var oPalm = "gaia/flora_tree_medit_fan_palm";
     33var oPine = "gaia/flora_tree_aleppo_pine";
     34var oPoplar = "gaia/flora_tree_poplar";
     35var oSheep = "gaia/fauna_sheep";
     36var oStone = "gaia/geology_stone_greek";
     37var oMetal = "gaia/geology_metal_greek";
     38
     39// actor / props
     40var aBushLargeDry = "actor|props/flora/bush_medit_la_dry.xml";
     41var aBushLarge = "actor|props/flora/bush_medit_la.xml";
     42var aBushMedDry = "actor|props/flora/bush_medit_me_dry.xml";
     43var aBushMed = "actor|props/flora/bush_medit_me.xml";
     44var aBushSmall = "actor|props/flora/bush_medit_sm.xml";
     45var aBushSmallDry = "actor|props/flora/bush_medit_sm_dry.xml";
     46var aGrass = "actor|props/flora/grass_medit_field.xml";
     47var aGrassDry = "actor|props/flora/grass_soft_dry_small.xml";
     48var aRockLarge = "actor|geology/stone_granite_greek_large.xml";
     49var aRockMed = "actor|geology/stone_granite_greek_med.xml";
     50var aRockSmall = "actor|geology/stone_granite_greek_small.xml";
     51var 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();
     76var clSettlement = createTileClass();
     77
     78// Place players
     79
     80log("Placing players...");
     81
     82var playerX = new Array(numPlayers+1);
     83var playerY = new Array(numPlayers+1);
     84
     85var numLeftPlayers = floor(numPlayers/2);
     86for (var i=1; i <= numLeftPlayers; i++)
     87{
     88    playerX[i] = 0.28 + (2*randFloat()-1)*0.01;
     89    playerY[i] = (0.5+i-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
     90}
     91for (var i=numLeftPlayers+1; i <= numPlayers; i++)
     92{
     93    playerX[i] = 0.72 + (2*randFloat()-1)*0.01;
     94    playerY[i] = (0.5+i-numLeftPlayers-1)/numLeftPlayers + (2*randFloat()-1)*0.01;
     95}
     96
     97for (var i=1; i <= numPlayers; i++)
     98{
     99    log("Creating base for player " + i + "...");
     100   
     101    // get fractional locations in tiles
     102    var ix = round(fractionToTiles(playerX[i]));
     103    var iy = round(fractionToTiles(playerY[i]));
     104    addToClass(ix, iy, clPlayer);
     105   
     106    // create TC and starting units
     107    // TODO: Get civ specific starting units
     108    var civ = getCivCode(i - 1);
     109    placeObject("structures/"+civ + "_civil_centre", i, ix, iy, PI*3/4);
     110    var group = new SimpleGroup(
     111        [new SimpleObject("units/"+civ+"_support_female_citizen", 3,3, 5,5)],
     112        true, null, ix, iy
     113    );
     114    createObjectGroup(group, i);
     115   
     116    // create starting berry bushes
     117    var bbAngle = randFloat()*2*PI;
     118    var bbDist = 9;
     119    var bbX = round(ix + bbDist * cos(bbAngle));
     120    var bbY = round(iy + bbDist * sin(bbAngle));
     121    group = new SimpleGroup(
     122        [new SimpleObject(oBerryBush, 5,5, 0,2)],
     123        true, clBaseResource, bbX, bbY
     124    );
     125    createObjectGroup(group, 0);
     126   
     127    // create starting mines
     128    var mAngle = bbAngle;
     129    while(abs(mAngle - bbAngle) < PI/3) {
     130        mAngle = randFloat()*2*PI;
     131    }
     132    var mDist = 9;
     133    var mX = round(ix + mDist * cos(mAngle));
     134    var mY = round(iy + mDist * sin(mAngle));
     135    group = new SimpleGroup(
     136        [new SimpleObject(oStone, 2,2, 0,3),
     137        new SimpleObject(oMetal, 2,2, 0,3)],
     138        true, clBaseResource, mX, mY
     139    );
     140    createObjectGroup(group, 0);
     141   
     142    // create starting straggler trees
     143    group = new SimpleGroup(
     144        [new SimpleObject(oPalm, 3,3, 7,10)],
     145        true, clBaseResource, ix, iy
     146    );
     147    createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
     148}
     149
     150function distanceToPlayers(x, y)
     151{
     152    var r = 10000;
     153    for (var i=1; i <= numPlayers; i++)
     154    {
     155        var dx = x - playerX[i];
     156        var dy = y - playerY[i];
     157        r = min(r, dx*dx + dy*dy);
     158    }
     159    return sqrt(r);
     160}
     161
     162function playerNearness(x, y)
     163{
     164    var d = fractionToTiles(distanceToPlayers(x,y));
     165   
     166    if (d < 13)
     167        return 0;
     168    else if (d < 19)
     169        return (d-13)/(19-13);
     170    else
     171        return 1;
     172}
     173
     174// Paint elevation
     175
     176log("Painting elevation...");
     177
     178var noise0 = new Noise2D(4 * mapSize/128);
     179var noise1 = new Noise2D(8 * mapSize/128);
     180var noise2 = new Noise2D(15 * mapSize/128);
     181
     182var noise2a = new Noise2D(20 * mapSize/128);
     183var noise2b = new Noise2D(35 * mapSize/128);
     184
     185var noise3 = new Noise2D(4 * mapSize/128);
     186var noise4 = new Noise2D(6 * mapSize/128);
     187var noise5 = new Noise2D(11 * mapSize/128);
     188
     189for (var ix=0; ix<=mapSize; ix++)
     190{
     191    for (var iy=0; iy<=mapSize; iy++)
     192    {
     193        var x = ix / (mapSize + 1.0);
     194        var y = iy / (mapSize + 1.0);
     195        var pn = playerNearness(x, y);
     196       
     197        var h = 0;
     198        var distToWater = 0;
     199       
     200        h = 32 * (x - 0.5);
     201       
     202        // add the rough shape of the water
     203        if (x < WATER_WIDTH)
     204        {
     205            h = max(-16.0, -28.0*(WATER_WIDTH-x)/WATER_WIDTH);
     206        }
     207        else if (x > 1.0-WATER_WIDTH)
     208        {
     209            h = max(-16.0, -28.0*(x-(1.0-WATER_WIDTH))/WATER_WIDTH);
     210        }
     211        else
     212        {
     213            distToWater = (0.5 - WATER_WIDTH - abs(x-0.5));
     214            var u = 1 - abs(x-0.5) / (0.5-WATER_WIDTH);
     215            h = 12*u;
     216        }
     217       
     218        // add some base noise
     219        var baseNoise = 16*noise0.get(x,y) + 8*noise1.get(x,y) + 4*noise2.get(x,y) - (16+8+4)/2;
     220        if ( baseNoise < 0 )
     221        {
     222            baseNoise *= pn;
     223            baseNoise *= max(0.1, distToWater / (0.5-WATER_WIDTH));
     224        }
     225        var oldH = h;
     226        h += baseNoise;
     227       
     228        // add some higher-frequency noise on land
     229        if ( oldH > 0 )
     230        {
     231            h += (0.4*noise2a.get(x,y) + 0.2*noise2b.get(x,y)) * min(oldH/10.0, 1.0);
     232        }
     233       
     234        // create cliff noise
     235        if ( h > -10 )
     236        {
     237            var cliffNoise = (noise3.get(x,y) + 0.5*noise4.get(x,y)) / 1.5;
     238            if (h < 1)
     239            {
     240                var u = 1 - 0.3*((h-1)/-10);
     241                cliffNoise *= u;
     242            }
     243            cliffNoise += 0.05 * distToWater / (0.5 - WATER_WIDTH);
     244            if (cliffNoise > 0.6)
     245            {
     246                var u = 0.8 * (cliffNoise - 0.6);
     247                cliffNoise += u * noise5.get(x,y);
     248                cliffNoise /= (1 + u);
     249            }
     250            cliffNoise -= 0.59;
     251            cliffNoise *= pn;
     252            if (cliffNoise > 0)
     253            {
     254                h += 19 * min(cliffNoise, 0.045) / 0.045;
     255            }
     256        }
     257       
     258        // set the height
     259        setHeight(ix, iy, h);
     260    }
     261}
     262
     263// Paint base terrain
     264
     265log("Painting terrain...");
     266
     267var noise6 = new Noise2D(10 * mapSize/128);
     268var noise7 = new Noise2D(20 * mapSize/128);
     269
     270var noise8 = new Noise2D(13 * mapSize/128);
     271var noise9 = new Noise2D(26 * mapSize/128);
     272
     273var noise10 = new Noise2D(50 * mapSize/128);
     274
     275for (var ix=0; ix<mapSize; ix++)
     276{
     277    for (var iy=0; iy<mapSize; iy++)
     278    {
     279        var x = ix / (mapSize + 1.0);
     280        var y = iy / (mapSize + 1.0);
     281        var pn = playerNearness(x, y);
     282       
     283        // get heights of surrounding vertices
     284        var h00 = getHeight(ix, iy);
     285        var h01 = getHeight(ix, iy+1);
     286        var h10 = getHeight(ix+1, iy);
     287        var h11 = getHeight(ix+1, iy+1);
     288       
     289        // find min and max height
     290        var maxH = Math.max(h00, h01, h10, h11);
     291        var minH = Math.min(h00, h01, h10, h11);
     292       
     293        // figure out if we're at the top of a cliff using min adjacent height
     294        var minAdjHeight = minH;
     295        if (maxH > 15)
     296        {
     297            for (var nx=max(ix-1, 0); nx<=min(ix+2, mapSize); nx++)
     298            {
     299                for (var ny=max(iy-1, 0); ny<=min(iy+2, mapSize); ny++)
     300                {
     301                    minAdjHeight = min(minAdjHeight, getHeight(nx, ny));
     302                }
     303            }
     304        }
     305       
     306        // choose a terrain based on elevation
     307        var t = tGrass;
     308       
     309        // water
     310        if (maxH < -12)
     311        {
     312            t = tOceanDepths;
     313        }
     314        else if (maxH < -8.8)
     315        {
     316            t = tOceanRockDeep;
     317        }
     318        else if (maxH < -4.7)
     319        {
     320            t = tOceanCoral;
     321        }
     322        else if (maxH < -2.8)
     323        {
     324            t = tOceanRockShallow;
     325        }
     326        else if (maxH < 0.9 && minH < 0.35)
     327        {
     328            t = tBeachWet;
     329        }
     330        else if (maxH < 1.5 && minH < 0.9)
     331        {
     332            t = tBeachDry;
     333        }
     334        else if (maxH < 2.3 && minH < 1.3)
     335        {
     336            t = tBeachGrass;
     337        }
     338       
     339        if (minH < 0)
     340        {
     341            addToClass(ix, iy, clWater);
     342        }
     343       
     344        // cliffs
     345        if (maxH - minH > 2.9 && minH > -7)
     346        {
     347            t = tCliff;
     348            addToClass(ix, iy, clCliff);
     349        }
     350        else if ((maxH - minH > 2.5 && minH > -5) || (maxH-minAdjHeight > 2.9 && minH > 0) )
     351        {
     352            if (minH < -1)
     353                t = tCliff;
     354            else if (minH < 0.5)
     355                t = tBeachCliff;
     356            else
     357                t = [tDirtCliff, tGrassCliff, tGrassCliff, tGrassRock, tCliff];
     358           
     359            addToClass(ix, iy, clCliff);
     360        }
     361       
     362        // forests
     363        if (maxH - minH < 1 && minH > 1)
     364        {
     365            var forestNoise = (noise6.get(x,y) + 0.5*noise7.get(x,y)) / 1.5 * pn;
     366            forestNoise -= 0.59;
     367           
     368            if (forestNoise > 0)
     369            {
     370                if (minH > 5)
     371                {
     372                    var typeNoise = noise10.get(x,y);
     373                   
     374                    if (typeNoise < 0.43 && forestNoise < 0.05)
     375                        t = tPoplarForest;
     376                    else if (typeNoise < 0.63)
     377                        t = tMainForest;
     378                    else
     379                        t = tPineForest;
     380                   
     381                    addToClass(ix, iy, clForest);
     382                }
     383                else if (minH < 3)
     384                {
     385                    t = tPalmForest;
     386                    addToClass(ix, iy, clForest);
     387                }
     388            }
     389        }
     390       
     391        // grass variations
     392        if (t == tGrass)
     393        {
     394            var grassNoise = (noise8.get(x,y) + 0.6*noise9.get(x,y)) / 1.6;
     395            if (grassNoise < 0.3)
     396            {
     397                t = (maxH - minH > 1.2) ? tDirtCliff : tDirt;
     398            }
     399            else if (grassNoise < 0.34)
     400            {
     401                t = (maxH - minH > 1.2) ? tGrassCliff : tGrassDry;
     402                if (maxH - minH < 0.5 && randFloat() < 0.03)
     403                {
     404                    placeObject(aGrassDry, 0, ix+randFloat(), iy+randFloat(), randFloat()*2*PI);
     405                }
     406            }
     407            else if (grassNoise > 0.61)
     408            {
     409                t = ((maxH - minH) > 1.2 ? tGrassRock : tGrassShrubs);
     410            }
     411            else
     412            {
     413                if ((maxH - minH) < 0.5 && randFloat() < 0.05)
     414                {
     415                    placeObject(aGrass, 0, ix+randFloat(), iy+randFloat(), randFloat()*2*PI);
     416                }
     417            }
     418        }
     419       
     420        placeTerrain(ix, iy, t);
     421    }
     422}
     423
     424log("Placing straggler trees...");
     425// create straggler trees
     426var trees = [oCarob, oBeech, oLombardyPoplar, oLombardyPoplar, oPine];
     427for (var t in trees)
     428{
     429    group = new SimpleGroup([new SimpleObject(trees[t], 1,1, 0,1)], true, clForest);
     430    createObjectGroups(group, 0,
     431        avoidClasses(clWater, 5, clCliff, 0, clForest, 1, clSettlement, 4, clPlayer, 15),
     432        mapSize*mapSize/7000, 50
     433    );
     434}
     435
     436log("Placing cypress trees...");
     437// create cypresses
     438group = new SimpleGroup(
     439    [new SimpleObject(oCypress2, 1,3, 0,3),
     440    new SimpleObject(oCypress1, 0,2, 0,2)]
     441);
     442createObjectGroups(group, 0,
     443    avoidClasses(clWater, 4, clCliff, 2, clForest, 1, clSettlement, 4, clPlayer, 15),
     444    mapSize*mapSize/3500, 50
     445);
     446
     447log("Placing bushes...");
     448// create bushes
     449group = new SimpleGroup(
     450    [new SimpleObject(aBushSmall, 0,2, 0,2), new SimpleObject(aBushSmallDry, 0,2, 0,2),
     451    new SimpleObject(aBushMed, 0,1, 0,2), new SimpleObject(aBushMedDry, 0,1, 0,2)]
     452);
     453createObjectGroups(group, 0,
     454    avoidClasses(clWater, 4, clCliff, 2),
     455    mapSize*mapSize/1800, 50
     456);
     457
     458log("Placing rocks...");
     459// create rocks
     460group = new SimpleGroup(
     461    [new SimpleObject(aRockSmall, 0,3, 0,2), new SimpleObject(aRockMed, 0,2, 0,2),
     462    new SimpleObject(aRockLarge, 0,1, 0,2)]
     463);
     464createObjectGroups(group, 0,
     465    avoidClasses(clWater, 0, clCliff, 0),
     466    mapSize*mapSize/1800, 50
     467);
     468
     469log("Placing stone mines...");
     470// create stone
     471group = new SimpleGroup([new SimpleObject(oStone, 2,3, 0,2)], true, clStone);
     472createObjectGroups(group, 0,
     473    [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clStone, 15, clSettlement, 4),
     474     new BorderTileClassConstraint(clCliff, 0, 5)],
     475    3 * numPlayers, 100
     476);
     477
     478log("Placing metal mines...");
     479// create metal
     480group = new SimpleGroup([new SimpleObject(oMetal, 2,3, 0,2)], true, clMetal);
     481createObjectGroups(group, 0,
     482    [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clMetal, 15, clStone, 5, clSettlement, 4),
     483     new BorderTileClassConstraint(clCliff, 0, 5)],
     484    3 * numPlayers, 100
     485);
     486
     487log("Placing sheep...");
     488// create sheep
     489group = new SimpleGroup([new SimpleObject(oSheep, 2,4, 0,2)], true, clFood);
     490createObjectGroups(group, 0,
     491    avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20, clMetal, 2, clStone, 2, clFood, 8, clSettlement, 4),
     492    3 * numPlayers, 100
     493);
     494
     495log("Placing berry bushes...");
     496// create berry bushes
     497group = new SimpleGroup([new SimpleObject(oBerryBush, 5,7, 0,3)], true, clFood);
     498createObjectGroups(group, 0,
     499    avoidClasses(clWater, 5, clForest, 1, clCliff, 1, clPlayer, 20, clMetal, 2, clStone, 2, clFood, 8, clSettlement, 4),
     500    1.5 * numPlayers, 100
     501);
  • 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/new_rms_test.js

     
     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
  • binaries/data/mods/public/maps/random/test.js

    Property changes on: binaries\data\mods\public\maps\random\new_rms_test.json
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    1 const SIZE = 160;
    2 
    3 const sand = "beach_medit_dry";
    4 const grass1 = "grass_temperate_a";
    5 const grass2 = "grass_mediterranean_green_flowers";
    6 const forestFloor = "forrestfloor";
    7 const dirt1 = "grass_sand_75";
    8 const dirt2 = "grass_sand_50";
    9 const dirt3 = "dirt_brown_e";
    10 const cliffBase = "cliff base a";
    11 const cliffBeach = "beech_cliff_a_75";
    12 const cliff = "cliff_face3";
    13 
    14 const oTree = "flora_tree_oak";
    15 const oGrass = "props/flora/grass_soft_small.xml"
    16 const oMine = "geology_stone_light";
    17 
    18 // Initialize
    19 
    20 init(SIZE, grass1, 0);
    21 
    22 // Create classes
    23 
    24 clImpassable = createTileClass();
    25 clRock = createTileClass();
    26 
    27 // Paint elevation
    28 
    29 noise0 = new Noise2D(4 * SIZE/128.0);
    30 noise1 = new Noise2D(8 * SIZE/128.0);
    31 noise2 = new Noise2D(11 * SIZE/128.0);
    32 noise3 = new Noise2D(30 * SIZE/128.0);
    33 noise4 = new Noise2D(60 * SIZE/128.0);
    34 
    35 for(ix=0; ix<SIZE+1; ix++) {
    36     for(iy=0; iy<SIZE+1; iy++) {
    37         x = ix / (SIZE + 1.0);
    38         y = iy / (SIZE + 1.0);
    39        
    40         // Calculate base noise
    41         n = (noise0.eval(x, y) + 0.4 * noise1.eval(x, y)) / 1.4;
    42        
    43         T = .4; // Water cutoff
    44        
    45         if(n < T) {
    46             // Tile is underwater - just scale the height down a bit
    47             h = Math.max(-50 * (T-n)/T, -8);
    48         }
    49         else {
    50             // Tile is above water - add some land noise depending on how far we are from the shoreline
    51             u = 27*noise1.eval(x, y) + 14*noise2.eval(x,y) + 9 * noise3.eval(x,y) - 14;
    52             h = 8*(n-T) + Math.max(0, lerp(0, u, Math.min(.1, n-T)*10));
    53             h += 0.4*noise4.eval(x, y);
    54         }
    55        
    56         setHeight(ix, iy, h);
    57     }
    58 }
    59 
    60 // Paint terrains
    61 
    62 for(ix=0; ix<SIZE; ix++) {
    63     for(iy=0; iy<SIZE; iy++) {
    64         h00 = getHeight(ix, iy);
    65         h01 = getHeight(ix, iy+1);
    66         h10 = getHeight(ix+1, iy);
    67         h11 = getHeight(ix+1, iy+1);
    68         maxH = Math.max(h00, h01, h10, h11);
    69         minH = Math.min(h00, h01, h10, h11);
    70         if(maxH <= 0) {
    71             setTexture(ix, iy, sand);
    72             addToClass(ix, iy, clImpassable);
    73         }
    74         else if(maxH - minH > 3.2) {
    75             setTexture(ix, iy, cliff);
    76             addToClass(ix, iy, clImpassable);
    77         }
    78         else if(maxH - minH > 2.7) {
    79             setTexture(ix, iy, cliffBase);
    80             addToClass(ix, iy, clImpassable);
    81         }
    82         else if(minH <= 0) {
    83             setTexture(ix, iy, sand);
    84             addToClass(ix, iy, clImpassable);
    85         }
    86         else {
    87             setTexture(ix, iy, grass1);
    88         }
    89     }
    90 }
    91 
    92 // Paint forest and dirt
    93 
    94 forestNoise1 = new Noise2D(20 * SIZE/128.0);
    95 forestNoise2 = new Noise2D(40 * SIZE/128.0);
    96 dirtNoise = new Noise2D(80 * SIZE/128.0);
    97 
    98 for(ix=0; ix<SIZE; ix++) {
    99     for(iy=0; iy<SIZE; iy++) {
    100         x = ix / (SIZE + 1.0);
    101         y = iy / (SIZE + 1.0);
    102         h00 = getHeight(ix, iy);
    103         h01 = getHeight(ix, iy+1);
    104         h10 = getHeight(ix+1, iy);
    105         h11 = getHeight(ix+1, iy+1);
    106         maxH = Math.max(h00, h01, h10, h11);
    107         minH = Math.min(h00, h01, h10, h11);
    108         if(maxH - minH < 1.7 && minH > 0) {
    109             fn = (forestNoise1.eval(x,y) + .5*forestNoise1.eval(x,y)) / 1.5;
    110            
    111             if(minH > .5 && fn < .38 && dirtNoise.eval(x,y) > .55) {
    112                 if(dirtNoise.eval(x,y) > .72) {
    113                     setTexture(ix, iy, dirt2);
    114                 }
    115                 else {
    116                     setTexture(ix, iy, dirt1);
    117                 }
    118             }
    119            
    120             if(fn > .6 && randFloat() < (.3 + .7 * Math.min(fn-.6, .1) / .1) ) {
    121                 placeObject(oTree, 0, ix+.4+.2*randFloat(), iy+.4+.2*randFloat(), randFloat()*2*Math.PI);
    122                 addToClass(ix, iy, clImpassable);
    123                 if(randFloat() < .7) {
    124                     setTexture(ix, iy, forestFloor);
    125                 }
    126             }
    127         }
    128     }
    129 }
    130 
    131 println("Creating mines...");
    132 group = new SimpleGroup([new SimpleObject(oMine, 3,4, 0,2)], true, clRock);
    133 createObjectGroups(group, 0,
    134     new AvoidTileClassConstraint(clImpassable, 2, clRock, 13),
    135     12, 100
    136 );
    137 
  • binaries/data/mods/public/maps/random/test2.js

     
    1 //TODO: Move to some library file?
    2 
    3 
    4 initFromScenario("mediterannean", LOAD_ALL);
    5 
  • binaries/data/mods/public/maps/test.html

     
     1
     2<script type="text/javascript">
     3    function log(text)
     4    {
     5        document.writeln(text+"<br />");
     6    }
     7   
     8    // Check for typed arrays
     9    if (typeof(Float32Array) == "undefined")
     10    {
     11        log("No typed array support, using Array...");
     12       
     13        // Standard arrays
     14        function Float32Array(size)
     15        {
     16            var arr = new Array(size);
     17            for (var i = 0; i < size; ++i)
     18                arr[i] = 0;
     19               
     20            return arr;
     21        }
     22        function Uint16Array(size)
     23        {
     24            var arr = new Array(size);
     25            for (var i = 0; i < size; ++i)
     26                arr[i] = 0;
     27               
     28            return arr;
     29        }
     30        function Int16Array(size)
     31        {
     32            var arr = new Array(size);
     33            for (var i = 0; i < size; ++i)
     34                arr[i] = 0;
     35               
     36            return arr;
     37        }
     38        function Uint8Array(size)
     39        {
     40            var arr = new Array(size);
     41            for (var i = 0; i < size; ++i)
     42                arr[i] = 0;
     43               
     44            return arr;
     45        }
     46    }
     47</script>
     48
     49<script src="mapgen/area.js"></script>
     50<script src="mapgen/constraint.js"></script>
     51<script src="mapgen/library.js"></script>
     52<script src="mapgen/map.js"></script>
     53<script src="mapgen/mapgen.js"></script>
     54<script src="mapgen/MersenneTwister19937.js"></script>
     55<script src="mapgen/noise.js"></script>
     56<script src="mapgen/object.js"></script>
     57<script src="mapgen/painter.js"></script>
     58<script src="mapgen/placer.js"></script>
     59<script src="mapgen/point.js"></script>
     60<script src="mapgen/random.js"></script>
     61<script src="mapgen/terrain.js"></script>
     62<script src="mapgen/tileclass.js"></script>
     63<script src="mapgen/vector.js"></script>
     64
     65<script type="text/javascript">
     66    // Settings to pass into map generator
     67    var settings = {
     68        Size: 176,
     69        Seed: 0,
     70        BaseTerrain: ["medit_grass_field", "medit_grass_field_a", "medit_grass_flowers"],
     71        BaseHeight: 0,
     72        PlayerData: [
     73            { Civ : "hele"},
     74            { Civ : "hele"},
     75            { Civ : "hele"},
     76            { Civ : "hele"}
     77        ]
     78    };
     79   
     80    InitMapGen(settings);
     81</script>
     82
     83<!--<script src="random/cantabrian_highlands.js"></script> -->
     84<script src="random/latium.js"></script>
     85
     86<script type="text/javascript">
     87    var output = SaveMap();
     88    log("Done!!");
     89   
     90    // Print results
     91    log("----------------------------------------------------------------------");
     92    log("Number of entities="+output.entities.length);
     93    for (var i = 0; i < output.entities.length; ++i)
     94    {
     95        var e = output.entities[i];
     96        log("Entity "+ e.id +" = " + e.name + " ("+e.x + ", "+e.y+ ")  player="+e.player);
     97    }
     98   
     99    log("----------------------------------------------------------------------");
     100    log("Number of textures="+output.numTextures);
     101    for (var i = 0; i < output.numTextures; ++i)
     102    {
     103        log("Texture "+ i +" = " + output.textureNames[i]);
     104    }
     105   
     106</script>
     107 No newline at end of file
  • source/graphics/Entity.h

     
     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 "ps/CLogger.h"
     23
     24#define LOG_CATEGORY L"graphics"
     25
     26CMapGenerator::CMapGenerator() : m_ScriptInterface("Generator")
     27{
     28    // load mapgen libraries
     29    LoadLibraries();
     30}
     31
     32CScriptValRooted CMapGenerator::GenerateMap(const CStrW& scriptFile, const CScriptValRooted& settings)
     33{
     34    // Init map generator
     35    jsval global = m_ScriptInterface.GetGlobalObject();
     36
     37    if (!m_ScriptInterface.CallFunctionVoid(global, "InitMapGen", settings))
     38    {
     39        LOGERROR(L"GenerateMap: Error calling 'InitMapGen' library function");
     40        return CScriptValRooted();
     41    }
     42
     43    // Load RMS
     44    LoadScript(scriptFile);
     45
     46    // Run save function
     47    CScriptValRooted ret;
     48    if (!m_ScriptInterface.CallFunction(global, "SaveMap", ret))
     49    {   
     50        LOGERROR(L"GenerateMap: Error calling 'SaveMap' library function");
     51        return CScriptValRooted();
     52    }
     53
     54    return ret;
     55}
     56
     57void CMapGenerator::LoadLibraries()
     58{
     59    VfsPaths pathnames;
     60
     61    // Load all scripts in mapgen directory
     62    if (fs_util::GetPathnames(g_VFS, VfsPath(L"maps/mapgen/"), L"*.js", pathnames) < 0)
     63        LOGERROR(L"Error reading scripts in directory: maps/mapgen/");
     64
     65    for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
     66    {
     67        LoadScript(it->string());
     68    }
     69}
     70
     71CScriptValRooted CMapGenerator::LoadScript(const std::wstring& filename)
     72{
     73    LOGMESSAGE(L"Loading map generator script '%ls'", filename.c_str());
     74
     75    VfsPath path(filename);
     76
     77    if (!FileExists(g_VFS, path))
     78    {
     79        LOGERROR(L"Script file '%ls' does not exist", filename.c_str());
     80        return CScriptValRooted();
     81    }
     82
     83    CVFSFile file;
     84
     85    PSRETURN ret = file.Load(g_VFS, path);
     86
     87    if (ret != PSRETURN_OK)
     88    {
     89        LOGERROR(L"Failed to load script '%ls': %hs", filename.c_str(), GetErrorString(ret));
     90        return CScriptValRooted();
     91    }
     92
     93    CScriptValRooted retVal;
     94    if (!m_ScriptInterface.Eval(file.GetAsString().c_str(), retVal))
     95    {
     96        LOGERROR(L"Failed to eval script '%ls'", filename.c_str());
     97        return CScriptValRooted();
     98    }
     99
     100    return retVal;
     101}
     102
     103ScriptInterface& CMapGenerator::GetScriptInterface()
     104{
     105    return m_ScriptInterface;
     106}
     107 No newline at end of file
  • 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 "MapIO.h"
     22#include "lib/res/handle.h"
     23#include "ps/CStr.h"
     24#include "ps/FileIo.h"
     25#include "scriptinterface/ScriptInterface.h"
     26
     27
     28class CScriptValRooted;
     29class ScriptInterface;
     30
     31
     32class CMapGenerator
     33{
     34
     35public:
     36    // constructor
     37    CMapGenerator();
     38
     39    CScriptValRooted GenerateMap(const CStrW& scriptFile, const CScriptValRooted& settings);
     40
     41    ScriptInterface& GetScriptInterface();
     42
     43private:
     44
     45    void LoadLibraries();
     46
     47    CScriptValRooted LoadScript(const std::wstring& filename);
     48
     49    ScriptInterface m_ScriptInterface;
     50
     51};
     52
     53#endif
     54 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 = L"maps/random/"+m_ScriptFile;
     1416
     1417    // Copy map settings from simulator to mapgen context
     1418    CScriptValRooted scriptSettings(mapGen.GetScriptInterface().GetContext(), mapGen.GetScriptInterface().CloneValueFromOtherContext(pSimulation2->GetScriptInterface(), m_ScriptSettings.get()));
     1419
     1420    CScriptValRooted mapData = mapGen.GenerateMap(scriptPath, scriptSettings);
     1421
     1422    // No map data, something bad happened
     1423    if(mapData.undefined())
     1424        throw PSERROR_File_ReadFailed("CMapReader::GenerateMap() failed to generate map");
     1425
     1426    // Copy data from mapgen to simulator context
     1427    m_MapData = CScriptValRooted(pSimulation2->GetScriptInterface().GetContext(), pSimulation2->GetScriptInterface().CloneValueFromOtherContext(mapGen.GetScriptInterface(), mapData.get()));
     1428
     1429    return 0;
     1430};
     1431
     1432
     1433int CMapReader::ParseTerrain()
     1434{
     1435    // TODO: Progressive loading
     1436
     1437    // parse terrain from map data
     1438
     1439#define GET_TERRAIN_PROPERTY(prop, out)\
     1440    if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), #prop, out))\
     1441        LOGERROR(L"CMapReader::ParseTerrain() failed to get '" L#prop L"' property");\
     1442
     1443    size_t size;
     1444    GET_TERRAIN_PROPERTY(size, size)
     1445
     1446    m_PatchesPerSide = size / PATCH_SIZE;
     1447   
     1448    // flat heightmap of u16 data
     1449    GET_TERRAIN_PROPERTY(height, m_Heightmap)
     1450
     1451    // load textures
     1452    GET_TERRAIN_PROPERTY(numTextures, num_terrain_tex)
     1453
     1454    std::vector<std::string> textureNames;
     1455    GET_TERRAIN_PROPERTY(textureNames, textureNames)
     1456
     1457    while (cur_terrain_tex < num_terrain_tex)
     1458    {
     1459        debug_assert(CTerrainTextureManager::IsInitialised()); // we need this for the terrain properties (even when graphics are disabled)
     1460        CTerrainTextureEntry* texentry = g_TexMan.FindTexture(textureNames[cur_terrain_tex]);
     1461        m_TerrainTextures.push_back(texentry);
     1462
     1463        cur_terrain_tex++;
     1464        //LDR_CHECK_TIMEOUT(cur_terrain_tex, num_terrain_tex);
     1465    }
     1466
     1467    // build tile data
     1468    m_Tiles.resize(SQR(size));
     1469
     1470    std::vector<u16> tileData;
     1471    GET_TERRAIN_PROPERTY(tileData, tileData)
     1472
     1473    size_t i;
     1474    CMapIO::STileDesc tileDesc = {0, 0xFFFF, 0};
     1475    for (i = 0; i < tileData.size(); ++i)
     1476    {
     1477        tileDesc.m_Tex1Index = tileData[i];
     1478
     1479        m_Tiles[i] = tileDesc;
     1480    }
     1481
     1482    // reset generator state
     1483    cur_terrain_tex = 0;
     1484
     1485#undef GET_TERRAIN_PROPERTY
     1486
     1487    return 0;
     1488}
     1489
     1490int CMapReader::ParseEntities()
     1491{
     1492    // parse entities from map data
     1493    std::vector<Entity> entities;
     1494
     1495    if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), "entities", entities))
     1496        LOGWARNING(L"CMapReader::ParseEntities() failed to get 'entities' property");
     1497
     1498    size_t entity_idx = 0;
     1499    size_t num_entities = entities.size();
     1500   
     1501    Entity currEnt;
     1502
     1503    while (entity_idx < num_entities)
     1504    {
     1505        // Get current entity struct
     1506        currEnt = entities[entity_idx];
     1507
     1508        entity_id_t ent = pSimulation2->AddEntity(currEnt.templateName, currEnt.entityID);
     1509        // Check that entity was added
     1510        if (ent == INVALID_ENTITY)
     1511        {
     1512            LOGERROR(L"Failed to load entity template '%ls'", currEnt.templateName.c_str());
     1513        }
     1514        else
     1515        {
     1516            CmpPtr<ICmpPosition> cmpPosition(*pSimulation2, ent);
     1517            if (!cmpPosition.null())
     1518            {
     1519                cmpPosition->JumpTo(entity_pos_t::FromFloat(currEnt.positionX), entity_pos_t::FromFloat(currEnt.positionZ));
     1520                cmpPosition->SetYRotation(entity_angle_t::FromFloat(currEnt.orientationY));
     1521                // TODO: other parts of the position
     1522            }
     1523
     1524            CmpPtr<ICmpOwnership> cmpOwner(*pSimulation2, ent);
     1525            if (!cmpOwner.null())
     1526                cmpOwner->SetOwner(currEnt.playerID);
     1527
     1528            if (boost::algorithm::ends_with(currEnt.templateName, L"civil_centre"))
     1529            {
     1530                // HACK: we special-case civil centre files to initialise the camera.
     1531                // This ought to be based on a more generic mechanism for indicating
     1532                // per-player camera start locations.
     1533                if (m_CameraStartupTarget == INVALID_ENTITY && currEnt.playerID == m_PlayerID && !cmpPosition.null())
     1534                    m_CameraStartupTarget = ent;
     1535
     1536            }
     1537        }
     1538
     1539        entity_idx++;
     1540    }
     1541
     1542    return 0;
     1543}
     1544
     1545int CMapReader::ParseEnvironment()
     1546{
     1547    // parse environment settings from map data
     1548
     1549#define GET_ENVIRONMENT_PROPERTY(val, prop, out)\
     1550    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
     1551        LOGWARNING(L"CMapReader::ParseEnvironment() failed to get '" L#prop L"' property");\
     1552
     1553    CScriptValRooted envObj;
     1554    GET_ENVIRONMENT_PROPERTY(m_MapData.get(), Environment, envObj)
     1555
     1556    if (envObj.undefined())
     1557    {
     1558        LOGWARNING(L"CMapReader::ParseEnvironment(): Environment settings not found");
     1559        return 0;
     1560    }
     1561
     1562    std::wstring skySet;
     1563    GET_ENVIRONMENT_PROPERTY(envObj.get(), SkySet, skySet)
     1564    pSkyMan->SetSkySet(skySet);
     1565
     1566    GET_ENVIRONMENT_PROPERTY(envObj.get(), SunColour, m_LightEnv.m_SunColor)
     1567    GET_ENVIRONMENT_PROPERTY(envObj.get(), SunElevation, m_LightEnv.m_Elevation)
     1568    GET_ENVIRONMENT_PROPERTY(envObj.get(), SunRotation, m_LightEnv.m_Rotation)
     1569    GET_ENVIRONMENT_PROPERTY(envObj.get(), TerrainAmbientColour, m_LightEnv.m_TerrainAmbientColor)
     1570    GET_ENVIRONMENT_PROPERTY(envObj.get(), UnitsAmbientColour, m_LightEnv.m_UnitsAmbientColor)
     1571
     1572
     1573    // Water properties
     1574    CScriptValRooted waterObj;
     1575    GET_ENVIRONMENT_PROPERTY(envObj.get(), Water, waterObj)
     1576
     1577    CScriptValRooted waterBodyObj;
     1578    GET_ENVIRONMENT_PROPERTY(waterObj.get(), WaterBody, waterBodyObj)
     1579
     1580    // Water level - necessary
     1581    float waterHeight;
     1582    GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Height, waterHeight)
     1583
     1584    CmpPtr<ICmpWaterManager> cmpWaterMan(*pSimulation2, SYSTEM_ENTITY);
     1585    debug_assert(!cmpWaterMan.null());
     1586    cmpWaterMan->SetWaterLevel(entity_pos_t::FromFloat(waterHeight));
     1587
     1588    // If we have graphics, get rest of settings
     1589    if (pWaterMan)
     1590    {
     1591        std::wstring waterType;
     1592        // TODO: Water type unimplemented
     1593        //GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Type, waterType)
     1594
     1595        RGBColor waterColour;
     1596        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Colour, waterColour)
     1597        pWaterMan->m_WaterColor = CColor(waterColour.X, waterColour.Y, waterColour.Z, 1.0f);
     1598
     1599        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Shininess, pWaterMan->m_Shininess)
     1600        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Waviness, pWaterMan->m_Waviness)
     1601        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Murkiness, pWaterMan->m_Murkiness)
     1602
     1603        RGBColor waterTint;
     1604        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Tint, waterTint)
     1605        pWaterMan->m_WaterTint = CColor(waterTint.X, waterTint.Y, waterTint.Z, 1.0f);
     1606
     1607        RGBColor reflectTint;
     1608        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), ReflectionTint, reflectTint)
     1609        pWaterMan->m_ReflectionTint = CColor(reflectTint.X, reflectTint.Y, reflectTint.Z, 1.0f);
     1610
     1611        GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), ReflectionTintStrength, pWaterMan->m_ReflectionTintStrength)
     1612    }
     1613
     1614    m_LightEnv.CalculateSunDirection();
     1615
     1616#undef GET_ENVIRONMENT_PROPERTY
     1617
     1618    return 0;
     1619}
     1620
     1621int CMapReader::ParseCamera()
     1622{
     1623    // parse camera settings from map data
     1624    // defaults if we don't find camera
     1625    float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
     1626    CVector3D translation = CVector3D(100, 150, -100);
     1627
     1628#define GET_CAMERA_PROPERTY(val, prop, out)\
     1629    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
     1630        LOGWARNING(L"CMapReader::ParseCamera() failed to get '" L#prop L"' property");\
     1631
     1632    CScriptValRooted cameraObj;
     1633    GET_CAMERA_PROPERTY(m_MapData.get(), Camera, cameraObj)
     1634
     1635    if (!cameraObj.undefined())
     1636    {   // If camera property exists, read values
     1637        CFixedVector3D pos;
     1638        GET_CAMERA_PROPERTY(cameraObj.get(), Position, pos)
     1639        translation = pos;
     1640
     1641        GET_CAMERA_PROPERTY(cameraObj.get(), Rotation, rotation)
     1642        GET_CAMERA_PROPERTY(cameraObj.get(), Declination, declination)
     1643    }
     1644#undef GET_CAMERA_PROPERTY
     1645
     1646    if (pGameView)
     1647    {
     1648        pGameView->GetCamera()->m_Orientation.SetXRotation(declination);
     1649        pGameView->GetCamera()->m_Orientation.RotateY(rotation);
     1650        pGameView->GetCamera()->m_Orientation.Translate(translation);
     1651        pGameView->GetCamera()->UpdateFrustum();
     1652    }
     1653
     1654    return 0;
     1655}
  • 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/World.cpp

     
    9494    }
    9595}
    9696
     97void CWorld::RegisterInit(const CStrW& scriptFile, const CScriptValRooted& settings, int playerID)
     98{
     99    // Load the map, if one was specified
     100    if (scriptFile.length())
     101    {
     102        CMapReader* reader = 0;
     103
     104        try
     105        {
     106            reader = new CMapReader;
     107            CTriggerManager* pTriggerManager = NULL;
     108            reader->LoadRandomMap(scriptFile, settings, m_Terrain,
     109                CRenderer::IsInitialised() ? g_Renderer.GetWaterManager() : NULL,
     110                CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL,
     111                &g_LightEnv, m_pGame->GetView(),
     112                m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL,
     113                pTriggerManager, m_pGame->GetSimulation2(), playerID);
     114                // fails immediately, or registers for delay loading
     115        }
     116        catch (PSERROR_File& err)
     117        {
     118            delete reader;
     119            LOGERROR(L"Failed to generate random map %ls: %hs", scriptFile.c_str(), err.what());
     120            throw PSERROR_Game_World_MapLoadFailed();
     121        }
     122    }
     123}
     124
     125
    97126/**
    98127 * Destructor.
    99128 *
  • 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

     
    2121
    2222#include "ps/utf16string.h"
    2323#include "ps/CLogger.h"
     24#include "graphics/Color.h"
     25#include "graphics/Entity.h"
    2426
    2527#include "js/jsapi.h"
    2628
     
    7981    return true;
    8082}
    8183
     84template<> bool ScriptInterface::FromJSVal<u16>(JSContext* cx, jsval v, u16& out)
     85{
     86    uint16 ret;
     87    //WARN_IF_NOT(JSVAL_IS_INT(v));
     88    if (!JS_ValueToUint16(cx, v, &ret))
     89        return false;
     90    out = ret;
     91    return true;
     92}
     93
    8294// NOTE: we can't define a jsval specialisation, because that conflicts with integer types
    8395template<> bool ScriptInterface::FromJSVal<CScriptVal>(JSContext* UNUSED(cx), jsval v, CScriptVal& out)
    8496{
     
    257269{
    258270    return FromJSVal_vector(cx, v, out);
    259271}
     272
     273template<> bool ScriptInterface::FromJSVal<std::vector<u16> >(JSContext* cx, jsval v, std::vector<u16>& out)
     274{
     275    return FromJSVal_vector(cx, v, out);
     276}
     277
     278template<> bool ScriptInterface::FromJSVal<std::vector<std::string> >(JSContext* cx, jsval v, std::vector<std::string>& out)
     279{
     280    return FromJSVal_vector(cx, v, out);
     281}
     282
     283
     284template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, jsval v, Entity& out)
     285{
     286    ScriptInterface::LocalRootScope scope(cx);
     287    if (!scope.OK())
     288        return false;
     289
     290    if (!JSVAL_IS_OBJECT(v))
     291        return false; // TODO: report type error
     292    JSObject* obj = JSVAL_TO_OBJECT(v);
     293
     294    jsval name, id, player, x, z, orient, actor;
     295
     296    if(!JS_GetProperty(cx, obj, "isActor", &actor)) return false;
     297    if (!FromJSVal(cx, actor, out.isActor)) return false;
     298
     299    if (!out.isActor)
     300    {
     301        if(!JS_GetProperty(cx, obj, "player", &player)) return false;
     302        if (!FromJSVal(cx, player, out.playerID)) return false;
     303    }
     304   
     305    if (!JS_GetProperty(cx, obj, "name", &name)) return false; // TODO: report type errors
     306    if (!JS_GetProperty(cx, obj, "id", &id)) return false;
     307    if (!JS_GetProperty(cx, obj, "x", &x)) return false;
     308    if (!JS_GetProperty(cx, obj, "y", &z)) return false;
     309    if (!JS_GetProperty(cx, obj, "orientation", &orient)) return false;
     310    // TODO: this probably has GC bugs if a getter returns an unrooted value
     311
     312    if (!FromJSVal(cx, name, out.templateName)) return false;
     313    if (!FromJSVal(cx, id, out.entityID)) return false;
     314    if (!FromJSVal(cx, x, out.positionX)) return false;
     315    if (!FromJSVal(cx, z, out.positionZ)) return false;
     316    if (!FromJSVal(cx, orient, out.orientationY)) return false;
     317
     318    return true;
     319}
     320
     321template<> bool ScriptInterface::FromJSVal<std::vector<Entity> >(JSContext* cx, jsval v, std::vector<Entity>& out)
     322{
     323    return FromJSVal_vector(cx, v, out);
     324}
     325
     326template<> bool ScriptInterface::FromJSVal<RGBColor>(JSContext* cx, jsval v, RGBColor& out)
     327{
     328    ScriptInterface::LocalRootScope scope(cx);
     329    if (!scope.OK())
     330        return false;
     331
     332    if (!JSVAL_IS_OBJECT(v))
     333        return false; // TODO: report type error
     334    JSObject* obj = JSVAL_TO_OBJECT(v);
     335
     336    jsval r, g, b;
     337    if (!JS_GetProperty(cx, obj, "r", &r)) return false; // TODO: report type errors
     338    if (!JS_GetProperty(cx, obj, "g", &g)) return false;
     339    if (!JS_GetProperty(cx, obj, "b", &b)) return false;
     340    // TODO: this probably has GC bugs if a getter returns an unrooted value
     341
     342    if (!FromJSVal(cx, r, out.X)) return false;
     343    if (!FromJSVal(cx, g, out.Y)) return false;
     344    if (!FromJSVal(cx, b, out.Z)) return false;
     345
     346    return true;
     347}
     348 No newline at end of file
  • source/scriptinterface/ScriptInterface.cpp

     
    272272        JS_SetOptions(m_cx, JSOPTION_STRICT // "warn on dubious practice"
    273273                | JSOPTION_XML // "ECMAScript for XML support: parse <!-- --> as a token"
    274274                | JSOPTION_VAROBJFIX // "recommended" (fixes variable scoping)
    275 //              | JSOPTION_JIT
     275                | JSOPTION_JIT
    276276        );
    277277
    278278        JS_SetVersion(m_cx, JSVERSION_LATEST);