Ticket #2944: wallgen_full_2015-08-16c.diff

File wallgen_full_2015-08-16c.diff, 170.3 KB (added by s0600204, 9 years ago)

Full patch this time. FeXoR's changes and mine. It's big.

  • binaries/data/mods/public/globalscripts/Templates.js

    function GetTemplateDataHelper(template, player)  
    251251            "templates": {
    252252                "tower": template.WallSet.Templates.Tower,
    253253                "gate": template.WallSet.Templates.Gate,
     254                "fort": template.WallSet.Templates.Fort || "structures/{civ}_fortress",
    254255                "long": template.WallSet.Templates.WallLong,
    255256                "medium": template.WallSet.Templates.WallMedium,
    256257                "short": template.WallSet.Templates.WallShort,
    function GetTemplateDataHelper(template, player)  
    258259            "maxTowerOverlap": +template.WallSet.MaxTowerOverlap,
    259260            "minTowerOverlap": +template.WallSet.MinTowerOverlap,
    260261        };
     262        if (template.WallSet.Templates.WallEnd)
     263            ret.wallSet.templates.end = template.WallSet.Templates.WallEnd;
     264        if (template.WallSet.Templates.WallCurveQuarter)
     265            ret.wallSet.templates.quarterCurve = template.WallSet.Templates.WallCurveQuarter;
     266        if (template.WallSet.Templates.WallCurveEighth)
     267            ret.wallSet.templates.eighthCurve = template.WallSet.Templates.WallCurveEighth;
    261268    }
    262269
    263270    if (template.WallPiece)
    264         ret.wallPiece = {"length": +template.WallPiece.Length};
     271        ret.wallPiece = {
     272            "length": +template.WallPiece.Length,
     273            "angle": +(template.WallPiece.Orientation || 1) * Math.PI,
     274            "indent": +(template.WallPiece.Indent || 0),
     275            "bend": +(template.WallPiece.Bend || 0) * Math.PI,
     276        };
    265277
    266278    return ret;
    267279}
  • binaries/data/mods/public/maps/random/belgian_uplands.js

    var mapSize = getMapSize();  
    2121// Heightmap functionality
    2222//////////
    2323
    24 // Some general heightmap settings
    25 const MIN_HEIGHT = - SEA_LEVEL; // 20, should be set in the libs!
    26 const MAX_HEIGHT = 0xFFFF/HEIGHT_UNITS_PER_METRE - SEA_LEVEL; // A bit smaler than 90, should be set in the libs!
    27 
    2824// Add random heightmap generation functionality
    2925function getRandomReliefmap(minHeight, maxHeight)
    3026{
    function getRandomReliefmap(minHeight, maxHeight)  
    3531    if (maxHeight > MAX_HEIGHT)
    3632        warn("getRandomReliefmap: Argument maxHeight is smaler then the supported maximum height of " + MAX_HEIGHT + " (const MAX_HEIGHT): " + maxHeight)
    3733    var reliefmap = [];
    38     for (var x = 0; x <= mapSize; x++)
     34    for (var x = 0; x <= mapSize; ++x)
    3935    {
    4036        reliefmap.push([]);
    41         for (var y = 0; y <= mapSize; y++)
     37        for (var y = 0; y <= mapSize; ++y)
    4238        {
    4339            reliefmap[x].push(randFloat(minHeight, maxHeight));
    4440        }
    function getRandomReliefmap(minHeight, maxHeight)  
    5046function setReliefmap(reliefmap)
    5147{
    5248    // g_Map.height = reliefmap;
    53     for (var x = 0; x <= mapSize; x++)
     49    for (var x = 0; x <= mapSize; ++x)
    5450    {
    55         for (var y = 0; y <= mapSize; y++)
     51        for (var y = 0; y <= mapSize; ++y)
    5652        {
    5753            setHeight(x, y, reliefmap[x][y]);
    5854        }
    function getMinAndMaxHeight(reliefmap)  
    6561    var height = {};
    6662    height.min = Infinity;
    6763    height.max = -Infinity;
    68     for (var x = 0; x <= mapSize; x++)
     64    for (var x = 0; x <= mapSize; ++x)
    6965    {
    70         for (var y = 0; y <= mapSize; y++)
     66        for (var y = 0; y <= mapSize; ++y)
    7167        {
    7268            if (reliefmap[x][y] < height.min)
    7369                height.min = reliefmap[x][y];
    function getRescaledReliefmap(reliefmap, minHeight, maxHeight)  
    8985    if (maxHeight > MAX_HEIGHT)
    9086        warn("getRescaledReliefmap: Argument maxHeight is smaler then the supported maximum height of " + MAX_HEIGHT + " (const MAX_HEIGHT): " + maxHeight)
    9187    var oldHeightRange = getMinAndMaxHeight(reliefmap);
    92     for (var x = 0; x <= mapSize; x++)
     88    for (var x = 0; x <= mapSize; ++x)
    9389    {
    94         for (var y = 0; y <= mapSize; y++)
     90        for (var y = 0; y <= mapSize; ++y)
    9591        {
    9692            newReliefmap[x][y] = minHeight + (reliefmap[x][y] - oldHeightRange.min) / (oldHeightRange.max - oldHeightRange.min) * (maxHeight - minHeight);
    9793        }
    function getHeightErrosionedReliefmap(reliefmap, strength)  
    105101    var newReliefmap = deepcopy(reliefmap);
    106102    strength = (strength || 1.0); // Values much higher then 1 (1.32+ for an 8 tile map, 1.45+ for a 12 tile map, 1.62+ @ 20 tile map, 0.99 @ 4 tiles) will result in a resonance disaster/self interference
    107103    var map = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]; // Default
    108     for (var x = 0; x <= mapSize; x++)
     104    for (var x = 0; x <= mapSize; ++x)
    109105    {
    110         for (var y = 0; y <= mapSize; y++)
     106        for (var y = 0; y <= mapSize; ++y)
    111107        {
    112108            var div = 0;
    113             for (var i = 0; i < map.length; i++)
     109            for (var i = 0; i < map.length; ++i)
    114110                newReliefmap[x][y] += strength / map.length * (reliefmap[(x + map[i][0] + mapSize + 1) % (mapSize + 1)][(y + map[i][1] + mapSize + 1) % (mapSize + 1)] - reliefmap[x][y]); // Not entirely sure if scaling with map.length is perfect but tested values seam to indicate it is
    115111        }
    116112    }
    var terreins = ["temp_grass_plants|gaia/flora_tree_euro_beech", "temp_grass_moss  
    173169    "temp_grass_long|gaia/flora_tree_apple", "temp_grass_clovers|gaia/flora_bush_berry", "temp_grass_clovers_2|gaia/flora_bush_grapes",
    174170    "temp_grass_plants|gaia/fauna_deer", "temp_grass_long_b|gaia/fauna_rabbit"];
    175171var numTerreins = terreins.length;
    176 for (var i = 0; i < numTerreins; i++)
     172for (var i = 0; i < numTerreins; ++i)
    177173    terreins.push("temp_grass_plants");
    178174textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 5/6 * (heightRange.max - waterHeightAdjusted), "terrain": terreins});
    179175// Unpassable woods
    var enoughTiles = false;  
    200196var tries = 0;
    201197while (!goodStartPositionsFound)
    202198{
    203     tries++;
     199    ++tries;
    204200    log("Starting giant while loop try " + tries);
    205201    // Generate reliefmap
    206202    var myReliefmap = getRandomReliefmap(heightRange.min, heightRange.max);
    207     for (var i = 0; i < 50 + mapSize/4; i++) // Cycles depend on mapsize (more cycles -> bigger structures)
     203    for (var i = 0; i < 50 + mapSize/4; ++i) // Cycles depend on mapsize (more cycles -> bigger structures)
    208204        myReliefmap = getHeightErrosionedReliefmap(myReliefmap, 1);
    209205    myReliefmap = getRescaledReliefmap(myReliefmap, heightRange.min, heightRange.max);
    210206    setReliefmap(myReliefmap);
    while (!goodStartPositionsFound)  
    217213    var lowerHeightLimit = textueByHeight[3].upperHeightLimit;
    218214    var upperHeightLimit = textueByHeight[6].upperHeightLimit;
    219215    // Check for valid points by height
    220     for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; x++)
     216    for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; ++x)
    221217    {
    222         for (var y = distToBorder + minTerrainDistToBorder; y < mapSize - distToBorder - minTerrainDistToBorder; y++)
     218        for (var y = distToBorder + minTerrainDistToBorder; y < mapSize - distToBorder - minTerrainDistToBorder; ++y)
    223219        {
    224220            var actualHeight = getHeight(x, y);
    225221            if (actualHeight > lowerHeightLimit && actualHeight < upperHeightLimit)
    226222            {
    227223                // Check for points within a valid area by height (rectangular since faster)
    228224                var isPossible = true;
    229                 for (var offX = - neededDistance; offX <= neededDistance; offX++)
     225                for (var offX = - neededDistance; offX <= neededDistance; ++offX)
    230226                {
    231                     for (var offY = - neededDistance; offY <= neededDistance; offY++)
     227                    for (var offY = - neededDistance; offY <= neededDistance; ++offY)
    232228                    {
    233229                        var testHeight = getHeight(x + offX, y + offY);
    234230                        if (testHeight <= lowerHeightLimit || testHeight >= upperHeightLimit)
    while (!goodStartPositionsFound)  
    252248    // Reduce to tiles in a circle of mapSize / 2 distance to the center (to avoid players placed in corners)
    253249    var possibleStartPositionsTemp = [];
    254250    var maxDistToCenter = mapSize / 2;
    255     for (var i = 0; i < possibleStartPositions.length; i++)
     251    for (var i = 0; i < possibleStartPositions.length; ++i)
    256252    {
    257253        var deltaX = possibleStartPositions[i][0] - mapSize / 2;
    258254        var deltaY = possibleStartPositions[i][1] - mapSize / 2;
    while (!goodStartPositionsFound)  
    270266    var maxDistToResources = distToBorder; // Has to be <= distToBorder!
    271267    var minNumLowTiles = 10;
    272268    var minNumHighTiles = 10;
    273     for (var i = 0; i < possibleStartPositions.length; i++)
     269    for (var i = 0; i < possibleStartPositions.length; ++i)
    274270    {
    275271        var numLowTiles = 0;
    276272        var numHighTiles = 0;
    277         for (var dx = - maxDistToResources; dx < maxDistToResources; dx++)
     273        for (var dx = - maxDistToResources; dx < maxDistToResources; ++dx)
    278274        {
    279             for (var dy = - maxDistToResources; dy < maxDistToResources; dy++)
     275            for (var dy = - maxDistToResources; dy < maxDistToResources; ++dy)
    280276            {
    281277                var testHeight = getHeight(possibleStartPositions[i][0] + dx, possibleStartPositions[i][1] + dy);
    282278                if (testHeight < lowerHeightLimit)
    283                     numLowTiles++;
     279                    ++numLowTiles;
    284280                if (testHeight > upperHeightLimit)
    285                     numHighTiles++;
     281                    ++numHighTiles;
    286282                if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles)
    287283                    break;
    288284            }
    while (!goodStartPositionsFound)  
    311307        // Get some random start location derivations. NOTE: Itterating over all possible derivations is just to much (valid points ** numPlayers)
    312308        var maxTries = 100000; // floor(800000 / (Math.pow(numPlayers, 2) / 2));
    313309        var possibleDerivations = [];
    314         for (var i = 0; i < maxTries; i++)
     310        for (var i = 0; i < maxTries; ++i)
    315311        {
    316312            var vector = [];
    317             for (var p = 0; p < numPlayers; p++)
     313            for (var p = 0; p < numPlayers; ++p)
    318314                vector.push(randInt(possibleStartPositions.length));
    319315            possibleDerivations.push(vector);
    320316        }
    321317       
    322318        // Choose the start location derivation with the greatest minimum distance between players
    323319        var maxMinDist = 0;
    324         for (var d = 0; d < possibleDerivations.length; d++)
     320        for (var d = 0; d < possibleDerivations.length; ++d)
    325321        {
    326322            var minDist = 2 * mapSize;
    327             for (var p1 = 0; p1 < numPlayers - 1; p1++)
     323            for (var p1 = 0; p1 < numPlayers - 1; ++p1)
    328324            {
    329                 for (var p2 = p1 + 1; p2 < numPlayers; p2++)
     325                for (var p2 = p1 + 1; p2 < numPlayers; ++p2)
    330326                {
    331327                    if (p1 != p2)
    332328                    {
    if (mapSize > 500)  
    372368    propDensity = 1/4;
    373369else if (mapSize > 400)
    374370    propDensity = 3/4;
    375 for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++)
     371for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; ++x)
    376372{
    377     for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; y++)
     373    for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; ++y)
    378374    {
    379375        var textureMinHeight = heightRange.min;
    380         for (var i = 0; i < textueByHeight.length; i++)
     376        for (var i = 0; i < textueByHeight.length; ++i)
    381377        {
    382378            if (getHeight(x, y) >= textureMinHeight && getHeight(x, y) <= textueByHeight[i].upperHeightLimit)
    383379            {
    RMS.SetProgress(90);  
    497493// Place players and start resources
    498494////////
    499495
    500 for (var p = 0; p < numPlayers; p++)
     496for (var p = 0; p < numPlayers; ++p)
    501497{
    502498    var actualX = possibleStartPositions[bestDerivation[p]][0];
    503499    var actualY = possibleStartPositions[bestDerivation[p]][1];
    for (var p = 0; p < numPlayers; p++)  
    509505    {
    510506        var uAngle = BUILDING_ANGlE - PI * (2-j) / 2;
    511507        var count = 4;
    512         for (var numberofentities = 0; numberofentities < count; numberofentities++)
     508        for (var numberofentities = 0; numberofentities < count; ++numberofentities)
    513509        {
    514510            var ux = actualX + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
    515511            var uz = actualY + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
    timeArray.push(new Date().getTime());  
    531527// Calculate progress percentage with the time checks
    532528var generationTime = timeArray[timeArray.length - 1] - timeArray[0];
    533529log("Total generation time (ms): " + generationTime);
    534 for (var i = 0; i < timeArray.length; i++)
     530for (var i = 0; i < timeArray.length; ++i)
    535531{
    536532    var timeSinceStart = timeArray[i] - timeArray[0];
    537533    var progressPercentage = 100 * timeSinceStart / generationTime;
  • binaries/data/mods/public/maps/random/rmgen/library.js

     
    44/////////////////////////////////////////////////////////////////////////////////////////////
    55
    66const PI = Math.PI;
    7 const TWO_PI = 2 * Math.PI;
     7const TWO_PI = 2 * Math.PI; // mathematically known as 'tau'
    88const TERRAIN_SEPARATOR = "|";
    9 const SEA_LEVEL = 20.0;
     9const SEA_LEVEL = 160.0;
    1010const CELL_SIZE = 4;
    1111const HEIGHT_UNITS_PER_METRE = 92;
    1212const MIN_MAP_SIZE = 128;
    1313const MAX_MAP_SIZE = 512;
    1414const FALLBACK_CIV = "athen";
     15// Constants needed for heightmap_manipulation.js
     16const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE // Engine limit, Roughly 700 meters
     17const MIN_HEIGHT = - SEA_LEVEL;
     18const MAX_HEIGHT = MAX_HEIGHT_RANGE - SEA_LEVEL;
     19// Entity template structure keys that might change, for easier mod support
     20const STARTING_ENTITY_KEY = "StartEntities";
     21const START_ENTITY_TEMPLATE_PATH_KEY = "Template"
     22const BUILDER_TEMPLATEPATH_KEYS = ["Builder", "Entities", "_string"];
     23const PRODUCTION_TEMPLATEPATH_KEYS = ["ProductionQueue", "Entities", "_string"];
     24const CIV_PLACEHOLDER_STRING = "{civ}";
    1525
    1626/////////////////////////////////////////////////////////////////////////////////////////////
    1727//  Utility functions
    function argsToArray(x)  
    103113    if (numArgs != 1)
    104114    {
    105115        var ret = new Array(numArgs);
    106         for (var i=0; i < numArgs; i++)
     116        for (var i=0; i < numArgs; ++i)
    107117        {
    108118            ret[i] = x[i];
    109119        }
    function shuffleArray(source)  
    132142        return [];
    133143
    134144    var result = [source[0]];
    135     for (var i = 1; i < source.length; i++)
     145    for (var i = 1; i < source.length; ++i)
    136146    {
    137147        var j = randInt(0, i);
    138148        result[i] = result[j];
    function createAreas(centeredPlacer, painter, constraint, num, retryFactor)  
    172182        var area = g_Map.createArea(centeredPlacer, painter, constraint);
    173183        if (area !== undefined)
    174184        {
    175             good++;
     185            ++good;
    176186            result.push(area);
    177187        }
    178188        else
    179189        {
    180             bad++;
     190            ++bad;
    181191        }
    182192    }
    183193    return result;
    function createAreasInAreas(centeredPlacer, painter, constraint, num, retryFacto  
    208218        var area = g_Map.createArea(centeredPlacer, painter, constraint);
    209219        if (area !== undefined)
    210220        {
    211             good++;
     221            ++good;
    212222            result.push(area);
    213223        }
    214224        else
    215225        {
    216             bad++;
     226            ++bad;
    217227        }
    218228    }
    219229    return result;
    function createObjectGroups(placer, player, constraint, num, retryFactor)  
    248258        var result = createObjectGroup(placer, player, constraint);
    249259        if (result !== undefined)
    250260        {
    251             good++;
     261            ++good;
    252262        }
    253263        else
    254264        {
    255             bad++;
     265            ++bad;
    256266        }
    257267    }
    258268    return good;
    function createObjectGroupsByAreas(placer, player, constraint, num, retryFactor,  
    282292        var result = createObjectGroup(placer, player, constraint);
    283293        if (result !== undefined)
    284294        {
    285             good++;
     295            ++good;
    286296        }
    287297        else
    288298        {
    289             bad++;
     299            ++bad;
    290300        }
    291301    }
    292302    return good;
    function getNumPlayers()  
    394404    return g_MapSettings.PlayerData.length - 1;
    395405}
    396406
     407// Takes nothing, returns an array of strings representing all available civilizations
     408function getCivList()
     409{
     410    var raw_civData = RMS.GetCivData();
     411    var civList = [];
     412    for (var i = 0; i < raw_civData.length; ++i)
     413        civList.push(JSON.parse(raw_civData[i]).Code);
     414   
     415    return civList;
     416}
     417
     418// Takes nothing, returns an associative array with civ strings as keys containing all unpacked civ data (Templates need to be unpacked with RMS.GetTemplate() if needed)
     419function getFullCivData()
     420{
     421    var rawCivData = RMS.GetCivData();
     422    var unpackedCivData = {};
     423    for (var i = 0; i < rawCivData.length; ++i)
     424    {
     425        var singleCivData = JSON.parse(rawCivData[i]);
     426        unpackedCivData[singleCivData.Code] = singleCivData;
     427    }
     428   
     429    return unpackedCivData;
     430}
     431
     432// Takes a player number (0-7, so Gaia excluded). Returns this players civ string
     433// ToDo: If the player number is to high an error will occur (and the fallback won't be reached)!
    397434function getCivCode(player)
    398435{
    399436    if (g_MapSettings.PlayerData[player+1].Civ)
    400437        return g_MapSettings.PlayerData[player+1].Civ;
    401438
    402     warn("undefined civ specified for player " + (player + 1) + ", falling back to '" + FALLBACK_CIV + "'");
     439    warn("Undefined civ specified for player " + (player + 1) + ", falling back to '" + FALLBACK_CIV + "'");
    403440    return FALLBACK_CIV;
    404441}
    405442
     443// Takes an entity path and a key list to get the templates value
     444function getTemplateValue(entPath, key_list)
     445{
     446    var subdata = RMS.GetTemplate(entPath);
     447    for (var i = 0; i < key_list.length; ++i)
     448    {
     449        if (!subdata[key_list[i]])
     450            {return false};
     451        subdata = subdata[key_list[i]];
     452    }
     453    return subdata;
     454}
     455
     456// Returns a list of all templates paths available to the given civ
     457function getTempatePathList(civ)
     458{
     459    var templatePaths = getFullCivData();
     460    if (!templatePaths[civ])
     461    {
     462        warn("getTempatePathList: Unknown civ '" + civ + "' not in " + Object.keys(templatePaths));
     463        return false;
     464    }
     465    templatePaths = templatePaths[civ];
     466   
     467    if (!templatePaths[STARTING_ENTITY_KEY])
     468    {
     469        warn("getTempatePathList: Civ has no starting entities as defined in STARTING_ENTITY_KEY (" + STARTING_ENTITY_KEY + "): " + Object.keys(templatePaths));
     470        return false;
     471    }
     472    templatePaths = templatePaths[STARTING_ENTITY_KEY];
     473   
     474    for (var i = 0; i < templatePaths.length; ++i)
     475    {
     476        if (!templatePaths[i][START_ENTITY_TEMPLATE_PATH_KEY])
     477        {
     478            warn("getTempatePathList: Starting entity list item has no template as defined in START_ENTITY_TEMPLATE_PATH_KEY (" + START_ENTITY_TEMPLATE_PATH_KEY + "): " + Object.keys(templatePaths));
     479            return false;
     480        }
     481        templatePaths[i] = templatePaths[i][START_ENTITY_TEMPLATE_PATH_KEY];
     482    }
     483    var foundNew = 1;
     484    while (foundNew > 0)
     485    {
     486        foundNew = 0;
     487        var methods = [BUILDER_TEMPLATEPATH_KEYS, PRODUCTION_TEMPLATEPATH_KEYS];
     488        for (var m = 0; m < methods.length; ++m)
     489        {
     490            for (var t = 0; t < templatePaths.length; ++t)
     491            {
     492                var pathsToCheck = getTemplateValue(templatePaths[t], methods[m]);
     493                if (typeof(pathsToCheck) === typeof(""))
     494                {
     495                    pathsToCheck = pathsToCheck.split(/\s+/);
     496                    for (var c = 0; c < pathsToCheck.length; ++c)
     497                    {
     498                        var actualPath = pathsToCheck[c].replace(CIV_PLACEHOLDER_STRING, civ);
     499                        if (templatePaths.indexOf(actualPath) == -1 && RMS.TemplateExists(actualPath))
     500                        {
     501                            templatePaths.push(actualPath);
     502                            ++foundNew;
     503                        }
     504                    }
     505                }
     506            }
     507        }
     508    }
     509    return templatePaths;
     510}
     511
    406512function areAllies(player1, player2)
    407513{
    408514    if ((g_MapSettings.PlayerData[player1+1].Team === undefined) || (g_MapSettings.PlayerData[player2+1].Team === undefined) || (g_MapSettings.PlayerData[player2+1].Team == -1) || (g_MapSettings.PlayerData[player1+1].Team == -1))
    function sortPlayers(source)  
    434540
    435541    var result = new Array(0);
    436542    var team = new Array(5);
    437     for (var q = 0; q < 5; q++)
     543    for (var q = 0; q < 5; ++q)
    438544    {
    439545        team[q] = new Array(1);
    440546    }
    441547
    442     for (var i = -1; i < 4; i++)
     548    for (var i = -1; i < 4; ++i)
    443549    {
    444         for (var j = 0; j < source.length; j++)
     550        for (var j = 0; j < source.length; ++j)
    445551        {
    446552            if (getPlayerTeam(j) == i)
    447553            {
    function primeSortPlayers(source)  
    461567
    462568    var prime = new Array(source.length);
    463569
    464     for (var i = 0; i < round(source.length/2); i++)
     570    for (var i = 0; i < round(source.length/2); ++i)
    465571    {
    466572        prime[2*i]=source[i];
    467573        prime[2*i+1]=source[source.length-1-i];
    function unPaintClass(id)  
    535641function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
    536642{
    537643    var ar = new Array(arguments.length/2);
    538     for (var i = 0; i < arguments.length/2; i++)
     644    for (var i = 0; i < arguments.length/2; ++i)
    539645    {
    540646        ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
    541647    }
    function avoidClasses(/*class1, dist1, class2, dist2, etc*/)  
    555661function stayClasses(/*class1, dist1, class2, dist2, etc*/)
    556662{
    557663    var ar = new Array(arguments.length/2);
    558     for (var i = 0; i < arguments.length/2; i++)
     664    for (var i = 0; i < arguments.length/2; ++i)
    559665    {
    560666        ar[i] = new StayInTileClassConstraint(arguments[2*i], arguments[2*i+1]);
    561667    }
    function stayClasses(/*class1, dist1, class2, dist2, etc*/)  
    575681function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/)
    576682{
    577683    var ar = new Array(arguments.length/3);
    578     for (var i = 0; i < arguments.length/3; i++)
     684    for (var i = 0; i < arguments.length/3; ++i)
    579685    {
    580686        ar[i] = new BorderTileClassConstraint(arguments[3*i], arguments[3*i+1], arguments[3*i+2]);
    581687    }
    function getTerrainTexture(x, y)  
    642748{
    643749    return g_Map.getTexture(x, y);
    644750}
    645 
  • binaries/data/mods/public/maps/random/rmgen/misc.js

    function passageMaker(x1, z1, x2, z2, width, maxheight, height, smooth, tileclas  
    2020    var tchm = TILE_CENTERED_HEIGHT_MAP;
    2121    TILE_CENTERED_HEIGHT_MAP = true;
    2222    var mapSize = g_Map.size;
    23     for (var ix = 0; ix < mapSize; ix++)
     23    for (var ix = 0; ix < mapSize; ++ix)
    2424    {
    25         for (var iz = 0; iz < mapSize; iz++)
     25        for (var iz = 0; iz < mapSize; ++iz)
    2626        {
    2727            var a = z1-z2;
    2828            var b = x2-x1;
    function rndRiver(f, seed)  
    9292    var rndRe = 0;
    9393    var rndRr = f-floor(f);
    9494    var rndRa = 0;
    95     for (var rndRx=0; rndRx<=floor(f); rndRx++)
     95    for (var rndRx=0; rndRx<=floor(f); ++rndRx)
    9696    {
    9797        rndRw = 10*(rndRw-floor(rndRw));
    9898    }
    function createStartingPlayerEntities(fx, fz, playerid, civEntities, BUILDING_AN  
    148148    {
    149149        var uAngle = BUILDING_ANGlE - PI * (2-j) / 2;
    150150        var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1);
    151         for (var numberofentities = 0; numberofentities < count; numberofentities++)
     151        for (var numberofentities = 0; numberofentities < count; ++numberofentities)
    152152        {
    153153            var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
    154154            var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
    function createStartingPlayerEntities(fx, fz, playerid, civEntities, BUILDING_AN  
    157157    }
    158158}
    159159
    160 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     160//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    161161// placeCivDefaultEntities
    162162//
    163163//  Creates the default starting player entities depending on the players civ
    164164//  fx&fy: position of player base
    165165//  playerid: id of player
    166166//  angle: angle of main base building, optional, default is BUILDING_ANGlE
    167 //  kwargs: Takes some optional keyword arguments to tweek things
    168 //      'iberWall': may be false, 'walls' (default) or 'towers'. Determines the defensive structures Iberians get as civ bonus
     167//  kwargs: Optional. Takes an associative array with keyword arguments to tweak things:
     168//      Known keys: 'iberWall': may be false, 'walls' (default) or 'towers'. Determines the defensive structures Iberians get as civ bonus
    169169//
    170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     170//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    171171function placeCivDefaultEntities(fx, fz, playerid, angle, kwargs)
    172172{
    173173    // Unpack kwargs
    function placeCivDefaultEntities(fx, fz, playerid, angle, kwargs)  
    187187    {
    188188        var uAngle = angle - PI * (2-j) / 2;
    189189        var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1);
    190         for (var numberofentities = 0; numberofentities < count; numberofentities++)
     190        for (var numberofentities = 0; numberofentities < count; ++numberofentities)
    191191        {
    192192            var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
    193193            var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
    function placeCivDefaultEntities(fx, fz, playerid, angle, kwargs)  
    221221function paintTerrainBasedOnHeight(minheight, maxheight, mode, terrain)
    222222{
    223223    var mSize = g_Map.size;
    224     for (var qx = 0; qx < mSize; qx++)
     224    for (var qx = 0; qx < mSize; ++qx)
    225225    {
    226         for (var qz = 0; qz < mSize; qz++)
     226        for (var qz = 0; qz < mSize; ++qz)
    227227        {
    228228            if (mode == 0)
    229229            {
    function paintTerrainBasedOnHeight(minheight, maxheight, mode, terrain)  
    273273function paintTileClassBasedOnHeight(minheight, maxheight, mode, tileclass)
    274274{
    275275    var mSize = g_Map.size;
    276     for (var qx = 0; qx < mSize; qx++)
     276    for (var qx = 0; qx < mSize; ++qx)
    277277    {
    278         for (var qz = 0; qz < mSize; qz++)
     278        for (var qz = 0; qz < mSize; ++qz)
    279279        {
    280280            if (mode == 0)
    281281            {
    function paintTileClassBasedOnHeight(minheight, maxheight, mode, tileclass)  
    313313function unPaintTileClassBasedOnHeight(minheight, maxheight, mode, tileclass)
    314314{
    315315    var mSize = g_Map.size;
    316     for (var qx = 0; qx < mSize; qx++)
     316    for (var qx = 0; qx < mSize; ++qx)
    317317    {
    318         for (var qz = 0; qz < mSize; qz++)
     318        for (var qz = 0; qz < mSize; ++qz)
    319319        {
    320320            if (mode == 0)
    321321            {
    function createMountain(maxHeight, minRadius, maxRadius, numCircles, constraint,  
    617617       
    618618        for (var ix = sx; ix <= lx; ++ix)
    619619        {
    620             for (var iz = sz; iz <= lz; ++ iz)
     620            for (var iz = sz; iz <= lz; ++iz)
    621621            {
    622622                dx = ix - cx;
    623623                dz = iz - cz;
    function createMountain(maxHeight, minRadius, maxRadius, numCircles, constraint,  
    666666       
    667667        for (var ix = sx; ix <= lx; ++ix)
    668668        {
    669             for (var iz = sz; iz <= lz; ++ iz)
     669            for (var iz = sz; iz <= lz; ++iz)
    670670            {
    671671                if (fcc)
    672672                    if ((x - ix) > fcc || (ix - x) > fcc || (z - iz) > fcc || (iz - z) > fcc)
    function createMountain(maxHeight, minRadius, maxRadius, numCircles, constraint,  
    737737       
    738738        for (var ix = sx; ix <= lx; ++ix)
    739739        {
    740             for (var iz = sz; iz <= lz; ++ iz)
     740            for (var iz = sz; iz <= lz; ++iz)
    741741            {
    742742                dx = ix - cx;
    743743                dz = iz - cz;
  • binaries/data/mods/public/maps/random/rmgen/wall_builder.js

     
    2727//      maxTrys
    2828// Add treasures to wall style "others"
    2929// Adjust documentation
    30 // Perhaps rename "endLeft" to "start" and "endRight" to "end"
    31 // ?Use available civ-type wall elements rather than palisades: Remove "endLeft" and "endRight" as default wall elements and adjust default palisade fortress types?
    32 // ?Remove "endRight", "endLeft" and adjust generic fortress types palisades?
    33 // ?Think of something to enable splitting walls into two walls so more complex walls can be build and roads can have branches/crossroads?
     30// ?Use available civ-type wall elements rather than palisades: Remove "end" as a default wall element and adjust default palisade fortress types?
     31// ?Adjust generic fortress types palisades?
     32// ?Think of something to enable splitting walls into two walls so more complex walls can be built?
    3433// ?Readjust placement angle for wall elements with bending when used in linear/circular walls by their bending?
    3534
     35/**
     36 * Set some globals for this module
     37 */
     38var g_WallStyles = {};
     39var g_WallStyleList = [];
     40var g_CivData = getFullCivData();
     41var g_CivList = Object.keys(g_CivData);
     42var g_FortressTypes = {};
     43var g_FortressTypeKeys = ["tiny", "small", "medium", "normal", "large", "veryLarge", "giant"];
    3644
    37 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    38 //  WallElement class definition
    39 //
    40 //  Concept: If placed unrotated the wall's course is towards positive Y (top) with "outside" right (+X) and "inside" left (-X) like unrotated entities has their drop-points right (in rmgen)
    41 //  The course of the wall will be changed by corners (bending != 0) and so the "inside"/"outside" direction
    42 //
    43 //  type    Descriptive string, example: "wallLong". NOTE: Not really needed. Mainly for custom wall elements and to get the wall element type in code
    44 //  entity  Optional. Template name string of the entity to be placed, example: "structures/cart_wall_long". Default is undefined (No entity placed)
    45 //  angle   Optional. The angle (float) added to place the entity so "outside" is right when the wall element is placed unrotated. Default is 0
    46 //  width   Optional. How far this wall element lengthens the wall (float), if unrotated the Y space needed. Default is 0
    47 //  indent  Optional. The lateral indentation of the entity, drawn "inside" (positive values) or pushed "outside" (negative values). Default is 0
    48 //  bending Optional. How the course of the wall is changed after this element, positive is bending "in"/left/counter clockwise (like entity placement)
    49 //      NOTE: Bending is not supported by all placement functions (see there)
    50 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    51 function WallElement(type, entity, angle, width, indent, bending)
     45/**
     46 * Basic Initialisation
     47 *
     48 * Fetches wallsets from {civ}.json files, and then uses them to load
     49 * basic wall elements
     50 */
     51for (let civ of g_CivList)
    5252{
    53     this.type = type;
    54     // Default wall element type documentation:
    55     // Lengthening straight blocking (mainly left/right symmetric) wall elements (Walls and wall fortifications)
    56         // "wall"          A blocking straight wall element that mainly lengthens the wall, self-explanatory
    57         // "wallShort"     self-explanatory
    58         // "wallLong"      self-explanatory
    59         // "tower"         A blocking straight wall element with damage potential (but for palisades) that slightly lengthens the wall, example: wall tower, palisade tower(No attack)
    60         // "wallFort"      A blocking straight wall element with massive damage potential that lengthens the wall, example: fortress, palisade fort
    61     // Lengthening straight non/custom blocking (mainly left/right symmetric) wall elements (Gates and entries)
    62         // "gate"          A blocking straight wall element with passability determined by owner, example: gate (Functionality not yet implemented)
    63         // "entry"         A non-blocking straight wall element (same width as gate) but without an actual template or just a flag/column/obelisk
    64         // "entryTower"    A non-blocking straight wall element (same width as gate) represented by a single (maybe indented) template, example: defence tower, wall tower, outpost, watchtower
    65         // "entryFort"     A non-blocking straight wall element represented by a single (maybe indented) template, example: fortress, palisade fort
    66     // Bending wall elements (Wall corners)
    67         // "cornerIn"      A wall element bending the wall by PI/2 "inside" (left, +, see above), example: wall tower, palisade curve
    68         // "cornerOut"     A wall element bending the wall by PI/2 "outside" (right, -, see above), example: wall tower, palisade curve
    69         // "cornerHalfIn"  A wall element bending the wall by PI/4 "inside" (left, +, see above), example: wall tower, palisade curve. NOTE: Not yet implemented
    70         // "cornerHalfOut" A wall element bending the wall by PI/4 "outside" (right, -, see above), example: wall tower, palisade curve. NOTE: Not yet implemented
    71     // Zero length straight indented (mainly left/right symmetric) wall elements (Outposts/watchtowers and non-defensive base structures)
    72         // "outpost"       A zero-length wall element without bending far indented so it stands outside the wall, example: outpost, defence tower, watchtower
    73         // "house"         A zero-length wall element without bending far indented so it stands inside the wall that grants population bonus, example: house, hut, longhouse
    74         // "barracks"      A zero-length wall element without bending far indented so it stands inside the wall that grants unit production, example: barracks, tavern, ...
    75     this.entity = entity;
    76     this.angle = (angle !== undefined) ? angle : 0*PI;
    77     this.width = (width !== undefined) ? width : 0;
    78     this.indent = (indent !== undefined) ? indent : 0;
    79     this.bending = (bending !== undefined) ? bending : 0*PI;
     53    let civInfo = g_CivData[civ];
     54    if (!civInfo.WallSets)
     55        continue;
     56
     57    for (let path of civInfo.WallSets)
     58    {
     59        let style = path.split("/")[1].split("_");
     60        style = (style[0]=="wallset") ? style[1] : style[0]+"_"+style[2];
     61
     62        if (g_WallStyleList.indexOf(style) == -1)
     63        {
     64            g_WallStyleList.push(style);
     65            g_WallStyles[style] = {};
     66            let wallset = GetTemplateDataHelper(RMS.GetTemplate(path)).wallSet;
     67            for (let element in wallset.templates)
     68                setWallElement(style, element, wallset.templates[element].replace("{civ}",civ))
     69            g_WallStyles[style]["@overlap"] = wallset.minTowerOverlap * getWallElement(style, "tower").length;
     70        }
     71    }
    8072}
    8173
    8274/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function WallElement(type, entity, angle, width, indent, bending)  
    8678//  It's mainly the abstract shape defined in a Fortress instances wall because different styles can be used for it (see wallStyles)
    8779//
    8880//  type                  Descriptive string, example: "tiny". Not really needed (WallTool.wallTypes["type string"] is used). Mainly for custom wall elements
    89 //  wall                  Optional. Array of wall element strings. Can be set afterwards. Default is an epty array.
     81//  wall                  Optional. Array of wall element strings. Can be set afterwards. Default is an empty array.
    9082//      Example: ["entrance", "wall", "cornerIn", "wall", "gate", "wall", "entrance", "wall", "cornerIn", "wall", "gate", "wall", "cornerIn", "wall"]
    9183//  centerToFirstElement  Optional. Object with properties "x" and "y" representing a vector from the visual center to the first wall element. Default is undefined
    9284/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    9385function Fortress(type, wall, centerToFirstElement)
    9486{
    95     this.type = type; // Only usefull to get the type of the actual fortress
    96     this.wall = (wall !== undefined) ? wall : [];
    97     this.centerToFirstElement = undefined;
    98 }
    99 
    100 
    101 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    102 //  wallStyles data structure for default wall styles
    103 //
    104 //  A wall style is an associative array with all wall elements of that style in it associated with the wall element type string
    105 //  wallStyles holds all the wall styles within an associative array with the civ string or another descriptive strings as key
    106 //  Examples: "athen", "rome_siege", "palisades", "fence", "road"
    107 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    108 var wallStyles = {};
    109 
    110 // Generic civ dependent wall style definition. "rome_siege" needs some tweek...
    111 var wallScaleByType = {"athen" : 1.5, "brit" : 1.5, "cart" : 1.8, "gaul" : 1.5, "iber" : 1.5, "mace" : 1.5, "maur": 1.5, "pers" : 1.5, "ptol" : 1.5, "rome" : 1.5, "sele" : 1.5, "spart" : 1.5, "rome_siege" : 1.5};
    112 for (var style in wallScaleByType)
    113 {
    114     var civ = style;
    115     if (style == "rome_siege")
    116         civ = "rome";
    117     wallStyles[style] = {};
    118     // Default wall elements
    119     wallStyles[style]["tower"] = new WallElement("tower", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]);
    120     wallStyles[style]["endLeft"] = new WallElement("endLeft", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades...
    121     wallStyles[style]["endRight"] = new WallElement("endRight", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades...
    122     wallStyles[style]["cornerIn"] = new WallElement("cornerIn", "structures/" + style + "_wall_tower", 5*PI/4, 0, 0.35*wallScaleByType[style], PI/2); // 2^0.5 / 4 ~= 0.35 ~= 1/3
    123     wallStyles[style]["cornerOut"] = new WallElement("cornerOut", "structures/" + style + "_wall_tower", 3*PI/4, 0.71*wallScaleByType[style], 0, -PI/2); // // 2^0.5 / 2 ~= 0.71 ~= 2/3
    124     wallStyles[style]["wallShort"] = new WallElement("wallShort", "structures/" + style + "_wall_short", 0*PI, 2*wallScaleByType[style]);
    125     wallStyles[style]["wall"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]);
    126     wallStyles[style]["wallMedium"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]);
    127     wallStyles[style]["wallLong"] = new WallElement("wallLong", "structures/" + style + "_wall_long", 0*PI, 6*wallScaleByType[style]);
    128     // Gate and entrance wall elements
    129     var gateWidth = 6*wallScaleByType[style];
    130     wallStyles[style]["gate"] = new WallElement("gate", "structures/" + style + "_wall_gate", PI, gateWidth);
    131     wallStyles[style]["entry"] = new WallElement("entry", undefined, 0*PI, gateWidth);
    132     wallStyles[style]["entryTower"] = new WallElement("entryTower", "structures/" + civ + "_defense_tower", PI, gateWidth, -4*wallScaleByType[style]);
    133     wallStyles[style]["entryFort"] = new WallElement("entryFort", "structures/" + civ + "_fortress", 0*PI, 8*wallScaleByType[style], 6*wallScaleByType[style]);
    134     // Defensive wall elements with 0 width outside the wall
    135     wallStyles[style]["outpost"] = new WallElement("outpost", "structures/" + civ + "_outpost", PI, 0, -4*wallScaleByType[style]);
    136     wallStyles[style]["defenseTower"] = new WallElement("defenseTower", "structures/" + civ + "_defense_tower", PI, 0, -4*wallScaleByType[style]);
    137     // Base buildings wall elements with 0 width inside the wall
    138     wallStyles[style]["barracks"] = new WallElement("barracks", "structures/" + civ + "_barracks", PI, 0, 4.5*wallScaleByType[style]);
    139     wallStyles[style]["civilCentre"] = new WallElement("civilCentre", "structures/" + civ + "_civil_centre", PI, 0, 4.5*wallScaleByType[style]);
    140     wallStyles[style]["farmstead"] = new WallElement("farmstead", "structures/" + civ + "_farmstead", PI, 0, 4.5*wallScaleByType[style]);
    141     wallStyles[style]["field"] = new WallElement("field", "structures/" + civ + "_field", PI, 0, 4.5*wallScaleByType[style]);
    142     wallStyles[style]["fortress"] = new WallElement("fortress", "structures/" + civ + "_fortress", PI, 0, 4.5*wallScaleByType[style]);
    143     wallStyles[style]["house"] = new WallElement("house", "structures/" + civ + "_house", PI, 0, 4.5*wallScaleByType[style]);
    144     wallStyles[style]["market"] = new WallElement("market", "structures/" + civ + "_market", PI, 0, 4.5*wallScaleByType[style]);
    145     wallStyles[style]["storehouse"] = new WallElement("storehouse", "structures/" + civ + "_storehouse", PI, 0, 4.5*wallScaleByType[style]);
    146     wallStyles[style]["temple"] = new WallElement("temple", "structures/" + civ + "_temple", PI, 0, 4.5*wallScaleByType[style]);
    147     // Generic space/gap wall elements
    148     wallStyles[style]["space1"] = new WallElement("space1", undefined, 0*PI, wallScaleByType[style]);
    149     wallStyles[style]["space2"] = new WallElement("space2", undefined, 0*PI, 2*wallScaleByType[style]);
    150     wallStyles[style]["space3"] = new WallElement("space3", undefined, 0*PI, 3*wallScaleByType[style]);
    151     wallStyles[style]["space4"] = new WallElement("space4", undefined, 0*PI, 4*wallScaleByType[style]);
     87    this.type = type;
     88    this.wall = wall || [];
     89    this.centerToFirstElement = centerToFirstElement || undefined;
    15290}
    153 // Add wall fortresses for all generic styles
    154 wallStyles["athen"]["wallFort"] = new WallElement("wallFort", "structures/athen_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
    155 wallStyles["brit"]["wallFort"] = new WallElement("wallFort", "structures/brit_fortress", PI, 2.8);
    156 wallStyles["cart"]["wallFort"] = new WallElement("wallFort", "structures/cart_fortress", PI, 5.1, 1.6);
    157 wallStyles["gaul"]["wallFort"] = new WallElement("wallFort", "structures/gaul_fortress", PI, 4.2, 1.5);
    158 wallStyles["iber"]["wallFort"] = new WallElement("wallFort", "structures/iber_fortress", PI, 5, 0.2);
    159 wallStyles["mace"]["wallFort"] = new WallElement("wallFort", "structures/mace_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
    160 wallStyles["maur"]["wallFort"] = new WallElement("wallFort", "structures/maur_fortress", PI, 5.5);
    161 wallStyles["pers"]["wallFort"] = new WallElement("wallFort", "structures/pers_fortress", PI, 5.6/*5.5*/, 1.9/*1.7*/);
    162 wallStyles["ptol"]["wallFort"] = new WallElement("wallFort", "structures/ptol_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
    163 wallStyles["rome"]["wallFort"] = new WallElement("wallFort", "structures/rome_fortress", PI, 6.3, 2.1);
    164 wallStyles["sele"]["wallFort"] = new WallElement("wallFort", "structures/sele_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
    165 wallStyles["spart"]["wallFort"] = new WallElement("wallFort", "structures/spart_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
    166 // Adjust "rome_siege" style
    167 wallStyles["rome_siege"]["wallFort"] = new WallElement("wallFort", "structures/rome_army_camp", PI, 7.2, 2);
    168 wallStyles["rome_siege"]["entryFort"] = new WallElement("entryFort", "structures/rome_army_camp", PI, 12, 7);
    169 wallStyles["rome_siege"]["house"] = new WallElement("house", "structures/rome_tent", PI, 0, 4);
    170 
    171 // Add special wall styles not well to implement generic (and to show how custom styles can be added)
    172 
    173 // Add wall style "palisades"
    174 wallScaleByType["palisades"] = 0.55;
    175 wallStyles["palisades"] = {};
    176 wallStyles["palisades"]["wall"] = new WallElement("wall", "other/palisades_rocks_medium", 0*PI, 2.3);
    177 wallStyles["palisades"]["wallMedium"] = new WallElement("wall", "other/palisades_rocks_medium", 0*PI, 2.3);
    178 wallStyles["palisades"]["wallLong"] = new WallElement("wall", "other/palisades_rocks_long", 0*PI, 3.5);
    179 wallStyles["palisades"]["wallShort"] = new WallElement("wall", "other/palisades_rocks_short", 0*PI, 1.2);
    180 wallStyles["palisades"]["tower"] = new WallElement("tower", "other/palisades_rocks_tower", -PI/2, 0.7);
    181 wallStyles["palisades"]["wallFort"] = new WallElement("wallFort", "other/palisades_rocks_fort", PI, 1.7);
    182 wallStyles["palisades"]["gate"] = new WallElement("gate", "other/palisades_rocks_gate", PI, 3.6);
    183 wallStyles["palisades"]["entry"] = new WallElement("entry", undefined, wallStyles["palisades"]["gate"].angle, wallStyles["palisades"]["gate"].width);
    184 wallStyles["palisades"]["entryTower"] = new WallElement("entryTower", "other/palisades_rocks_watchtower", 0*PI, wallStyles["palisades"]["gate"].width, -3);
    185 wallStyles["palisades"]["entryFort"] = new WallElement("entryFort", "other/palisades_rocks_fort", PI, 6, 3);
    186 wallStyles["palisades"]["cornerIn"] = new WallElement("cornerIn", "other/palisades_rocks_curve", 3*PI/4, 2.1, 0.7, PI/2);
    187 wallStyles["palisades"]["cornerOut"] = new WallElement("cornerOut", "other/palisades_rocks_curve", 5*PI/4, 2.1, -0.7, -PI/2);
    188 wallStyles["palisades"]["outpost"] = new WallElement("outpost", "other/palisades_rocks_outpost", PI, 0, -2);
    189 wallStyles["palisades"]["house"] = new WallElement("house", "other/celt_hut", PI, 0, 5);
    190 wallStyles["palisades"]["barracks"] = new WallElement("barracks", "structures/gaul_tavern", PI, 0, 5);
    191 wallStyles["palisades"]["endRight"] = new WallElement("endRight", "other/palisades_rocks_end", -PI/2, 0.2);
    192 wallStyles["palisades"]["endLeft"] = new WallElement("endLeft", "other/palisades_rocks_end", PI/2, 0.2);
    193 
    194 // Add special wall style "road"
    195 // NOTE: This is not a wall style in the common sense. Use with care!
    196 wallStyles["road"] = {};
    197 wallStyles["road"]["short"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_short.xml", PI/2, 4.5);
    198 wallStyles["road"]["long"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_long.xml", PI/2, 9.5);
    199 wallStyles["road"]["cornerLeft"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_corner.xml", -PI/2, 4.5-2*1.25, 1.25, PI/2); // Correct width by -2*indent to fit xStraicht/corner
    200 wallStyles["road"]["cornerRight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_corner.xml", 0*PI, 4.5-2*1.25, -1.25, -PI/2); // Correct width by -2*indent to fit xStraicht/corner
    201 wallStyles["road"]["curveLeft"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_curve_small.xml", -PI/2, 4.5+2*0.2, -0.2, PI/2); // Correct width by -2*indent to fit xStraicht/corner
    202 wallStyles["road"]["curveRight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_curve_small.xml", 0*PI, 4.5+2*0.2, 0.2, -PI/2); // Correct width by -2*indent to fit xStraicht/corner
    203 wallStyles["road"]["start"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_end.xml", PI/2, 2);
    204 wallStyles["road"]["end"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_end.xml", -PI/2, 2);
    205 wallStyles["road"]["xStraight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5);
    206 wallStyles["road"]["xLeft"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, PI/2);
    207 wallStyles["road"]["xRight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, -PI/2);
    208 wallStyles["road"]["tLeft"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_T.xml", PI, 4.5, 1.25);
    209 wallStyles["road"]["tRight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_T.xml", 0*PI, 4.5, -1.25);
    210 
    211 // Add special wall element collection "other"
    212 // NOTE: This is not a wall style in the common sense. Use with care!
    213 wallStyles["other"] = {};
    214 wallStyles["other"]["fence"] = new WallElement("fence", "other/fence_long", -PI/2, 3.1);
    215 wallStyles["other"]["fence_medium"] = new WallElement("fence", "other/fence_long", -PI/2, 3.1);
    216 wallStyles["other"]["fence_short"] = new WallElement("fence_short", "other/fence_short", -PI/2, 1.5);
    217 wallStyles["other"]["fence_stone"] = new WallElement("fence_stone", "other/fence_stone", -PI/2, 2.5);
    218 wallStyles["other"]["palisade"] = new WallElement("palisade", "other/palisades_rocks_short", 0, 1.2);
    219 wallStyles["other"]["column"] = new WallElement("column", "other/column_doric", 0, 1);
    220 wallStyles["other"]["obelisk"] = new WallElement("obelisk", "other/obelisk", 0, 2);
    221 wallStyles["other"]["spike"] = new WallElement("spike", "other/palisades_angle_spike", -PI/2, 1);
    222 wallStyles["other"]["bench"] = new WallElement("bench", "other/bench", PI/2, 1.5);
    223 wallStyles["other"]["benchForTable"] = new WallElement("benchForTable", "other/bench", 0, 0.5);
    224 wallStyles["other"]["table"] = new WallElement("table", "other/table_rectangle", 0, 1);
    225 wallStyles["other"]["table_square"] = new WallElement("table_square", "other/table_square", PI/2, 1);
    226 wallStyles["other"]["flag"] = new WallElement("flag", "special/rallypoint", PI, 1);
    227 wallStyles["other"]["standing_stone"] = new WallElement("standing_stone", "gaia/special_ruins_standing_stone", PI, 1);
    228 wallStyles["other"]["settlement"] = new WallElement("settlement", "gaia/special_settlement", PI, 6);
    229 wallStyles["other"]["gap"] = new WallElement("gap", undefined, 0, 2);
    230 wallStyles["other"]["gapSmall"] = new WallElement("gapSmall", undefined, 0, 1);
    231 wallStyles["other"]["gapLarge"] = new WallElement("gapLarge", undefined, 0, 4);
    232 wallStyles["other"]["cornerIn"] = new WallElement("cornerIn", undefined, 0, 0, 0, PI/2);
    233 wallStyles["other"]["cornerOut"] = new WallElement("cornerOut", undefined, 0, 0, 0, -PI/2);
    234 
    23591
    23692////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    237 //  fortressTypes data structure for some default fortress types
     93//  g_FortressTypes data structure for some default fortress types (defined above)
    23894//
    23995//  A fortress type is just an instance of the Fortress class with actually something in it
    24096//  fortressTypes holds all the fortresses within an associative array with a descriptive string as key (e.g. matching the map size)
    24197//  Examples: "tiny", "veryLarge"
    24298////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    243 var fortressTypes = {};
    244 // Setup some default fortress types
    245 // Add fortress type "tiny"
    246 fortressTypes["tiny"] = new Fortress("tiny");
    247 var wallPart = ["gate", "tower", "wallShort", "cornerIn", "wallShort", "tower"];
    248 fortressTypes["tiny"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    249 // Add fortress type "small"
    250 fortressTypes["small"] = new Fortress("small");
    251 var wallPart = ["gate", "tower", "wall", "cornerIn", "wall", "tower"];
    252 fortressTypes["small"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    253 // Add fortress type "medium"
    254 fortressTypes["medium"] = new Fortress("medium");
    255 var wallPart = ["gate", "tower", "wallLong", "cornerIn", "wallLong", "tower"];
    256 fortressTypes["medium"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    257 // Add fortress type "normal"
    258 fortressTypes["normal"] = new Fortress("normal");
    259 var wallPart = ["gate", "tower", "wall", "cornerIn", "wall", "cornerOut", "wall", "cornerIn", "wall", "tower"];
    260 fortressTypes["normal"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    261 // Add fortress type "large"
    262 fortressTypes["large"] = new Fortress("large");
    263 var wallPart = ["gate", "tower", "wallLong", "cornerIn", "wallLong", "cornerOut", "wallLong", "cornerIn", "wallLong", "tower"];
    264 fortressTypes["large"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    265 // Add fortress type "veryLarge"
    266 fortressTypes["veryLarge"] = new Fortress("veryLarge");
    267 var wallPart = ["gate", "tower", "wall", "cornerIn", "wall", "cornerOut", "wallLong", "cornerIn", "wallLong", "cornerOut", "wall", "cornerIn", "wall", "tower"];
    268 fortressTypes["veryLarge"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    269 // Add fortress type "giant"
    270 fortressTypes["giant"] = new Fortress("giant");
    271 var wallPart = ["gate", "tower", "wallLong", "cornerIn", "wallLong", "cornerOut", "wallLong", "cornerIn", "wallLong", "cornerOut", "wallLong", "cornerIn", "wallLong", "tower"];
    272 fortressTypes["giant"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     99
     100// Set some default fortress types
     101for (let key of g_FortressTypeKeys)
     102    g_FortressTypes[key] = new Fortress(key);
     103
     104g_FortressTypes["tiny"].wall = ["gate", "tower", "short", "cornerIn", "short", "tower"];
     105g_FortressTypes["small"].wall = ["gate", "tower", "medium", "cornerIn", "medium", "tower"];
     106g_FortressTypes["medium"].wall = ["gate", "tower", "long", "cornerIn", "long", "tower"];
     107g_FortressTypes["normal"].wall = ["gate", "tower", "medium", "cornerIn", "medium", "cornerOut", "medium", "cornerIn", "medium", "tower"];
     108g_FortressTypes["large"].wall = ["gate", "tower", "long", "cornerIn", "long", "cornerOut", "long", "cornerIn", "long", "tower"];
     109g_FortressTypes["veryLarge"].wall = ["gate", "tower", "medium", "cornerIn", "medium", "cornerOut", "long", "cornerIn", "long", "cornerOut", "medium", "cornerIn", "medium", "tower"];
     110g_FortressTypes["giant"].wall = ["gate", "tower", "long", "cornerIn", "long", "cornerOut", "long", "cornerIn", "long", "cornerOut", "long", "cornerIn", "long", "tower"];
     111
     112for (let type in g_FortressTypes)
     113{
     114    let wallPart = g_FortressTypes[type].wall;
     115    g_FortressTypes[type].wall = wallPart.concat(wallPart, wallPart, wallPart);
     116}
    273117
    274118// Setup some better looking semi default fortresses for "palisades" style
    275 var fortressTypeKeys = ["tiny", "small", "medium", "normal", "large", "veryLarge", "giant"];
    276 for (var i = 0; i < fortressTypeKeys.length; i++)
     119for (let fortType of g_FortressTypeKeys)
    277120{
    278     var newKey = fortressTypeKeys[i] + "Palisades";
    279     var oldWall = fortressTypes[fortressTypeKeys[i]].wall;
    280     fortressTypes[newKey] = new Fortress(newKey);
     121    var newKey = fortType + "Palisades";
     122    var oldWall = g_FortressTypes[fortType].wall;
     123    g_FortressTypes[newKey] = new Fortress(newKey);
    281124    var fillTowersBetween = ["wallShort", "wall", "wallLong", "endLeft", "endRight", "cornerIn", "cornerOut"];
    282     for (var j = 0; j < oldWall.length; j++)
     125    for (var j = 0; j < oldWall.length; ++j)
    283126    {
    284         fortressTypes[newKey].wall.push(oldWall[j]); // Only works if the first element is not in fillTowersBetween (e.g. entry or gate like it should be)
     127        g_FortressTypes[newKey].wall.push(oldWall[j]); // Only works if the first element is not in fillTowersBetween (e.g. entry or gate like it should be)
    285128        if (j+1 < oldWall.length)
    286129            if (fillTowersBetween.indexOf(oldWall[j]) > -1 && fillTowersBetween.indexOf(oldWall[j+1]) > -1) // ... > -1 means "exists" here
    287                 fortressTypes[newKey].wall.push("tower");
     130                g_FortressTypes[newKey].wall.push("tower");
    288131    }
    289132}
    290133
    291134// Setup some balanced (to civ type fortresses) semi default fortresses for "palisades" style
    292135// TODO
    293136
    294 // Add some "fortress types" for roads (will only work with style "road")
    295 // ["start", "short", "xRight", "xLeft", "cornerLeft", "xStraight", "long", "xLeft", "xRight", "cornerRight", "tRight", "tLeft", "xRight", "xLeft", "curveLeft", "xStraight", "curveRight", "end"];
    296 var wall = ["short", "curveLeft", "short", "curveLeft", "short", "curveLeft", "short", "curveLeft"];
    297 fortressTypes["road01"] = new Fortress("road01", wall);
    298 var wall = ["short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft"];
    299 fortressTypes["road02"] = new Fortress("road02", wall);
    300 var wall = ["xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft"];
    301 fortressTypes["road03"] = new Fortress("road03", wall);
    302 var wall = ["start", "curveLeft", "tRight", "cornerLeft", "tRight", "curveRight", "short", "xRight", "curveLeft", "xRight", "short", "cornerLeft", "tRight", "short",
    303     "curveLeft", "short", "tRight", "cornerLeft", "short", "xRight", "curveLeft", "xRight", "short", "curveRight", "tRight", "cornerLeft", "tRight", "curveLeft", "end"];
    304 fortressTypes["road04"] = new Fortress("road04", wall);
    305 var wall = ["start", "tLeft", "short", "xRight",
    306     "curveLeft", "xRight", "tRight", "cornerLeft", "tRight",
    307     "curveLeft", "short", "tRight", "cornerLeft", "xRight",
    308     "cornerLeft", "xRight", "short", "tRight", "curveLeft", "end"];
    309 fortressTypes["road05"] = new Fortress("road05", wall);
    310 
    311137
    312138///////////////////////////////
    313139// Define some helper functions
    314140///////////////////////////////
    315141
     142/**
     143 * Get a wall element of a style.
     144 *
     145 * Valid elements:
     146 *   long, medium, short, start, end, cornerIn, cornerOut, tower, fort, gate
     147 *
     148 * Kept for backwards compatibility:
     149 *   wallLong, wallMedium, wall, wallShort, endLeft, endRight, entry, entryTower, entryFort
     150 *
     151 * If an element of the form `gap{x}` is requested, where `{x}` is a number,
     152 * then a non-blocking gap of `x` length is returned.
     153 *
     154 * If an element of the form `turn{x}` is requested where `{x}` is either
     155 * `out` or `in` (case in-sensitive), then a 90 degree (PI/2 radians) bend
     156 * with zero length is returned in the specified direction.
     157 *
     158 * You can specify a normal structure (ie. `house`, `apadana` `barracks`)
     159 * and the function will attempt to return the appropriate civ's building
     160 * of that type with appropriate indentation away from the wall.
     161 * @todo do something about the arbitrary-ness of the indent.
     162 *
     163 * If after all that, the function still can't work out what's requested,
     164 * it returns a wall tower.
     165 *
     166 * @param style The style from which this element should come from
     167 * @param element The element to fetch
     168 * @return The wall element requested. Or a tower element.
     169 */
     170function getWallElement(style="athen_stone", element)
     171{
     172    if (g_WallStyleList.indexOf(style) < 0)
     173    {
     174        warn("getWallElement: Style '"+style+"' not recognised. (Falling back to '" + FALLBACK_CIV + "_stone'.)");
     175        style = FALLBACK_CIV + "_stone";
     176    }
     177    if (g_WallStyles[style][element])
     178        return g_WallStyles[style][element];
     179
     180    // Attempt to derive any unknown elements.
     181    // Defaults to a wall tower piece
     182    var wallset = g_WallStyles[style];
     183    var civ = style.split("_")[0];
     184    var ret = clone(wallset.tower);
     185
     186    // We use clone() so we don't change the attributes of the object we're referencing
     187    switch (element)
     188    {
     189
     190    case "cornerIn":
     191        if (wallset.quarterCurve)
     192            ret = clone(wallset.quarterCurve);
     193        else
     194        {
     195            ret.angle += PI/4
     196            ret.indent = ret.length * 0.25;
     197            ret.length = 0;
     198        }
     199        ret.bend = PI/2;
     200        break;
     201
     202    case "cornerOut":
     203        if (wallset.quarterCurve)
     204        {
     205            ret = clone(wallset.quarterCurve);
     206            ret.angle += PI/2;
     207            ret.indent -= ret.indent*2;
     208        }
     209        else
     210        {
     211            ret.angle -= PI/4;
     212            ret.length *= 0.71;
     213        }
     214        ret.bend = -PI/2;
     215        break;
     216
     217    case "wallShort":
     218        warn("getWallElement: Deprecated use of 'wallShort' (please use 'short')");
     219        ret = clone(wallset.short);
     220        break;
     221
     222    case "wallMedium":
     223    case "wall":
     224        warn("getWallElement: Deprecated use of '"+element+"' (please use 'medium')");
     225        ret = clone(wallset.medium);
     226        break;
     227
     228    case "wallLong":
     229        warn("getWallElement: Deprecated use of 'wallLong' (please use 'long')");
     230        ret = clone(wallset.long);
     231        break;
     232
     233    case "entry":
     234        ret.entPath = undefined;
     235        ret.length = clone(g_WallStyles[style].gate.length);
     236        break;
     237
     238    case "entryTower":
     239        ret.entPath = (g_CivList.indexOf(civ) > -1) ? "structures/"+civ+"_defense_tower" : "other/palisades_rocks_watchtower";
     240        ret.indent = ret.length * -3;
     241        ret.length = clone(g_WallStyles[style].gate.length);
     242        break;
     243
     244    case "entryFort":
     245        ret = clone(g_WallStyles[style].fort);
     246        ret.angle -= PI;
     247        ret.length *= 1.5;
     248        ret.indent = ret.length;
     249        break;
     250
     251    case "endLeft":
     252        warn("getWallElement: Deprecated use of 'endLeft' (please use 'start')");
     253    case "start":
     254        if (wallset.end)
     255        {
     256            ret = clone(wallset.end);
     257            ret.angle += PI;
     258        }
     259        break;
     260
     261    case "endRight":
     262        warn("getWallElement: Deprecated use of 'endRight' (please use 'end')");
     263    case "end":
     264        if (wallset.end)
     265            ret = clone(wallset.end);
     266        break;
     267
     268    default:
     269        if (g_CivList.indexOf(civ) == -1)
     270            civ = FALLBACK_CIV;
     271        // Is it a structure?
     272        var entPath = "structures/"+civ+"_"+element;
     273        if (RMS.TemplateExists(entPath))
     274        {
     275            if (["outpost", "defense_tower"].indexOf(element) > -1)
     276                ret.indent = ret.length * -3;
     277            else
     278                ret.indent = ret.length * 3.5;
     279            ret.entPath = entPath;
     280            ret.length = 0;
     281        }
     282        else if (element.slice(0, 3) === "gap") // A gap?
     283        {
     284            ret.entPath = undefined;
     285            ret.angle = 0;
     286            ret.length = +element.slice(3);
     287        }
     288        else if (element.slice(0, 4) === "turn") // A bend?
     289        {
     290            let dir = element.slice(4).toLowerCase();
     291            if (dir === "out" || dir === "in")
     292            {
     293                ret.entPath = undefined;
     294                ret.angle = PI/2;
     295                ret.length = 0;
     296                if (dir === "out")
     297                    ret.angle -= ret.angle;
     298            }
     299            else
     300                warn("Unrecognised turn direction given: '"+dir+"' ("+ style+").");
     301        }
     302        else // Or... I give up.
     303            warn("Unrecognised wall element: '"+element+"' ("+ style+"). Defaulting to 'tower'.");
     304    }
     305
     306    // Cache to save having to calculate this element again
     307    g_WallStyles[style][element] = ret;
     308
     309    return ret;
     310}
     311
     312/**
     313 * Set a wall element of a style.
     314 *
     315 * @param style The style to which this element belongs
     316 * @param element The element to add
     317 * @param path The template path to read values from
     318 */
     319function setWallElement(style, element, path)
     320{
     321    var template = RMS.GetTemplate(path);
     322    template = GetTemplateDataHelper(template);
     323
     324    if (!g_WallStyles[style])
     325        g_WallStyles[style] = {};
     326
     327    var length = (template.wallPiece) ? template.wallPiece.length : template.obstruction.shape.width;
     328    g_WallStyles[style][element] = {
     329        "entPath": path,
     330        "angle": (template.wallPiece) ? template.wallPiece.angle : PI,
     331        "length": length / CELL_SIZE,
     332        "indent": (template.wallPiece) ? template.wallPiece.indent / CELL_SIZE : 0,
     333        "bend": (template.wallPiece) ? template.wallPiece.bend : 0
     334    };
     335}
     336
    316337/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    317338//  getWallAlignment
    318339//
    fortressTypes["road05"] = new Fortress("road05", wall);  
    320341//  Placing the first wall element at startX/startY placed with an angle given by orientation
    321342//  An alignment can be used to get the "center" of a "wall" (more likely used for fortresses) with getCenterToFirstElement
    322343/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    323 function getWallAlignment(startX, startY, wall, style, orientation)
     344function getWallAlignment(startX, startY, wall=[], style="athen_stone", orientation=0)
    324345{
    325     // Graciously handle arguments
    326     if (wall === undefined)
    327         wall = [];
    328     if (!wallStyles.hasOwnProperty(style))
    329     {
    330         warn("Function getWallAlignment: Unknown style: " + style + ' (falling back to "athen")');
    331         style = "athen";
    332     }
    333     orientation = (orientation || 0);
    334    
    335346    var alignment = [];
    336347    var wallX = startX;
    337348    var wallY = startY;
    338     for (var i = 0; i < wall.length; i++)
     349
     350    for (var i = 0; i < wall.length; ++i)
    339351    {
    340         var element = wallStyles[style][wall[i]];
     352        var element = getWallElement(style, wall[i]);
    341353        if (element === undefined && i == 0)
    342             warn("No valid wall element: " + wall[i]);
     354        {
     355            warn("Not a valid wall element: style = " + style + ", wall[" +i+ "] = " +wall[i]+ "; .entPath = " +element.entPath+ ", .length = " +element.length+ ", .angle = " +element.angle+ ", .indent = " +element.indent+ ", .bend = " +element.bend);
     356            continue;
     357        }
     358
    343359        // Indentation
    344360        var placeX = wallX - element.indent * cos(orientation);
    345361        var placeY = wallY - element.indent * sin(orientation);
     362
    346363        // Add wall elements entity placement arguments to the alignment
    347         alignment.push({"x": placeX, "y": placeY, "entity": element.entity, "angle":orientation + element.angle});
     364        alignment.push({"x": placeX, "y": placeY, "entPath": element.entPath, "angle":orientation + element.angle});
     365
    348366        // Preset vars for the next wall element
    349367        if (i+1 < wall.length)
    350368        {
    351             orientation += element.bending;
    352             var nextElement = wallStyles[style][wall[i+1]];
     369            orientation += element.bend;
     370            var nextElement = getWallElement(style, wall[i+1]);
    353371            if (nextElement === undefined)
    354                 warn("No valid wall element: " + wall[i+1]);
    355             var distance = (element.width + nextElement.width)/2;
     372            {
     373                warn("Not a valid wall element: style = " + style + ", wall[" +(i+1)+ "] = " +wall[i+1]+ "; .entPath = " +nextElement.entPath+ ", .length = " +nextElement.length+ ", .angle = " +nextElement.angle+ ", .indent = " +nextElement.indent+ ", .bend = " +nextElement.bend);
     374                continue;
     375            }
     376           
     377            var distance = (element.length + nextElement.length)/2 - getOverlap(style);
    356378            // Corrections for elements with indent AND bending
    357379            var indent = element.indent;
    358             var bending = element.bending;
    359             if (bending !== 0 && indent !== 0)
     380            var bend = element.bend;
     381            if (bend !== 0 && indent !== 0)
    360382            {
    361383                // Indent correction to adjust distance
    362                 distance += indent*sin(bending);
     384                distance += indent*sin(bend);
    363385                // Indent correction to normalize indentation
    364386                wallX += indent * cos(orientation);
    365387                wallY += indent * sin(orientation);
    366388            }
     389           
    367390            // Set the next coordinates of the next element in the wall without indentation adjustment
    368391            wallX -= distance * sin(orientation);
    369392            wallY += distance * cos(orientation);
    function getWallAlignment(startX, startY, wall, style, orientation)  
    383406function getCenterToFirstElement(alignment)
    384407{
    385408    var centerToFirstElement = {"x": 0, "y": 0};
    386     for (var i = 0; i < alignment.length; i++)
     409    for (var i = 0; i < alignment.length; ++i)
    387410    {
    388411        centerToFirstElement.x -= alignment[i].x/alignment.length;
    389412        centerToFirstElement.y -= alignment[i].y/alignment.length;
    function getCenterToFirstElement(alignment)  
    395418//  getWallLength
    396419//
    397420//  NOTE: Does not support bending wall elements like corners!
    398 //  e.g. used by placeIrregularPolygonalWall
    399421//////////////////////////////////////////////////////////////////
    400 function getWallLength(wall, style)
     422function getWallLength(style, wall=[])
    401423{
    402424    // Graciously handle arguments
    403     if (wall === undefined)
    404         wall = [];
    405     if (!wallStyles.hasOwnProperty(style))
     425    if (g_WallStyleList.indexOf(style) < 0)
    406426    {
    407         warn("Function getWallLength: Unknown style: " + style + ' (falling back to "athen")');
    408         style = "athen";
     427        warn("getWallLength: Unknown style: '" + style + "'. (Falling back to '" + FALLBACK_CIV + "_stone').");
     428        style = FALLBACK_CIV +"_stone";
    409429    }
    410    
     430
    411431    var length = 0;
    412     for (var i = 0; i < wall.length; i++)
    413     {
    414         length += wallStyles[style][wall[i]].width;
    415     }
     432    var overlap = getOverlap(style);
     433    for (let element of wall)
     434        length += getWallElement(style, element).length - overlap;
     435
    416436    return length;
    417437}
    418438
     439function getOverlap(style)
     440{
     441    if (!style || g_WallStyleList.indexOf(style) == -1)
     442        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
     443    return g_WallStyles[style]["@overlap"];
     444}
     445
    419446
    420447/////////////////////////////////////////////
    421448// Define the different wall placer functions
    function getWallLength(wall, style)  
    427454//  Places a wall with wall elements attached to another like determined by WallElement properties.
    428455//
    429456//  startX, startY  Where the first wall element should be placed
    430 //  wall            Array of wall element type strings. Example: ["endLeft", "wallLong", "tower", "wallLong", "endRight"]
     457//  wall            Array of wall element types. Example: ["start", "long", "tower", "long", "end"]
    431458//  style           Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    432459//  playerId        Optional. Number of the player the wall will be placed for. Default is 0 (gaia)
    433460//  orientation     Optional. Angle the first wall element is placed. Default is 0
    function getWallLength(wall, style)  
    435462//                  It will then be build towards top/positive Y (if no bending wall elements like corners are used)
    436463//                  Raising orientation means the wall is rotated counter-clockwise like placeObject
    437464/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    438 function placeWall(startX, startY, wall, style, playerId, orientation)
     465function placeWall(startX=0, startY=0, wall=[], style, playerId=0, orientation=0)
    439466{
    440     // Graciously handle arguments
    441     if (wall === undefined)
    442         wall = [];
    443     playerId = (playerId || 0);
    444     if (!wallStyles.hasOwnProperty(style))
    445     {
    446         if (playerId == 0)
    447             style = (style || "palisades");
    448         else
    449             style = (getCivCode(playerId-1));
    450     }
    451     orientation = (orientation || 0);
     467    if (!style || g_WallStyleList.indexOf(style) == -1)
     468        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
    452469   
    453470    // Get wall alignment
    454471    var AM = getWallAlignment(startX, startY, wall, style, orientation);
     472   
    455473    // Place the wall
    456     for (var iWall = 0; iWall < wall.length; iWall++)
     474    for (var iWall = 0; iWall < wall.length; ++iWall)
    457475    {
    458         var entity = AM[iWall].entity;
    459         if (entity !== undefined)
    460             placeObject(AM[iWall].x, AM[iWall].y, entity, playerId, AM[iWall].angle);
     476        var entPath = AM[iWall].entPath;
     477        if (entPath !== undefined)
     478            placeObject(AM[iWall].x, AM[iWall].y, entPath, playerId, AM[iWall].angle);
    461479    }
    462480}
    463481
    function placeWall(startX, startY, wall, style, playerId, orientation)  
    472490//  playerId       Optional. Number of the player the wall will be placed for. Default is 0 (gaia)
    473491//  orientation    Optional. Angle the first wall element (should be a gate or entrance) is placed. Default is 0
    474492/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    475 function placeCustomFortress(centerX, centerY, fortress, style, playerId, orientation)
     493function placeCustomFortress(centerX, centerY, fortress, style, playerId=0, orientation=0)
    476494{
    477495    // Graciously handle arguments
    478     fortress = (fortress || fortressTypes["medium"]);
    479     playerId = (playerId || 0);
    480     if (!wallStyles.hasOwnProperty(style))
    481     {
    482         if (playerId == 0)
    483             style = (style || "palisades");
    484         else
    485             style = (getCivCode(playerId-1));
    486     }
    487     orientation = (orientation || 0);
     496    fortress = fortress || g_FortressTypes["medium"];
     497    if (!style || g_WallStyleList.indexOf(style) == -1)
     498        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
    488499   
    489500    // Calculate center if fortress.centerToFirstElement is undefined (default)
    490501    var centerToFirstElement = fortress.centerToFirstElement;
    function placeCustomFortress(centerX, centerY, fortress, style, playerId, orient  
    501512//
    502513//  Like placeCustomFortress just it takes type (a fortress type string, has to be in fortressTypes) instead of an instance of Fortress
    503514///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    504 function placeFortress(centerX, centerY, type, style, playerId, orientation)
     515function placeFortress(centerX, centerY, type="medium", style, playerId=0, orientation=0)
    505516{
    506517    // Graciously handle arguments
    507     type = (type || "medium");
    508     playerId = (playerId || 0);
    509     if (!wallStyles.hasOwnProperty(style))
    510     {
    511         if (playerId == 0)
    512             style = (style || "palisades");
    513         else
    514             style = (getCivCode(playerId-1));
    515     }
    516     orientation = (orientation || 0);
     518    if (!style || g_WallStyleList.indexOf(style) == -1)
     519        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
    517520   
    518521    // Call placeCustomFortress with the given arguments
    519     placeCustomFortress(centerX, centerY, fortressTypes[type], style, playerId, orientation);
     522    placeCustomFortress(centerX, centerY, g_FortressTypes[type], style, playerId, orientation);
    520523}
    521524
    522525//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function placeFortress(centerX, centerY, type, style, playerId, orientation)  
    526529//
    527530//  startX/startY    Coordinate of the approximate beginning of the wall (Not the place of the first wall element)
    528531//  targetX/targetY  Coordinate of the approximate ending of the wall (Not the place of the last wall element)
    529 //  wallPart         Optional. An array of NON-BENDING wall element type strings. Default is ["tower", "wallLong"]
     532//  wallPart         Optional. An array of NON-BENDING wall element types. Default is ["tower", "wallLong"]
    530533//  style            Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    531534//  playerId         Optional. Integer number of the player. Default is 0 (gaia)
    532535//  endWithFirst     Optional. A boolean value. If true the 1st wall element in the wallPart array will finalize the wall. Default is true
    533536//
    534537//  TODO: Maybe add angle offset for more generic looking?
    535538//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    536 function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, playerId, endWithFirst)
     539function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, playerId=0, endWithFirst=true)
    537540{
    538541    // Setup optional arguments to the default
    539     wallPart = (wallPart || ["tower", "wallLong"]);
    540     playerId = (playerId || 0);
    541     if (!wallStyles.hasOwnProperty(style))
    542     {
    543         if (playerId == 0)
    544             style = (style || "palisades");
    545         else
    546             style = (getCivCode(playerId-1));
    547     }
    548     endWithFirst = typeof endWithFirst == "undefined" ? true : endWithFirst;
     542    wallPart = wallPart || ["tower", "long"];
     543    if (!style || g_WallStyleList.indexOf(style) == -1)
     544        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
    549545   
    550546    // Check arguments
    551     for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    552     {
    553         var bending = wallStyles[style][wallPart[elementIndex]].bending;
    554         if (bending != 0)
    555             warn("Bending is not supported by placeLinearWall but a bending wall element is used: " + wallPart[elementIndex] + " -> wallStyles[style][wallPart[elementIndex]].entity");
    556     }
     547    for (let element of wallPart)
     548        if (getWallElement(style, element).bend != 0)
     549            warn("Bending is not supported by placeLinearWall but the following bending wall element was used: " + element);
     550
    557551    // Setup number of wall parts
    558552    var totalLength = getDistance(startX, startY, targetX, targetY);
    559     var wallPartLength = 0;
    560     for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    561         wallPartLength += wallStyles[style][wallPart[elementIndex]].width;
     553    var wallPartLength = getWallLength(style, wallPart);
    562554    var numParts = 0;
    563555    if (endWithFirst == true)
    564         numParts = ceil((totalLength - wallStyles[style][wallPart[0]].width) / wallPartLength);
     556        numParts = ceil((totalLength - getWallElement(style, wallPart[0]).length) / wallPartLength);
    565557    else
    566558        numParts = ceil(totalLength / wallPartLength);
     559
    567560    // Setup scale factor
    568561    var scaleFactor = 1;
    569562    if (endWithFirst == true)
    570         scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width);
     563        scaleFactor = totalLength / (numParts * wallPartLength + getWallElement(style, wallPart[0]).length);
    571564    else
    572565        scaleFactor = totalLength / (numParts * wallPartLength);
     566
    573567    // Setup angle
    574568    var wallAngle = getAngle(startX, startY, targetX, targetY); // NOTE: function "getAngle()" is about to be changed...
    575569    var placeAngle = wallAngle - PI/2;
    576570    // Place wall entities
    577571    var x = startX;
    578572    var y = startY;
    579     for (var partIndex = 0; partIndex < numParts; partIndex++)
     573    for (var partIndex = 0; partIndex < numParts; ++partIndex)
    580574    {
    581         for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
     575        for (var elementIndex = 0; elementIndex < wallPart.length; ++elementIndex)
    582576        {
    583             var wallEle = wallStyles[style][wallPart[elementIndex]];
    584             // Width correction
    585             x += scaleFactor * wallEle.width/2 * cos(wallAngle);
    586             y += scaleFactor * wallEle.width/2 * sin(wallAngle);
     577            let wallEle = getWallElement(style, wallPart[elementIndex]);
     578            let wallLength = (wallEle.length - getOverlap(style)) / 2;
     579            let distX = scaleFactor * wallLength * cos(wallAngle);
     580            let distY = scaleFactor * wallLength * sin(wallAngle);
     581            // Length correction
     582            x += distX;
     583            y += distY;
    587584            // Indent correction
    588             var placeX = x - wallEle.indent * sin(wallAngle);
    589             var placeY = y + wallEle.indent * cos(wallAngle);
     585            let placeX = x - wallEle.indent * sin(wallAngle);
     586            let placeY = y + wallEle.indent * cos(wallAngle);
    590587            // Placement
    591             var entity = wallEle.entity;
    592             if (entity !== undefined)
    593                 placeObject(placeX, placeY, entity, playerId, placeAngle + wallEle.angle);
    594             x += scaleFactor * wallEle.width/2 * cos(wallAngle);
    595             y += scaleFactor * wallEle.width/2 * sin(wallAngle);
     588            let entPath = wallEle.entPath;
     589            if (entPath !== undefined)
     590                placeObject(placeX, placeY, entPath, playerId, placeAngle + wallEle.angle);
     591            // Prep for next object
     592            x += distX;
     593            y += distY;
    596594        }
    597595    }
    598596    if (endWithFirst == true)
    599597    {
    600         var wallEle = wallStyles[style][wallPart[0]];
    601         x += scaleFactor * wallEle.width/2 * cos(wallAngle);
    602         y += scaleFactor * wallEle.width/2 * sin(wallAngle);
    603         var entity = wallEle.entity;
    604         if (entity !== undefined)
    605             placeObject(x, y, entity, playerId, placeAngle + wallEle.angle);
     598        var wallEle = getWallElement(style, wallPart[0]);
     599        let wallLength = (wallEle.length - getOverlap(style)) / 2;
     600        x += scaleFactor * wallLength * cos(wallAngle);
     601        y += scaleFactor * wallLength * sin(wallAngle);
     602        var entPath = wallEle.entPath;
     603        if (entPath !== undefined)
     604            placeObject(x, y, entPath, playerId, placeAngle + wallEle.angle);
    606605    }
    607606}
    608607
    function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, play  
    615614//
    616615//  centerX/Y     Coordinates of the circle's center
    617616//  radius        How wide the circle should be (approximate, especially if maxBendOff != 0)
    618 //  wallPart      Optional. An array of NON-BENDING wall element type strings. Default is ["tower", "wallLong"]
     617//  wallPart      Optional. An array of NON-BENDING wall element types. Default is ["tower", "wallLong"]
    619618//  style         Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    620619//  playerId      Optional. Integer number of the player. Default is 0 (gaia)
    621620//  orientation   Optional. Where the open part of the (circular) arc should face (if maxAngle is < 2*PI). Default is 0
    function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, play  
    624623//  maxBendOff    Optional. How irregular the circle should be. 0 means regular circle, PI/2 means very irregular. Default is 0 (regular circle)
    625624//
    626625//  NOTE: Don't use wall elements with bending like corners!
    627 //  TODO: Perhaps add eccentricity and maxBendOff functionality (untill now an unused argument)
     626//  TODO: Perhaps add eccentricity
     627//  TODO: Check if maxBendOff parameter works in all cases
    628628//  TODO: Perhaps add functionality for spirals
    629629/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    630 function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, orientation, maxAngle, endWithFirst, maxBendOff)
     630function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId=0, orientation=0, maxAngle=TWO_PI, endWithFirst, maxBendOff=0)
    631631{
    632632    // Setup optional arguments to the default
    633     wallPart = (wallPart || ["tower", "wallLong"]);
    634     playerId = (playerId || 0);
    635     if (!wallStyles.hasOwnProperty(style))
    636     {
    637         if (playerId == 0)
    638             style = (style || "palisades");
    639         else
    640             style = (getCivCode(playerId-1));
    641     }
    642     orientation = (orientation || 0);
    643     maxAngle = (maxAngle || 2*PI);
     633    wallPart = wallPart || ["tower", "long"];
     634    if (!style || g_WallStyleList.indexOf(style) == -1)
     635        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
    644636    if (endWithFirst === undefined)
    645637    {
    646         if (maxAngle >= 2*PI - 0.001) // Can this be done better?
     638        if (maxAngle >= TWO_PI - 0.001) // Can this be done better?
    647639            endWithFirst = false;
    648640        else
    649641            endWithFirst = true;
    650642    }
    651     maxBendOff = (maxBendOff || 0);
    652643   
    653644    // Check arguments
    654645    if (maxBendOff > PI/2 || maxBendOff < 0)
    655         warn("placeCircularWall maxBendOff sould satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff);
    656     for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    657     {
    658         var bending = wallStyles[style][wallPart[elementIndex]].bending;
    659         if (bending != 0)
    660             warn("Bending is not supported by placeCircularWall but a bending wall element is used: " + wallPart[elementIndex]);
    661     }
     646        warn("placeCircularWall maxBendOff should satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff);
     647    for (let element of wallPart)
     648        if (getWallElement(style, element).bend != 0)
     649            warn("Bending is not supported by placeCircularWall but the following bending wall element was used: " + element);
     650
    662651    // Setup number of wall parts
    663652    var totalLength = maxAngle * radius;
    664     var wallPartLength = 0;
    665     for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    666         wallPartLength += wallStyles[style][wallPart[elementIndex]].width;
     653    var wallPartLength = getWallLength(style, wallPart);
    667654    var numParts = 0;
    668655    if (endWithFirst == true)
    669656    {
    670         numParts = ceil((totalLength - wallStyles[style][wallPart[0]].width) / wallPartLength);
     657        numParts = ceil((totalLength - getWallElement(style, wallPart[0]).length) / wallPartLength);
    671658    }
    672659    else
    673660    {
    function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId,  
    676663    // Setup scale factor
    677664    var scaleFactor = 1;
    678665    if (endWithFirst == true)
    679         scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width);
     666        scaleFactor = totalLength / (numParts * wallPartLength + getWallElement(style, wallPart[0]).length);
    680667    else
    681668        scaleFactor = totalLength / (numParts * wallPartLength);
    682669    // Place wall entities
    683670    var actualAngle = orientation + (2*PI - maxAngle) / 2;
    684671    var x = centerX + radius*cos(actualAngle);
    685672    var y = centerY + radius*sin(actualAngle);
    686     for (var partIndex = 0; partIndex < numParts; partIndex++)
     673    for (let partIndex = 0; partIndex < numParts; ++partIndex)
    687674    {
    688         for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
     675        for (let wallEle of wallPart)
    689676        {
    690             var wallEle = wallStyles[style][wallPart[elementIndex]];
     677            wallEle = getWallElement(style, wallEle);
    691678            // Width correction
    692             var addAngle = scaleFactor * wallEle.width / radius;
    693             var targetX = centerX + radius * cos(actualAngle + addAngle);
    694             var targetY = centerY + radius * sin(actualAngle + addAngle);
    695             var placeX = x + (targetX - x)/2;
    696             var placeY = y + (targetY - y)/2;
    697             var placeAngle = actualAngle + addAngle/2;
     679            let addAngle = scaleFactor * (wallEle.length - getOverlap(style)) / radius;
     680            let targetX = centerX + radius * cos(actualAngle + addAngle);
     681            let targetY = centerY + radius * sin(actualAngle + addAngle);
     682            let placeX = x + (targetX - x)/2;
     683            let placeY = y + (targetY - y)/2;
     684            let placeAngle = actualAngle + addAngle/2;
    698685            // Indent correction
    699686            placeX -= wallEle.indent * cos(placeAngle);
    700687            placeY -= wallEle.indent * sin(placeAngle);
    701688            // Placement
    702             var entity = wallEle.entity;
    703             if (entity !== undefined)
    704                 placeObject(placeX, placeY, entity, playerId, placeAngle + wallEle.angle);
     689            var entPath = wallEle.entPath;
     690            if (entPath !== undefined)
     691                placeObject(placeX, placeY, entPath, playerId, placeAngle + wallEle.angle);
    705692            // Prepare for the next wall element
    706693            actualAngle += addAngle;
    707694            x = centerX + radius*cos(actualAngle);
    function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId,  
    710697    }
    711698    if (endWithFirst == true)
    712699    {
    713         var wallEle = wallStyles[style][wallPart[0]];
    714         var addAngle = scaleFactor * wallEle.width / radius;
     700        var wallEle = getWallElement(style, wallPart[0]);
     701        var addAngle = scaleFactor * wallEle.length / radius;
    715702        var targetX = centerX + radius * cos(actualAngle + addAngle);
    716703        var targetY = centerY + radius * sin(actualAngle + addAngle);
    717704        var placeX = x + (targetX - x)/2;
    718705        var placeY = y + (targetY - y)/2;
    719706        var placeAngle = actualAngle + addAngle/2;
    720         placeObject(placeX, placeY, wallEle.entity, playerId, placeAngle + wallEle.angle);
     707        placeObject(placeX, placeY, wallEle.entPath, playerId, placeAngle + wallEle.angle);
    721708    }
    722709}
    723710
    function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId,  
    728715//
    729716//  centerX/Y          Coordinates of the polygon's center
    730717//  radius             How wide the circle should be in which the polygon fits
    731 //  wallPart           Optional. An array of NON-BENDING wall element type strings. Default is ["wallLong", "tower"]
     718//  wallPart           Optional. An array of NON-BENDING wall element types. Default is ["wallLong", "tower"]
    732719//  cornerWallElement  Optional. Wall element to be placed at the polygon's corners. Default is "tower"
    733720//  style              Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    734721//  playerId           Optional. Integer number of the player. Default is 0 (gaia)
    function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId,  
    741728//  TODO: Check some arguments
    742729//  TODO: Add eccentricity and perhaps make it just call placeIrregularPolygonalWall with irregularity = 0
    743730/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    744 function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElement, style, playerId, orientation, numCorners, skipFirstWall)
     731function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElement, style, playerId=0, orientation=0, numCorners=8, skipFirstWall=true)
    745732{
    746733    // Setup optional arguments to the default
    747     wallPart = (wallPart || ["wallLong", "tower"]);
    748     cornerWallElement = (cornerWallElement || "tower"); // Don't use wide elements for this. Not supported well...
    749     playerId = (playerId || 0);
    750     if (!wallStyles.hasOwnProperty(style))
    751     {
    752         if (playerId == 0)
    753             style = (style || "palisades");
    754         else
    755             style = (getCivCode(playerId-1));
    756     }
    757     orientation = (orientation || 0);
    758     numCorners = (numCorners || 8);
    759     skipFirstWall = (skipFirstWall || true);
    760    
     734    wallPart = wallPart || ["long", "tower"];
     735    cornerWallElement = cornerWallElement || "tower"; // Don't use wide elements for this. Not supported well...
     736    if (!style || g_WallStyleList.indexOf(style) == -1)
     737        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
     738
    761739    // Setup angles
    762     var angleAdd = 2*PI/numCorners;
     740    var angleAdd = TWO_PI/numCorners;
    763741    var angleStart = orientation - angleAdd/2;
     742
    764743    // Setup corners
    765744    var corners = [];
    766     for (var i = 0; i < numCorners; i++)
     745    for (let i = 0; i < numCorners; ++i)
    767746        corners.push([centerX + radius*cos(angleStart + i*angleAdd), centerY + radius*sin(angleStart + i*angleAdd)]);
     747
    768748    // Place Corners and walls
    769     for (var i = 0; i < numCorners; i++)
     749    for (let i = 0; i < numCorners; ++i)
    770750    {
    771         var angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY);
    772         placeObject(corners[i][0], corners[i][1], wallStyles[style][cornerWallElement].entity, playerId, angleToCorner);
     751        let angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY);
     752        placeObject(corners[i][0], corners[i][1], getWallElement(style, cornerWallElement).entPath, playerId, angleToCorner);
    773753        if (!(skipFirstWall && i == 0))
    774754        {
     755            let cornerLength = getWallElement(style, cornerWallElement).length / 2;
     756            let cornerAngle = angleToCorner + angleAdd / 2;
     757            let cornerX = cornerLength * sin(cornerAngle);
     758            let cornerY = cornerLength * cos(cornerAngle);
    775759            placeLinearWall(
    776760                // Adjustment to the corner element width (approximately)
    777                 corners[i][0] + wallStyles[style][cornerWallElement].width/2 * sin(angleToCorner + angleAdd/2), // startX
    778                 corners[i][1] - wallStyles[style][cornerWallElement].width/2 * cos(angleToCorner + angleAdd/2), // startY
    779                 corners[(i+1)%numCorners][0] - wallStyles[style][cornerWallElement].width/2 * sin(angleToCorner + angleAdd/2), // targetX
    780                 corners[(i+1)%numCorners][1] + wallStyles[style][cornerWallElement].width/2 * cos(angleToCorner + angleAdd/2), // targetY
     761                corners[i][0] + cornerX, // startX
     762                corners[i][1] - cornerY, // startY
     763                corners[(i+1)%numCorners][0] - cornerX, // targetX
     764                corners[(i+1)%numCorners][1] + cornerY, // targetY
    781765                wallPart, style, playerId);
    782766        }
    783767    }
    function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElemen  
    794778//  style                Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    795779//  playerId             Optional. Integer number of the player. Default is 0 (gaia)
    796780//  orientation          Optional. Angle from the center to the first linear wall part placed. Default is 0 (towards positive X/right)
    797 //  numCorners           Optional. How many corners the polygon will have. Default is 8 (matching a civ centers territory)
     781//  numCorners           Optional. How many corners the polygon will have. Default is randomly chosen from 'tween 5 & 7 inclusive
    798782//  irregularity         Optional. How irregular the polygon will be. 0 means regular, 1 means VERY irregular. Default is 0.5
    799 //  skipFirstWall        Optional. Boolean. If the first linear wall part will be left opened as entrance. Default is true
     783//  skipFirstWall        Optional. Boolean. If the first linear wall part will be left opened as entrance. Default is false
    800784//  wallPartsAssortment  Optional. An array of wall part arrays to choose from for each linear wall connecting the corners. Default is hard to describe ^^
    801785//
    802786//  NOTE: wallPartsAssortment is put to the end because it's hardest to set
    function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElemen  
    805789//  TODO: Check some arguments
    806790//  TODO: Perhaps add eccentricity
    807791////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    808 function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement, style, playerId, orientation, numCorners, irregularity, skipFirstWall, wallPartsAssortment)
     792function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement="tower", style, playerId=0, orientation=0, numCorners, irregularity=0.5, skipFirstWall=false, wallPartsAssortment)
    809793{
    810794    // Setup optional arguments
    811     playerId = (playerId || 0);
    812     if (!wallStyles.hasOwnProperty(style))
    813     {
    814         if (playerId == 0)
    815             style = (style || "palisades");
    816         else
    817             style = (getCivCode(playerId-1));
    818     }
    819    
     795    if (!style || g_WallStyleList.indexOf(style) == -1)
     796        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
     797    numCorners = (numCorners || randInt(5, 7));
     798
    820799    // Generating a generic wall part assortment with each wall part including 1 gate lengthened by walls and towers
    821800    // NOTE: It might be a good idea to write an own function for that...
    822     var defaultWallPartsAssortment = [["wallShort"], ["wall"], ["wallLong"], ["gate", "tower", "wallShort"]];
     801    var defaultWallPartsAssortment = [["short"], ["medium"], ["long"], ["gate", "tower", "short"]];
    823802    var centeredWallPart = ["gate"];
    824     var extandingWallPartAssortment = [["tower", "wallLong"], ["tower", "wall"]];
     803    var extandingWallPartAssortment = [["tower", "long"], ["tower", "medium"]];
    825804    defaultWallPartsAssortment.push(centeredWallPart);
    826     for (var i = 0; i < extandingWallPartAssortment.length; i++)
     805    for (var i = 0; i < extandingWallPartAssortment.length; ++i)
    827806    {
    828807        var wallPart = centeredWallPart;
    829         for (var j = 0; j < radius; j++)
     808        for (var j = 0; j < radius; ++j)
    830809        {
    831810            if (j%2 == 0)
    832811                wallPart = wallPart.concat(extandingWallPartAssortment[i]);
    function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement  
    841820    }
    842821    // Setup optional arguments to the default
    843822    wallPartsAssortment = (wallPartsAssortment || defaultWallPartsAssortment);
    844     cornerWallElement = (cornerWallElement || "tower"); // Don't use wide elements for this. Not supported well...
    845     style = (style || "palisades");
    846     playerId = (playerId || 0);
    847     orientation = (orientation || 0);
    848     numCorners = (numCorners || randInt(5, 7));
    849     irregularity = (irregularity || 0.5);
    850     skipFirstWall = (skipFirstWall || false);
     823
    851824    // Setup angles
    852     var angleToCover = 2*PI;
     825    var angleToCover = TWO_PI;
    853826    var angleAddList = [];
    854     for (var i = 0; i < numCorners; i++)
     827    for (var i = 0; i < numCorners; ++i)
    855828    {
    856829        // Randomize covered angles. Variety scales down with raising angle though...
    857830        angleAddList.push(angleToCover/(numCorners-i) * (1 + randFloat(-irregularity, irregularity)));
    function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement  
    860833    // Setup corners
    861834    var corners = [];
    862835    var angleActual = orientation - angleAddList[0]/2;
    863     for (var i = 0; i < numCorners; i++)
     836    for (var i = 0; i < numCorners; ++i)
    864837    {
    865838        corners.push([centerX + radius*cos(angleActual), centerY + radius*sin(angleActual)]);
    866839        if (i < numCorners - 1)
    function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement  
    869842    // Setup best wall parts for the different walls (a bit confusing naming...)
    870843    var wallPartLengths = [];
    871844    var maxWallPartLength = 0;
    872     for (var partIndex = 0; partIndex < wallPartsAssortment.length; partIndex++)
     845    for (let wallPart of wallPartsAssortment)
    873846    {
    874         var length = wallPartLengths[partIndex];
    875         wallPartLengths.push(getWallLength(wallPartsAssortment[partIndex], style));
     847        var length = getWallLength(style, wallPart);
     848        wallPartLengths.push(length);
    876849        if (length > maxWallPartLength)
    877850            maxWallPartLength = length;
    878851    }
     852   
    879853    var wallPartList = []; // This is the list of the wall parts to use for the walls between the corners, not to confuse with wallPartsAssortment!
    880     for (var i = 0; i < numCorners; i++)
     854    for (var i = 0; i < numCorners; ++i)
    881855    {
    882         var bestWallPart = []; // This is a simpel wall part not a wallPartsAssortment!
    883         var bestWallLength = 99999999;
     856        var bestWallPart = []; // This is a simple wall part not a wallPartsAssortment!
     857        var bestWallLength = Number.MAX_VALUE;
    884858        // NOTE: This is not exactly like the length the wall will be in the end. Has to be tweaked...
    885859        var wallLength = getDistance(corners[i][0], corners[i][1], corners[(i+1)%numCorners][0], corners[(i+1)%numCorners][1]);
    886860        var numWallParts = ceil(wallLength/maxWallPartLength);
    887         for (var partIndex = 0; partIndex < wallPartsAssortment.length; partIndex++)
     861        for (var partIndex = 0; partIndex < wallPartsAssortment.length; ++partIndex)
    888862        {
    889863            var linearWallLength = numWallParts*wallPartLengths[partIndex];
    890864            if (linearWallLength < bestWallLength && linearWallLength > wallLength)
    function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement  
    895869        }
    896870        wallPartList.push(bestWallPart);
    897871    }
     872
    898873    // Place Corners and walls
    899     for (var i = 0; i < numCorners; i++)
     874    for (var i = 0; i < numCorners; ++i)
    900875    {
    901876        var angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY);
    902         placeObject(corners[i][0], corners[i][1], wallStyles[style][cornerWallElement].entity, playerId, angleToCorner);
     877        placeObject(corners[i][0], corners[i][1], getWallElement(style, cornerWallElement).entPath, playerId, angleToCorner);
    903878        if (!(skipFirstWall && i == 0))
    904879        {
     880            let cornerLength = getWallElement(style, cornerWallElement).length / 2;
    905881            placeLinearWall(
    906882                // Adjustment to the corner element width (approximately)
    907                 corners[i][0] + wallStyles[style][cornerWallElement].width/2 * sin(angleToCorner + angleAddList[i]/2), // startX
    908                 corners[i][1] - wallStyles[style][cornerWallElement].width/2 * cos(angleToCorner + angleAddList[i]/2), // startY
    909                 corners[(i+1)%numCorners][0] - wallStyles[style][cornerWallElement].width/2 * sin(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetX
    910                 corners[(i+1)%numCorners][1] + wallStyles[style][cornerWallElement].width/2 * cos(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetY
     883                corners[i][0] + cornerLength * sin(angleToCorner + angleAddList[i]/2), // startX
     884                corners[i][1] - cornerLength * cos(angleToCorner + angleAddList[i]/2), // startY
     885                corners[(i+1)%numCorners][0] - cornerLength * sin(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetX
     886                corners[(i+1)%numCorners][1] + cornerLength * cos(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetY
    911887                wallPartList[i], style, playerId, false);
    912888        }
    913889    }
    function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement  
    920896//  This is the default Iberian civ bonus starting wall
    921897//
    922898//  centerX/Y      The approximate center coordinates of the fortress
    923 //  radius         The approximate radius of the wall to be placed
     899//  radius         Optional. The approximate radius of the wall to be placed. Default is 20
    924900//  playerId       Optional. Integer number of the player. Default is 0 (gaia)
    925901//  style          Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    926 //  irregularity   Optional. Float between 0 (circle) and 1 (very spiky), default is 1/2
     902//  irregularity   Optional. Float between 0 (circle) and 1 (very spiky), default is 0.5
    927903//  gateOccurence  Optional. Integer number, every n-th walls will be a gate instead. Default is 3
    928904//  maxTrys        Optional. How often the function tries to find a better fitting shape at max. Default is 100
    929905//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    930 function placeGenericFortress(centerX, centerY, radius, playerId, style, irregularity, gateOccurence, maxTrys)
     906function placeGenericFortress(centerX, centerY, radius=20, playerId=0, style, irregularity=0.5, gateOccurence=3, maxTrys=100)
    931907{
    932908    // Setup optional arguments
    933     radius = (radius || 20);
    934     playerId = (playerId || 0);
    935     if (!wallStyles.hasOwnProperty(style))
    936     {
    937         if (playerId == 0)
    938             style = (style || "palisades");
    939         else
    940             style = (getCivCode(playerId-1));
    941     }
    942     irregularity = (irregularity || 1/2);
    943     gateOccurence = (gateOccurence || 3);
    944     maxTrys = (maxTrys || 100);
     909    if (!style || g_WallStyleList.indexOf(style) == -1)
     910        style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone";
    945911   
    946912    // Setup some vars
    947913    var startAngle = randFloat(0, 2*PI);
    948914    var actualOffX = radius*cos(startAngle);
    949915    var actualOffY = radius*sin(startAngle);
    950916    var actualAngle = startAngle;
    951     var pointDistance = wallStyles[style]["wallLong"].width + wallStyles[style]["tower"].width;
     917    var pointDistance = getWallLength(style, ["long", "tower"]);
    952918    // Searching for a well fitting point derivation
    953919    var tries = 0;
    954920    var bestPointDerivation = undefined;
    955921    var minOverlap = 1000;
    956922    var overlap = undefined;
    957     while (tries < maxTrys && minOverlap > wallStyles[style]["tower"].width / 10)
     923    while (tries < maxTrys && minOverlap > getOverlap(style))
    958924    {
    959925        var pointDerivation = [];
    960926        var distanceToTarget = 1000;
    function placeGenericFortress(centerX, centerY, radius, playerId, style, irregul  
    963929        {
    964930            var indent = randFloat(-irregularity*pointDistance, irregularity*pointDistance);
    965931            var tmpAngle = getAngle(actualOffX, actualOffY,
    966                 (radius + indent)*cos(actualAngle + (pointDistance / radius)),
    967                 (radius + indent)*sin(actualAngle + (pointDistance / radius)));
     932                (radius + indent)*cos(actualAngle + pointDistance / radius),
     933                (radius + indent)*sin(actualAngle + pointDistance / radius));
    968934            actualOffX += pointDistance*cos(tmpAngle);
    969935            actualOffY += pointDistance*sin(tmpAngle);
    970936            actualAngle = getAngle(0, 0, actualOffX, actualOffY);
    function placeGenericFortress(centerX, centerY, radius, playerId, style, irregul  
    982948                }
    983949            }
    984950        }
    985         tries++;
     951        ++tries;
    986952    }
    987953    log("placeGenericFortress: Reduced overlap to " + minOverlap + " after " + tries + " tries");
    988954    // Place wall
    989     for (var pointIndex = 0; pointIndex < bestPointDerivation.length; pointIndex++)
     955    for (var pointIndex = 0; pointIndex < bestPointDerivation.length; ++pointIndex)
    990956    {
    991957        var startX = centerX + bestPointDerivation[pointIndex][0];
    992958        var startY = centerY + bestPointDerivation[pointIndex][1];
    993959        var targetX = centerX + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][0];
    994960        var targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1];
    995961        var angle = getAngle(startX, startY, targetX, targetY);
    996         var wallElement = "wallLong";
     962        var wallElement = "long";
    997963        if ((pointIndex + 1) % gateOccurence == 0)
    998964            wallElement = "gate";
    999         var entity = wallStyles[style][wallElement].entity;
    1000         if (entity)
     965
     966        var entPath = getWallElement(style, wallElement).entPath;
     967        if (entPath)
    1001968        {
    1002969            placeObject(startX + (getDistance(startX, startY, targetX, targetY)/2)*cos(angle), // placeX
    1003970                startY + (getDistance(startX, startY, targetX, targetY)/2)*sin(angle), // placeY
    1004                 entity, playerId, angle - PI/2 + wallStyles[style][wallElement].angle);
     971                entPath, playerId, angle - PI/2 + getWallElement(style, wallElement).angle);
    1005972        }
    1006973        // Place tower
    1007974        var startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0];
    1008975        var startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1];
    1009976        var angle = getAngle(startX, startY, targetX, targetY);
    1010         placeObject(centerX + bestPointDerivation[pointIndex][0], centerY + bestPointDerivation[pointIndex][1], wallStyles[style]["tower"].entity, playerId, angle - PI/2 + wallStyles[style]["tower"].angle);
     977
     978        var tower = getWallElement(style, "tower");
     979        placeObject(centerX + bestPointDerivation[pointIndex][0], centerY + bestPointDerivation[pointIndex][1], tower.entPath, playerId, angle - PI/2 + tower.angle);
    1011980    }
    1012981}
  • binaries/data/mods/public/maps/random/schwarzwald.js

    var playerAngleMaxOff = playerAngleAddAvrg/4;  
    131131// Setup paths
    132132var pathSucsessRadius = baseRadius/2;
    133133var pathAngleOff = PI/2;
    134 var pathWidth = 10; // This is not really the path's thickness in tiles but the number of tiles in the clumbs of the path
     134var pathWidth = 10; // This is not really the path's thickness in tiles but the number of tiles in the clumps of the path
    135135
    136136// Setup additional resources
    137137var resourceRadius = 2*mapRadius/3; // 3*mapRadius/8;
    HeightPlacer.prototype.place = function (constraint) {  
    159159    constraint = (constraint || new NullConstraint());
    160160   
    161161    var ret = [];
    162     for (var x = 0; x < g_Map.size; x++) {
    163         for (var y = 0; y < g_Map.size; y++) {
     162    for (var x = 0; x < g_Map.size; ++x) {
     163        for (var y = 0; y < g_Map.size; ++y) {
    164164            if (g_Map.height[x][y] >= this.lowerBound && g_Map.height[x][y] <= this.upperBound && constraint.allows(x, y)) {
    165165                ret.push(new PointXZ(x, y));
    166166            }
    function getOrderOfPointsForShortestClosePath(points)  
    179179    var distances = [];
    180180    if (points.length <= 3)
    181181    {
    182         for (var i = 0; i < points.length; i++)
     182        for (var i = 0; i < points.length; ++i)
    183183            order.push(i);
    184184       
    185185        return order;
    function getOrderOfPointsForShortestClosePath(points)  
    187187   
    188188    // Just add the first 3 points
    189189    var pointsToAdd = deepcopy(points);
    190     for (var i = 0; i < min(points.length, 3); i++)
     190    for (var i = 0; i < min(points.length, 3); i)
    191191    {
    192192        order.push(i);
    193193        pointsToAdd.shift(i);
    function getOrderOfPointsForShortestClosePath(points)  
    198198   
    199199    // Add remaining points so the path lengthens the least
    200200    var numPointsToAdd = pointsToAdd.length;
    201     for (var i = 0; i < numPointsToAdd; i++)
     201    for (var i = 0; i < numPointsToAdd; ++i)
    202202    {
    203203        var indexToAddTo = undefined;
    204204        var minEnlengthen = Infinity;
    205205        var minDist1 = 0;
    206206        var minDist2 = 0;
    207         for (var k = 0; k < order.length; k++)
     207        for (var k = 0; k < order.length; ++k)
    208208        {
    209209            var dist1 = getDistance(pointsToAdd[0][0], pointsToAdd[0][1], points[order[k]][0], points[order[k]][1]);
    210210            var dist2 = getDistance(pointsToAdd[0][0], pointsToAdd[0][1], points[order[(k + 1) % order.length]][0], points[order[(k + 1) % order.length]][1]);
    function getOrderOfPointsForShortestClosePath(points)  
    232232//
    233233////////////////
    234234
    235 // Some heightmap constants
    236 const MIN_HEIGHT = - SEA_LEVEL; // -20
    237 const MAX_HEIGHT = 0xFFFF/HEIGHT_UNITS_PER_METRE - SEA_LEVEL; // A bit smaller than 90
    238 
    239235// Get the diferrence between minimum and maxumum height
    240236function getMinAndMaxHeight(reliefmap)
    241237{
    242238    var height = {};
    243239    height.min = Infinity;
    244240    height.max = - Infinity;
    245     for (var x = 0; x < reliefmap.length; x++)
     241    for (var x = 0; x < reliefmap.length; ++x)
    246242    {
    247         for (var y = 0; y < reliefmap[x].length; y++)
     243        for (var y = 0; y < reliefmap[x].length; ++y)
    248244        {
    249245            if (reliefmap[x][y] < height.min)
    250246                height.min = reliefmap[x][y];
    function rescaleHeightmap(minHeight, maxHeight, heightmap)  
    264260    var oldHeightRange = getMinAndMaxHeight(heightmap);
    265261    var max_x = heightmap.length;
    266262    var max_y = heightmap[0].length;
    267     for (var x = 0; x < max_x; x++)
    268         for (var y = 0; y < max_y; y++)
     263    for (var x = 0; x < max_x; ++x)
     264        for (var y = 0; y < max_y; ++y)
    269265            heightmap[x][y] = minHeight + (heightmap[x][y] - oldHeightRange.min) / (oldHeightRange.max - oldHeightRange.min) * (maxHeight - minHeight);
    270266}
    271267
    function getStartLocationsByHeightmap(hightRange, maxTries, minDistToBorder, num  
    288284    heightmap = (heightmap || g_Map.height);
    289285   
    290286    var validStartLocTiles = [];
    291     for (var x = minDistToBorder; x < heightmap.length - minDistToBorder; x++)
    292         for (var y = minDistToBorder; y < heightmap[0].length - minDistToBorder; y++)
     287    for (var x = minDistToBorder; x < heightmap.length - minDistToBorder; ++x)
     288        for (var y = minDistToBorder; y < heightmap[0].length - minDistToBorder; ++y)
    293289            if (heightmap[x][y] > hightRange.min && heightmap[x][y] < hightRange.max) // Has the right hight
    294290                validStartLocTiles.push([x, y]);
    295291   
    296292    var maxMinDist = 0;
    297     for (var tries = 0; tries < maxTries; tries++)
     293    for (var tries = 0; tries < maxTries; ++tries)
    298294    {
    299295        var startLoc = [];
    300296        var minDist = heightmap.length;
    301         for (var p = 0; p < numberOfPlayers; p++)
     297        for (var p = 0; p < numberOfPlayers; ++p)
    302298            startLoc.push(validStartLocTiles[randInt(validStartLocTiles.length)]);
    303         for (var p1 = 0; p1 < numberOfPlayers - 1; p1++)
     299        for (var p1 = 0; p1 < numberOfPlayers - 1; ++p1)
    304300        {
    305             for (var p2 = p1 + 1; p2 < numberOfPlayers; p2++)
     301            for (var p2 = p1 + 1; p2 < numberOfPlayers; ++p2)
    306302            {
    307303                var dist = getDistance(startLoc[p1][0], startLoc[p1][1], startLoc[p2][0], startLoc[p2][1]);
    308304                if (dist < minDist)
    function derivateEntitiesByHeight(hightRange, startLoc, entityList, maxTries, mi  
    340336   
    341337    var placements = deepcopy(startLoc);
    342338    var validTiles = [];
    343     for (var x = minDistance; x < heightmap.length - minDistance; x++)
    344         for (var y = minDistance; y < heightmap[0].length - minDistance; y++)
     339    for (var x = minDistance; x < heightmap.length - minDistance; ++x)
     340        for (var y = minDistance; y < heightmap[0].length - minDistance; ++y)
    345341            if (heightmap[x][y] > hightRange.min && heightmap[x][y] < hightRange.max) // Has the right hight
    346342                validTiles.push([x, y]);
    347343   
    348344    if (!validTiles.length)
    349345        return;
    350346   
    351     for (var tries = 0; tries < maxTries; tries++)
     347    for (var tries = 0; tries < maxTries; ++tries)
    352348    {
    353349        var tile = validTiles[randInt(validTiles.length)];
    354350        var isValid = true;
    355         for (var p = 0; p < placements.length; p++)
     351        for (var p = 0; p < placements.length; ++p)
    356352        {
    357353            if (getDistance(placements[p][0], placements[p][1], tile[0], tile[1]) < minDistance)
    358354            {
    function setBaseTerrainDiamondSquare(minHeight, maxHeight, smoothness, initialHe  
    395391        var newHeightmap = [];
    396392        var oldWidth = initialHeightmap.length;
    397393        // Square
    398         for (var x = 0; x < 2 * oldWidth - 1; x++)
     394        for (var x = 0; x < 2 * oldWidth - 1; ++x)
    399395        {
    400396            newHeightmap.push([]);
    401             for (var y = 0; y < 2 * oldWidth - 1; y++)
     397            for (var y = 0; y < 2 * oldWidth - 1; ++y)
    402398            {
    403399                if (x % 2 === 0 && y % 2 === 0) // Old tile
    404400                    newHeightmap[x].push(initialHeightmap[x/2][y/2]);
    function setBaseTerrainDiamondSquare(minHeight, maxHeight, smoothness, initialHe  
    412408            }
    413409        }
    414410        // Diamond
    415         for (var x = 0; x < 2 * oldWidth - 1; x++)
     411        for (var x = 0; x < 2 * oldWidth - 1; ++x)
    416412        {
    417             for (var y = 0; y < 2 * oldWidth - 1; y++)
     413            for (var y = 0; y < 2 * oldWidth - 1; ++y)
    418414            {
    419415                if (newHeightmap[x][y] === undefined)
    420416                {
    function setBaseTerrainDiamondSquare(minHeight, maxHeight, smoothness, initialHe  
    452448   
    453449    // Cut initialHeightmap to fit target width
    454450    var shift = [floor((newHeightmap.length - heightmap.length) / 2), floor((newHeightmap[0].length - heightmap[0].length) / 2)];
    455     for (var x = 0; x < heightmap.length; x++)
    456         for (var y = 0; y < heightmap[0].length; y++)
     451    for (var x = 0; x < heightmap.length; ++x)
     452        for (var y = 0; y < heightmap[0].length; ++y)
    457453            heightmap[x][y] = newHeightmap[x][y];
    458454}
    459455
    function decayErrodeHeightmap(strength, heightmap)  
    474470    var map = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]; // smoother
    475471    var max_x = heightmap.length;
    476472    var max_y = heightmap[0].length;
    477     for (var x = 0; x < max_x; x++)
    478         for (var y = 0; y < max_y; y++)
    479             for (var i = 0; i < map.length; i++)
     473    for (var x = 0; x < max_x; ++x)
     474        for (var y = 0; y < max_y; ++y)
     475            for (var i = 0; i < map.length; ++i)
    480476                heightmap[x][y] += strength / map.length * (referenceHeightmap[(x + map[i][0] + max_x) % max_x][(y + map[i][1] + max_y) % max_y] - referenceHeightmap[x][y]); // Not entirely sure if scaling with map.length is perfect but tested values seam to indicate it is
    481477}
    482478
    function rectangularSmoothToHeight(center, dx, dy, targetHeight, strength, heigh  
    490486    heightmap = (heightmap || g_Map.height);
    491487   
    492488    var heightmapWin = [];
    493     for (var wx = 0; wx < 2 * dx + 1; wx++)
     489    for (var wx = 0; wx < 2 * dx + 1; ++wx)
    494490    {
    495491        heightmapWin.push([]);
    496         for (var wy = 0; wy < 2 * dy + 1; wy++)
     492        for (var wy = 0; wy < 2 * dy + 1; ++wy)
    497493        {
    498494            var actualX = x - dx + wx;
    499495            var actualY = y - dy + wy;
    function rectangularSmoothToHeight(center, dx, dy, targetHeight, strength, heigh  
    503499                heightmapWin[wx].push(targetHeight);
    504500        }
    505501    }
    506     for (var wx = 0; wx < 2 * dx + 1; wx++)
     502    for (var wx = 0; wx < 2 * dx + 1; ++wx)
    507503    {
    508         for (var wy = 0; wy < 2 * dy + 1; wy++)
     504        for (var wy = 0; wy < 2 * dy + 1; ++wy)
    509505        {
    510506            var actualX = x - dx + wx;
    511507            var actualY = y - dy + wy;
    var initialReliefmap = [[heightRange.max, heightRange.max, heightRange.max], [he  
    550546
    551547setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, 0.5, initialReliefmap, g_Map.height);
    552548// Apply simple erosion
    553 for (var i = 0; i < 5; i++)
     549for (var i = 0; i < 5; ++i)
    554550    decayErrodeHeightmap(0.5);
    555551rescaleHeightmap(heightRange.min, heightRange.max);
    556552
    var heighLimits = [  
    582578var startLocations = getStartLocationsByHeightmap({'min': heighLimits[4], 'max': heighLimits[5]});
    583579var playerHeight = (heighLimits[4] + heighLimits[5]) / 2;
    584580
    585 for (var i=0; i < numPlayers; i++)
     581for (var i=0; i < numPlayers; ++i)
    586582{
    587583    playerAngle[i] = (playerAngleStart + i*playerAngleAddAvrg + randFloat(0, playerAngleMaxOff))%(2*PI);
    588584    var x = round(mapCenterX + randFloat(minPlayerRadius, maxPlayerRadius)*cos(playerAngle[i]));
    for (var i=0; i < numPlayers; i++)  
    604600    var distToSL = 15;
    605601    var resStartAngle = playerAngle[i] + PI;
    606602    var resAddAngle = 2*PI / startingResources.length;
    607     for (var rIndex = 0; rIndex < startingResources.length; rIndex++)
     603    for (var rIndex = 0; rIndex < startingResources.length; ++rIndex)
    608604    {
    609605        var angleOff = randFloat(-resAddAngle/2, resAddAngle/2);
    610606        var placeX = x + distToSL*cos(resStartAngle + rIndex*resAddAngle + angleOff);
    if (doublePaths === true)  
    644640    var maxI = numPlayers+1;
    645641else
    646642    var maxI = numPlayers;
    647 for (var i = 0; i < maxI; i++)
     643for (var i = 0; i < maxI; ++i)
    648644{
    649645    if (doublePaths === true)
    650646        var minJ = 0;
    651647    else
    652648        var minJ = i+1;
    653     for (var j = minJ; j < numPlayers+1; j++)
     649    for (var j = minJ; j < numPlayers+1; ++j)
    654650    {
    655651        // Setup start and target coordinates
    656652        if (i < numPlayers)
    for (var i = 0; i < maxI; i++)  
    700696            }
    701697            if (getDistance(x, z, targetX, targetZ) < pathSucsessRadius)
    702698                targetReached = true;
    703             tries++;
     699            ++tries;
    704700
    705701        }
    706702    }
    RMS.SetProgress(90);  
    761757
    762758// place trees
    763759log("Planting trees...");
    764 for (var x = 0; x < mapSize; x++)
     760for (var x = 0; x < mapSize; ++x)
    765761{
    766     for (var z = 0;z < mapSize;z++)
     762    for (var z = 0; z < mapSize; ++z)
    767763    {
    768764        // Some variables
    769765        var radius = Math.pow(Math.pow(mapCenterX - x - 0.5, 2) + Math.pow(mapCenterZ - z - 0.5, 2), 1/2); // The 0.5 is a correction for the entities placed on the center of tiles
    770766        var minDistToSL = mapSize;
    771         for (var i=0; i < numPlayers; i++)
     767        for (var i=0; i < numPlayers; ++i)
    772768            minDistToSL = min(minDistToSL, getDistance(playerStartLocX[i], playerStartLocZ[i], x, z));
    773769        // Woods tile based
    774770        var tDensFactSL = max(min((minDistToSL - baseRadius) / baseRadius, 1), 0);
  • binaries/data/mods/public/maps/random/wall_demo.js

    const distToOtherWalls = 10;  
    6161var buildableMapSize = mapSize - 2 * distToMapBorder;
    6262var actualX = distToMapBorder;
    6363var actualY = distToMapBorder;
    64 // Wall styles are chosen by strings so the civ strings got by getCivCode() can be used
    65 // Other styles may be present as well but besides the civ styles only 'palisades' includes all wall element types (yet)
    66 const wallStyleList = ["athen", "brit", "cart", "gaul", "iber", "mace", "maur", "pers", "ptol", "rome", "sele", "spart", "rome_siege", "palisades"];
    67 
     64var wallStyleList = g_WallStyleList;
    6865
    6966////////////////////////////////////////
    7067// Custom wall placement (element based)
    7168////////////////////////////////////////
    72 var wall = ['endLeft', 'wallLong', 'tower', 'wall', 'outpost', 'wall', 'cornerOut', 'wall', 'cornerIn', 'wall', 'house', 'endRight', 'entryTower', 'endLeft', 'wallShort', 'barracks', 'gate', 'tower', 'wall', 'wallFort', 'wall', 'endRight'];
    73 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)
     69var wall = ['start', 'long', 'tower', 'tower', 'tower', 'medium', 'outpost', 'medium', 'cornerOut', 'medium', 'cornerIn', 'medium', 'house', 'end', 'entryTower', 'start', 'short', 'barracks', 'gate', 'tower', 'medium', 'fort', 'medium', 'end'];
     70for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
    7471{
    7572    var startX = actualX + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the first wall element
    7673    var startY = actualY; // Y coordinate of the first wall element
    77     var style = wallStyleList[styleIndex]; // // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
    78     var orientation = styleIndex * PI/64; // Orientation of the first wall element. 0 means 'outside' or 'front' is right (positive X, like object placement)
     74    var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
     75    var orientation = PI/16 * sin(styleIndex * PI/4); // Orientation of the first wall element. 0 means 'outside' or 'front' is right (positive X, like object placement in Atlas)
    7976    // That means the wall will be build towards top (positive Y) if no corners are used
    8077    var playerId = 0; // Owner of the wall (like in placeObject). 0 is Gaia, 1 is Player 1 (default color blue), ...
    81     placeWall(startX, startY, wall, style, playerId, orientation); // Actually placing the wall
     78    placeWall(startX, startY, wall, style, playerId, orientation); // Actually place the wall
    8279}
    8380actualX = distToMapBorder; // Reset actualX
    8481actualY += 80 + distToOtherWalls; // Increase actualY for next wall placement method
    8582
     83
    8684//////////////////////////////////////////////////////////////
    8785// Default fortress placement (chosen by fortress type string)
    8886//////////////////////////////////////////////////////////////
    8987var fortressRadius = 15; // The space the fortresses take in average. Just for design of this map
    90 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)
     88for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
    9189{
    9290    var centerX = actualX + fortressRadius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the fortress
    9391    var centerY = actualY + fortressRadius; // Y coordinate of the center of the fortress
    for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)  
    9997    placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the fortress
    10098}
    10199actualX = distToMapBorder; // Reset actualX
    102 actualY += 2 * fortressRadius + 2 * distToOtherWalls; // Increase actualY for next wall placement method
     100actualY += 2 * fortressRadius + distToOtherWalls; // Increase actualY for next wall placement method
     101
     102//////////////////////////////////////////////////////////////
     103// 'generic' fortress placement (iberian wall circuit code)
     104//////////////////////////////////////////////////////////////
     105var radius = min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall circle
     106for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
     107{
     108    var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the fortress
     109    var centerY = actualY + radius; // Y coordinate of the center of the fortress
     110    var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
     111    var playerId = 0; // Owner of the wall. 0 is Gaia, 1 is Player 1 (default color blue), ...
     112    placeGenericFortress(centerX, centerY, radius, playerId, style); // Actually place the fortress
     113    placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the fortress
     114}
     115actualX = distToMapBorder; // Reset actualX
     116actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method
    103117
    104118//////////////////////////
    105119// Circular wall placement
    actualY += 2 * fortressRadius + 2 * distToOtherWalls; // Increase actualY for ne  
    108122var radius = min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall circle
    109123var centerY = actualY + radius; // Y coordinate of the center of the wall circle
    110124var orientation = 0; // Where the wall circle will be open if maxAngle < 2*PI, see below. Otherwise where the first wall element will be placed
    111 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)
     125for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
    112126{
    113127    var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle
    114128    var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
    115     var wallPart = ['tower', 'wall', 'house']; // List of wall elements the wall will be build of. Optional, default id ['wall']
     129    var wallPart = ['tower', 'medium', 'house']; // List of wall elements the wall will be build of. Optional, default id ['wall']
    116130    var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
    117131    var maxAngle = PI/2 * (styleIndex%3 + 2); // How far the wall should circumvent the center
    118132    placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, orientation, maxAngle); // Actually placing the wall
    for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)  
    122136actualX = distToMapBorder; // Reset actualX
    123137actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method
    124138
    125 ///////////////////////////
    126 // Polygonal wall placement
    127 ///////////////////////////
     139///////////////////////////////////
     140// Regular Polygonal wall placement
     141///////////////////////////////////
    128142// NOTE: Don't use bending wall elements like corners here!
    129143var radius = min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons
    130144var centerY = actualY + radius; // Y coordinate of the center of the wall polygon
    131145var orientation = 0; // Where the wall circle will be open if ???, see below. Otherwise where the first wall will be placed
    132 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)
     146for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
    133147{
    134148    var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle
    135149    var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
    136150    var cornerWallElement = 'tower'; // With wall element type will be uset for the corners of the polygon
    137     var wallPart = ['wall', 'tower']; // List of wall elements the wall will be build of. Optional, default id ['wall']
     151    var wallPart = ['medium', 'tower']; // List of wall elements the wall will be build of. Optional, default id ['wall']
    138152    var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
    139153    var numCorners = (styleIndex)%6 + 3; // How many corners the plogon will have
    140154    var skipFirstWall = true; // If the wall should be open towards orientation
    for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)  
    145159actualX = distToMapBorder; // Reset actualX
    146160actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method
    147161
     162/////////////////////////////////////
     163// Irregular Polygonal wall placement
     164/////////////////////////////////////
     165// NOTE: Don't use bending wall elements like corners here!
     166var radius = min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons
     167var centerY = actualY + radius; // Y coordinate of the center of the wall polygon
     168var orientation = 0; // Where the wall circle will be open if ???, see below. Otherwise where the first wall will be placed
     169for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
     170{
     171    var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle
     172    var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
     173    var cornerWallElement = 'tower'; // With wall element type will be uset for the corners of the polygon
     174    var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
     175    var numCorners = (styleIndex)%6 + 3; // How many corners the plogon will have
     176    var skipFirstWall = true; // If the wall should be open towards orientation
     177    placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement, style, playerId, orientation, numCorners, undefined, skipFirstWall);
     178    placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the wall circle
     179    orientation += PI/16; // Increasing orientation to see how rotation works (like for object placement)
     180}
     181actualX = distToMapBorder; // Reset actualX
     182actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method
     183
     184
    148185////////////////////////
    149186// Linear wall placement
    150187////////////////////////
    151188// NOTE: Don't use bending wall elements like corners here!
    152189var maxWallLength = (mapSize - actualY - distToMapBorder - distToOtherWalls); // Just for this maps design. How long the longest wall will be
    153190var numWallsPerStyle = floor(buildableMapSize / distToOtherWalls / wallStyleList.length); // Just for this maps design. How many walls of the same style will be placed
    154 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++)
     191for (var styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
    155192{
    156     for (var wallIndex = 0; wallIndex < numWallsPerStyle; wallIndex++)
     193    for (var wallIndex = 0; wallIndex < numWallsPerStyle; ++wallIndex)
    157194    {
    158         var startX = actualX + (styleIndex * numWallsPerStyle + wallIndex) * distToOtherWalls; // X coordinate the wall will start from
     195        var startX = actualX + (styleIndex * numWallsPerStyle + wallIndex) * buildableMapSize/wallStyleList.length/numWallsPerStyle; // X coordinate the wall will start from
    159196        var startY = actualY; // Y coordinate the wall will start from
    160197        var endX = startX; // X coordinate the wall will end
    161198        var endY = actualY + (wallIndex + 1) * maxWallLength/numWallsPerStyle; // Y coordinate the wall will end
    162199        var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
    163         var wallPart = ['tower', 'wall']; // List of wall elements the wall will be build of
     200        var wallPart = ['tower', 'medium']; // List of wall elements the wall will be build of
    164201        var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
    165202        placeLinearWall(startX, startY, endX, endY, wallPart, style, playerId); // Actually placing the wall
    166203        // placeObject(startX, startY, 'other/obelisk', 0, 0*PI); // Place visual marker to see where exsactly the wall begins
    167204        // placeObject(endX, endY, 'other/obelisk', 0, 0*PI); // Place visual marker to see where exsactly the wall ends
    168205    }
    169206}
    170 actualX = distToMapBorder; // Reset actualX
    171 actualY += maxWallLength + distToOtherWalls; // Increase actualY for next wall placement method
    172207
    173208
    174209// Export map data
  • binaries/data/mods/public/maps/random/wall_demo.json

     
    22    "settings" : {
    33        "Name" : "Wall Demo",
    44        "Script" : "wall_demo.js",
    5         "Description" : "A demonstration of wall placement methods/code in random maps. Very large map size is recommended.",
     5        "Description" : "A demonstration of wall placement methods/code in random maps. Giant map size is recommended!",
    66        "BaseTerrain" : ["grass1"],
    77        "BaseHeight" : 0,
    88        "Keywords": ["demo"],
    99        "CircularMap" : false,
     10        "RevealMap": true,
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
     14 No newline at end of file
  • binaries/data/mods/public/simulation/components/WallPiece.js

    WallPiece.prototype.Schema =  
    66    "</a:example>" +
    77    "<element name='Length'>" +
    88        "<ref name='nonNegativeDecimal'/>" +
    9     "</element>";
     9    "</element>" +
     10    "<optional>" +
     11        "<element name='Orientation'>" +
     12            "<ref name='nonNegativeDecimal'/>" +
     13        "</element>" +
     14    "</optional>" +
     15    "<optional>" +
     16        "<element name='Indent'>" +
     17            "<data type='decimal'/>" +
     18        "</element>" +
     19    "</optional>" +
     20    "<optional>" +
     21        "<element name='Bend'>" +
     22            "<data type='decimal'/>" +
     23        "</element>" +
     24    "</optional>";
    1025
    1126
    1227WallPiece.prototype.Init = function()
  • binaries/data/mods/public/simulation/components/WallSet.js

    WallSet.prototype.Schema =  
    2121            "<element name='WallShort' a:help='Template name of the short wall segment'>" +
    2222                "<text/>" +
    2323            "</element>" +
     24            "<optional>" +
     25                "<element name='WallCurveQuarter'>" +
     26                    "<text/>" +
     27                "</element>" +
     28            "</optional>" +
     29            "<optional>" +
     30                "<element name='WallCurveEighth'>" +
     31                    "<text/>" +
     32                "</element>" +
     33            "</optional>" +
     34            "<optional>" +
     35                "<element name='WallEnd'>" +
     36                    "<text/>" +
     37                "</element>" +
     38            "</optional>" +
     39            "<optional>" +
     40                "<element name='Fort'>" +
     41                    "<text/>" +
     42                "</element>" +
     43            "</optional>" +
    2444        "</interleave>" +
    2545    "</element>" +
    2646    "<element name='MinTowerOverlap' a:help='Maximum fraction that wall segments are allowed to overlap towers, where 0 signifies no overlap and 1 full overlap'>" +
  • binaries/data/mods/public/simulation/data/civs/athen.json

     
    109109            "Special":"Train heroes and research technology pertaining to heroes."
    110110        }
    111111    ],
     112    "WallSets":
     113    [
     114        "other/wallset_palisade",
     115        "structures/athen_wallset_stone"
     116    ],
    112117    "StartEntities":
    113118    [
    114119        {
  • binaries/data/mods/public/simulation/data/civs/brit.json

     
    8787            "Special": ""
    8888        }
    8989    ],
     90    "WallSets":
     91    [
     92        "other/wallset_palisade",
     93        "structures/brit_wallset_stone"
     94    ],
    9095    "StartEntities":
    9196    [
    9297        {
  • binaries/data/mods/public/simulation/data/civs/cart.json

     
    112112            "Special":"Hire Iberian mercenaries."
    113113        }       
    114114    ],
     115    "WallSets":
     116    [
     117        "other/wallset_palisade",
     118        "structures/cart_wallset_stone"
     119    ],
    115120    "StartEntities":
    116121    [
    117122        {
  • binaries/data/mods/public/simulation/data/civs/gaul.json

     
    8787            "Special": ""
    8888        }
    8989    ],
     90    "WallSets":
     91    [
     92        "other/wallset_palisade",
     93        "structures/gaul_wallset_stone"
     94    ],
    9095    "StartEntities":
    9196    [
    9297        {
  • binaries/data/mods/public/simulation/data/civs/iber.json

     
    8585            "Special": "Defensive Aura - Gives all Iberian units and buildings within vision range of the monument a 10-15% attack boost. Build Limit: Only 5 may be built per map."
    8686        }
    8787    ],
     88    "WallSets":
     89    [
     90        "other/wallset_palisade",
     91        "structures/iber_wallset_stone"
     92       
     93    ],
    8894    "StartEntities":
    8995    [
    9096        {
  • binaries/data/mods/public/simulation/data/civs/mace.json

     
    114114            "Special":"Constructs and upgrades all Macedonian siege engines."
    115115        }
    116116    ],
     117    "WallSets":
     118    [
     119        "other/wallset_palisade",
     120        "structures/mace_wallset_stone"
     121       
     122    ],
    117123    "StartEntities":
    118124    [
    119125        {
  • binaries/data/mods/public/simulation/data/civs/maur.json

     
    9494            "Special":"Contentment: +10% Health and +10% resource gathering rates for all citizens and allied citizens within its range. Can be built anywhere except in enemy territory. Max Built: 10."
    9595        }
    9696    ],
     97    "WallSets":
     98    [
     99        "other/wallset_palisade",
     100        "structures/maur_wallset_stone"
     101       
     102    ],
    97103    "StartEntities":
    98104    [
    99105        {
  • binaries/data/mods/public/simulation/data/civs/pers.json

     
    104104            "Special": "Train heroes and Persian Immortals. Gives a slow trickle of all resources as 'Satrapy Tribute.'"
    105105        }
    106106    ],
     107    "WallSets":
     108    [
     109        "other/wallset_palisade",
     110        "structures/pers_wallset_stone"
     111       
     112    ],
    107113    "StartEntities":
    108114    [
    109115        {
  • binaries/data/mods/public/simulation/data/civs/ptol.json

     
    113113            "Special":"When built along the shoreline, removes shroud of darkness over all the water, revealing all the coast lines on the map. Limit: 1."
    114114        }
    115115    ],
     116    "WallSets":
     117    [
     118        "other/wallset_palisade",
     119        "structures/ptol_wallset_stone"
     120       
     121    ],
    116122    "StartEntities":
    117123    [
    118124        {
  • binaries/data/mods/public/simulation/data/civs/rome.json

     
    8989            "Special": "Can be built in neutral and enemy territory to strangle enemy towns."
    9090        }
    9191    ],
     92    "WallSets":
     93    [
     94        "structures/rome_wallset_stone",
     95        "structures/rome_wallset_siege"
     96       
     97    ],
    9298    "StartEntities":
    9399    [
    94100        {
  • binaries/data/mods/public/simulation/data/civs/sele.json

     
    114114            "Special":"This is the Seleucid expansion building, similar to Civic Centers for other factions. It is weaker and carries a smaller territory influence, but is cheaper and built faster."
    115115        }
    116116    ],
     117    "WallSets":
     118    [
     119        "other/wallset_palisade",
     120        "structures/sele_wallset_stone"
     121       
     122    ],
    117123    "StartEntities":
    118124    [
    119125        {
  • binaries/data/mods/public/simulation/data/civs/spart.json

     
    105105            "Special":"Train heroes and Spartiates and research technologies related to them."
    106106        }
    107107    ],
     108    "WallSets":
     109    [
     110        "other/wallset_palisade",
     111        "structures/spart_wallset_stone"
     112       
     113    ],
    108114    "StartEntities":
    109115    [
    110116        {
  • binaries/data/mods/public/simulation/templates/other/palisades_rocks_curve.xml

     
    2525  <VisualActor>
    2626    <Actor>props/special/palisade_rocks_curve.xml</Actor>
    2727  </VisualActor>
     28  <WallPiece>
     29    <Length>8.0</Length>
     30    <Orientation>0.75</Orientation>
     31    <Indent>2.8</Indent>
     32    <Bend>0.5</Bend>
     33  </WallPiece>
    2834</Entity>
  • binaries/data/mods/public/simulation/templates/other/palisades_rocks_end.xml

     
    2525  <VisualActor>
    2626    <Actor>props/special/palisade_rocks_end.xml</Actor>
    2727  </VisualActor>
     28  <WallPiece>
     29    <Length>0.8</Length>
     30    <Orientation>1.5</Orientation>
     31  </WallPiece>
    2832</Entity>
  • binaries/data/mods/public/simulation/templates/other/palisades_rocks_fort.xml

     
    88    <Icon>structures/palisade_fort.png</Icon>
    99    <Classes datatype="tokens">Palisade</Classes>
    1010  </Identity>
     11  <WallPiece>
     12    <Length>8.0</Length>
     13  </WallPiece>
    1114</Entity>
  • binaries/data/mods/public/simulation/templates/other/palisades_rocks_long.xml

     
    3939  </VisualActor>
    4040  <TerritoryInfluence disable=""/>
    4141  <WallPiece>
    42     <Length>11.0</Length>
     42    <Length>14.0</Length>
    4343  </WallPiece>
    4444</Entity>
  • binaries/data/mods/public/simulation/templates/other/palisades_rocks_medium.xml

     
    3838  </VisualActor>
    3939  <TerritoryInfluence disable=""/>
    4040  <WallPiece>
    41     <Length>8.0</Length>
     41    <Length>9.2</Length>
    4242  </WallPiece>
    4343</Entity>
  • binaries/data/mods/public/simulation/templates/other/palisades_rocks_short.xml

     
    3737    <FoundationActor>structures/fndn_1x1pal.xml</FoundationActor>
    3838  </VisualActor>
    3939  <WallPiece>
    40     <Length>4.0</Length>
     40    <Length>4.8</Length>
    4141  </WallPiece>
    4242</Entity>
  • binaries/data/mods/public/simulation/templates/other/wallset_palisade.xml

     
    1313    <Templates>
    1414      <Tower>other/palisades_rocks_tower</Tower>
    1515      <Gate>other/palisades_rocks_gate</Gate>
     16      <Fort>other/palisades_rocks_fort</Fort>
    1617      <WallLong>other/palisades_rocks_long</WallLong>
    1718      <WallMedium>other/palisades_rocks_medium</WallMedium>
    1819      <WallShort>other/palisades_rocks_short</WallShort>
     20      <WallCurveQuarter>other/palisades_rocks_curve</WallCurveQuarter>
     21      <WallEnd>other/palisades_rocks_end</WallEnd>
    1922    </Templates>
    2023  </WallSet>
    2124</Entity>
  • binaries/data/mods/public/simulation/templates/structures/athen_fortress.xml

     
    2525  <VisualActor>
    2626    <Actor>structures/athenians/fortress_up.xml</Actor>
    2727  </VisualActor>
     28  <WallPiece>
     29    <Length>24.0</Length>
     30    <Indent>7.6</Indent>
     31  </WallPiece>
    2832</Entity>
  • binaries/data/mods/public/simulation/templates/structures/athen_wall_gate.xml

     
    2020    <Actor>structures/hellenes/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>38.0</Length>
     23    <Length>35.4</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/athen_wall_long.xml

     
    1717    <Actor>structures/hellenes/wall_long.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>37.0</Length>
     20    <Length>36.2</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/athen_wall_medium.xml

     
    1717    <Actor>structures/hellenes/wall_medium.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>24.0</Length>
     20    <Length>24.2</Length>
    2121  </WallPiece>
    22 </Entity>
    23  No newline at end of file
     22</Entity>
  • binaries/data/mods/public/simulation/templates/structures/athen_wall_short.xml

     
    1717    <Actor>structures/hellenes/wall_short.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>13.0</Length>
     20    <Length>12.3</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/athen_wall_tower.xml

     
    1616    <Actor>structures/hellenes/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>7.5</Length>
     19    <Length>7.1</Length>
    2020  </WallPiece>
    21 </Entity>
    22  No newline at end of file
     21</Entity>
  • binaries/data/mods/public/simulation/templates/structures/brit_fortress.xml

     
    5454    <Actor>structures/britons/fortress_briton.xml</Actor>
    5555    <FoundationActor>structures/fndn_5x5.xml</FoundationActor>
    5656  </VisualActor>
     57  <WallPiece>
     58    <Length>28</Length>
     59  </WallPiece>
    5760</Entity>
  • binaries/data/mods/public/simulation/templates/structures/brit_wall_gate.xml

     
    2727    <Actor>structures/celts/wall_gate.xml</Actor>
    2828  </VisualActor>
    2929  <WallPiece>
    30     <Length>25.0</Length>
     30    <Length>37.0</Length>
    3131  </WallPiece>
    3232</Entity>
  • binaries/data/mods/public/simulation/templates/structures/brit_wall_long.xml

     
    3636    <Actor>structures/celts/wall_long.xml</Actor>
    3737  </VisualActor>
    3838  <WallPiece>
    39     <Length>37.0</Length>
     39    <Length>36.6</Length>
    4040  </WallPiece>
    4141</Entity>
  • binaries/data/mods/public/simulation/templates/structures/brit_wall_medium.xml

     
    3333    <Actor>structures/celts/wall_medium.xml</Actor>
    3434  </VisualActor>
    3535  <WallPiece>
    36     <Length>25.0</Length>
     36    <Length>24.6</Length>
    3737  </WallPiece>
    3838</Entity>
  • binaries/data/mods/public/simulation/templates/structures/brit_wall_short.xml

     
    2020    <Actor>structures/celts/wall_short.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>13.0</Length>
     23    <Length>12.5</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/brit_wall_tower.xml

     
    2020    <Actor>structures/celts/wall_tower.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>9.0</Length>
     23    <Length>8.7</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/cart_fortress.xml

     
    3131  <VisualActor>
    3232    <Actor>structures/carthaginians/fortress.xml</Actor>
    3333  </VisualActor>
     34  <WallPiece>
     35    <Length>25.0</Length>
     36    <Indent>6.4</Indent>
     37  </WallPiece>
    3438</Entity>
  • binaries/data/mods/public/simulation/templates/structures/cart_wall_gate.xml

     
    2020    <Actor>structures/carthaginians/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>25.0</Length>
     23    <Length>43.8</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/cart_wall_long.xml

     
    3636    <Actor>structures/carthaginians/wall_long.xml</Actor>
    3737  </VisualActor>
    3838  <WallPiece>
    39     <Length>46.0</Length>
     39    <Length>43.7</Length>
    4040  </WallPiece>
    4141</Entity>
  • binaries/data/mods/public/simulation/templates/structures/cart_wall_medium.xml

     
    3030    <Actor>structures/carthaginians/wall_medium.xml</Actor>
    3131  </VisualActor>
    3232  <WallPiece>
    33     <Length>30.0</Length>
     33    <Length>29.3</Length>
    3434  </WallPiece>
    3535</Entity>
  • binaries/data/mods/public/simulation/templates/structures/cart_wall_short.xml

     
    1717    <Actor>structures/carthaginians/wall_short.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>16.0</Length>
     20    <Length>14.7</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/cart_wall_tower.xml

     
    2020    <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>11.0</Length>
     23    <Length>11.8</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/gaul_fortress.xml

     
    3434  <VisualActor>
    3535    <Actor>structures/gauls/fortress_gallic.xml</Actor>
    3636  </VisualActor>
     37  <WallPiece>
     38    <Length>16.8</Length>
     39    <Indent>5.8</Indent>
     40  </WallPiece>
    3741</Entity>
  • binaries/data/mods/public/simulation/templates/structures/gaul_wall_gate.xml

     
    2727    <Actor>structures/celts/wall_gate.xml</Actor>
    2828  </VisualActor>
    2929  <WallPiece>
    30     <Length>25.0</Length>
     30    <Length>37.0</Length>
    3131  </WallPiece>
    3232</Entity>
  • binaries/data/mods/public/simulation/templates/structures/gaul_wall_long.xml

     
    3636    <Actor>structures/celts/wall_long.xml</Actor>
    3737  </VisualActor>
    3838  <WallPiece>
    39     <Length>37.0</Length>
     39    <Length>36.6</Length>
    4040  </WallPiece>
    4141</Entity>
  • binaries/data/mods/public/simulation/templates/structures/gaul_wall_medium.xml

     
    3333    <Actor>structures/celts/wall_medium.xml</Actor>
    3434  </VisualActor>
    3535  <WallPiece>
    36     <Length>25.0</Length>
     36    <Length>24.6</Length>
    3737  </WallPiece>
    3838</Entity>
  • binaries/data/mods/public/simulation/templates/structures/gaul_wall_short.xml

     
    2020    <Actor>structures/celts/wall_short.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>13.0</Length>
     23    <Length>12.6</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/gaul_wall_tower.xml

     
    2020    <Actor>structures/celts/wall_tower.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>9.0</Length>
     23    <Length>8.7</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/iber_fortress.xml

     
    3737  <VisualActor>
    3838    <Actor>structures/iberians/fortress.xml</Actor>
    3939  </VisualActor>
     40  <WallPiece>
     41    <Length>24.5</Length>
     42  </WallPiece>
    4043</Entity>
  • binaries/data/mods/public/simulation/templates/structures/iber_wall_long.xml

     
    3636    <Actor>structures/iberians/wall_long.xml</Actor>
    3737  </VisualActor>
    3838  <WallPiece>
    39     <Length>36.0</Length>
     39    <Length>36.4</Length>
    4040  </WallPiece>
    4141</Entity>
  • binaries/data/mods/public/simulation/templates/structures/iber_wall_medium.xml

     
    3333    <Actor>structures/iberians/wall_medium.xml</Actor>
    3434  </VisualActor>
    3535  <WallPiece>
    36     <Length>24.0</Length>
     36    <Length>24.4</Length>
    3737  </WallPiece>
    3838</Entity>
  • binaries/data/mods/public/simulation/templates/structures/iber_wall_short.xml

     
    2020    <Actor>structures/iberians/wall_short.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>12.0</Length>
     23    <Length>12.4</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/iber_wall_tower.xml

     
    2121    <Actor>structures/iberians/wall_tower.xml</Actor>
    2222  </VisualActor>
    2323  <WallPiece>
    24     <Length>10</Length>
     24    <Length>10.8</Length>
    2525  </WallPiece>
    2626</Entity>
  • binaries/data/mods/public/simulation/templates/structures/mace_fortress.xml

     
    4040  <VisualActor>
    4141    <Actor>structures/macedonians/fortress_up.xml</Actor>
    4242  </VisualActor>
     43  <WallPiece>
     44    <Length>24.0</Length>
     45    <Indent>7.6</Indent>
     46  </WallPiece>
    4347</Entity>
  • binaries/data/mods/public/simulation/templates/structures/mace_wall_gate.xml

     
    2020    <Actor>structures/hellenes/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>38.0</Length>
     23    <Length>35.4</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/mace_wall_long.xml

     
    1717    <Actor>structures/hellenes/wall_long.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>37.0</Length>
     20    <Length>36.2</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/mace_wall_medium.xml

     
    1717    <Actor>structures/hellenes/wall_medium.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>24.0</Length>
     20    <Length>24.2</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/mace_wall_short.xml

     
    1717    <Actor>structures/hellenes/wall_short.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>13.0</Length>
     20    <Length>12.3</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/mace_wall_tower.xml

     
    1616    <Actor>structures/hellenes/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>7.5</Length>
     19    <Length>7.1</Length>
    2020  </WallPiece>
    21 </Entity>
    22  No newline at end of file
     21</Entity>
  • binaries/data/mods/public/simulation/templates/structures/maur_fortress.xml

     
    2828  <VisualActor>
    2929    <Actor>structures/mauryans/fortress.xml</Actor>
    3030  </VisualActor>
     31  <WallPiece>
     32    <Length>22.0</Length>
     33  </WallPiece>
    3134</Entity>
  • binaries/data/mods/public/simulation/templates/structures/maur_wall_gate.xml

     
    2020    <Actor>structures/mauryans/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>37.0</Length>
     23    <Length>36.7</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/maur_wall_long.xml

     
    4242    <Actor>structures/mauryans/wall_long.xml</Actor>
    4343  </VisualActor>
    4444  <WallPiece>
    45     <Length>35.0</Length>
     45    <Length>36.6</Length>
    4646  </WallPiece>
    4747</Entity>
  • binaries/data/mods/public/simulation/templates/structures/maur_wall_medium.xml

     
    3636    <Actor>structures/mauryans/wall_medium.xml</Actor>
    3737  </VisualActor>
    3838  <WallPiece>
    39     <Length>24.0</Length>
     39    <Length>24.4</Length>
    4040  </WallPiece>
    4141</Entity>
  • binaries/data/mods/public/simulation/templates/structures/maur_wall_short.xml

     
    2323    <Actor>structures/mauryans/wall_short.xml</Actor>
    2424  </VisualActor>
    2525  <WallPiece>
    26     <Length>13.0</Length>
     26    <Length>12.4</Length>
    2727  </WallPiece>
    2828</Entity>
  • binaries/data/mods/public/simulation/templates/structures/maur_wall_tower.xml

     
    2525    <Actor>structures/mauryans/wall_tower.xml</Actor>
    2626  </VisualActor>
    2727  <WallPiece>
    28     <Length>9.5</Length>
     28    <Length>7.8</Length>
    2929  </WallPiece>
    3030</Entity>
  • binaries/data/mods/public/simulation/templates/structures/pers_fortress.xml

     
    2020  <VisualActor>
    2121    <Actor>structures/persians/fortress.xml</Actor>
    2222  </VisualActor>
     23  <WallPiece>
     24    <Length>24.5</Length>
     25    <Indent>7.6</Indent>
     26  </WallPiece>
    2327</Entity>
  • binaries/data/mods/public/simulation/templates/structures/pers_wall_tower.xml

     
    1616    <Actor>structures/persians/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>8.5</Length>
     19    <Length>7.5</Length>
    2020  </WallPiece>
    2121</Entity>
  • binaries/data/mods/public/simulation/templates/structures/ptol_fortress.xml

     
    3131  <VisualActor>
    3232    <Actor>structures/ptolemies/fortress.xml</Actor>
    3333  </VisualActor>
     34  <WallPiece>
     35    <Length>24.0</Length>
     36    <Indent>8.7</Indent>
     37  </WallPiece>
    3438</Entity>
  • binaries/data/mods/public/simulation/templates/structures/ptol_wall_gate.xml

     
    2020    <Actor>structures/ptolemies/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>38.0</Length>
     23    <Length>38.8</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/ptol_wall_medium.xml

     
    3030    <Actor>structures/ptolemies/wall_medium.xml</Actor>
    3131  </VisualActor>
    3232  <WallPiece>
    33     <Length>26.0</Length>
     33    <Length>25.0</Length>
    3434  </WallPiece>
    3535</Entity>
  • binaries/data/mods/public/simulation/templates/structures/ptol_wall_short.xml

     
    1717    <Actor>structures/ptolemies/wall_short.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>14.0</Length>
     20    <Length>16.0</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/ptol_wall_tower.xml

     
    1616    <Actor>structures/ptolemies/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>10</Length>
     19    <Length>9.0</Length>
    2020  </WallPiece>
    21 </Entity>
    22  No newline at end of file
     21</Entity>
  • binaries/data/mods/public/simulation/templates/structures/ptol_wallset_stone.xml

     
    1414      <WallShort>structures/ptol_wall_short</WallShort>
    1515    </Templates>
    1616    <MaxTowerOverlap>0.90</MaxTowerOverlap>
    17     <MinTowerOverlap>0.05</MinTowerOverlap>
     17    <MinTowerOverlap>0.10</MinTowerOverlap>
    1818  </WallSet>
    1919</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml

     
    101101    <Actor>structures/romans/camp.xml</Actor>
    102102    <FoundationActor>structures/fndn_8x8.xml</FoundationActor>
    103103  </VisualActor>
     104  <WallPiece>
     105    <Length>29.5</Length>
     106    <Indent>8</Indent>
     107  </WallPiece>
    104108</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_fortress.xml

     
    2323  <VisualActor>
    2424    <Actor>structures/romans/fortress.xml</Actor>
    2525  </VisualActor>
     26  <WallPiece>
     27    <Length>25.0</Length>
     28    <Indent>8.4</Indent>
     29  </WallPiece>
    2630</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_tower.xml

     
    4343    <Actor>structures/romans/siege_wall_tower.xml</Actor>
    4444  </VisualActor>
    4545  <WallPiece>
    46     <Length>6.0</Length>
     46    <Length>5.5</Length>
    4747  </WallPiece>
    4848</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_wall_gate.xml

     
    2020    <Actor>structures/romans/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>37.0</Length>
     23    <Length>36.8</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_wall_long.xml

     
    3636    <Actor>structures/romans/wall_long.xml</Actor>
    3737  </VisualActor>
    3838  <WallPiece>
    39     <Length>37.0</Length>
     39    <Length>36.8</Length>
    4040  </WallPiece>
    4141</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_wall_medium.xml

     
    3333    <Actor>structures/romans/wall_medium.xml</Actor>
    3434  </VisualActor>
    3535  <WallPiece>
    36     <Length>25.0</Length>
     36    <Length>24.8</Length>
    3737  </WallPiece>
    3838</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_wall_short.xml

     
    2020    <Actor>structures/romans/wall_short.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>13.0</Length>
     23    <Length>12.9</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_wall_tower.xml

     
    1616    <Actor>structures/romans/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>9.5</Length>
     19    <Length>10</Length>
    2020  </WallPiece>
    2121</Entity>
  • binaries/data/mods/public/simulation/templates/structures/rome_wallset_siege.xml

     
    1313    <Templates>
    1414      <Tower>structures/rome_siege_wall_tower</Tower>
    1515      <Gate>structures/rome_siege_wall_gate</Gate>
     16      <Fort>structures/rome_army_camp</Fort>
    1617      <WallLong>structures/rome_siege_wall_long</WallLong>
    1718      <WallMedium>structures/rome_siege_wall_medium</WallMedium>
    1819      <WallShort>structures/rome_siege_wall_short</WallShort>
  • binaries/data/mods/public/simulation/templates/structures/sele_fortress.xml

     
    3434  <VisualActor>
    3535    <Actor>structures/seleucids/fortress.xml</Actor>
    3636  </VisualActor>
     37  <WallPiece>
     38    <Length>23</Length>
     39    <Indent>7.8</Indent>
     40  </WallPiece>
    3741</Entity>
  • binaries/data/mods/public/simulation/templates/structures/sele_wall_gate.xml

     
    2020    <Actor>structures/hellenes/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>38.0</Length>
     23    <Length>35.4</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/sele_wall_long.xml

     
    1717    <Actor>structures/hellenes/wall_long.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>37.0</Length>
     20    <Length>36.2</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/sele_wall_medium.xml

     
    1717    <Actor>structures/hellenes/wall_medium.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>24.0</Length>
     20    <Length>24.2</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/sele_wall_short.xml

     
    1717    <Actor>structures/hellenes/wall_short.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>13.0</Length>
     20    <Length>12.3</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/sele_wall_tower.xml

     
    1616    <Actor>structures/hellenes/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>7.5</Length>
     19    <Length>7.1</Length>
    2020  </WallPiece>
    21 </Entity>
    22  No newline at end of file
     21</Entity>
  • binaries/data/mods/public/simulation/templates/structures/spart_fortress.xml

     
    2525  <VisualActor>
    2626    <Actor>structures/spartans/fortress_up.xml</Actor>
    2727  </VisualActor>
     28  <WallPiece>
     29    <Length>24.0</Length>
     30    <Indent>7.6</Indent>
     31  </WallPiece>
    2832</Entity>
  • binaries/data/mods/public/simulation/templates/structures/spart_wall_gate.xml

     
    2020    <Actor>structures/hellenes/wall_gate.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>38.0</Length>
     23    <Length>35.4</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/spart_wall_long.xml

     
    1717    <Actor>structures/hellenes/wall_long.xml</Actor>
    1818  </VisualActor>
    1919  <WallPiece>
    20     <Length>37.0</Length>
     20    <Length>36.2</Length>
    2121  </WallPiece>
    2222</Entity>
  • binaries/data/mods/public/simulation/templates/structures/spart_wall_medium.xml

     
    2020    <Actor>structures/hellenes/wall_medium.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>24.0</Length>
     23    <Length>24.2</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/spart_wall_short.xml

     
    2020    <Actor>structures/hellenes/wall_short.xml</Actor>
    2121  </VisualActor>
    2222  <WallPiece>
    23     <Length>13.0</Length>
     23    <Length>12.3</Length>
    2424  </WallPiece>
    2525</Entity>
  • binaries/data/mods/public/simulation/templates/structures/spart_wall_tower.xml

     
    1616    <Actor>structures/hellenes/wall_tower.xml</Actor>
    1717  </VisualActor>
    1818  <WallPiece>
    19     <Length>7.5</Length>
     19    <Length>7.1</Length>
    2020  </WallPiece>
    21 </Entity>
    22  No newline at end of file
     21</Entity>